1 /** @file 2 3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 4 Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 #include <Base.h> 16 17 #include <Library/BaseLib.h> 18 #include <Library/SemihostLib.h> 19 20 #include "SemihostPrivate.h" 21 22 BOOLEAN 23 SemihostConnectionSupported ( 24 VOID 25 ) 26 { 27 return SEMIHOST_SUPPORTED; 28 } 29 30 RETURN_STATUS 31 SemihostFileOpen ( 32 IN CHAR8 *FileName, 33 IN UINT32 Mode, 34 OUT UINTN *FileHandle 35 ) 36 { 37 SEMIHOST_FILE_OPEN_BLOCK OpenBlock; 38 INT32 Result; 39 40 if (FileHandle == NULL) { 41 return RETURN_INVALID_PARAMETER; 42 } 43 44 // Remove any leading separator (e.g.: '\'). EFI Shell adds one. 45 if (*FileName == '\\') { 46 FileName++; 47 } 48 49 OpenBlock.FileName = FileName; 50 OpenBlock.Mode = Mode; 51 OpenBlock.NameLength = AsciiStrLen(FileName); 52 53 Result = Semihost_SYS_OPEN(&OpenBlock); 54 55 if (Result == -1) { 56 return RETURN_NOT_FOUND; 57 } else { 58 *FileHandle = Result; 59 return RETURN_SUCCESS; 60 } 61 } 62 63 RETURN_STATUS 64 SemihostFileSeek ( 65 IN UINTN FileHandle, 66 IN UINTN Offset 67 ) 68 { 69 SEMIHOST_FILE_SEEK_BLOCK SeekBlock; 70 INT32 Result; 71 72 SeekBlock.Handle = FileHandle; 73 SeekBlock.Location = Offset; 74 75 Result = Semihost_SYS_SEEK(&SeekBlock); 76 77 // Semihosting does not behave as documented. It returns the offset on 78 // success. 79 if (Result < 0) { 80 return RETURN_ABORTED; 81 } else { 82 return RETURN_SUCCESS; 83 } 84 } 85 86 RETURN_STATUS 87 SemihostFileRead ( 88 IN UINTN FileHandle, 89 IN OUT UINTN *Length, 90 OUT VOID *Buffer 91 ) 92 { 93 SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock; 94 UINT32 Result; 95 96 if ((Length == NULL) || (Buffer == NULL)) { 97 return RETURN_INVALID_PARAMETER; 98 } 99 100 ReadBlock.Handle = FileHandle; 101 ReadBlock.Buffer = Buffer; 102 ReadBlock.Length = *Length; 103 104 Result = Semihost_SYS_READ(&ReadBlock); 105 106 if ((*Length != 0) && (Result == *Length)) { 107 return RETURN_ABORTED; 108 } else { 109 *Length -= Result; 110 return RETURN_SUCCESS; 111 } 112 } 113 114 RETURN_STATUS 115 SemihostFileWrite ( 116 IN UINTN FileHandle, 117 IN OUT UINTN *Length, 118 IN VOID *Buffer 119 ) 120 { 121 SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock; 122 123 if ((Length == NULL) || (Buffer == NULL)) { 124 return RETURN_INVALID_PARAMETER; 125 } 126 127 WriteBlock.Handle = FileHandle; 128 WriteBlock.Buffer = Buffer; 129 WriteBlock.Length = *Length; 130 131 *Length = Semihost_SYS_WRITE(&WriteBlock); 132 133 if (*Length != 0) 134 return RETURN_ABORTED; 135 else 136 return RETURN_SUCCESS; 137 } 138 139 RETURN_STATUS 140 SemihostFileClose ( 141 IN UINTN FileHandle 142 ) 143 { 144 INT32 Result = Semihost_SYS_CLOSE(&FileHandle); 145 146 if (Result == -1) { 147 return RETURN_INVALID_PARAMETER; 148 } else { 149 return RETURN_SUCCESS; 150 } 151 } 152 153 RETURN_STATUS 154 SemihostFileLength ( 155 IN UINTN FileHandle, 156 OUT UINTN *Length 157 ) 158 { 159 INT32 Result; 160 161 if (Length == NULL) { 162 return RETURN_INVALID_PARAMETER; 163 } 164 165 Result = Semihost_SYS_FLEN(&FileHandle); 166 167 if (Result == -1) { 168 return RETURN_ABORTED; 169 } else { 170 *Length = Result; 171 return RETURN_SUCCESS; 172 } 173 } 174 175 /** 176 Get a temporary name for a file from the host running the debug agent. 177 178 @param[out] Buffer Pointer to the buffer where the temporary name has to 179 be stored 180 @param[in] Identifier File name identifier (integer in the range 0 to 255) 181 @param[in] Length Length of the buffer to store the temporary name 182 183 @retval RETURN_SUCCESS Temporary name returned 184 @retval RETURN_INVALID_PARAMETER Invalid buffer address 185 @retval RETURN_ABORTED Temporary name not returned 186 187 **/ 188 RETURN_STATUS 189 SemihostFileTmpName( 190 OUT VOID *Buffer, 191 IN UINT8 Identifier, 192 IN UINTN Length 193 ) 194 { 195 SEMIHOST_FILE_TMPNAME_BLOCK TmpNameBlock; 196 INT32 Result; 197 198 if (Buffer == NULL) { 199 return RETURN_INVALID_PARAMETER; 200 } 201 202 TmpNameBlock.Buffer = Buffer; 203 TmpNameBlock.Identifier = Identifier; 204 TmpNameBlock.Length = Length; 205 206 Result = Semihost_SYS_TMPNAME (&TmpNameBlock); 207 208 if (Result != 0) { 209 return RETURN_ABORTED; 210 } else { 211 return RETURN_SUCCESS; 212 } 213 } 214 215 RETURN_STATUS 216 SemihostFileRemove ( 217 IN CHAR8 *FileName 218 ) 219 { 220 SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock; 221 UINT32 Result; 222 223 // Remove any leading separator (e.g.: '\'). EFI Shell adds one. 224 if (*FileName == '\\') { 225 FileName++; 226 } 227 228 RemoveBlock.FileName = FileName; 229 RemoveBlock.NameLength = AsciiStrLen(FileName); 230 231 Result = Semihost_SYS_REMOVE(&RemoveBlock); 232 233 if (Result == 0) { 234 return RETURN_SUCCESS; 235 } else { 236 return RETURN_ABORTED; 237 } 238 } 239 240 /** 241 Rename a specified file. 242 243 @param[in] FileName Name of the file to rename. 244 @param[in] NewFileName The new name of the file. 245 246 @retval RETURN_SUCCESS File Renamed 247 @retval RETURN_INVALID_PARAMETER Either the current or the new name is not specified 248 @retval RETURN_ABORTED Rename failed 249 250 **/ 251 RETURN_STATUS 252 SemihostFileRename( 253 IN CHAR8 *FileName, 254 IN CHAR8 *NewFileName 255 ) 256 { 257 SEMIHOST_FILE_RENAME_BLOCK RenameBlock; 258 INT32 Result; 259 260 if ((FileName == NULL) || (NewFileName == NULL)) { 261 return RETURN_INVALID_PARAMETER; 262 } 263 264 RenameBlock.FileName = FileName; 265 RenameBlock.FileNameLength = AsciiStrLen (FileName); 266 RenameBlock.NewFileName = NewFileName; 267 RenameBlock.NewFileNameLength = AsciiStrLen (NewFileName); 268 269 Result = Semihost_SYS_RENAME (&RenameBlock); 270 271 if (Result != 0) { 272 return RETURN_ABORTED; 273 } else { 274 return RETURN_SUCCESS; 275 } 276 } 277 278 CHAR8 279 SemihostReadCharacter ( 280 VOID 281 ) 282 { 283 return Semihost_SYS_READC(); 284 } 285 286 VOID 287 SemihostWriteCharacter ( 288 IN CHAR8 Character 289 ) 290 { 291 Semihost_SYS_WRITEC(&Character); 292 } 293 294 VOID 295 SemihostWriteString ( 296 IN CHAR8 *String 297 ) 298 { 299 Semihost_SYS_WRITE0(String); 300 } 301 302 UINT32 303 SemihostSystem ( 304 IN CHAR8 *CommandLine 305 ) 306 { 307 SEMIHOST_SYSTEM_BLOCK SystemBlock; 308 309 SystemBlock.CommandLine = CommandLine; 310 SystemBlock.CommandLength = AsciiStrLen(CommandLine); 311 312 return Semihost_SYS_SYSTEM(&SystemBlock); 313 } 314