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