]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
ArmPkg/SemihostFs: Make the driver more compliant with the UEFI specification
[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
09f2cf82 5 Portions copyright (c) 2011 - 2013, 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
24#include <Library/BaseMemoryLib.h> \r
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
60// Device path for SemiHosting. It contains our autogened Caller ID GUID.\r
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
69 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },\r
70 EFI_CALLER_ID_GUID\r
71 },\r
72 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}\r
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
132 \r
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
141 \r
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
152EFI_STATUS\r
153FileOpen (\r
154 IN EFI_FILE *File,\r
155 OUT EFI_FILE **NewHandle,\r
156 IN CHAR16 *FileName,\r
157 IN UINT64 OpenMode,\r
158 IN UINT64 Attributes\r
159 )\r
160{\r
161 SEMIHOST_FCB *FileFcb = NULL;\r
162 EFI_STATUS Status = EFI_SUCCESS;\r
c63626b7 163 UINTN SemihostHandle;\r
2ef2b01e 164 CHAR8 *AsciiFileName;\r
2ef2b01e
A
165 UINT32 SemihostMode;\r
166 BOOLEAN IsRoot;\r
09f2cf82 167 UINTN Length;\r
2ef2b01e
A
168\r
169 if ((FileName == NULL) || (NewHandle == NULL)) {\r
170 return EFI_INVALID_PARAMETER;\r
171 }\r
172\r
09f2cf82 173 // Semihosting does not support directories\r
174 if (Attributes & EFI_FILE_DIRECTORY) {\r
175 return EFI_UNSUPPORTED;\r
176 }\r
177\r
ed2405a0 178 // Semihost interface requires ASCII filenames\r
179 AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));\r
2ef2b01e
A
180 if (AsciiFileName == NULL) {\r
181 return EFI_OUT_OF_RESOURCES;\r
182 }\r
ed2405a0 183 UnicodeStrToAsciiStr (FileName, AsciiFileName);\r
2ef2b01e 184\r
1ea31716 185 if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||\r
186 (AsciiStrCmp (AsciiFileName, "/") == 0) ||\r
187 (AsciiStrCmp (AsciiFileName, "") == 0) ||\r
188 (AsciiStrCmp (AsciiFileName, ".") == 0)) {\r
189 // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
2ef2b01e
A
190 IsRoot = TRUE;\r
191\r
192 // Root directory node doesn't have a name.\r
193 FreePool (AsciiFileName);\r
194 AsciiFileName = NULL;\r
195 } else {\r
196 // Translate EFI_FILE_MODE into Semihosting mode\r
197 if (OpenMode & EFI_FILE_MODE_WRITE) {\r
198 SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;\r
199 } else if (OpenMode & EFI_FILE_MODE_READ) {\r
200 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
201 } else {\r
202 return EFI_UNSUPPORTED;\r
203 }\r
204\r
205 // Add the creation flag if necessary\r
206 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
207 SemihostMode |= SEMIHOST_FILE_MODE_CREATE;\r
208 }\r
209\r
210 // Call the semihosting interface to open the file.\r
211 Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
212 if (EFI_ERROR(Status)) {\r
213 return Status;\r
214 }\r
215 \r
216 IsRoot = FALSE;\r
217 }\r
218\r
219 // Allocate a control block and fill it\r
220 FileFcb = AllocateFCB ();\r
221 if (FileFcb == NULL) {\r
222 return EFI_OUT_OF_RESOURCES;\r
223 }\r
224\r
225 FileFcb->FileName = AsciiFileName;\r
226 FileFcb->SemihostHandle = SemihostHandle;\r
227 FileFcb->Position = 0;\r
228 FileFcb->IsRoot = IsRoot;\r
09f2cf82 229 FileFcb->OpenMode = OpenMode;\r
230\r
231 if (!IsRoot) {\r
232 Status = SemihostFileLength (SemihostHandle, &Length);\r
233 if (EFI_ERROR(Status)) {\r
234 return Status;\r
235 }\r
236\r
237 FileFcb->Info.FileSize = Length;\r
238 FileFcb->Info.PhysicalSize = Length;\r
239 FileFcb->Info.Attribute = Attributes;\r
240 }\r
2ef2b01e
A
241\r
242 InsertTailList (&gFileList, &FileFcb->Link);\r
243\r
244 *NewHandle = &FileFcb->File;\r
245\r
246 return Status;\r
247}\r
248\r
249\r
250EFI_STATUS\r
251FileClose (\r
252 IN EFI_FILE *File\r
253 )\r
254{\r
255 SEMIHOST_FCB *Fcb = NULL;\r
256 EFI_STATUS Status = EFI_SUCCESS;\r
257\r
258 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
259\r
260 if (Fcb->IsRoot == TRUE) {\r
261 FreeFCB (Fcb);\r
262 Status = EFI_SUCCESS;\r
263 } else {\r
264 Status = SemihostFileClose (Fcb->SemihostHandle);\r
265 if (!EFI_ERROR(Status)) {\r
266 FreePool (Fcb->FileName);\r
267 FreeFCB (Fcb);\r
268 }\r
269 }\r
270 \r
271 return Status;\r
272}\r
273\r
274EFI_STATUS\r
275FileDelete (\r
276 IN EFI_FILE *File\r
277 )\r
278{\r
279 SEMIHOST_FCB *Fcb = NULL;\r
280 EFI_STATUS Status;\r
281 CHAR8 *FileName;\r
282 UINTN NameSize;\r
283\r
284 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
285\r
3bb46df2 286 if (!Fcb->IsRoot) {\r
287 // Get the filename from the Fcb\r
288 NameSize = AsciiStrLen (Fcb->FileName);\r
289 FileName = AllocatePool (NameSize + 1);\r
2ef2b01e 290\r
3bb46df2 291 AsciiStrCpy (FileName, Fcb->FileName);\r
2ef2b01e 292\r
3bb46df2 293 // Close the file if it's open. Disregard return status,\r
294 // since it might give an error if the file isn't open.\r
295 File->Close (File);\r
296\r
297 // Call the semihost interface to delete the file.\r
298 Status = SemihostFileRemove (FileName);\r
09f2cf82 299 if (EFI_ERROR(Status)) {\r
300 Status = EFI_WARN_DELETE_FAILURE;\r
301 }\r
3bb46df2 302 } else {\r
09f2cf82 303 Status = EFI_WARN_DELETE_FAILURE;\r
3bb46df2 304 }\r
2ef2b01e
A
305\r
306 return Status;\r
307}\r
308\r
309EFI_STATUS\r
310FileRead (\r
311 IN EFI_FILE *File,\r
312 IN OUT UINTN *BufferSize,\r
313 OUT VOID *Buffer\r
314 )\r
315{\r
316 SEMIHOST_FCB *Fcb = NULL;\r
317 EFI_STATUS Status;\r
318\r
319 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
320\r
321 if (Fcb->IsRoot == TRUE) {\r
b1cab81f 322 // By design, the Semihosting feature does not allow to list files on the host machine.\r
2ef2b01e
A
323 Status = EFI_UNSUPPORTED;\r
324 } else {\r
325 Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
326 if (!EFI_ERROR (Status)) {\r
327 Fcb->Position += *BufferSize;\r
328 }\r
329 }\r
330\r
331 return Status;\r
332}\r
333\r
334EFI_STATUS\r
335FileWrite (\r
336 IN EFI_FILE *File,\r
337 IN OUT UINTN *BufferSize,\r
338 IN VOID *Buffer\r
339 )\r
340{\r
341 SEMIHOST_FCB *Fcb = NULL;\r
342 EFI_STATUS Status;\r
343 UINTN WriteSize = *BufferSize;\r
344\r
345 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
346\r
09f2cf82 347 // We cannot write a read-only file\r
348 if (Fcb->OpenMode & EFI_FILE_READ_ONLY) {\r
349 return EFI_ACCESS_DENIED;\r
350 }\r
351\r
2ef2b01e
A
352 Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
353\r
354 if (!EFI_ERROR(Status)) {\r
355 // Semihost write return the number of bytes *NOT* written.\r
356 *BufferSize -= WriteSize;\r
357 Fcb->Position += *BufferSize;\r
358 }\r
359 \r
360 return Status;\r
361}\r
362\r
363EFI_STATUS\r
364FileGetPosition (\r
365 IN EFI_FILE *File,\r
366 OUT UINT64 *Position\r
367 )\r
368{\r
369 SEMIHOST_FCB *Fcb = NULL;\r
370 \r
371 if (Position == NULL) {\r
372 return EFI_INVALID_PARAMETER;\r
373 }\r
374\r
375 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
376\r
377 *Position = Fcb->Position;\r
378\r
379 return EFI_SUCCESS;\r
380}\r
381\r
382EFI_STATUS\r
383FileSetPosition (\r
384 IN EFI_FILE *File,\r
385 IN UINT64 Position\r
386 )\r
387{\r
388 SEMIHOST_FCB *Fcb = NULL;\r
c63626b7 389 UINTN Length;\r
2ef2b01e
A
390 EFI_STATUS Status;\r
391\r
392 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
393\r
3bb46df2 394 if (!Fcb->IsRoot) {\r
395 Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
396 if (!EFI_ERROR(Status) && (Length < Position)) {\r
397 Position = Length;\r
398 }\r
2ef2b01e 399\r
3bb46df2 400 Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);\r
401 if (!EFI_ERROR(Status)) {\r
402 Fcb->Position = Position;\r
403 }\r
404 } else {\r
2ef2b01e 405 Fcb->Position = Position;\r
3bb46df2 406 Status = EFI_SUCCESS;\r
2ef2b01e
A
407 }\r
408\r
409 return Status;\r
410}\r
411\r
412STATIC\r
413EFI_STATUS\r
414GetFileInfo (\r
415 IN SEMIHOST_FCB *Fcb,\r
416 IN OUT UINTN *BufferSize,\r
417 OUT VOID *Buffer\r
418 )\r
419{\r
420 EFI_FILE_INFO *Info = NULL;\r
421 UINTN NameSize = 0;\r
422 UINTN ResultSize;\r
423 UINTN Index;\r
2ef2b01e
A
424\r
425 if (Fcb->IsRoot == TRUE) {\r
426 ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
427 } else {\r
428 NameSize = AsciiStrLen (Fcb->FileName) + 1;\r
429 ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);\r
430 }\r
431\r
432 if (*BufferSize < ResultSize) {\r
433 *BufferSize = ResultSize;\r
434 return EFI_BUFFER_TOO_SMALL;\r
435 }\r
436\r
437 Info = Buffer;\r
438\r
09f2cf82 439 // Copy the current file info\r
440 CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);\r
2ef2b01e
A
441\r
442 // Fill in the structure\r
443 Info->Size = ResultSize;\r
444\r
445 if (Fcb->IsRoot == TRUE) {\r
2ef2b01e
A
446 Info->FileName[0] = L'\0';\r
447 } else {\r
2ef2b01e
A
448 for (Index = 0; Index < NameSize; Index++) {\r
449 Info->FileName[Index] = Fcb->FileName[Index]; \r
450 }\r
451 }\r
452\r
2ef2b01e
A
453 *BufferSize = ResultSize; \r
454\r
455 return EFI_SUCCESS;\r
456}\r
457\r
458STATIC\r
459EFI_STATUS\r
460GetFilesystemInfo (\r
461 IN SEMIHOST_FCB *Fcb,\r
462 IN OUT UINTN *BufferSize,\r
463 OUT VOID *Buffer\r
464 )\r
465{\r
466 EFI_FILE_SYSTEM_INFO *Info = NULL;\r
467 EFI_STATUS Status;\r
09f2cf82 468 UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel);\r
2ef2b01e 469 \r
09f2cf82 470 if (*BufferSize >= ResultSize) {\r
2ef2b01e
A
471 ZeroMem (Buffer, ResultSize);\r
472 Status = EFI_SUCCESS;\r
473 \r
474 Info = Buffer;\r
475\r
476 Info->Size = ResultSize;\r
477 Info->ReadOnly = FALSE;\r
478 Info->VolumeSize = 0;\r
479 Info->FreeSpace = 0;\r
480 Info->BlockSize = 0;\r
481\r
09f2cf82 482 StrCpy (Info->VolumeLabel, mSemihostFsLabel);\r
2ef2b01e
A
483 } else {\r
484 Status = EFI_BUFFER_TOO_SMALL;\r
485 }\r
486\r
487 *BufferSize = ResultSize; \r
488 return Status;\r
489}\r
490\r
491EFI_STATUS\r
492FileGetInfo (\r
493 IN EFI_FILE *File,\r
494 IN EFI_GUID *InformationType,\r
495 IN OUT UINTN *BufferSize,\r
496 OUT VOID *Buffer\r
497 )\r
498{\r
09f2cf82 499 SEMIHOST_FCB *Fcb;\r
500 EFI_STATUS Status;\r
501 UINTN ResultSize;\r
2ef2b01e
A
502 \r
503 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
504 \r
09f2cf82 505 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
506 Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);\r
507 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
508 Status = GetFileInfo (Fcb, BufferSize, Buffer);\r
509 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
510 ResultSize = StrSize (mSemihostFsLabel);\r
511\r
512 if (*BufferSize >= ResultSize) {\r
513 StrCpy (Buffer, mSemihostFsLabel);\r
514 Status = EFI_SUCCESS;\r
515 } else {\r
516 Status = EFI_BUFFER_TOO_SMALL;\r
517 }\r
518\r
519 *BufferSize = ResultSize;\r
520 } else {\r
521 Status = EFI_UNSUPPORTED;\r
2ef2b01e 522 }\r
09f2cf82 523\r
2ef2b01e
A
524 return Status;\r
525}\r
526\r
527EFI_STATUS\r
528FileSetInfo (\r
529 IN EFI_FILE *File,\r
530 IN EFI_GUID *InformationType,\r
531 IN UINTN BufferSize,\r
532 IN VOID *Buffer\r
533 )\r
534{\r
09f2cf82 535 EFI_STATUS Status;\r
536\r
537 if (Buffer == NULL) {\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540\r
541 Status = EFI_UNSUPPORTED;\r
542\r
543 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
544 //Status = SetFilesystemInfo (Fcb, BufferSize, Buffer);\r
545 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
546 //Status = SetFileInfo (Fcb, BufferSize, Buffer);\r
547 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
548 if (StrSize (Buffer) > 0) {\r
549 FreePool (mSemihostFsLabel);\r
550 mSemihostFsLabel = AllocateCopyPool (StrSize (Buffer), Buffer);\r
551 Status = EFI_SUCCESS;\r
552 }\r
553 }\r
554\r
555 return Status;\r
2ef2b01e
A
556}\r
557\r
558EFI_STATUS\r
559FileFlush (\r
560 IN EFI_FILE *File\r
561 )\r
562{\r
09f2cf82 563 SEMIHOST_FCB *Fcb;\r
564\r
565 Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
566\r
567 if (Fcb->IsRoot) {\r
568 return EFI_SUCCESS;\r
569 } else {\r
570 if (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) {\r
571 return EFI_ACCESS_DENIED;\r
572 } else {\r
573 return EFI_SUCCESS;\r
574 }\r
575 }\r
2ef2b01e
A
576}\r
577\r
578EFI_STATUS\r
579SemihostFsEntryPoint (\r
580 IN EFI_HANDLE ImageHandle,\r
581 IN EFI_SYSTEM_TABLE *SystemTable\r
582 )\r
583{\r
09f2cf82 584 EFI_STATUS Status;\r
585\r
586 Status = EFI_NOT_FOUND;\r
2ef2b01e
A
587\r
588 if (SemihostConnectionSupported ()) {\r
09f2cf82 589 mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);\r
590 if (mSemihostFsLabel == NULL) {\r
591 return EFI_OUT_OF_RESOURCES;\r
592 }\r
593\r
2ef2b01e
A
594 Status = gBS->InstallMultipleProtocolInterfaces (\r
595 &gInstallHandle, \r
596 &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, \r
597 &gEfiDevicePathProtocolGuid, &gDevicePath,\r
598 NULL\r
599 );\r
09f2cf82 600\r
601 if (EFI_ERROR(Status)) {\r
602 FreePool (mSemihostFsLabel);\r
603 }\r
2ef2b01e
A
604 }\r
605 \r
606 return Status;\r
607}\r