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