]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
Patch from open source community for CryptoPkg to allow it to build for ARM using...
[mirror_edk2.git] / ArmPkg / Filesystem / SemihostFs / Arm / SemihostFs.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Support a Semi Host file system over a debuggers JTAG\r
3\r
d6ebcab7 4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
2ef2b01e 5 \r
d6ebcab7 6 This program and the accompanying materials\r
2ef2b01e
A
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <Uefi.h>\r
17\r
18#include <Guid/FileInfo.h>\r
19#include <Guid/FileSystemInfo.h>\r
20\r
21#include <Library/BaseLib.h>\r
22#include <Library/BaseMemoryLib.h> \r
23#include <Library/DebugLib.h>\r
24#include <Library/MemoryAllocationLib.h>\r
25#include <Library/SemihostLib.h>\r
26#include <Library/UefiBootServicesTableLib.h>\r
27#include <Library/UefiLib.h>\r
28\r
29#include <Protocol/DevicePath.h>\r
30#include <Protocol/SimpleFileSystem.h>\r
31\r
32#include "SemihostFs.h"\r
33\r
34\r
35EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {\r
36 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
37 VolumeOpen\r
38};\r
39\r
40EFI_FILE gSemihostFsFile = {\r
41 EFI_FILE_PROTOCOL_REVISION,\r
42 FileOpen,\r
43 FileClose,\r
44 FileDelete,\r
45 FileRead,\r
46 FileWrite,\r
47 FileGetPosition,\r
48 FileSetPosition,\r
49 FileGetInfo,\r
50 FileSetInfo,\r
51 FileFlush\r
52};\r
53\r
54//\r
55// Device path for SemiHosting. It contains our autogened Caller ID GUID.\r
56//\r
57typedef struct {\r
58 VENDOR_DEVICE_PATH Guid;\r
59 EFI_DEVICE_PATH_PROTOCOL End;\r
60} SEMIHOST_DEVICE_PATH;\r
61\r
62SEMIHOST_DEVICE_PATH gDevicePath = {\r
63 {\r
64 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },\r
65 EFI_CALLER_ID_GUID\r
66 },\r
67 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}\r
68};\r
69\r
70typedef struct {\r
71 LIST_ENTRY Link;\r
72 UINT64 Signature;\r
73 EFI_FILE File;\r
74 CHAR8 *FileName;\r
75 UINT32 Position;\r
76 UINT32 SemihostHandle;\r
77 BOOLEAN IsRoot;\r
78} SEMIHOST_FCB;\r
79\r
80#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )\r
81#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)\r
82#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);\r
83\r
84EFI_HANDLE gInstallHandle = NULL;\r
85LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList);\r
86\r
87SEMIHOST_FCB *\r
88AllocateFCB (\r
89 VOID\r
90 )\r
91{\r
92 SEMIHOST_FCB *Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));\r
93\r
94 if (Fcb != NULL) {\r
95 CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));\r
96 Fcb->Signature = SEMIHOST_FCB_SIGNATURE;\r
97 }\r
98\r
99 return Fcb;\r
100}\r
101\r
102VOID\r
103FreeFCB (\r
104 IN SEMIHOST_FCB *Fcb\r
105 )\r
106{\r
107 // Remove Fcb from gFileList.\r
108 RemoveEntryList (&Fcb->Link);\r
109\r
110 // To help debugging...\r
111 Fcb->Signature = 0;\r
112\r
113 FreePool (Fcb);\r
114}\r
115\r
116\r
117\r
118EFI_STATUS\r
119VolumeOpen (\r
120 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
121 OUT EFI_FILE **Root\r
122 )\r
123{\r
124 SEMIHOST_FCB *RootFcb = NULL;\r
125 \r
126 if (Root == NULL) {\r
127 return EFI_INVALID_PARAMETER;\r
128 }\r
129\r
130 RootFcb = AllocateFCB ();\r
131 if (RootFcb == NULL) {\r
132 return EFI_OUT_OF_RESOURCES;\r
133 }\r
134 \r
135 RootFcb->IsRoot = TRUE;\r
136\r
137 InsertTailList (&gFileList, &RootFcb->Link);\r
138\r
139 *Root = &RootFcb->File;\r
140\r
141 return EFI_SUCCESS;\r
142}\r
143\r
144EFI_STATUS\r
145FileOpen (\r
146 IN EFI_FILE *File,\r
147 OUT EFI_FILE **NewHandle,\r
148 IN CHAR16 *FileName,\r
149 IN UINT64 OpenMode,\r
150 IN UINT64 Attributes\r
151 )\r
152{\r
153 SEMIHOST_FCB *FileFcb = NULL;\r
154 EFI_STATUS Status = EFI_SUCCESS;\r
155 UINT32 SemihostHandle;\r
156 CHAR8 *AsciiFileName;\r
157 CHAR8 *AsciiPtr;\r
158 UINTN Length;\r
159 UINT32 SemihostMode;\r
160 BOOLEAN IsRoot;\r
161\r
162 if ((FileName == NULL) || (NewHandle == NULL)) {\r
163 return EFI_INVALID_PARAMETER;\r
164 }\r
165\r
166 // Semihost interface requires ASCII filesnames\r
167 Length = StrSize (FileName);\r
168\r
169 AsciiFileName = AllocatePool (Length);\r
170 if (AsciiFileName == NULL) {\r
171 return EFI_OUT_OF_RESOURCES;\r
172 }\r
173\r
174 AsciiPtr = AsciiFileName;\r
175\r
176 while (Length--) {\r
177 *AsciiPtr++ = *FileName++ & 0xFF;\r
178 }\r
179\r
180 if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0)) {\r
181 // Opening '/', '\', or the NULL pathname is trying to open the root directory\r
182 IsRoot = TRUE;\r
183\r
184 // Root directory node doesn't have a name.\r
185 FreePool (AsciiFileName);\r
186 AsciiFileName = NULL;\r
187 } else {\r
188 // Translate EFI_FILE_MODE into Semihosting mode\r
189 if (OpenMode & EFI_FILE_MODE_WRITE) {\r
190 SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;\r
191 } else if (OpenMode & EFI_FILE_MODE_READ) {\r
192 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
193 } else {\r
194 return EFI_UNSUPPORTED;\r
195 }\r
196\r
197 // Add the creation flag if necessary\r
198 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
199 SemihostMode |= SEMIHOST_FILE_MODE_CREATE;\r
200 }\r
201\r
202 // Call the semihosting interface to open the file.\r
203 Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
204 if (EFI_ERROR(Status)) {\r
205 return Status;\r
206 }\r
207 \r
208 IsRoot = FALSE;\r
209 }\r
210\r
211 // Allocate a control block and fill it\r
212 FileFcb = AllocateFCB ();\r
213 if (FileFcb == NULL) {\r
214 return EFI_OUT_OF_RESOURCES;\r
215 }\r
216\r
217 FileFcb->FileName = AsciiFileName;\r
218 FileFcb->SemihostHandle = SemihostHandle;\r
219 FileFcb->Position = 0;\r
220 FileFcb->IsRoot = IsRoot;\r
221\r
222 InsertTailList (&gFileList, &FileFcb->Link);\r
223\r
224 *NewHandle = &FileFcb->File;\r
225\r
226 return Status;\r
227}\r
228\r
229\r
230EFI_STATUS\r
231FileClose (\r
232 IN EFI_FILE *File\r
233 )\r
234{\r
235 SEMIHOST_FCB *Fcb = NULL;\r
236 EFI_STATUS Status = EFI_SUCCESS;\r
237\r
238 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
239\r
240 if (Fcb->IsRoot == TRUE) {\r
241 FreeFCB (Fcb);\r
242 Status = EFI_SUCCESS;\r
243 } else {\r
244 Status = SemihostFileClose (Fcb->SemihostHandle);\r
245 if (!EFI_ERROR(Status)) {\r
246 FreePool (Fcb->FileName);\r
247 FreeFCB (Fcb);\r
248 }\r
249 }\r
250 \r
251 return Status;\r
252}\r
253\r
254EFI_STATUS\r
255FileDelete (\r
256 IN EFI_FILE *File\r
257 )\r
258{\r
259 SEMIHOST_FCB *Fcb = NULL;\r
260 EFI_STATUS Status;\r
261 CHAR8 *FileName;\r
262 UINTN NameSize;\r
263\r
264 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
265\r
266 // Get the filename from the Fcb\r
267 NameSize = AsciiStrLen (Fcb->FileName);\r
268 FileName = AllocatePool (NameSize + 1);\r
269\r
270 AsciiStrCpy (FileName, Fcb->FileName);\r
271\r
272 // Close the file if it's open. Disregard return status,\r
273 // since it might give an error if the file isn't open.\r
274 File->Close (File);\r
275 \r
276 // Call the semihost interface to delete the file.\r
277 Status = SemihostFileRemove (FileName);\r
278\r
279 return Status;\r
280}\r
281\r
282EFI_STATUS\r
283FileRead (\r
284 IN EFI_FILE *File,\r
285 IN OUT UINTN *BufferSize,\r
286 OUT VOID *Buffer\r
287 )\r
288{\r
289 SEMIHOST_FCB *Fcb = NULL;\r
290 EFI_STATUS Status;\r
291\r
292 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
293\r
294 if (Fcb->IsRoot == TRUE) {\r
295 Status = EFI_UNSUPPORTED;\r
296 } else {\r
297 Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
298 if (!EFI_ERROR (Status)) {\r
299 Fcb->Position += *BufferSize;\r
300 }\r
301 }\r
302\r
303 return Status;\r
304}\r
305\r
306EFI_STATUS\r
307FileWrite (\r
308 IN EFI_FILE *File,\r
309 IN OUT UINTN *BufferSize,\r
310 IN VOID *Buffer\r
311 )\r
312{\r
313 SEMIHOST_FCB *Fcb = NULL;\r
314 EFI_STATUS Status;\r
315 UINTN WriteSize = *BufferSize;\r
316\r
317 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
318\r
319 Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
320\r
321 if (!EFI_ERROR(Status)) {\r
322 // Semihost write return the number of bytes *NOT* written.\r
323 *BufferSize -= WriteSize;\r
324 Fcb->Position += *BufferSize;\r
325 }\r
326 \r
327 return Status;\r
328}\r
329\r
330EFI_STATUS\r
331FileGetPosition (\r
332 IN EFI_FILE *File,\r
333 OUT UINT64 *Position\r
334 )\r
335{\r
336 SEMIHOST_FCB *Fcb = NULL;\r
337 \r
338 if (Position == NULL) {\r
339 return EFI_INVALID_PARAMETER;\r
340 }\r
341\r
342 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
343\r
344 *Position = Fcb->Position;\r
345\r
346 return EFI_SUCCESS;\r
347}\r
348\r
349EFI_STATUS\r
350FileSetPosition (\r
351 IN EFI_FILE *File,\r
352 IN UINT64 Position\r
353 )\r
354{\r
355 SEMIHOST_FCB *Fcb = NULL;\r
356 UINT32 Length;\r
357 EFI_STATUS Status;\r
358\r
359 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
360\r
361 Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
362 if (!EFI_ERROR(Status) && (Length < Position)) {\r
363 Position = Length;\r
364 }\r
365\r
366 Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);\r
367 if (!EFI_ERROR(Status)) {\r
368 Fcb->Position = Position;\r
369 }\r
370\r
371 return Status;\r
372}\r
373\r
374STATIC\r
375EFI_STATUS\r
376GetFileInfo (\r
377 IN SEMIHOST_FCB *Fcb,\r
378 IN OUT UINTN *BufferSize,\r
379 OUT VOID *Buffer\r
380 )\r
381{\r
382 EFI_FILE_INFO *Info = NULL;\r
383 UINTN NameSize = 0;\r
384 UINTN ResultSize;\r
385 UINTN Index;\r
386 UINT32 Length;\r
387 EFI_STATUS Status;\r
388\r
389 if (Fcb->IsRoot == TRUE) {\r
390 ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
391 } else {\r
392 NameSize = AsciiStrLen (Fcb->FileName) + 1;\r
393 ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);\r
394 }\r
395\r
396 if (*BufferSize < ResultSize) {\r
397 *BufferSize = ResultSize;\r
398 return EFI_BUFFER_TOO_SMALL;\r
399 }\r
400\r
401 Info = Buffer;\r
402\r
403 // Zero out the structure\r
404 ZeroMem (Info, SIZE_OF_EFI_FILE_INFO);\r
405\r
406 // Fill in the structure\r
407 Info->Size = ResultSize;\r
408\r
409 if (Fcb->IsRoot == TRUE) {\r
410 Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
411 Info->FileName[0] = L'\0';\r
412 } else {\r
413 Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
414 if (EFI_ERROR(Status)) {\r
415 return Status;\r
416 }\r
417\r
418 Info->FileSize = Length;\r
419 Info->PhysicalSize = Length;\r
420\r
421 for (Index = 0; Index < NameSize; Index++) {\r
422 Info->FileName[Index] = Fcb->FileName[Index]; \r
423 }\r
424 }\r
425\r
426\r
427 *BufferSize = ResultSize; \r
428\r
429 return EFI_SUCCESS;\r
430}\r
431\r
432STATIC\r
433EFI_STATUS\r
434GetFilesystemInfo (\r
435 IN SEMIHOST_FCB *Fcb,\r
436 IN OUT UINTN *BufferSize,\r
437 OUT VOID *Buffer\r
438 )\r
439{\r
440 EFI_FILE_SYSTEM_INFO *Info = NULL;\r
441 EFI_STATUS Status;\r
442 STATIC CHAR16 Label[] = L"SemihostFs";\r
443 UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label);\r
444 \r
445 if(*BufferSize >= ResultSize) {\r
446 ZeroMem (Buffer, ResultSize);\r
447 Status = EFI_SUCCESS;\r
448 \r
449 Info = Buffer;\r
450\r
451 Info->Size = ResultSize;\r
452 Info->ReadOnly = FALSE;\r
453 Info->VolumeSize = 0;\r
454 Info->FreeSpace = 0;\r
455 Info->BlockSize = 0;\r
456\r
457 StrCpy (Info->VolumeLabel, Label);\r
458 } else {\r
459 Status = EFI_BUFFER_TOO_SMALL;\r
460 }\r
461\r
462 *BufferSize = ResultSize; \r
463 return Status;\r
464}\r
465\r
466EFI_STATUS\r
467FileGetInfo (\r
468 IN EFI_FILE *File,\r
469 IN EFI_GUID *InformationType,\r
470 IN OUT UINTN *BufferSize,\r
471 OUT VOID *Buffer\r
472 )\r
473{\r
474 SEMIHOST_FCB *Fcb = NULL;\r
475 EFI_STATUS Status = EFI_UNSUPPORTED;\r
476 \r
477 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
478 \r
479 if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
480 Status = GetFilesystemInfo(Fcb, BufferSize, Buffer); \r
481 } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) {\r
482 Status = GetFileInfo(Fcb, BufferSize, Buffer); \r
483 }\r
484 \r
485 return Status;\r
486}\r
487\r
488EFI_STATUS\r
489FileSetInfo (\r
490 IN EFI_FILE *File,\r
491 IN EFI_GUID *InformationType,\r
492 IN UINTN BufferSize,\r
493 IN VOID *Buffer\r
494 )\r
495{\r
496 return EFI_UNSUPPORTED;\r
497}\r
498\r
499EFI_STATUS\r
500FileFlush (\r
501 IN EFI_FILE *File\r
502 )\r
503{\r
504 return EFI_SUCCESS;\r
505}\r
506\r
507EFI_STATUS\r
508SemihostFsEntryPoint (\r
509 IN EFI_HANDLE ImageHandle,\r
510 IN EFI_SYSTEM_TABLE *SystemTable\r
511 )\r
512{\r
513 EFI_STATUS Status = EFI_NOT_FOUND;\r
514\r
515 if (SemihostConnectionSupported ()) {\r
516 Status = gBS->InstallMultipleProtocolInterfaces (\r
517 &gInstallHandle, \r
518 &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, \r
519 &gEfiDevicePathProtocolGuid, &gDevicePath,\r
520 NULL\r
521 );\r
522 }\r
523 \r
524 return Status;\r
525}\r
526\r