]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
ArmPkg: Fix Ecc error 5007 in SemihostFs
[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
f66c2b32 5 Portions copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>\r
c63626b7 6\r
4059386c 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
2ef2b01e
A
8\r
9**/\r
10\r
11#include <Uefi.h>\r
12\r
13#include <Guid/FileInfo.h>\r
14#include <Guid/FileSystemInfo.h>\r
09f2cf82 15#include <Guid/FileSystemVolumeLabelInfo.h>\r
2ef2b01e
A
16\r
17#include <Library/BaseLib.h>\r
3402aac7 18#include <Library/BaseMemoryLib.h>\r
2ef2b01e
A
19#include <Library/DebugLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/SemihostLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/UefiLib.h>\r
24\r
25#include <Protocol/DevicePath.h>\r
26#include <Protocol/SimpleFileSystem.h>\r
27\r
28#include "SemihostFs.h"\r
29\r
09f2cf82 30#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs"\r
31\r
32STATIC CHAR16 *mSemihostFsLabel;\r
2ef2b01e
A
33\r
34EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {\r
35 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
36 VolumeOpen\r
37};\r
38\r
39EFI_FILE gSemihostFsFile = {\r
40 EFI_FILE_PROTOCOL_REVISION,\r
41 FileOpen,\r
42 FileClose,\r
43 FileDelete,\r
44 FileRead,\r
45 FileWrite,\r
46 FileGetPosition,\r
47 FileSetPosition,\r
48 FileGetInfo,\r
49 FileSetInfo,\r
50 FileFlush\r
51};\r
52\r
53//\r
fdd12bd5 54// Device path for semi-hosting. It contains our autogened Caller ID GUID.\r
2ef2b01e
A
55//\r
56typedef struct {\r
57 VENDOR_DEVICE_PATH Guid;\r
58 EFI_DEVICE_PATH_PROTOCOL End;\r
59} SEMIHOST_DEVICE_PATH;\r
60\r
61SEMIHOST_DEVICE_PATH gDevicePath = {\r
62 {\r
b0fdce95 63 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } },\r
2ef2b01e
A
64 EFI_CALLER_ID_GUID\r
65 },\r
b0fdce95 66 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }\r
2ef2b01e
A
67};\r
68\r
69typedef struct {\r
09f2cf82 70 LIST_ENTRY Link;\r
71 UINT64 Signature;\r
72 EFI_FILE File;\r
73 CHAR8 *FileName;\r
74 UINT64 OpenMode;\r
75 UINT32 Position;\r
76 UINTN SemihostHandle;\r
77 BOOLEAN IsRoot;\r
78 EFI_FILE_INFO Info;\r
2ef2b01e
A
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
88a7d4aa 93 SEMIHOST_FCB *Fcb;\r
2ef2b01e 94\r
88a7d4aa 95 Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));\r
2ef2b01e
A
96 if (Fcb != NULL) {\r
97 CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));\r
98 Fcb->Signature = SEMIHOST_FCB_SIGNATURE;\r
99 }\r
100\r
101 return Fcb;\r
102}\r
103\r
104VOID\r
105FreeFCB (\r
106 IN SEMIHOST_FCB *Fcb\r
107 )\r
108{\r
109 // Remove Fcb from gFileList.\r
110 RemoveEntryList (&Fcb->Link);\r
111\r
112 // To help debugging...\r
113 Fcb->Signature = 0;\r
114\r
115 FreePool (Fcb);\r
116}\r
117\r
118\r
119\r
120EFI_STATUS\r
121VolumeOpen (\r
122 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
123 OUT EFI_FILE **Root\r
124 )\r
125{\r
88a7d4aa 126 SEMIHOST_FCB *RootFcb;\r
3402aac7 127\r
2ef2b01e
A
128 if (Root == NULL) {\r
129 return EFI_INVALID_PARAMETER;\r
130 }\r
131\r
132 RootFcb = AllocateFCB ();\r
133 if (RootFcb == NULL) {\r
134 return EFI_OUT_OF_RESOURCES;\r
135 }\r
3402aac7 136\r
2ef2b01e 137 RootFcb->IsRoot = TRUE;\r
09f2cf82 138 RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
2ef2b01e
A
139\r
140 InsertTailList (&gFileList, &RootFcb->Link);\r
141\r
142 *Root = &RootFcb->File;\r
143\r
144 return EFI_SUCCESS;\r
145}\r
146\r
fdd12bd5
RC
147/**\r
148 Open a file on the host system by means of the semihosting interface.\r
149\r
150 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
151 the file handle to source location.\r
152 @param[out] NewHandle A pointer to the location to return the opened\r
153 handle for the new file.\r
154 @param[in] FileName The Null-terminated string of the name of the file\r
155 to be opened.\r
156 @param[in] OpenMode The mode to open the file : Read or Read/Write or\r
157 Read/Write/Create\r
158 @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these\r
159 are the attribute bits for the newly created file. The\r
160 mnemonics of the attribute bits are : EFI_FILE_READ_ONLY,\r
161 EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED,\r
162 EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE.\r
163\r
164 @retval EFI_SUCCESS The file was open.\r
165 @retval EFI_NOT_FOUND The specified file could not be found.\r
166 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
167 @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible\r
168 with the semi-hosting interface.\r
169 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.\r
170 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.\r
171\r
172**/\r
2ef2b01e
A
173EFI_STATUS\r
174FileOpen (\r
fdd12bd5
RC
175 IN EFI_FILE *This,\r
176 OUT EFI_FILE **NewHandle,\r
177 IN CHAR16 *FileName,\r
178 IN UINT64 OpenMode,\r
179 IN UINT64 Attributes\r
2ef2b01e
A
180 )\r
181{\r
fdd12bd5
RC
182 SEMIHOST_FCB *FileFcb;\r
183 RETURN_STATUS Return;\r
184 EFI_STATUS Status;\r
185 UINTN SemihostHandle;\r
186 CHAR8 *AsciiFileName;\r
187 UINT32 SemihostMode;\r
188 UINTN Length;\r
2ef2b01e
A
189\r
190 if ((FileName == NULL) || (NewHandle == NULL)) {\r
191 return EFI_INVALID_PARAMETER;\r
192 }\r
193\r
fdd12bd5
RC
194 if ( (OpenMode != EFI_FILE_MODE_READ) &&\r
195 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&\r
196 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {\r
197 return EFI_INVALID_PARAMETER;\r
198 }\r
199\r
f66c2b32
PG
200 if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) &&\r
201 ((Attributes & EFI_FILE_DIRECTORY) != 0)) {\r
fdd12bd5 202 return EFI_WRITE_PROTECTED;\r
09f2cf82 203 }\r
204\r
f6c4d99a
AB
205 Length = StrLen (FileName) + 1;\r
206 AsciiFileName = AllocatePool (Length);\r
2ef2b01e
A
207 if (AsciiFileName == NULL) {\r
208 return EFI_OUT_OF_RESOURCES;\r
209 }\r
f6c4d99a 210 UnicodeStrToAsciiStrS (FileName, AsciiFileName, Length);\r
2ef2b01e 211\r
fdd12bd5 212 // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
1ea31716 213 if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||\r
214 (AsciiStrCmp (AsciiFileName, "/") == 0) ||\r
215 (AsciiStrCmp (AsciiFileName, "") == 0) ||\r
fdd12bd5 216 (AsciiStrCmp (AsciiFileName, ".") == 0) ) {\r
2ef2b01e 217 FreePool (AsciiFileName);\r
fdd12bd5
RC
218 return (VolumeOpen (&gSemihostFs, NewHandle));\r
219 }\r
220\r
221 //\r
222 // No control is done here concerning the file path. It is passed\r
223 // as it is to the host operating system through the semi-hosting\r
224 // interface. We first try to open the file in the read or update\r
225 // mode even if the file creation has been asked for. That way, if\r
226 // the file already exists, it is not truncated to zero length. In\r
227 // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already\r
228 // exists, it is reset to an empty file.\r
229 //\r
230 if (OpenMode == EFI_FILE_MODE_READ) {\r
231 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
2ef2b01e 232 } else {\r
fdd12bd5
RC
233 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE;\r
234 }\r
235 Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
2ef2b01e 236\r
fdd12bd5 237 if (RETURN_ERROR (Return)) {\r
f66c2b32 238 if ((OpenMode & EFI_FILE_MODE_CREATE) != 0) {\r
fdd12bd5
RC
239 //\r
240 // In the create if does not exist case, if the opening in update\r
241 // mode failed, create it and open it in update mode. The update\r
242 // mode allows for both read and write from and to the file.\r
243 //\r
244 Return = SemihostFileOpen (\r
245 AsciiFileName,\r
246 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE,\r
247 &SemihostHandle\r
248 );\r
249 if (RETURN_ERROR (Return)) {\r
250 Status = EFI_DEVICE_ERROR;\r
251 goto Error;\r
252 }\r
253 } else {\r
254 Status = EFI_NOT_FOUND;\r
255 goto Error;\r
2ef2b01e 256 }\r
2ef2b01e
A
257 }\r
258\r
259 // Allocate a control block and fill it\r
260 FileFcb = AllocateFCB ();\r
261 if (FileFcb == NULL) {\r
fdd12bd5
RC
262 Status = EFI_OUT_OF_RESOURCES;\r
263 goto Error;\r
2ef2b01e
A
264 }\r
265\r
266 FileFcb->FileName = AsciiFileName;\r
267 FileFcb->SemihostHandle = SemihostHandle;\r
268 FileFcb->Position = 0;\r
fdd12bd5 269 FileFcb->IsRoot = 0;\r
09f2cf82 270 FileFcb->OpenMode = OpenMode;\r
271\r
fdd12bd5
RC
272 Return = SemihostFileLength (SemihostHandle, &Length);\r
273 if (RETURN_ERROR (Return)) {\r
274 Status = EFI_DEVICE_ERROR;\r
275 FreeFCB (FileFcb);\r
276 goto Error;\r
09f2cf82 277 }\r
2ef2b01e 278\r
fdd12bd5
RC
279 FileFcb->Info.FileSize = Length;\r
280 FileFcb->Info.PhysicalSize = Length;\r
f66c2b32
PG
281 FileFcb->Info.Attribute = ((OpenMode & EFI_FILE_MODE_CREATE) != 0) ?\r
282 Attributes : 0;\r
fdd12bd5 283\r
2ef2b01e
A
284 InsertTailList (&gFileList, &FileFcb->Link);\r
285\r
286 *NewHandle = &FileFcb->File;\r
287\r
fdd12bd5
RC
288 return EFI_SUCCESS;\r
289\r
290Error:\r
291\r
292 FreePool (AsciiFileName);\r
293\r
2ef2b01e
A
294 return Status;\r
295}\r
296\r
daefd574
RC
297/**\r
298 Worker function that truncate a file specified by its name to a given size.\r
299\r
300 @param[in] FileName The Null-terminated string of the name of the file to be opened.\r
301 @param[in] Size The target size for the file.\r
302\r
303 @retval EFI_SUCCESS The file was truncated.\r
304 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
305\r
306**/\r
307STATIC\r
308EFI_STATUS\r
309TruncateFile (\r
310 IN CHAR8 *FileName,\r
311 IN UINTN Size\r
312 )\r
313{\r
314 EFI_STATUS Status;\r
315 RETURN_STATUS Return;\r
316 UINTN FileHandle;\r
317 UINT8 *Buffer;\r
318 UINTN Remaining;\r
319 UINTN Read;\r
320 UINTN ToRead;\r
321\r
322 Status = EFI_DEVICE_ERROR;\r
323 FileHandle = 0;\r
324 Buffer = NULL;\r
325\r
326 Return = SemihostFileOpen (\r
327 FileName,\r
328 SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,\r
329 &FileHandle\r
330 );\r
331 if (RETURN_ERROR (Return)) {\r
332 goto Error;\r
333 }\r
334\r
335 Buffer = AllocatePool (Size);\r
336 if (Buffer == NULL) {\r
337 Status = EFI_OUT_OF_RESOURCES;\r
338 goto Error;\r
339 }\r
340\r
341 Read = 0;\r
342 Remaining = Size;\r
343 while (Remaining > 0) {\r
344 ToRead = Remaining;\r
345 Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read);\r
346 if (RETURN_ERROR (Return)) {\r
347 goto Error;\r
348 }\r
349 Remaining -= ToRead;\r
350 Read += ToRead;\r
351 }\r
352\r
353 Return = SemihostFileClose (FileHandle);\r
354 FileHandle = 0;\r
355 if (RETURN_ERROR (Return)) {\r
356 goto Error;\r
357 }\r
358\r
359 Return = SemihostFileOpen (\r
360 FileName,\r
361 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY,\r
362 &FileHandle\r
363 );\r
364 if (RETURN_ERROR (Return)) {\r
365 goto Error;\r
366 }\r
367\r
368 if (Size > 0) {\r
369 Return = SemihostFileWrite (FileHandle, &Size, Buffer);\r
370 if (RETURN_ERROR (Return)) {\r
371 goto Error;\r
372 }\r
373 }\r
374\r
375 Status = EFI_SUCCESS;\r
2ef2b01e 376\r
daefd574
RC
377Error:\r
378\r
379 if (FileHandle != 0) {\r
380 SemihostFileClose (FileHandle);\r
381 }\r
382 if (Buffer != NULL) {\r
383 FreePool (Buffer);\r
384 }\r
385\r
386 return (Status);\r
387\r
388}\r
389\r
390/**\r
391 Close a specified file handle.\r
392\r
393 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
394 handle to close.\r
395\r
396 @retval EFI_SUCCESS The file was closed.\r
397 @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
398\r
399**/\r
2ef2b01e
A
400EFI_STATUS\r
401FileClose (\r
daefd574 402 IN EFI_FILE *This\r
2ef2b01e
A
403 )\r
404{\r
daefd574 405 SEMIHOST_FCB *Fcb;\r
2ef2b01e 406\r
daefd574
RC
407 if (This == NULL) {\r
408 return EFI_INVALID_PARAMETER;\r
409 }\r
2ef2b01e 410\r
daefd574
RC
411 Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
412\r
413 if (!Fcb->IsRoot) {\r
414 SemihostFileClose (Fcb->SemihostHandle);\r
415 //\r
416 // The file size might have been reduced from its actual\r
417 // size on the host file system with FileSetInfo(). In\r
418 // that case, the file has to be truncated.\r
419 //\r
420 if (Fcb->Info.FileSize < Fcb->Info.PhysicalSize) {\r
421 TruncateFile (Fcb->FileName, Fcb->Info.FileSize);\r
2ef2b01e 422 }\r
daefd574 423 FreePool (Fcb->FileName);\r
2ef2b01e 424 }\r
3402aac7 425\r
daefd574
RC
426 FreeFCB (Fcb);\r
427\r
428 return EFI_SUCCESS;\r
2ef2b01e
A
429}\r
430\r
daefd574
RC
431/**\r
432 Close and delete a file.\r
433\r
434 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
435 handle to delete.\r
436\r
437 @retval EFI_SUCCESS The file was closed and deleted.\r
438 @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.\r
439 @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
440\r
441**/\r
2ef2b01e
A
442EFI_STATUS\r
443FileDelete (\r
daefd574 444 IN EFI_FILE *This\r
2ef2b01e
A
445 )\r
446{\r
daefd574
RC
447 SEMIHOST_FCB *Fcb;\r
448 RETURN_STATUS Return;\r
449 CHAR8 *FileName;\r
450 UINTN NameSize;\r
2ef2b01e 451\r
daefd574
RC
452 if (This == NULL) {\r
453 return EFI_INVALID_PARAMETER;\r
454 }\r
455\r
456 Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
2ef2b01e 457\r
3bb46df2 458 if (!Fcb->IsRoot) {\r
459 // Get the filename from the Fcb\r
460 NameSize = AsciiStrLen (Fcb->FileName);\r
461 FileName = AllocatePool (NameSize + 1);\r
2ef2b01e 462\r
f6c4d99a 463 AsciiStrCpyS (FileName, NameSize + 1, Fcb->FileName);\r
2ef2b01e 464\r
3bb46df2 465 // Close the file if it's open. Disregard return status,\r
466 // since it might give an error if the file isn't open.\r
daefd574 467 This->Close (This);\r
3bb46df2 468\r
469 // Call the semihost interface to delete the file.\r
daefd574
RC
470 Return = SemihostFileRemove (FileName);\r
471 if (RETURN_ERROR (Return)) {\r
472 return EFI_WARN_DELETE_FAILURE;\r
09f2cf82 473 }\r
daefd574 474 return EFI_SUCCESS;\r
3bb46df2 475 } else {\r
daefd574 476 return EFI_WARN_DELETE_FAILURE;\r
3bb46df2 477 }\r
2ef2b01e
A
478}\r
479\r
daefd574
RC
480/**\r
481 Read data from an open file.\r
482\r
483 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
484 is the file handle to read data from.\r
485 @param[in out] BufferSize On input, the size of the Buffer. On output, the\r
486 amount of data returned in Buffer. In both cases,\r
487 the size is measured in bytes.\r
488 @param[out] Buffer The buffer into which the data is read.\r
489\r
490 @retval EFI_SUCCESS The data was read.\r
491 @retval EFI_DEVICE_ERROR On entry, the current file position is\r
492 beyond the end of the file, or the semi-hosting\r
493 interface reported an error while performing the\r
494 read operation.\r
495 @retval EFI_INVALID_PARAMETER At least one of the three input pointers is NULL.\r
496\r
497**/\r
2ef2b01e
A
498EFI_STATUS\r
499FileRead (\r
daefd574
RC
500 IN EFI_FILE *This,\r
501 IN OUT UINTN *BufferSize,\r
502 OUT VOID *Buffer\r
2ef2b01e
A
503 )\r
504{\r
daefd574
RC
505 SEMIHOST_FCB *Fcb;\r
506 EFI_STATUS Status;\r
507 RETURN_STATUS Return;\r
2ef2b01e 508\r
daefd574
RC
509 if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {\r
510 return EFI_INVALID_PARAMETER;\r
511 }\r
2ef2b01e 512\r
daefd574
RC
513 Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
514\r
515 if (Fcb->IsRoot) {\r
516 // The semi-hosting interface does not allow to list files on the host machine.\r
2ef2b01e
A
517 Status = EFI_UNSUPPORTED;\r
518 } else {\r
daefd574
RC
519 Status = EFI_SUCCESS;\r
520 if (Fcb->Position >= Fcb->Info.FileSize) {\r
521 *BufferSize = 0;\r
522 if (Fcb->Position > Fcb->Info.FileSize) {\r
523 Status = EFI_DEVICE_ERROR;\r
524 }\r
525 } else {\r
526 Return = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
527 if (RETURN_ERROR (Return)) {\r
528 Status = EFI_DEVICE_ERROR;\r
529 } else {\r
530 Fcb->Position += *BufferSize;\r
531 }\r
2ef2b01e
A
532 }\r
533 }\r
534\r
535 return Status;\r
536}\r
537\r
daefd574
RC
538/**\r
539 Worker function that extends the size of an open file.\r
540\r
541 The extension is filled with zeros.\r
542\r
543 @param[in] Fcb Internal description of the opened file\r
544 @param[in] Size The number of bytes, the file has to be extended.\r
545\r
546 @retval EFI_SUCCESS The file was extended.\r
547 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
548\r
549**/\r
550STATIC\r
551EFI_STATUS\r
552ExtendFile (\r
553 IN SEMIHOST_FCB *Fcb,\r
554 IN UINTN Size\r
555 )\r
556{\r
557 RETURN_STATUS Return;\r
558 UINTN Remaining;\r
559 CHAR8 WriteBuffer[128];\r
560 UINTN WriteNb;\r
561 UINTN WriteSize;\r
562\r
563 Return = SemihostFileSeek (Fcb->SemihostHandle, Fcb->Info.FileSize);\r
564 if (RETURN_ERROR (Return)) {\r
565 return EFI_DEVICE_ERROR;\r
566 }\r
567\r
568 Remaining = Size;\r
569 SetMem (WriteBuffer, 0, sizeof(WriteBuffer));\r
570 while (Remaining > 0) {\r
571 WriteNb = MIN (Remaining, sizeof(WriteBuffer));\r
572 WriteSize = WriteNb;\r
573 Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, WriteBuffer);\r
574 if (RETURN_ERROR (Return)) {\r
575 return EFI_DEVICE_ERROR;\r
576 }\r
577 Remaining -= WriteNb;\r
578 }\r
579\r
580 return EFI_SUCCESS;\r
581}\r
582\r
583/**\r
584 Write data to an open file.\r
585\r
586 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
587 is the file handle to write data to.\r
588 @param[in out] BufferSize On input, the size of the Buffer. On output, the\r
589 size of the data actually written. In both cases,\r
590 the size is measured in bytes.\r
591 @param[in] Buffer The buffer of data to write.\r
592\r
593 @retval EFI_SUCCESS The data was written.\r
594 @retval EFI_ACCESS_DENIED Attempt to write into a read only file or\r
595 in a file opened in read only mode.\r
596 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
597 @retval EFI_INVALID_PARAMETER At least one of the three input pointers is NULL.\r
598\r
599**/\r
2ef2b01e
A
600EFI_STATUS\r
601FileWrite (\r
daefd574 602 IN EFI_FILE *This,\r
2ef2b01e
A
603 IN OUT UINTN *BufferSize,\r
604 IN VOID *Buffer\r
605 )\r
606{\r
daefd574
RC
607 SEMIHOST_FCB *Fcb;\r
608 EFI_STATUS Status;\r
609 UINTN WriteSize;\r
610 RETURN_STATUS Return;\r
611 UINTN Length;\r
2ef2b01e 612\r
daefd574
RC
613 if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {\r
614 return EFI_INVALID_PARAMETER;\r
615 }\r
616\r
617 Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
2ef2b01e 618\r
09f2cf82 619 // We cannot write a read-only file\r
cc271ec3
OM
620 if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)\r
621 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {\r
09f2cf82 622 return EFI_ACCESS_DENIED;\r
623 }\r
624\r
daefd574
RC
625 //\r
626 // If the position has been set past the end of the file, first grow the\r
627 // file from its current size "Fcb->Info.FileSize" to "Fcb->Position"\r
628 // size, filling the gap with zeros.\r
629 //\r
630 if (Fcb->Position > Fcb->Info.FileSize) {\r
631 Status = ExtendFile (Fcb, Fcb->Position - Fcb->Info.FileSize);\r
632 if (EFI_ERROR (Status)) {\r
633 return Status;\r
634 }\r
635 Fcb->Info.FileSize = Fcb->Position;\r
636 }\r
2ef2b01e 637\r
daefd574
RC
638 WriteSize = *BufferSize;\r
639 Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
640 if (RETURN_ERROR (Return)) {\r
641 return EFI_DEVICE_ERROR;\r
2ef2b01e 642 }\r
3402aac7 643\r
daefd574
RC
644 Fcb->Position += *BufferSize;\r
645 if (Fcb->Position > Fcb->Info.FileSize) {\r
646 Fcb->Info.FileSize = Fcb->Position;\r
647 }\r
648\r
649 Return = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
650 if (RETURN_ERROR (Return)) {\r
651 return EFI_DEVICE_ERROR;\r
652 }\r
653 Fcb->Info.PhysicalSize = Length;\r
654\r
655 return EFI_SUCCESS;\r
2ef2b01e
A
656}\r
657\r
daefd574
RC
658/**\r
659 Return a file's current position.\r
660\r
661 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
662 the file handle to get the current position on.\r
663 @param[out] Position The address to return the file's current position value.\r
664\r
665 @retval EFI_SUCCESS The position was returned.\r
666 @retval EFI_INVALID_PARAMETER The parameter "This" or "Position" is NULL.\r
667\r
668**/\r
2ef2b01e
A
669EFI_STATUS\r
670FileGetPosition (\r
daefd574 671 IN EFI_FILE *This,\r
2ef2b01e
A
672 OUT UINT64 *Position\r
673 )\r
674{\r
daefd574 675 SEMIHOST_FCB *Fcb;\r
3402aac7 676\r
daefd574 677 if ((This == NULL) || (Position == NULL)) {\r
2ef2b01e
A
678 return EFI_INVALID_PARAMETER;\r
679 }\r
680\r
daefd574 681 Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
2ef2b01e
A
682\r
683 *Position = Fcb->Position;\r
684\r
685 return EFI_SUCCESS;\r
686}\r
687\r
daefd574
RC
688/**\r
689 Set a file's current position.\r
690\r
691 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
692 the file handle to set the requested position on.\r
693 @param[in] Position The byte position from the start of the file to set.\r
694\r
695 @retval EFI_SUCCESS The position was set.\r
ff5fef14 696 @retval EFI_DEVICE_ERROR The semi-hosting positioning operation failed.\r
daefd574
RC
697 @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open\r
698 directories.\r
699 @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
700\r
701**/\r
2ef2b01e
A
702EFI_STATUS\r
703FileSetPosition (\r
daefd574 704 IN EFI_FILE *This,\r
2ef2b01e
A
705 IN UINT64 Position\r
706 )\r
707{\r
daefd574
RC
708 SEMIHOST_FCB *Fcb;\r
709 RETURN_STATUS Return;\r
2ef2b01e 710\r
daefd574
RC
711 if (This == NULL) {\r
712 return EFI_INVALID_PARAMETER;\r
713 }\r
2ef2b01e 714\r
daefd574 715 Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
2ef2b01e 716\r
daefd574
RC
717 if (Fcb->IsRoot) {\r
718 if (Position != 0) {\r
719 return EFI_UNSUPPORTED;\r
720 }\r
721 }\r
722 else {\r
723 //\r
724 // UEFI Spec section 12.5:\r
725 // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to\r
726 // be set to the end of the file."\r
727 //\r
728 if (Position == 0xFFFFFFFFFFFFFFFF) {\r
729 Position = Fcb->Info.FileSize;\r
730 }\r
731 Return = SemihostFileSeek (Fcb->SemihostHandle, MIN (Position, Fcb->Info.FileSize));\r
732 if (RETURN_ERROR (Return)) {\r
733 return EFI_DEVICE_ERROR;\r
3bb46df2 734 }\r
2ef2b01e
A
735 }\r
736\r
daefd574
RC
737 Fcb->Position = Position;\r
738\r
739 return EFI_SUCCESS;\r
2ef2b01e
A
740}\r
741\r
daefd574
RC
742/**\r
743 Return information about a file.\r
744\r
745 @param[in] Fcb A pointer to the description of an open file.\r
746 @param[in out] BufferSize The size, in bytes, of Buffer.\r
747 @param[out] Buffer A pointer to the data buffer to return. Not NULL if\r
748 "*BufferSize" is greater than 0.\r
749\r
750 @retval EFI_SUCCESS The information was returned.\r
751 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
752 BufferSize has been updated with the size needed to\r
753 complete the request.\r
754**/\r
2ef2b01e
A
755STATIC\r
756EFI_STATUS\r
757GetFileInfo (\r
758 IN SEMIHOST_FCB *Fcb,\r
daefd574
RC
759 IN OUT UINTN *BufferSize,\r
760 OUT VOID *Buffer\r
2ef2b01e
A
761 )\r
762{\r
88a7d4aa
PG
763 EFI_FILE_INFO *Info;\r
764 UINTN NameSize;\r
2ef2b01e
A
765 UINTN ResultSize;\r
766 UINTN Index;\r
2ef2b01e 767\r
17ad8ce7 768 if (Fcb->IsRoot) {\r
88a7d4aa 769 NameSize = 0;\r
2ef2b01e
A
770 ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
771 } else {\r
772 NameSize = AsciiStrLen (Fcb->FileName) + 1;\r
773 ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);\r
774 }\r
775\r
776 if (*BufferSize < ResultSize) {\r
777 *BufferSize = ResultSize;\r
778 return EFI_BUFFER_TOO_SMALL;\r
779 }\r
780\r
781 Info = Buffer;\r
782\r
09f2cf82 783 // Copy the current file info\r
784 CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);\r
2ef2b01e
A
785\r
786 // Fill in the structure\r
787 Info->Size = ResultSize;\r
788\r
17ad8ce7 789 if (Fcb->IsRoot) {\r
2ef2b01e
A
790 Info->FileName[0] = L'\0';\r
791 } else {\r
2ef2b01e 792 for (Index = 0; Index < NameSize; Index++) {\r
3402aac7 793 Info->FileName[Index] = Fcb->FileName[Index];\r
2ef2b01e
A
794 }\r
795 }\r
796\r
3402aac7 797 *BufferSize = ResultSize;\r
2ef2b01e
A
798\r
799 return EFI_SUCCESS;\r
800}\r
801\r
daefd574
RC
802/**\r
803 Return information about a file system.\r
804\r
805 @param[in] Fcb A pointer to the description of an open file\r
806 which belongs to the file system, the information\r
807 is requested for.\r
808 @param[in out] BufferSize The size, in bytes, of Buffer.\r
809 @param[out] Buffer A pointer to the data buffer to return. Not NULL if\r
810 "*BufferSize" is greater than 0.\r
811\r
812 @retval EFI_SUCCESS The information was returned.\r
813 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
814 BufferSize has been updated with the size needed to\r
815 complete the request.\r
816\r
817**/\r
2ef2b01e
A
818STATIC\r
819EFI_STATUS\r
820GetFilesystemInfo (\r
821 IN SEMIHOST_FCB *Fcb,\r
822 IN OUT UINTN *BufferSize,\r
823 OUT VOID *Buffer\r
824 )\r
825{\r
daefd574
RC
826 EFI_FILE_SYSTEM_INFO *Info;\r
827 EFI_STATUS Status;\r
828 UINTN ResultSize;\r
f6c4d99a 829 UINTN StringSize;\r
daefd574 830\r
f6c4d99a
AB
831 StringSize = StrSize (mSemihostFsLabel);\r
832 ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StringSize;\r
3402aac7 833\r
09f2cf82 834 if (*BufferSize >= ResultSize) {\r
2ef2b01e
A
835 ZeroMem (Buffer, ResultSize);\r
836 Status = EFI_SUCCESS;\r
3402aac7 837\r
2ef2b01e
A
838 Info = Buffer;\r
839\r
840 Info->Size = ResultSize;\r
841 Info->ReadOnly = FALSE;\r
842 Info->VolumeSize = 0;\r
843 Info->FreeSpace = 0;\r
844 Info->BlockSize = 0;\r
845\r
f6c4d99a 846 CopyMem (Info->VolumeLabel, mSemihostFsLabel, StringSize);\r
2ef2b01e
A
847 } else {\r
848 Status = EFI_BUFFER_TOO_SMALL;\r
849 }\r
850\r
3402aac7 851 *BufferSize = ResultSize;\r
2ef2b01e
A
852 return Status;\r
853}\r
854\r
daefd574
RC
855/**\r
856 Return information about a file or a file system.\r
857\r
858 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
859 is the file handle the requested information is for.\r
860 @param[in] InformationType The type identifier for the information being requested :\r
861 EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or\r
862 EFI_FILE_SYSTEM_VOLUME_LABEL_ID\r
863 @param[in out] BufferSize The size, in bytes, of Buffer.\r
864 @param[out] Buffer A pointer to the data buffer to return. The type of the\r
865 data inside the buffer is indicated by InformationType.\r
866\r
867 @retval EFI_SUCCESS The information was returned.\r
868 @retval EFI_UNSUPPORTED The InformationType is not known.\r
869 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
870 BufferSize has been updated with the size needed to\r
871 complete the request.\r
872 @retval EFI_INVALID_PARAMETER The parameter "This" or "InformationType" or "BufferSize"\r
873 is NULL or "Buffer" is NULL and "*Buffersize" is greater\r
874 than 0.\r
875\r
876**/\r
2ef2b01e
A
877EFI_STATUS\r
878FileGetInfo (\r
daefd574
RC
879 IN EFI_FILE *This,\r
880 IN EFI_GUID *InformationType,\r
881 IN OUT UINTN *BufferSize,\r
882 OUT VOID *Buffer\r
2ef2b01e
A
883 )\r
884{\r
09f2cf82 885 SEMIHOST_FCB *Fcb;\r
886 EFI_STATUS Status;\r
887 UINTN ResultSize;\r
3402aac7 888\r
daefd574
RC
889 if ((This == NULL) ||\r
890 (InformationType == NULL) ||\r
891 (BufferSize == NULL) ||\r
892 ((Buffer == NULL) && (*BufferSize > 0)) ) {\r
893 return EFI_INVALID_PARAMETER;\r
894 }\r
895\r
896 Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
3402aac7 897\r
daefd574 898 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
09f2cf82 899 Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);\r
daefd574 900 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
09f2cf82 901 Status = GetFileInfo (Fcb, BufferSize, Buffer);\r
daefd574 902 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
09f2cf82 903 ResultSize = StrSize (mSemihostFsLabel);\r
904\r
905 if (*BufferSize >= ResultSize) {\r
f6c4d99a 906 CopyMem (Buffer, mSemihostFsLabel, ResultSize);\r
09f2cf82 907 Status = EFI_SUCCESS;\r
908 } else {\r
909 Status = EFI_BUFFER_TOO_SMALL;\r
910 }\r
911\r
912 *BufferSize = ResultSize;\r
913 } else {\r
914 Status = EFI_UNSUPPORTED;\r
2ef2b01e 915 }\r
09f2cf82 916\r
2ef2b01e
A
917 return Status;\r
918}\r
919\r
daefd574
RC
920/**\r
921 Set information about a file.\r
922\r
923 @param[in] Fcb A pointer to the description of the open file.\r
924 @param[in] Info A pointer to the file information to write.\r
925\r
926 @retval EFI_SUCCESS The information was set.\r
927 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
928 to a file that is already present.\r
929 @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
930 EFI_FILE_DIRECTORY Attribute.\r
931 @retval EFI_ACCESS_DENIED The file is a read-only file or has been\r
932 opened in read-only mode and an attempt is\r
933 being made to modify a field other than\r
934 Attribute.\r
935 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a\r
936 read-only attribute.\r
937 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
938 @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.\r
939\r
940**/\r
941STATIC\r
942EFI_STATUS\r
943SetFileInfo (\r
944 IN SEMIHOST_FCB *Fcb,\r
945 IN EFI_FILE_INFO *Info\r
946 )\r
947{\r
948 EFI_STATUS Status;\r
949 RETURN_STATUS Return;\r
950 BOOLEAN FileSizeIsDifferent;\r
951 BOOLEAN FileNameIsDifferent;\r
952 BOOLEAN ReadOnlyIsDifferent;\r
953 CHAR8 *AsciiFileName;\r
954 UINTN FileSize;\r
955 UINTN Length;\r
956 UINTN SemihostHandle;\r
957\r
958 //\r
959 // A directory can not be changed to a file and a file can\r
960 // not be changed to a directory.\r
961 //\r
962 if (((Info->Attribute & EFI_FILE_DIRECTORY) != 0) != Fcb->IsRoot) {\r
963 return EFI_ACCESS_DENIED;\r
964 }\r
965\r
f6c4d99a
AB
966 Length = StrLen (Info->FileName) + 1;\r
967 AsciiFileName = AllocatePool (Length);\r
daefd574
RC
968 if (AsciiFileName == NULL) {\r
969 return EFI_OUT_OF_RESOURCES;\r
970 }\r
f6c4d99a 971 UnicodeStrToAsciiStrS (Info->FileName, AsciiFileName, Length);\r
daefd574
RC
972\r
973 FileSizeIsDifferent = (Info->FileSize != Fcb->Info.FileSize);\r
974 FileNameIsDifferent = (AsciiStrCmp (AsciiFileName, Fcb->FileName) != 0);\r
975 ReadOnlyIsDifferent = CompareMem (\r
976 &Info->CreateTime,\r
977 &Fcb->Info.CreateTime,\r
978 3 * sizeof (EFI_TIME)\r
979 ) != 0;\r
980\r
981 //\r
982 // For a read-only file or a file opened in read-only mode, only\r
983 // the Attribute field can be modified. As the root directory is\r
984 // read-only (i.e. VolumeOpen()), this protects the root directory\r
985 // description.\r
986 //\r
987 if ((Fcb->OpenMode == EFI_FILE_MODE_READ) ||\r
988 (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) ) {\r
989 if (FileSizeIsDifferent || FileNameIsDifferent || ReadOnlyIsDifferent) {\r
990 Status = EFI_ACCESS_DENIED;\r
991 goto Error;\r
992 }\r
993 }\r
994\r
995 if (ReadOnlyIsDifferent) {\r
996 Status = EFI_WRITE_PROTECTED;\r
997 goto Error;\r
998 }\r
999\r
1000 Status = EFI_DEVICE_ERROR;\r
1001\r
1002 if (FileSizeIsDifferent) {\r
1003 FileSize = Info->FileSize;\r
1004 if (Fcb->Info.FileSize < FileSize) {\r
1005 Status = ExtendFile (Fcb, FileSize - Fcb->Info.FileSize);\r
1006 if (EFI_ERROR (Status)) {\r
1007 goto Error;\r
1008 }\r
1009 //\r
1010 // The read/write position from the host file system point of view\r
1011 // is at the end of the file. If the position from this module\r
1012 // point of view is smaller than the new file size, then\r
1013 // ask the host file system to move to that position.\r
1014 //\r
1015 if (Fcb->Position < FileSize) {\r
1016 FileSetPosition (&Fcb->File, Fcb->Position);\r
1017 }\r
1018 }\r
1019 Fcb->Info.FileSize = FileSize;\r
1020\r
1021 Return = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
1022 if (RETURN_ERROR (Return)) {\r
1023 goto Error;\r
1024 }\r
1025 Fcb->Info.PhysicalSize = Length;\r
1026 }\r
1027\r
1028 //\r
1029 // Note down in RAM the Attribute field but we can not ask\r
1030 // for its modification to the host file system as the\r
1031 // semi-host interface does not provide this feature.\r
1032 //\r
1033 Fcb->Info.Attribute = Info->Attribute;\r
1034\r
1035 if (FileNameIsDifferent) {\r
1036 Return = SemihostFileOpen (\r
1037 AsciiFileName,\r
1038 SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,\r
1039 &SemihostHandle\r
1040 );\r
1041 if (!RETURN_ERROR (Return)) {\r
1042 SemihostFileClose (SemihostHandle);\r
1043 Status = EFI_ACCESS_DENIED;\r
1044 goto Error;\r
1045 }\r
1046\r
1047 Return = SemihostFileRename (Fcb->FileName, AsciiFileName);\r
1048 if (RETURN_ERROR (Return)) {\r
1049 goto Error;\r
1050 }\r
1051 FreePool (Fcb->FileName);\r
1052 Fcb->FileName = AsciiFileName;\r
1053 AsciiFileName = NULL;\r
1054 }\r
1055\r
1056 Status = EFI_SUCCESS;\r
1057\r
1058Error:\r
1059 if (AsciiFileName != NULL) {\r
1060 FreePool (AsciiFileName);\r
1061 }\r
1062\r
1063 return Status;\r
1064}\r
1065\r
1066/**\r
1067 Set information about a file or a file system.\r
1068\r
1069 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
1070 is the file handle the information is for.\r
1071 @param[in] InformationType The type identifier for the information being set :\r
1072 EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or\r
1073 EFI_FILE_SYSTEM_VOLUME_LABEL_ID\r
1074 @param[in] BufferSize The size, in bytes, of Buffer.\r
1075 @param[in] Buffer A pointer to the data buffer to write. The type of the\r
1076 data inside the buffer is indicated by InformationType.\r
1077\r
1078 @retval EFI_SUCCESS The information was set.\r
1079 @retval EFI_UNSUPPORTED The InformationType is not known.\r
1080 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
1081 @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
1082 EFI_FILE_DIRECTORY Attribute.\r
1083 @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and\r
1084 the file is a read-only file or has been\r
1085 opened in read-only mode and an attempt is\r
1086 being made to modify a field other than\r
1087 Attribute.\r
1088 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
1089 to a file that is already present.\r
1090 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a\r
1091 read-only attribute.\r
1092 @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by\r
1093 the data inside the buffer.\r
1094 @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.\r
1095 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.\r
1096\r
1097**/\r
2ef2b01e
A
1098EFI_STATUS\r
1099FileSetInfo (\r
daefd574
RC
1100 IN EFI_FILE *This,\r
1101 IN EFI_GUID *InformationType,\r
1102 IN UINTN BufferSize,\r
1103 IN VOID *Buffer\r
2ef2b01e
A
1104 )\r
1105{\r
daefd574
RC
1106 SEMIHOST_FCB *Fcb;\r
1107 EFI_FILE_INFO *Info;\r
1108 EFI_FILE_SYSTEM_INFO *SystemInfo;\r
1109 CHAR16 *VolumeLabel;\r
09f2cf82 1110\r
daefd574 1111 if ((This == NULL) || (InformationType == NULL) || (Buffer == NULL)) {\r
09f2cf82 1112 return EFI_INVALID_PARAMETER;\r
1113 }\r
1114\r
daefd574
RC
1115 Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
1116\r
1117 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1118 Info = Buffer;\r
1119 if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {\r
1120 return EFI_INVALID_PARAMETER;\r
1121 }\r
1122 if (BufferSize < Info->Size) {\r
1123 return EFI_BAD_BUFFER_SIZE;\r
1124 }\r
1125 return SetFileInfo (Fcb, Info);\r
1126 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1127 SystemInfo = Buffer;\r
1128 if (SystemInfo->Size <\r
1129 (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {\r
1130 return EFI_INVALID_PARAMETER;\r
1131 }\r
1132 if (BufferSize < SystemInfo->Size) {\r
1133 return EFI_BAD_BUFFER_SIZE;\r
1134 }\r
1135 Buffer = SystemInfo->VolumeLabel;\r
09f2cf82 1136\r
09f2cf82 1137 if (StrSize (Buffer) > 0) {\r
daefd574
RC
1138 VolumeLabel = AllocateCopyPool (StrSize (Buffer), Buffer);\r
1139 if (VolumeLabel != NULL) {\r
1140 FreePool (mSemihostFsLabel);\r
1141 mSemihostFsLabel = VolumeLabel;\r
1142 return EFI_SUCCESS;\r
1143 } else {\r
1144 return EFI_OUT_OF_RESOURCES;\r
1145 }\r
1146 } else {\r
1147 return EFI_INVALID_PARAMETER;\r
09f2cf82 1148 }\r
daefd574
RC
1149 } else if (!CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1150 return EFI_UNSUPPORTED;\r
1151 } else {\r
1152 return EFI_UNSUPPORTED;\r
09f2cf82 1153 }\r
2ef2b01e
A
1154}\r
1155\r
1156EFI_STATUS\r
1157FileFlush (\r
1158 IN EFI_FILE *File\r
1159 )\r
1160{\r
09f2cf82 1161 SEMIHOST_FCB *Fcb;\r
1162\r
1163 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
1164\r
1165 if (Fcb->IsRoot) {\r
1166 return EFI_SUCCESS;\r
1167 } else {\r
cc271ec3
OM
1168 if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)\r
1169 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {\r
09f2cf82 1170 return EFI_ACCESS_DENIED;\r
1171 } else {\r
1172 return EFI_SUCCESS;\r
1173 }\r
1174 }\r
2ef2b01e
A
1175}\r
1176\r
1177EFI_STATUS\r
1178SemihostFsEntryPoint (\r
1179 IN EFI_HANDLE ImageHandle,\r
1180 IN EFI_SYSTEM_TABLE *SystemTable\r
1181 )\r
1182{\r
09f2cf82 1183 EFI_STATUS Status;\r
1184\r
1185 Status = EFI_NOT_FOUND;\r
2ef2b01e
A
1186\r
1187 if (SemihostConnectionSupported ()) {\r
09f2cf82 1188 mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);\r
1189 if (mSemihostFsLabel == NULL) {\r
1190 return EFI_OUT_OF_RESOURCES;\r
1191 }\r
1192\r
2ef2b01e 1193 Status = gBS->InstallMultipleProtocolInterfaces (\r
3402aac7
RC
1194 &gInstallHandle,\r
1195 &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,\r
2ef2b01e
A
1196 &gEfiDevicePathProtocolGuid, &gDevicePath,\r
1197 NULL\r
1198 );\r
09f2cf82 1199\r
1200 if (EFI_ERROR(Status)) {\r
1201 FreePool (mSemihostFsLabel);\r
1202 }\r
2ef2b01e 1203 }\r
3402aac7 1204\r
2ef2b01e
A
1205 return Status;\r
1206}\r