]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
UefiPayloadPkg: Fix build error
[mirror_edk2.git] / OvmfPkg / QemuKernelLoaderFsDxe / QemuKernelLoaderFsDxe.c
CommitLineData
57f9b7f8
AB
1/** @file\r
2 DXE driver to expose the 'kernel', 'initrd' and 'cmdline' blobs\r
3 provided by QEMU as files in an abstract file system\r
4\r
5 Copyright (C) 2014-2016, Red Hat, Inc.\r
6 Copyright (C) 2020, Arm, Limited.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9**/\r
10\r
11#include <PiDxe.h>\r
12\r
13#include <Guid/FileInfo.h>\r
14#include <Guid/FileSystemInfo.h>\r
15#include <Guid/FileSystemVolumeLabelInfo.h>\r
f98608ab 16#include <Guid/LinuxEfiInitrdMedia.h>\r
57f9b7f8
AB
17#include <Guid/QemuKernelLoaderFsMedia.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
d10ad844 20#include <Library/BlobVerifierLib.h>\r
57f9b7f8 21#include <Library/DebugLib.h>\r
f98608ab 22#include <Library/DevicePathLib.h>\r
57f9b7f8
AB
23#include <Library/MemoryAllocationLib.h>\r
24#include <Library/QemuFwCfgLib.h>\r
25#include <Library/UefiBootServicesTableLib.h>\r
26#include <Library/UefiRuntimeServicesTableLib.h>\r
27#include <Protocol/DevicePath.h>\r
f98608ab 28#include <Protocol/LoadFile2.h>\r
57f9b7f8
AB
29#include <Protocol/SimpleFileSystem.h>\r
30\r
31//\r
32// Static data that hosts the fw_cfg blobs and serves file requests.\r
33//\r
34typedef enum {\r
35 KernelBlobTypeKernel,\r
36 KernelBlobTypeInitrd,\r
24b0e9d1 37 KernelBlobTypeCommandLine,\r
57f9b7f8
AB
38 KernelBlobTypeMax\r
39} KERNEL_BLOB_TYPE;\r
40\r
41typedef struct {\r
ac0a286f 42 CONST CHAR16 Name[8];\r
0758a8e9 43 struct {\r
ac0a286f
MK
44 FIRMWARE_CONFIG_ITEM CONST SizeKey;\r
45 FIRMWARE_CONFIG_ITEM CONST DataKey;\r
46 UINT32 Size;\r
0758a8e9 47 } FwCfgItem[2];\r
ac0a286f
MK
48 UINT32 Size;\r
49 UINT8 *Data;\r
57f9b7f8
AB
50} KERNEL_BLOB;\r
51\r
ac0a286f 52STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {\r
0758a8e9
AB
53 {\r
54 L"kernel",\r
55 {\r
56 { QemuFwCfgItemKernelSetupSize, QemuFwCfgItemKernelSetupData, },\r
57 { QemuFwCfgItemKernelSize, QemuFwCfgItemKernelData, },\r
58 }\r
ac0a286f 59 }, {\r
0758a8e9
AB
60 L"initrd",\r
61 {\r
62 { QemuFwCfgItemInitrdSize, QemuFwCfgItemInitrdData, },\r
63 }\r
ac0a286f 64 }, {\r
24b0e9d1
DM
65 L"cmdline",\r
66 {\r
67 { QemuFwCfgItemCommandLineSize, QemuFwCfgItemCommandLineData, },\r
68 }\r
0758a8e9 69 }\r
57f9b7f8
AB
70};\r
71\r
ac0a286f 72STATIC UINT64 mTotalBlobBytes;\r
57f9b7f8
AB
73\r
74//\r
75// Device path for the handle that incorporates our "EFI stub filesystem".\r
76//\r
77#pragma pack (1)\r
78typedef struct {\r
ac0a286f
MK
79 VENDOR_DEVICE_PATH VenMediaNode;\r
80 EFI_DEVICE_PATH_PROTOCOL EndNode;\r
57f9b7f8
AB
81} SINGLE_VENMEDIA_NODE_DEVPATH;\r
82#pragma pack ()\r
83\r
ac0a286f 84STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mFileSystemDevicePath = {\r
57f9b7f8
AB
85 {\r
86 {\r
87 MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
ac0a286f 88 { sizeof (VENDOR_DEVICE_PATH) }\r
57f9b7f8
AB
89 },\r
90 QEMU_KERNEL_LOADER_FS_MEDIA_GUID\r
ac0a286f 91 }, {\r
57f9b7f8
AB
92 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
93 { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
94 }\r
95};\r
96\r
ac0a286f 97STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mInitrdDevicePath = {\r
f98608ab
AB
98 {\r
99 {\r
100 MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
ac0a286f 101 { sizeof (VENDOR_DEVICE_PATH) }\r
f98608ab
AB
102 },\r
103 LINUX_EFI_INITRD_MEDIA_GUID\r
ac0a286f 104 }, {\r
f98608ab
AB
105 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
106 { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
107 }\r
108};\r
109\r
57f9b7f8
AB
110//\r
111// The "file in the EFI stub filesystem" abstraction.\r
112//\r
ac0a286f 113STATIC EFI_TIME mInitTime;\r
57f9b7f8 114\r
ac0a286f 115#define STUB_FILE_SIG SIGNATURE_64 ('S', 'T', 'U', 'B', 'F', 'I', 'L', 'E')\r
57f9b7f8
AB
116\r
117typedef struct {\r
ac0a286f 118 UINT64 Signature; // Carries STUB_FILE_SIG.\r
57f9b7f8 119\r
ac0a286f
MK
120 KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax\r
121 // denotes the root directory of the filesystem.\r
57f9b7f8 122\r
ac0a286f
MK
123 UINT64 Position; // Byte position for regular files;\r
124 // next directory entry to return for the root\r
125 // directory.\r
57f9b7f8 126\r
ac0a286f 127 EFI_FILE_PROTOCOL File; // Standard protocol interface.\r
57f9b7f8
AB
128} STUB_FILE;\r
129\r
130#define STUB_FILE_FROM_FILE(FilePointer) \\r
131 CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG)\r
132\r
57f9b7f8
AB
133//\r
134// Protocol member functions for File.\r
135//\r
136\r
137/**\r
138 Opens a new file relative to the source file's location.\r
139\r
40d572f7
AB
140 (Forward declaration.)\r
141\r
57f9b7f8
AB
142 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
143 the file handle to the source location. This would\r
144 typically be an open handle to a directory.\r
145\r
146 @param[out] NewHandle A pointer to the location to return the opened handle\r
147 for the new file.\r
148\r
149 @param[in] FileName The Null-terminated string of the name of the file to\r
150 be opened. The file name may contain the following\r
151 path modifiers: "\", ".", and "..".\r
152\r
153 @param[in] OpenMode The mode to open the file. The only valid\r
154 combinations that the file may be opened with are:\r
155 Read, Read/Write, or Create/Read/Write.\r
156\r
157 @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case\r
158 these are the attribute bits for the newly created\r
159 file.\r
160\r
161 @retval EFI_SUCCESS The file was opened.\r
162 @retval EFI_NOT_FOUND The specified file could not be found on the\r
163 device.\r
164 @retval EFI_NO_MEDIA The device has no medium.\r
165 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
166 medium is no longer supported.\r
167 @retval EFI_DEVICE_ERROR The device reported an error.\r
168 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
169 @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a\r
170 file for write when the media is\r
171 write-protected.\r
172 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
173 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
174 file.\r
175 @retval EFI_VOLUME_FULL The volume is full.\r
176**/\r
177STATIC\r
178EFI_STATUS\r
179EFIAPI\r
180StubFileOpen (\r
ac0a286f
MK
181 IN EFI_FILE_PROTOCOL *This,\r
182 OUT EFI_FILE_PROTOCOL **NewHandle,\r
183 IN CHAR16 *FileName,\r
184 IN UINT64 OpenMode,\r
185 IN UINT64 Attributes\r
40d572f7 186 );\r
57f9b7f8
AB
187\r
188/**\r
189 Closes a specified file handle.\r
190\r
191 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
192 handle to close.\r
193\r
194 @retval EFI_SUCCESS The file was closed.\r
195**/\r
196STATIC\r
197EFI_STATUS\r
198EFIAPI\r
199StubFileClose (\r
ac0a286f 200 IN EFI_FILE_PROTOCOL *This\r
57f9b7f8
AB
201 )\r
202{\r
203 FreePool (STUB_FILE_FROM_FILE (This));\r
204 return EFI_SUCCESS;\r
205}\r
206\r
57f9b7f8
AB
207/**\r
208 Close and delete the file handle.\r
209\r
210 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
211 handle to the file to delete.\r
212\r
213 @retval EFI_SUCCESS The file was closed and deleted, and the\r
214 handle was closed.\r
215 @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not\r
216 deleted.\r
217\r
218**/\r
219STATIC\r
220EFI_STATUS\r
221EFIAPI\r
222StubFileDelete (\r
ac0a286f 223 IN EFI_FILE_PROTOCOL *This\r
57f9b7f8
AB
224 )\r
225{\r
226 FreePool (STUB_FILE_FROM_FILE (This));\r
227 return EFI_WARN_DELETE_FAILURE;\r
228}\r
229\r
57f9b7f8
AB
230/**\r
231 Helper function that formats an EFI_FILE_INFO structure into the\r
232 user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including\r
233 KernelBlobTypeMax, which stands for the root directory).\r
234\r
235 The interface follows the EFI_FILE_GET_INFO -- and for directories, the\r
236 EFI_FILE_READ -- interfaces.\r
237\r
238 @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg\r
239 blob backing the STUB_FILE that information is\r
240 being requested about. If BlobType equals\r
241 KernelBlobTypeMax, then information will be\r
242 provided about the root directory of the\r
243 filesystem.\r
244\r
245 @param[in,out] BufferSize On input, the size of Buffer. On output, the\r
246 amount of data returned in Buffer. In both cases,\r
247 the size is measured in bytes.\r
248\r
249 @param[out] Buffer A pointer to the data buffer to return. The\r
250 buffer's type is EFI_FILE_INFO.\r
251\r
252 @retval EFI_SUCCESS The information was returned.\r
253 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to store the\r
254 EFI_FILE_INFO structure. BufferSize has been\r
255 updated with the size needed to complete the\r
256 request.\r
257**/\r
258STATIC\r
259EFI_STATUS\r
260ConvertKernelBlobTypeToFileInfo (\r
ac0a286f
MK
261 IN KERNEL_BLOB_TYPE BlobType,\r
262 IN OUT UINTN *BufferSize,\r
263 OUT VOID *Buffer\r
57f9b7f8
AB
264 )\r
265{\r
266 CONST CHAR16 *Name;\r
267 UINT64 FileSize;\r
268 UINT64 Attribute;\r
269\r
ac0a286f
MK
270 UINTN NameSize;\r
271 UINTN FileInfoSize;\r
272 EFI_FILE_INFO *FileInfo;\r
273 UINTN OriginalBufferSize;\r
57f9b7f8
AB
274\r
275 if (BlobType == KernelBlobTypeMax) {\r
276 //\r
277 // getting file info about the root directory\r
278 //\r
279 Name = L"\\";\r
280 FileSize = KernelBlobTypeMax;\r
281 Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
282 } else {\r
ac0a286f 283 CONST KERNEL_BLOB *Blob;\r
57f9b7f8
AB
284\r
285 Blob = &mKernelBlob[BlobType];\r
286 Name = Blob->Name;\r
287 FileSize = Blob->Size;\r
288 Attribute = EFI_FILE_READ_ONLY;\r
289 }\r
290\r
ac0a286f 291 NameSize = (StrLen (Name) + 1) * 2;\r
57f9b7f8
AB
292 FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize;\r
293 ASSERT (FileInfoSize >= sizeof *FileInfo);\r
294\r
295 OriginalBufferSize = *BufferSize;\r
296 *BufferSize = FileInfoSize;\r
297 if (OriginalBufferSize < *BufferSize) {\r
298 return EFI_BUFFER_TOO_SMALL;\r
299 }\r
300\r
301 FileInfo = (EFI_FILE_INFO *)Buffer;\r
302 FileInfo->Size = FileInfoSize;\r
303 FileInfo->FileSize = FileSize;\r
304 FileInfo->PhysicalSize = FileSize;\r
305 FileInfo->Attribute = Attribute;\r
306\r
ac0a286f
MK
307 CopyMem (&FileInfo->CreateTime, &mInitTime, sizeof mInitTime);\r
308 CopyMem (&FileInfo->LastAccessTime, &mInitTime, sizeof mInitTime);\r
57f9b7f8 309 CopyMem (&FileInfo->ModificationTime, &mInitTime, sizeof mInitTime);\r
ac0a286f 310 CopyMem (FileInfo->FileName, Name, NameSize);\r
57f9b7f8
AB
311\r
312 return EFI_SUCCESS;\r
313}\r
314\r
57f9b7f8
AB
315/**\r
316 Reads data from a file, or continues scanning a directory.\r
317\r
318 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
319 is the file handle to read data from.\r
320\r
321 @param[in,out] BufferSize On input, the size of the Buffer. On output, the\r
322 amount of data returned in Buffer. In both cases,\r
323 the size is measured in bytes. If the read goes\r
324 beyond the end of the file, the read length is\r
325 truncated to the end of the file.\r
326\r
327 If This is a directory, the function reads the\r
328 directory entry at the current position and\r
329 returns the entry (as EFI_FILE_INFO) in Buffer. If\r
330 there are no more directory entries, the\r
331 BufferSize is set to zero on output.\r
332\r
333 @param[out] Buffer The buffer into which the data is read.\r
334\r
335 @retval EFI_SUCCESS Data was read.\r
336 @retval EFI_NO_MEDIA The device has no medium.\r
337 @retval EFI_DEVICE_ERROR The device reported an error.\r
338 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted\r
339 file.\r
340 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond\r
341 the end of the file.\r
342 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
343 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the\r
344 current directory entry as a EFI_FILE_INFO\r
345 structure. BufferSize has been updated with the\r
346 size needed to complete the request, and the\r
347 directory position has not been advanced.\r
348**/\r
349STATIC\r
350EFI_STATUS\r
351EFIAPI\r
352StubFileRead (\r
ac0a286f
MK
353 IN EFI_FILE_PROTOCOL *This,\r
354 IN OUT UINTN *BufferSize,\r
355 OUT VOID *Buffer\r
57f9b7f8
AB
356 )\r
357{\r
ac0a286f
MK
358 STUB_FILE *StubFile;\r
359 CONST KERNEL_BLOB *Blob;\r
360 UINT64 Left;\r
57f9b7f8
AB
361\r
362 StubFile = STUB_FILE_FROM_FILE (This);\r
363\r
364 //\r
365 // Scanning the root directory?\r
366 //\r
367 if (StubFile->BlobType == KernelBlobTypeMax) {\r
ac0a286f 368 EFI_STATUS Status;\r
57f9b7f8
AB
369\r
370 if (StubFile->Position == KernelBlobTypeMax) {\r
371 //\r
372 // Scanning complete.\r
373 //\r
374 *BufferSize = 0;\r
375 return EFI_SUCCESS;\r
376 }\r
377\r
378 Status = ConvertKernelBlobTypeToFileInfo (\r
379 (KERNEL_BLOB_TYPE)StubFile->Position,\r
380 BufferSize,\r
ac0a286f
MK
381 Buffer\r
382 );\r
57f9b7f8
AB
383 if (EFI_ERROR (Status)) {\r
384 return Status;\r
385 }\r
386\r
387 ++StubFile->Position;\r
388 return EFI_SUCCESS;\r
389 }\r
390\r
391 //\r
392 // Reading a file.\r
393 //\r
394 Blob = &mKernelBlob[StubFile->BlobType];\r
395 if (StubFile->Position > Blob->Size) {\r
396 return EFI_DEVICE_ERROR;\r
397 }\r
398\r
399 Left = Blob->Size - StubFile->Position;\r
400 if (*BufferSize > Left) {\r
401 *BufferSize = (UINTN)Left;\r
402 }\r
ac0a286f 403\r
57f9b7f8
AB
404 if (Blob->Data != NULL) {\r
405 CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);\r
406 }\r
ac0a286f 407\r
57f9b7f8
AB
408 StubFile->Position += *BufferSize;\r
409 return EFI_SUCCESS;\r
410}\r
411\r
57f9b7f8
AB
412/**\r
413 Writes data to a file.\r
414\r
415 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
416 is the file handle to write data to.\r
417\r
418 @param[in,out] BufferSize On input, the size of the Buffer. On output, the\r
419 amount of data actually written. In both cases,\r
420 the size is measured in bytes.\r
421\r
422 @param[in] Buffer The buffer of data to write.\r
423\r
424 @retval EFI_SUCCESS Data was written.\r
425 @retval EFI_UNSUPPORTED Writes to open directory files are not\r
426 supported.\r
427 @retval EFI_NO_MEDIA The device has no medium.\r
428 @retval EFI_DEVICE_ERROR The device reported an error.\r
429 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.\r
430 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
431 @retval EFI_WRITE_PROTECTED The file or medium is write-protected.\r
432 @retval EFI_ACCESS_DENIED The file was opened read only.\r
433 @retval EFI_VOLUME_FULL The volume is full.\r
434**/\r
435STATIC\r
436EFI_STATUS\r
437EFIAPI\r
438StubFileWrite (\r
ac0a286f
MK
439 IN EFI_FILE_PROTOCOL *This,\r
440 IN OUT UINTN *BufferSize,\r
441 IN VOID *Buffer\r
57f9b7f8
AB
442 )\r
443{\r
ac0a286f 444 STUB_FILE *StubFile;\r
57f9b7f8
AB
445\r
446 StubFile = STUB_FILE_FROM_FILE (This);\r
447 return (StubFile->BlobType == KernelBlobTypeMax) ?\r
448 EFI_UNSUPPORTED :\r
449 EFI_WRITE_PROTECTED;\r
450}\r
451\r
57f9b7f8
AB
452/**\r
453 Returns a file's current position.\r
454\r
455 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
456 file handle to get the current position on.\r
457\r
458 @param[out] Position The address to return the file's current position\r
459 value.\r
460\r
461 @retval EFI_SUCCESS The position was returned.\r
462 @retval EFI_UNSUPPORTED The request is not valid on open directories.\r
463 @retval EFI_DEVICE_ERROR An attempt was made to get the position from a\r
464 deleted file.\r
465**/\r
466STATIC\r
467EFI_STATUS\r
468EFIAPI\r
469StubFileGetPosition (\r
ac0a286f
MK
470 IN EFI_FILE_PROTOCOL *This,\r
471 OUT UINT64 *Position\r
57f9b7f8
AB
472 )\r
473{\r
ac0a286f 474 STUB_FILE *StubFile;\r
57f9b7f8
AB
475\r
476 StubFile = STUB_FILE_FROM_FILE (This);\r
477 if (StubFile->BlobType == KernelBlobTypeMax) {\r
478 return EFI_UNSUPPORTED;\r
479 }\r
480\r
481 *Position = StubFile->Position;\r
482 return EFI_SUCCESS;\r
483}\r
484\r
57f9b7f8
AB
485/**\r
486 Sets a file's current position.\r
487\r
488 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
489 file handle to set the requested position on.\r
490\r
491 @param[in] Position The byte position from the start of the file to set. For\r
492 regular files, MAX_UINT64 means "seek to end". For\r
493 directories, zero means "rewind directory scan".\r
494\r
495 @retval EFI_SUCCESS The position was set.\r
496 @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open\r
497 directories.\r
498 @retval EFI_DEVICE_ERROR An attempt was made to set the position of a\r
499 deleted file.\r
500**/\r
501STATIC\r
502EFI_STATUS\r
503EFIAPI\r
504StubFileSetPosition (\r
ac0a286f
MK
505 IN EFI_FILE_PROTOCOL *This,\r
506 IN UINT64 Position\r
57f9b7f8
AB
507 )\r
508{\r
ac0a286f
MK
509 STUB_FILE *StubFile;\r
510 KERNEL_BLOB *Blob;\r
57f9b7f8
AB
511\r
512 StubFile = STUB_FILE_FROM_FILE (This);\r
513\r
514 if (StubFile->BlobType == KernelBlobTypeMax) {\r
515 if (Position == 0) {\r
516 //\r
517 // rewinding a directory scan is allowed\r
518 //\r
519 StubFile->Position = 0;\r
520 return EFI_SUCCESS;\r
521 }\r
ac0a286f 522\r
57f9b7f8
AB
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 //\r
527 // regular file seek\r
528 //\r
529 Blob = &mKernelBlob[StubFile->BlobType];\r
530 if (Position == MAX_UINT64) {\r
531 //\r
532 // seek to end\r
533 //\r
534 StubFile->Position = Blob->Size;\r
535 } else {\r
536 //\r
537 // absolute seek from beginning -- seeking past the end is allowed\r
538 //\r
539 StubFile->Position = Position;\r
540 }\r
ac0a286f 541\r
57f9b7f8
AB
542 return EFI_SUCCESS;\r
543}\r
544\r
57f9b7f8
AB
545/**\r
546 Returns information about a file.\r
547\r
548 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance\r
549 that is the file handle the requested\r
550 information is for.\r
551\r
552 @param[in] InformationType The type identifier GUID for the information\r
553 being requested. The following information\r
554 types are supported, storing the\r
555 corresponding structures in Buffer:\r
556\r
557 - gEfiFileInfoGuid: EFI_FILE_INFO\r
558\r
559 - gEfiFileSystemInfoGuid:\r
560 EFI_FILE_SYSTEM_INFO\r
561\r
562 - gEfiFileSystemVolumeLabelInfoIdGuid:\r
563 EFI_FILE_SYSTEM_VOLUME_LABEL\r
564\r
565 @param[in,out] BufferSize On input, the size of Buffer. On output, the\r
566 amount of data returned in Buffer. In both\r
567 cases, the size is measured in bytes.\r
568\r
569 @param[out] Buffer A pointer to the data buffer to return. The\r
570 buffer's type is indicated by\r
571 InformationType.\r
572\r
573 @retval EFI_SUCCESS The information was returned.\r
574 @retval EFI_UNSUPPORTED The InformationType is not known.\r
575 @retval EFI_NO_MEDIA The device has no medium.\r
576 @retval EFI_DEVICE_ERROR The device reported an error.\r
577 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
578 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the\r
579 information structure requested by\r
580 InformationType. BufferSize has been updated\r
581 with the size needed to complete the request.\r
582**/\r
583STATIC\r
584EFI_STATUS\r
585EFIAPI\r
586StubFileGetInfo (\r
ac0a286f
MK
587 IN EFI_FILE_PROTOCOL *This,\r
588 IN EFI_GUID *InformationType,\r
589 IN OUT UINTN *BufferSize,\r
590 OUT VOID *Buffer\r
57f9b7f8
AB
591 )\r
592{\r
ac0a286f
MK
593 CONST STUB_FILE *StubFile;\r
594 UINTN OriginalBufferSize;\r
57f9b7f8
AB
595\r
596 StubFile = STUB_FILE_FROM_FILE (This);\r
597\r
598 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
ac0a286f
MK
599 return ConvertKernelBlobTypeToFileInfo (\r
600 StubFile->BlobType,\r
601 BufferSize,\r
602 Buffer\r
603 );\r
57f9b7f8
AB
604 }\r
605\r
606 OriginalBufferSize = *BufferSize;\r
607\r
608 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
ac0a286f 609 EFI_FILE_SYSTEM_INFO *FileSystemInfo;\r
57f9b7f8
AB
610\r
611 *BufferSize = sizeof *FileSystemInfo;\r
612 if (OriginalBufferSize < *BufferSize) {\r
613 return EFI_BUFFER_TOO_SMALL;\r
614 }\r
615\r
616 FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
617 FileSystemInfo->Size = sizeof *FileSystemInfo;\r
618 FileSystemInfo->ReadOnly = TRUE;\r
619 FileSystemInfo->VolumeSize = mTotalBlobBytes;\r
620 FileSystemInfo->FreeSpace = 0;\r
621 FileSystemInfo->BlockSize = 1;\r
622 FileSystemInfo->VolumeLabel[0] = L'\0';\r
623\r
624 return EFI_SUCCESS;\r
625 }\r
626\r
627 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
ac0a286f 628 EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;\r
57f9b7f8
AB
629\r
630 *BufferSize = sizeof *FileSystemVolumeLabel;\r
631 if (OriginalBufferSize < *BufferSize) {\r
632 return EFI_BUFFER_TOO_SMALL;\r
633 }\r
634\r
ac0a286f 635 FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;\r
57f9b7f8
AB
636 FileSystemVolumeLabel->VolumeLabel[0] = L'\0';\r
637\r
638 return EFI_SUCCESS;\r
639 }\r
640\r
641 return EFI_UNSUPPORTED;\r
642}\r
643\r
57f9b7f8
AB
644/**\r
645 Sets information about a file.\r
646\r
647 @param[in] File A pointer to the EFI_FILE_PROTOCOL instance that\r
648 is the file handle the information is for.\r
649\r
650 @param[in] InformationType The type identifier for the information being\r
651 set.\r
652\r
653 @param[in] BufferSize The size, in bytes, of Buffer.\r
654\r
655 @param[in] Buffer A pointer to the data buffer to write. The\r
656 buffer's type is indicated by InformationType.\r
657\r
658 @retval EFI_SUCCESS The information was set.\r
659 @retval EFI_UNSUPPORTED The InformationType is not known.\r
660 @retval EFI_NO_MEDIA The device has no medium.\r
661 @retval EFI_DEVICE_ERROR The device reported an error.\r
662 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
663 @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the\r
664 media is read-only.\r
665 @retval EFI_WRITE_PROTECTED InformationType is\r
666 EFI_FILE_PROTOCOL_SYSTEM_INFO_ID and the media\r
667 is read only.\r
668 @retval EFI_WRITE_PROTECTED InformationType is\r
669 EFI_FILE_SYSTEM_VOLUME_LABEL_ID and the media\r
670 is read-only.\r
671 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
672 to a file that is already present.\r
673 @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
674 EFI_FILE_DIRECTORY Attribute.\r
675 @retval EFI_ACCESS_DENIED An attempt is being made to change the size of\r
676 a directory.\r
677 @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the\r
678 file was opened read-only and an attempt is\r
679 being made to modify a field other than\r
680 Attribute.\r
681 @retval EFI_VOLUME_FULL The volume is full.\r
682 @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type\r
683 indicated by InformationType.\r
684**/\r
685STATIC\r
686EFI_STATUS\r
687EFIAPI\r
688StubFileSetInfo (\r
ac0a286f
MK
689 IN EFI_FILE_PROTOCOL *This,\r
690 IN EFI_GUID *InformationType,\r
691 IN UINTN BufferSize,\r
692 IN VOID *Buffer\r
57f9b7f8
AB
693 )\r
694{\r
695 return EFI_WRITE_PROTECTED;\r
696}\r
697\r
57f9b7f8
AB
698/**\r
699 Flushes all modified data associated with a file to a device.\r
700\r
701 @param [in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
702 file handle to flush.\r
703\r
704 @retval EFI_SUCCESS The data was flushed.\r
705 @retval EFI_NO_MEDIA The device has no medium.\r
706 @retval EFI_DEVICE_ERROR The device reported an error.\r
707 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
708 @retval EFI_WRITE_PROTECTED The file or medium is write-protected.\r
709 @retval EFI_ACCESS_DENIED The file was opened read-only.\r
710 @retval EFI_VOLUME_FULL The volume is full.\r
711**/\r
712STATIC\r
713EFI_STATUS\r
714EFIAPI\r
715StubFileFlush (\r
ac0a286f 716 IN EFI_FILE_PROTOCOL *This\r
57f9b7f8
AB
717 )\r
718{\r
719 return EFI_WRITE_PROTECTED;\r
720}\r
721\r
722//\r
723// External definition of the file protocol template.\r
724//\r
ac0a286f 725STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {\r
57f9b7f8
AB
726 EFI_FILE_PROTOCOL_REVISION, // revision 1\r
727 StubFileOpen,\r
728 StubFileClose,\r
729 StubFileDelete,\r
730 StubFileRead,\r
731 StubFileWrite,\r
732 StubFileGetPosition,\r
733 StubFileSetPosition,\r
734 StubFileGetInfo,\r
735 StubFileSetInfo,\r
736 StubFileFlush,\r
737 NULL, // OpenEx, revision 2\r
738 NULL, // ReadEx, revision 2\r
739 NULL, // WriteEx, revision 2\r
740 NULL // FlushEx, revision 2\r
741};\r
742\r
40d572f7
AB
743STATIC\r
744EFI_STATUS\r
745EFIAPI\r
746StubFileOpen (\r
ac0a286f
MK
747 IN EFI_FILE_PROTOCOL *This,\r
748 OUT EFI_FILE_PROTOCOL **NewHandle,\r
749 IN CHAR16 *FileName,\r
750 IN UINT64 OpenMode,\r
751 IN UINT64 Attributes\r
40d572f7
AB
752 )\r
753{\r
ac0a286f
MK
754 CONST STUB_FILE *StubFile;\r
755 UINTN BlobType;\r
756 STUB_FILE *NewStubFile;\r
40d572f7
AB
757\r
758 //\r
759 // We're read-only.\r
760 //\r
761 switch (OpenMode) {\r
762 case EFI_FILE_MODE_READ:\r
763 break;\r
764\r
765 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
766 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r
767 return EFI_WRITE_PROTECTED;\r
768\r
769 default:\r
770 return EFI_INVALID_PARAMETER;\r
771 }\r
772\r
773 //\r
774 // Only the root directory supports opening files in it.\r
775 //\r
776 StubFile = STUB_FILE_FROM_FILE (This);\r
777 if (StubFile->BlobType != KernelBlobTypeMax) {\r
778 return EFI_UNSUPPORTED;\r
779 }\r
780\r
781 //\r
782 // Locate the file.\r
783 //\r
784 for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
785 if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {\r
786 break;\r
787 }\r
788 }\r
ac0a286f 789\r
40d572f7
AB
790 if (BlobType == KernelBlobTypeMax) {\r
791 return EFI_NOT_FOUND;\r
792 }\r
793\r
794 //\r
795 // Found it.\r
796 //\r
797 NewStubFile = AllocatePool (sizeof *NewStubFile);\r
798 if (NewStubFile == NULL) {\r
799 return EFI_OUT_OF_RESOURCES;\r
800 }\r
801\r
802 NewStubFile->Signature = STUB_FILE_SIG;\r
803 NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType;\r
804 NewStubFile->Position = 0;\r
ac0a286f
MK
805 CopyMem (\r
806 &NewStubFile->File,\r
807 &mEfiFileProtocolTemplate,\r
808 sizeof mEfiFileProtocolTemplate\r
809 );\r
40d572f7
AB
810 *NewHandle = &NewStubFile->File;\r
811\r
812 return EFI_SUCCESS;\r
813}\r
814\r
57f9b7f8
AB
815//\r
816// Protocol member functions for SimpleFileSystem.\r
817//\r
818\r
819/**\r
820 Open the root directory on a volume.\r
821\r
822 @param[in] This A pointer to the volume to open the root directory on.\r
823\r
824 @param[out] Root A pointer to the location to return the opened file handle\r
825 for the root directory in.\r
826\r
827 @retval EFI_SUCCESS The device was opened.\r
828 @retval EFI_UNSUPPORTED This volume does not support the requested file\r
829 system type.\r
830 @retval EFI_NO_MEDIA The device has no medium.\r
831 @retval EFI_DEVICE_ERROR The device reported an error.\r
832 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
833 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
834 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
835 resources.\r
836 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
837 medium is no longer supported. Any existing\r
838 file handles for this volume are no longer\r
839 valid. To access the files on the new medium,\r
840 the volume must be reopened with OpenVolume().\r
841**/\r
842STATIC\r
843EFI_STATUS\r
844EFIAPI\r
845StubFileSystemOpenVolume (\r
ac0a286f
MK
846 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
847 OUT EFI_FILE_PROTOCOL **Root\r
57f9b7f8
AB
848 )\r
849{\r
ac0a286f 850 STUB_FILE *StubFile;\r
57f9b7f8
AB
851\r
852 StubFile = AllocatePool (sizeof *StubFile);\r
853 if (StubFile == NULL) {\r
854 return EFI_OUT_OF_RESOURCES;\r
855 }\r
856\r
857 StubFile->Signature = STUB_FILE_SIG;\r
858 StubFile->BlobType = KernelBlobTypeMax;\r
859 StubFile->Position = 0;\r
ac0a286f
MK
860 CopyMem (\r
861 &StubFile->File,\r
862 &mEfiFileProtocolTemplate,\r
863 sizeof mEfiFileProtocolTemplate\r
864 );\r
57f9b7f8
AB
865 *Root = &StubFile->File;\r
866\r
867 return EFI_SUCCESS;\r
868}\r
869\r
ac0a286f 870STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {\r
57f9b7f8
AB
871 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
872 StubFileSystemOpenVolume\r
873};\r
874\r
f98608ab
AB
875STATIC\r
876EFI_STATUS\r
877EFIAPI\r
878InitrdLoadFile2 (\r
ac0a286f
MK
879 IN EFI_LOAD_FILE2_PROTOCOL *This,\r
880 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
881 IN BOOLEAN BootPolicy,\r
882 IN OUT UINTN *BufferSize,\r
883 OUT VOID *Buffer OPTIONAL\r
f98608ab
AB
884 )\r
885{\r
ac0a286f 886 CONST KERNEL_BLOB *InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];\r
f98608ab
AB
887\r
888 ASSERT (InitrdBlob->Size > 0);\r
889\r
890 if (BootPolicy) {\r
891 return EFI_UNSUPPORTED;\r
892 }\r
893\r
ac0a286f 894 if ((BufferSize == NULL) || !IsDevicePathValid (FilePath, 0)) {\r
f98608ab
AB
895 return EFI_INVALID_PARAMETER;\r
896 }\r
897\r
ac0a286f
MK
898 if ((FilePath->Type != END_DEVICE_PATH_TYPE) ||\r
899 (FilePath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE))\r
900 {\r
f98608ab
AB
901 return EFI_NOT_FOUND;\r
902 }\r
903\r
ac0a286f 904 if ((Buffer == NULL) || (*BufferSize < InitrdBlob->Size)) {\r
f98608ab
AB
905 *BufferSize = InitrdBlob->Size;\r
906 return EFI_BUFFER_TOO_SMALL;\r
907 }\r
908\r
909 CopyMem (Buffer, InitrdBlob->Data, InitrdBlob->Size);\r
910\r
911 *BufferSize = InitrdBlob->Size;\r
912 return EFI_SUCCESS;\r
913}\r
914\r
ac0a286f 915STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {\r
f98608ab
AB
916 InitrdLoadFile2,\r
917};\r
57f9b7f8
AB
918\r
919//\r
920// Utility functions.\r
921//\r
922\r
923/**\r
924 Populate a blob in mKernelBlob.\r
925\r
926 param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is\r
927 to be filled from fw_cfg.\r
928\r
929 @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a\r
930 size of zero for the blob, then Blob->Data has\r
931 been left unchanged.\r
932\r
933 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Blob->Data.\r
934**/\r
935STATIC\r
936EFI_STATUS\r
937FetchBlob (\r
ac0a286f 938 IN OUT KERNEL_BLOB *Blob\r
57f9b7f8
AB
939 )\r
940{\r
ac0a286f
MK
941 UINT32 Left;\r
942 UINTN Idx;\r
943 UINT8 *ChunkData;\r
57f9b7f8
AB
944\r
945 //\r
946 // Read blob size.\r
947 //\r
0758a8e9
AB
948 Blob->Size = 0;\r
949 for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {\r
950 if (Blob->FwCfgItem[Idx].SizeKey == 0) {\r
951 break;\r
952 }\r
ac0a286f 953\r
0758a8e9
AB
954 QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].SizeKey);\r
955 Blob->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();\r
ac0a286f 956 Blob->Size += Blob->FwCfgItem[Idx].Size;\r
0758a8e9 957 }\r
ac0a286f 958\r
57f9b7f8
AB
959 if (Blob->Size == 0) {\r
960 return EFI_SUCCESS;\r
961 }\r
962\r
963 //\r
964 // Read blob.\r
965 //\r
24b0e9d1 966 Blob->Data = AllocatePool (Blob->Size);\r
57f9b7f8 967 if (Blob->Data == NULL) {\r
ac0a286f
MK
968 DEBUG ((\r
969 DEBUG_ERROR,\r
970 "%a: failed to allocate %Ld bytes for \"%s\"\n",\r
971 __FUNCTION__,\r
972 (INT64)Blob->Size,\r
973 Blob->Name\r
974 ));\r
57f9b7f8
AB
975 return EFI_OUT_OF_RESOURCES;\r
976 }\r
977\r
ac0a286f
MK
978 DEBUG ((\r
979 DEBUG_INFO,\r
980 "%a: loading %Ld bytes for \"%s\"\n",\r
981 __FUNCTION__,\r
982 (INT64)Blob->Size,\r
983 Blob->Name\r
984 ));\r
0758a8e9
AB
985\r
986 ChunkData = Blob->Data;\r
987 for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {\r
988 if (Blob->FwCfgItem[Idx].DataKey == 0) {\r
989 break;\r
990 }\r
ac0a286f 991\r
0758a8e9
AB
992 QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].DataKey);\r
993\r
994 Left = Blob->FwCfgItem[Idx].Size;\r
995 while (Left > 0) {\r
ac0a286f 996 UINT32 Chunk;\r
0758a8e9
AB
997\r
998 Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB;\r
999 QemuFwCfgReadBytes (Chunk, ChunkData + Blob->FwCfgItem[Idx].Size - Left);\r
1000 Left -= Chunk;\r
ac0a286f
MK
1001 DEBUG ((\r
1002 DEBUG_VERBOSE,\r
1003 "%a: %Ld bytes remaining for \"%s\" (%d)\n",\r
1004 __FUNCTION__,\r
1005 (INT64)Left,\r
1006 Blob->Name,\r
1007 (INT32)Idx\r
1008 ));\r
0758a8e9
AB
1009 }\r
1010\r
1011 ChunkData += Blob->FwCfgItem[Idx].Size;\r
1012 }\r
1013\r
57f9b7f8
AB
1014 return EFI_SUCCESS;\r
1015}\r
1016\r
57f9b7f8
AB
1017//\r
1018// The entry point of the feature.\r
1019//\r
1020\r
1021/**\r
1022 Download the kernel, the initial ramdisk, and the kernel command line from\r
1023 QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
1024 image files.\r
1025\r
1026 @retval EFI_NOT_FOUND Kernel image was not found.\r
1027 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1028 @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.\r
1029\r
1030 @return Error codes from any of the underlying\r
1031 functions. On success, the function doesn't\r
1032 return.\r
1033**/\r
1034EFI_STATUS\r
1035EFIAPI\r
1036QemuKernelLoaderFsDxeEntrypoint (\r
ac0a286f
MK
1037 IN EFI_HANDLE ImageHandle,\r
1038 IN EFI_SYSTEM_TABLE *SystemTable\r
57f9b7f8
AB
1039 )\r
1040{\r
ac0a286f
MK
1041 UINTN BlobType;\r
1042 KERNEL_BLOB *CurrentBlob;\r
1043 KERNEL_BLOB *KernelBlob;\r
1044 EFI_STATUS Status;\r
1045 EFI_HANDLE FileSystemHandle;\r
1046 EFI_HANDLE InitrdLoadFile2Handle;\r
57f9b7f8
AB
1047\r
1048 if (!QemuFwCfgIsAvailable ()) {\r
1049 return EFI_NOT_FOUND;\r
1050 }\r
1051\r
1052 Status = gRT->GetTime (&mInitTime, NULL /* Capabilities */);\r
1053 if (EFI_ERROR (Status)) {\r
1054 DEBUG ((DEBUG_ERROR, "%a: GetTime(): %r\n", __FUNCTION__, Status));\r
1055 return Status;\r
1056 }\r
1057\r
1058 //\r
1059 // Fetch all blobs.\r
1060 //\r
1061 for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
1062 CurrentBlob = &mKernelBlob[BlobType];\r
ac0a286f 1063 Status = FetchBlob (CurrentBlob);\r
57f9b7f8
AB
1064 if (EFI_ERROR (Status)) {\r
1065 goto FreeBlobs;\r
1066 }\r
ac0a286f 1067\r
d10ad844
DM
1068 Status = VerifyBlob (\r
1069 CurrentBlob->Name,\r
1070 CurrentBlob->Data,\r
1071 CurrentBlob->Size\r
1072 );\r
1073 if (EFI_ERROR (Status)) {\r
1074 goto FreeBlobs;\r
1075 }\r
ac0a286f 1076\r
57f9b7f8
AB
1077 mTotalBlobBytes += CurrentBlob->Size;\r
1078 }\r
ac0a286f
MK
1079\r
1080 KernelBlob = &mKernelBlob[KernelBlobTypeKernel];\r
57f9b7f8
AB
1081\r
1082 if (KernelBlob->Data == NULL) {\r
1083 Status = EFI_NOT_FOUND;\r
1084 goto FreeBlobs;\r
1085 }\r
1086\r
1087 //\r
1088 // Create a new handle with a single VenMedia() node device path protocol on\r
1089 // it, plus a custom SimpleFileSystem protocol on it.\r
1090 //\r
1091 FileSystemHandle = NULL;\r
ac0a286f
MK
1092 Status = gBS->InstallMultipleProtocolInterfaces (\r
1093 &FileSystemHandle,\r
1094 &gEfiDevicePathProtocolGuid,\r
1095 &mFileSystemDevicePath,\r
1096 &gEfiSimpleFileSystemProtocolGuid,\r
1097 &mFileSystem,\r
1098 NULL\r
1099 );\r
57f9b7f8 1100 if (EFI_ERROR (Status)) {\r
ac0a286f
MK
1101 DEBUG ((\r
1102 DEBUG_ERROR,\r
1103 "%a: InstallMultipleProtocolInterfaces(): %r\n",\r
1104 __FUNCTION__,\r
1105 Status\r
1106 ));\r
57f9b7f8
AB
1107 goto FreeBlobs;\r
1108 }\r
1109\r
f98608ab
AB
1110 if (KernelBlob[KernelBlobTypeInitrd].Size > 0) {\r
1111 InitrdLoadFile2Handle = NULL;\r
ac0a286f
MK
1112 Status = gBS->InstallMultipleProtocolInterfaces (\r
1113 &InitrdLoadFile2Handle,\r
1114 &gEfiDevicePathProtocolGuid,\r
1115 &mInitrdDevicePath,\r
1116 &gEfiLoadFile2ProtocolGuid,\r
1117 &mInitrdLoadFile2,\r
1118 NULL\r
1119 );\r
f98608ab 1120 if (EFI_ERROR (Status)) {\r
ac0a286f
MK
1121 DEBUG ((\r
1122 DEBUG_ERROR,\r
1123 "%a: InstallMultipleProtocolInterfaces(): %r\n",\r
1124 __FUNCTION__,\r
1125 Status\r
1126 ));\r
f98608ab
AB
1127 goto UninstallFileSystemHandle;\r
1128 }\r
1129 }\r
1130\r
57f9b7f8
AB
1131 return EFI_SUCCESS;\r
1132\r
f98608ab 1133UninstallFileSystemHandle:\r
ac0a286f
MK
1134 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1135 FileSystemHandle,\r
1136 &gEfiDevicePathProtocolGuid,\r
1137 &mFileSystemDevicePath,\r
1138 &gEfiSimpleFileSystemProtocolGuid,\r
1139 &mFileSystem,\r
1140 NULL\r
1141 );\r
f98608ab
AB
1142 ASSERT_EFI_ERROR (Status);\r
1143\r
57f9b7f8
AB
1144FreeBlobs:\r
1145 while (BlobType > 0) {\r
1146 CurrentBlob = &mKernelBlob[--BlobType];\r
1147 if (CurrentBlob->Data != NULL) {\r
24b0e9d1 1148 FreePool (CurrentBlob->Data);\r
57f9b7f8
AB
1149 CurrentBlob->Size = 0;\r
1150 CurrentBlob->Data = NULL;\r
1151 }\r
1152 }\r
1153\r
1154 return Status;\r
1155}\r