]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
ArmPkg/SemihostFs: Fix open file issues revealed by SCT
[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
d276ac10 5 Portions copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>\r
c63626b7 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
09f2cf82 21#include <Guid/FileSystemVolumeLabelInfo.h>\r
2ef2b01e
A
22\r
23#include <Library/BaseLib.h>\r
3402aac7 24#include <Library/BaseMemoryLib.h>\r
2ef2b01e
A
25#include <Library/DebugLib.h>\r
26#include <Library/MemoryAllocationLib.h>\r
27#include <Library/SemihostLib.h>\r
28#include <Library/UefiBootServicesTableLib.h>\r
29#include <Library/UefiLib.h>\r
30\r
31#include <Protocol/DevicePath.h>\r
32#include <Protocol/SimpleFileSystem.h>\r
33\r
34#include "SemihostFs.h"\r
35\r
09f2cf82 36#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs"\r
37\r
38STATIC CHAR16 *mSemihostFsLabel;\r
2ef2b01e
A
39\r
40EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {\r
41 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
42 VolumeOpen\r
43};\r
44\r
45EFI_FILE gSemihostFsFile = {\r
46 EFI_FILE_PROTOCOL_REVISION,\r
47 FileOpen,\r
48 FileClose,\r
49 FileDelete,\r
50 FileRead,\r
51 FileWrite,\r
52 FileGetPosition,\r
53 FileSetPosition,\r
54 FileGetInfo,\r
55 FileSetInfo,\r
56 FileFlush\r
57};\r
58\r
59//\r
fdd12bd5 60// Device path for semi-hosting. It contains our autogened Caller ID GUID.\r
2ef2b01e
A
61//\r
62typedef struct {\r
63 VENDOR_DEVICE_PATH Guid;\r
64 EFI_DEVICE_PATH_PROTOCOL End;\r
65} SEMIHOST_DEVICE_PATH;\r
66\r
67SEMIHOST_DEVICE_PATH gDevicePath = {\r
68 {\r
b0fdce95 69 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } },\r
2ef2b01e
A
70 EFI_CALLER_ID_GUID\r
71 },\r
b0fdce95 72 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }\r
2ef2b01e
A
73};\r
74\r
75typedef struct {\r
09f2cf82 76 LIST_ENTRY Link;\r
77 UINT64 Signature;\r
78 EFI_FILE File;\r
79 CHAR8 *FileName;\r
80 UINT64 OpenMode;\r
81 UINT32 Position;\r
82 UINTN SemihostHandle;\r
83 BOOLEAN IsRoot;\r
84 EFI_FILE_INFO Info;\r
2ef2b01e
A
85} SEMIHOST_FCB;\r
86\r
87#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )\r
88#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)\r
89#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);\r
90\r
91EFI_HANDLE gInstallHandle = NULL;\r
92LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList);\r
93\r
94SEMIHOST_FCB *\r
95AllocateFCB (\r
96 VOID\r
97 )\r
98{\r
99 SEMIHOST_FCB *Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));\r
100\r
101 if (Fcb != NULL) {\r
102 CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));\r
103 Fcb->Signature = SEMIHOST_FCB_SIGNATURE;\r
104 }\r
105\r
106 return Fcb;\r
107}\r
108\r
109VOID\r
110FreeFCB (\r
111 IN SEMIHOST_FCB *Fcb\r
112 )\r
113{\r
114 // Remove Fcb from gFileList.\r
115 RemoveEntryList (&Fcb->Link);\r
116\r
117 // To help debugging...\r
118 Fcb->Signature = 0;\r
119\r
120 FreePool (Fcb);\r
121}\r
122\r
123\r
124\r
125EFI_STATUS\r
126VolumeOpen (\r
127 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
128 OUT EFI_FILE **Root\r
129 )\r
130{\r
131 SEMIHOST_FCB *RootFcb = NULL;\r
3402aac7 132\r
2ef2b01e
A
133 if (Root == NULL) {\r
134 return EFI_INVALID_PARAMETER;\r
135 }\r
136\r
137 RootFcb = AllocateFCB ();\r
138 if (RootFcb == NULL) {\r
139 return EFI_OUT_OF_RESOURCES;\r
140 }\r
3402aac7 141\r
2ef2b01e 142 RootFcb->IsRoot = TRUE;\r
09f2cf82 143 RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
2ef2b01e
A
144\r
145 InsertTailList (&gFileList, &RootFcb->Link);\r
146\r
147 *Root = &RootFcb->File;\r
148\r
149 return EFI_SUCCESS;\r
150}\r
151\r
fdd12bd5
RC
152/**\r
153 Open a file on the host system by means of the semihosting interface.\r
154\r
155 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
156 the file handle to source location.\r
157 @param[out] NewHandle A pointer to the location to return the opened\r
158 handle for the new file.\r
159 @param[in] FileName The Null-terminated string of the name of the file\r
160 to be opened.\r
161 @param[in] OpenMode The mode to open the file : Read or Read/Write or\r
162 Read/Write/Create\r
163 @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these\r
164 are the attribute bits for the newly created file. The\r
165 mnemonics of the attribute bits are : EFI_FILE_READ_ONLY,\r
166 EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED,\r
167 EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE.\r
168\r
169 @retval EFI_SUCCESS The file was open.\r
170 @retval EFI_NOT_FOUND The specified file could not be found.\r
171 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
172 @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible\r
173 with the semi-hosting interface.\r
174 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.\r
175 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.\r
176\r
177**/\r
2ef2b01e
A
178EFI_STATUS\r
179FileOpen (\r
fdd12bd5
RC
180 IN EFI_FILE *This,\r
181 OUT EFI_FILE **NewHandle,\r
182 IN CHAR16 *FileName,\r
183 IN UINT64 OpenMode,\r
184 IN UINT64 Attributes\r
2ef2b01e
A
185 )\r
186{\r
fdd12bd5
RC
187 SEMIHOST_FCB *FileFcb;\r
188 RETURN_STATUS Return;\r
189 EFI_STATUS Status;\r
190 UINTN SemihostHandle;\r
191 CHAR8 *AsciiFileName;\r
192 UINT32 SemihostMode;\r
193 UINTN Length;\r
2ef2b01e
A
194\r
195 if ((FileName == NULL) || (NewHandle == NULL)) {\r
196 return EFI_INVALID_PARAMETER;\r
197 }\r
198\r
fdd12bd5
RC
199 if ( (OpenMode != EFI_FILE_MODE_READ) &&\r
200 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&\r
201 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {\r
202 return EFI_INVALID_PARAMETER;\r
203 }\r
204\r
205 if ((OpenMode & EFI_FILE_MODE_CREATE) &&\r
206 (Attributes & EFI_FILE_DIRECTORY) ) {\r
207 return EFI_WRITE_PROTECTED;\r
09f2cf82 208 }\r
209\r
fdd12bd5 210 AsciiFileName = AllocatePool (StrLen (FileName) + 1);\r
2ef2b01e
A
211 if (AsciiFileName == NULL) {\r
212 return EFI_OUT_OF_RESOURCES;\r
213 }\r
ed2405a0 214 UnicodeStrToAsciiStr (FileName, AsciiFileName);\r
2ef2b01e 215\r
fdd12bd5 216 // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
1ea31716 217 if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||\r
218 (AsciiStrCmp (AsciiFileName, "/") == 0) ||\r
219 (AsciiStrCmp (AsciiFileName, "") == 0) ||\r
fdd12bd5 220 (AsciiStrCmp (AsciiFileName, ".") == 0) ) {\r
2ef2b01e 221 FreePool (AsciiFileName);\r
fdd12bd5
RC
222 return (VolumeOpen (&gSemihostFs, NewHandle));\r
223 }\r
224\r
225 //\r
226 // No control is done here concerning the file path. It is passed\r
227 // as it is to the host operating system through the semi-hosting\r
228 // interface. We first try to open the file in the read or update\r
229 // mode even if the file creation has been asked for. That way, if\r
230 // the file already exists, it is not truncated to zero length. In\r
231 // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already\r
232 // exists, it is reset to an empty file.\r
233 //\r
234 if (OpenMode == EFI_FILE_MODE_READ) {\r
235 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
2ef2b01e 236 } else {\r
fdd12bd5
RC
237 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE;\r
238 }\r
239 Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
2ef2b01e 240\r
fdd12bd5 241 if (RETURN_ERROR (Return)) {\r
2ef2b01e 242 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
fdd12bd5
RC
243 //\r
244 // In the create if does not exist case, if the opening in update\r
245 // mode failed, create it and open it in update mode. The update\r
246 // mode allows for both read and write from and to the file.\r
247 //\r
248 Return = SemihostFileOpen (\r
249 AsciiFileName,\r
250 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE,\r
251 &SemihostHandle\r
252 );\r
253 if (RETURN_ERROR (Return)) {\r
254 Status = EFI_DEVICE_ERROR;\r
255 goto Error;\r
256 }\r
257 } else {\r
258 Status = EFI_NOT_FOUND;\r
259 goto Error;\r
2ef2b01e 260 }\r
2ef2b01e
A
261 }\r
262\r
263 // Allocate a control block and fill it\r
264 FileFcb = AllocateFCB ();\r
265 if (FileFcb == NULL) {\r
fdd12bd5
RC
266 Status = EFI_OUT_OF_RESOURCES;\r
267 goto Error;\r
2ef2b01e
A
268 }\r
269\r
270 FileFcb->FileName = AsciiFileName;\r
271 FileFcb->SemihostHandle = SemihostHandle;\r
272 FileFcb->Position = 0;\r
fdd12bd5 273 FileFcb->IsRoot = 0;\r
09f2cf82 274 FileFcb->OpenMode = OpenMode;\r
275\r
fdd12bd5
RC
276 Return = SemihostFileLength (SemihostHandle, &Length);\r
277 if (RETURN_ERROR (Return)) {\r
278 Status = EFI_DEVICE_ERROR;\r
279 FreeFCB (FileFcb);\r
280 goto Error;\r
09f2cf82 281 }\r
2ef2b01e 282\r
fdd12bd5
RC
283 FileFcb->Info.FileSize = Length;\r
284 FileFcb->Info.PhysicalSize = Length;\r
285 FileFcb->Info.Attribute = (OpenMode & EFI_FILE_MODE_CREATE) ? Attributes : 0;\r
286\r
2ef2b01e
A
287 InsertTailList (&gFileList, &FileFcb->Link);\r
288\r
289 *NewHandle = &FileFcb->File;\r
290\r
fdd12bd5
RC
291 return EFI_SUCCESS;\r
292\r
293Error:\r
294\r
295 FreePool (AsciiFileName);\r
296\r
2ef2b01e
A
297 return Status;\r
298}\r
299\r
300\r
301EFI_STATUS\r
302FileClose (\r
303 IN EFI_FILE *File\r
304 )\r
305{\r
306 SEMIHOST_FCB *Fcb = NULL;\r
307 EFI_STATUS Status = EFI_SUCCESS;\r
308\r
309 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
310\r
311 if (Fcb->IsRoot == TRUE) {\r
312 FreeFCB (Fcb);\r
313 Status = EFI_SUCCESS;\r
314 } else {\r
315 Status = SemihostFileClose (Fcb->SemihostHandle);\r
316 if (!EFI_ERROR(Status)) {\r
317 FreePool (Fcb->FileName);\r
318 FreeFCB (Fcb);\r
319 }\r
320 }\r
3402aac7 321\r
2ef2b01e
A
322 return Status;\r
323}\r
324\r
325EFI_STATUS\r
326FileDelete (\r
327 IN EFI_FILE *File\r
328 )\r
329{\r
330 SEMIHOST_FCB *Fcb = NULL;\r
331 EFI_STATUS Status;\r
332 CHAR8 *FileName;\r
333 UINTN NameSize;\r
334\r
335 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
336\r
3bb46df2 337 if (!Fcb->IsRoot) {\r
338 // Get the filename from the Fcb\r
339 NameSize = AsciiStrLen (Fcb->FileName);\r
340 FileName = AllocatePool (NameSize + 1);\r
2ef2b01e 341\r
3bb46df2 342 AsciiStrCpy (FileName, Fcb->FileName);\r
2ef2b01e 343\r
3bb46df2 344 // Close the file if it's open. Disregard return status,\r
345 // since it might give an error if the file isn't open.\r
346 File->Close (File);\r
347\r
348 // Call the semihost interface to delete the file.\r
349 Status = SemihostFileRemove (FileName);\r
09f2cf82 350 if (EFI_ERROR(Status)) {\r
351 Status = EFI_WARN_DELETE_FAILURE;\r
352 }\r
3bb46df2 353 } else {\r
09f2cf82 354 Status = EFI_WARN_DELETE_FAILURE;\r
3bb46df2 355 }\r
2ef2b01e
A
356\r
357 return Status;\r
358}\r
359\r
360EFI_STATUS\r
361FileRead (\r
362 IN EFI_FILE *File,\r
363 IN OUT UINTN *BufferSize,\r
364 OUT VOID *Buffer\r
365 )\r
366{\r
367 SEMIHOST_FCB *Fcb = NULL;\r
368 EFI_STATUS Status;\r
369\r
370 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
371\r
372 if (Fcb->IsRoot == TRUE) {\r
b1cab81f 373 // By design, the Semihosting feature does not allow to list files on the host machine.\r
2ef2b01e
A
374 Status = EFI_UNSUPPORTED;\r
375 } else {\r
376 Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
377 if (!EFI_ERROR (Status)) {\r
378 Fcb->Position += *BufferSize;\r
379 }\r
380 }\r
381\r
382 return Status;\r
383}\r
384\r
385EFI_STATUS\r
386FileWrite (\r
387 IN EFI_FILE *File,\r
388 IN OUT UINTN *BufferSize,\r
389 IN VOID *Buffer\r
390 )\r
391{\r
392 SEMIHOST_FCB *Fcb = NULL;\r
393 EFI_STATUS Status;\r
394 UINTN WriteSize = *BufferSize;\r
395\r
396 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
397\r
09f2cf82 398 // We cannot write a read-only file\r
cc271ec3
OM
399 if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)\r
400 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {\r
09f2cf82 401 return EFI_ACCESS_DENIED;\r
402 }\r
403\r
2ef2b01e
A
404 Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
405\r
406 if (!EFI_ERROR(Status)) {\r
407 // Semihost write return the number of bytes *NOT* written.\r
408 *BufferSize -= WriteSize;\r
409 Fcb->Position += *BufferSize;\r
410 }\r
3402aac7 411\r
2ef2b01e
A
412 return Status;\r
413}\r
414\r
415EFI_STATUS\r
416FileGetPosition (\r
417 IN EFI_FILE *File,\r
418 OUT UINT64 *Position\r
419 )\r
420{\r
421 SEMIHOST_FCB *Fcb = NULL;\r
3402aac7 422\r
2ef2b01e
A
423 if (Position == NULL) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426\r
427 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
428\r
429 *Position = Fcb->Position;\r
430\r
431 return EFI_SUCCESS;\r
432}\r
433\r
434EFI_STATUS\r
435FileSetPosition (\r
436 IN EFI_FILE *File,\r
437 IN UINT64 Position\r
438 )\r
439{\r
440 SEMIHOST_FCB *Fcb = NULL;\r
c63626b7 441 UINTN Length;\r
2ef2b01e
A
442 EFI_STATUS Status;\r
443\r
444 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
445\r
3bb46df2 446 if (!Fcb->IsRoot) {\r
447 Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
448 if (!EFI_ERROR(Status) && (Length < Position)) {\r
449 Position = Length;\r
450 }\r
2ef2b01e 451\r
3bb46df2 452 Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);\r
453 if (!EFI_ERROR(Status)) {\r
454 Fcb->Position = Position;\r
455 }\r
456 } else {\r
2ef2b01e 457 Fcb->Position = Position;\r
3bb46df2 458 Status = EFI_SUCCESS;\r
2ef2b01e
A
459 }\r
460\r
461 return Status;\r
462}\r
463\r
464STATIC\r
465EFI_STATUS\r
466GetFileInfo (\r
467 IN SEMIHOST_FCB *Fcb,\r
468 IN OUT UINTN *BufferSize,\r
469 OUT VOID *Buffer\r
470 )\r
471{\r
472 EFI_FILE_INFO *Info = NULL;\r
473 UINTN NameSize = 0;\r
474 UINTN ResultSize;\r
475 UINTN Index;\r
2ef2b01e
A
476\r
477 if (Fcb->IsRoot == TRUE) {\r
478 ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
479 } else {\r
480 NameSize = AsciiStrLen (Fcb->FileName) + 1;\r
481 ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);\r
482 }\r
483\r
484 if (*BufferSize < ResultSize) {\r
485 *BufferSize = ResultSize;\r
486 return EFI_BUFFER_TOO_SMALL;\r
487 }\r
488\r
489 Info = Buffer;\r
490\r
09f2cf82 491 // Copy the current file info\r
492 CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);\r
2ef2b01e
A
493\r
494 // Fill in the structure\r
495 Info->Size = ResultSize;\r
496\r
497 if (Fcb->IsRoot == TRUE) {\r
2ef2b01e
A
498 Info->FileName[0] = L'\0';\r
499 } else {\r
2ef2b01e 500 for (Index = 0; Index < NameSize; Index++) {\r
3402aac7 501 Info->FileName[Index] = Fcb->FileName[Index];\r
2ef2b01e
A
502 }\r
503 }\r
504\r
3402aac7 505 *BufferSize = ResultSize;\r
2ef2b01e
A
506\r
507 return EFI_SUCCESS;\r
508}\r
509\r
510STATIC\r
511EFI_STATUS\r
512GetFilesystemInfo (\r
513 IN SEMIHOST_FCB *Fcb,\r
514 IN OUT UINTN *BufferSize,\r
515 OUT VOID *Buffer\r
516 )\r
517{\r
518 EFI_FILE_SYSTEM_INFO *Info = NULL;\r
519 EFI_STATUS Status;\r
09f2cf82 520 UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel);\r
3402aac7 521\r
09f2cf82 522 if (*BufferSize >= ResultSize) {\r
2ef2b01e
A
523 ZeroMem (Buffer, ResultSize);\r
524 Status = EFI_SUCCESS;\r
3402aac7 525\r
2ef2b01e
A
526 Info = Buffer;\r
527\r
528 Info->Size = ResultSize;\r
529 Info->ReadOnly = FALSE;\r
530 Info->VolumeSize = 0;\r
531 Info->FreeSpace = 0;\r
532 Info->BlockSize = 0;\r
533\r
09f2cf82 534 StrCpy (Info->VolumeLabel, mSemihostFsLabel);\r
2ef2b01e
A
535 } else {\r
536 Status = EFI_BUFFER_TOO_SMALL;\r
537 }\r
538\r
3402aac7 539 *BufferSize = ResultSize;\r
2ef2b01e
A
540 return Status;\r
541}\r
542\r
543EFI_STATUS\r
544FileGetInfo (\r
545 IN EFI_FILE *File,\r
546 IN EFI_GUID *InformationType,\r
547 IN OUT UINTN *BufferSize,\r
548 OUT VOID *Buffer\r
549 )\r
550{\r
09f2cf82 551 SEMIHOST_FCB *Fcb;\r
552 EFI_STATUS Status;\r
553 UINTN ResultSize;\r
3402aac7 554\r
2ef2b01e 555 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
3402aac7 556\r
09f2cf82 557 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
558 Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);\r
559 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
560 Status = GetFileInfo (Fcb, BufferSize, Buffer);\r
561 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
562 ResultSize = StrSize (mSemihostFsLabel);\r
563\r
564 if (*BufferSize >= ResultSize) {\r
565 StrCpy (Buffer, mSemihostFsLabel);\r
566 Status = EFI_SUCCESS;\r
567 } else {\r
568 Status = EFI_BUFFER_TOO_SMALL;\r
569 }\r
570\r
571 *BufferSize = ResultSize;\r
572 } else {\r
573 Status = EFI_UNSUPPORTED;\r
2ef2b01e 574 }\r
09f2cf82 575\r
2ef2b01e
A
576 return Status;\r
577}\r
578\r
579EFI_STATUS\r
580FileSetInfo (\r
581 IN EFI_FILE *File,\r
582 IN EFI_GUID *InformationType,\r
583 IN UINTN BufferSize,\r
584 IN VOID *Buffer\r
585 )\r
586{\r
09f2cf82 587 EFI_STATUS Status;\r
588\r
589 if (Buffer == NULL) {\r
590 return EFI_INVALID_PARAMETER;\r
591 }\r
592\r
593 Status = EFI_UNSUPPORTED;\r
594\r
595 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
596 //Status = SetFilesystemInfo (Fcb, BufferSize, Buffer);\r
597 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
d276ac10
HL
598 // Semihosting does not give us access to setting file info, but\r
599 // if we fail here we cannot create new files.\r
600 Status = EFI_SUCCESS;\r
09f2cf82 601 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
602 if (StrSize (Buffer) > 0) {\r
603 FreePool (mSemihostFsLabel);\r
604 mSemihostFsLabel = AllocateCopyPool (StrSize (Buffer), Buffer);\r
605 Status = EFI_SUCCESS;\r
606 }\r
607 }\r
608\r
609 return Status;\r
2ef2b01e
A
610}\r
611\r
612EFI_STATUS\r
613FileFlush (\r
614 IN EFI_FILE *File\r
615 )\r
616{\r
09f2cf82 617 SEMIHOST_FCB *Fcb;\r
618\r
619 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
620\r
621 if (Fcb->IsRoot) {\r
622 return EFI_SUCCESS;\r
623 } else {\r
cc271ec3
OM
624 if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)\r
625 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {\r
09f2cf82 626 return EFI_ACCESS_DENIED;\r
627 } else {\r
628 return EFI_SUCCESS;\r
629 }\r
630 }\r
2ef2b01e
A
631}\r
632\r
633EFI_STATUS\r
634SemihostFsEntryPoint (\r
635 IN EFI_HANDLE ImageHandle,\r
636 IN EFI_SYSTEM_TABLE *SystemTable\r
637 )\r
638{\r
09f2cf82 639 EFI_STATUS Status;\r
640\r
641 Status = EFI_NOT_FOUND;\r
2ef2b01e
A
642\r
643 if (SemihostConnectionSupported ()) {\r
09f2cf82 644 mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);\r
645 if (mSemihostFsLabel == NULL) {\r
646 return EFI_OUT_OF_RESOURCES;\r
647 }\r
648\r
2ef2b01e 649 Status = gBS->InstallMultipleProtocolInterfaces (\r
3402aac7
RC
650 &gInstallHandle,\r
651 &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,\r
2ef2b01e
A
652 &gEfiDevicePathProtocolGuid, &gDevicePath,\r
653 NULL\r
654 );\r
09f2cf82 655\r
656 if (EFI_ERROR(Status)) {\r
657 FreePool (mSemihostFsLabel);\r
658 }\r
2ef2b01e 659 }\r
3402aac7 660\r
2ef2b01e
A
661 return Status;\r
662}\r