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