From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 91C3B20D77DC6 for ; Thu, 6 Apr 2017 19:49:43 -0700 (PDT) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP; 06 Apr 2017 19:49:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,162,1488873600"; d="scan'208";a="74793339" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga004.jf.intel.com with ESMTP; 06 Apr 2017 19:49:41 -0700 Received: from fmsmsx151.amr.corp.intel.com (10.18.125.4) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 6 Apr 2017 19:49:21 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by FMSMSX151.amr.corp.intel.com (10.18.125.4) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 6 Apr 2017 19:49:14 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.193]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.217]) with mapi id 14.03.0319.002; Fri, 7 Apr 2017 10:48:05 +0800 From: "Tian, Feng" To: "Ni, Ruiyu" , "edk2-devel@lists.01.org" CC: "Dong, Eric" , "Fan, Jeff" , "Tian, Feng" Thread-Topic: [PATCH] MdeModulePkg/UefiBootManagerLib: Enhance short-form expanding logic Thread-Index: AQHSrrp1EQ7pJKBS8UiykDkLhlpRQ6G5NTxQ Date: Fri, 7 Apr 2017 02:48:04 +0000 Message-ID: <7F1BAD85ADEA444D97065A60D2E97EE5699E1A53@SHSMSX101.ccr.corp.intel.com> References: <20170406094446.211852-1-ruiyu.ni@intel.com> In-Reply-To: <20170406094446.211852-1-ruiyu.ni@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH] MdeModulePkg/UefiBootManagerLib: Enhance short-form expanding logic X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 Apr 2017 02:49:43 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Feng Tian Thanks Feng -----Original Message----- From: Ni, Ruiyu=20 Sent: Thursday, April 6, 2017 5:45 PM To: edk2-devel@lists.01.org Cc: Tian, Feng ; Dong, Eric ; Fan= , Jeff Subject: [PATCH] MdeModulePkg/UefiBootManagerLib: Enhance short-form expand= ing logic Old implementation only finds first matched full device path for a given sh= ort-form device path. The patch adds internal function BmGetNextLoadOptionBuffer() to finds all m= atched full device path for a given short-form device path. There are 6 kinds of device paths. Some of them match to multiple load opti= ons, some of them don't. 1. Media device path: Returns multiple load options: The media device path may point to a physical BlockIo which contains multiple logic partitions, each logic partitions contains \EFI\BOOT\BOOT${ARCH}.EFI. 2. Short-form hard-drive device path: Returns one load option because the partition signature is unique. 3. Short-form file-path device path: Returns multiple load options: There are multiple SimpleFileSystem instances and each contains the same file. 4. Short-form URI device path: Returns multiple load options: There are multiple LoadFile instances and each can boot. 5. Short-form USB device path: Returns multiple load options: There are multiple UsbIo instances and each contains the boot-able file. 6. FV device path, device path pointing to SimpleFileSystem, device path pointing to LoadFile Returns one load option. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni Cc: Feng Tian Cc: Eric Dong Cc: Jeff Fan --- MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 470 ++++++++++++-----= ---- .../Library/UefiBootManagerLib/BmLoadOption.c | 173 ++++++-- .../Library/UefiBootManagerLib/InternalBm.h | 100 +++-- 3 files changed, 475 insertions(+), 268 deletions(-) diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePk= g/Library/UefiBootManagerLib/BmBoot.c index 8a3a402..aa79c90 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -131,21 +131,16 @@ BmFindBootOptionInVariable ( } =20 /** - Get the file buffer using a Memory Mapped Device Path. - + Return the correct FV file path. FV address may change across reboot. This routine promises the FV file d= evice path is right. =20 @param FilePath The Memory Mapped Device Path to get the file buffe= r. - @param FullPath Receive the updated FV Device Path pointint to the = file. - @param FileSize Receive the file buffer size. =20 - @return The file buffer. + @return The updated FV Device Path pointint to the file. **/ -VOID * -BmGetFileBufferByFvFilePath ( - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize +EFI_DEVICE_PATH_PROTOCOL * +BmAdjustFvFilePath ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; @@ -153,11 +148,10 @@ BmGetFileBufferByFvFilePath ( EFI_DEVICE_PATH_PROTOCOL *FvFileNode; EFI_HANDLE FvHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - UINT32 AuthenticationStatus; UINTN FvHandleCount; EFI_HANDLE *FvHandles; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; - VOID *FileBuffer; + EFI_DEVICE_PATH_PROTOCOL *FullPath; =20 // // Get the file buffer by using the exactly FilePath. @@ -165,11 +159,7 @@ BmGetFileBufferByFvFilePath ( FvFileNode =3D FilePath; Status =3D gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvF= ileNode, &FvHandle); if (!EFI_ERROR (Status)) { - FileBuffer =3D GetFileBufferByFilePath (TRUE, FilePath, FileSize, &Aut= henticationStatus); - if (FileBuffer !=3D NULL) { - *FullPath =3D DuplicateDevicePath (FilePath); - } - return FileBuffer; + return DuplicateDevicePath (FilePath); } =20 // @@ -190,11 +180,10 @@ BmGetFileBufferByFvFilePath ( (VOID **) &LoadedImage ); NewDevicePath =3D AppendDevicePathNode (DevicePathFromHandle (LoadedImag= e->DeviceHandle), FvFileNode); - FileBuffer =3D BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, Fil= eSize); + FullPath =3D BmAdjustFvFilePath (NewDevicePath); FreePool (NewDevicePath); - - if (FileBuffer !=3D NULL) { - return FileBuffer; + if (FullPath !=3D NULL) { + return FullPath; } =20 // @@ -207,22 +196,25 @@ BmGetFileBufferByFvFilePath ( &FvHandleCount, &FvHandles ); - for (Index =3D 0; (Index < FvHandleCount) && (FileBuffer =3D=3D NULL); I= ndex++) { + for (Index =3D 0; Index < FvHandleCount; Index++) { if (FvHandles[Index] =3D=3D LoadedImage->DeviceHandle) { // - // Skip current FV + // Skip current FV, it was handed in first step. // continue; } NewDevicePath =3D AppendDevicePathNode (DevicePathFromHandle (FvHandle= s[Index]), FvFileNode); - FileBuffer =3D BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, F= ileSize); + FullPath =3D BmAdjustFvFilePath (NewDevicePath); FreePool (NewDevicePath); + if (FullPath !=3D NULL) { + break; + } } =20 if (FvHandles !=3D NULL) { FreePool (FvHandles); } - return FileBuffer; + return FullPath; } =20 /** @@ -555,46 +547,64 @@ BmFindUsbDevice ( =20 @param FilePath The device path pointing to a load option. It could be a short-form device path. - @param FullPath Return the full device path of the load option afte= r - short-form device path expanding. - Caller is responsible to free it. - @param FileSize Return the load option size. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. @param ShortformNode Pointer to the USB short-form device path node in t= he FilePath buffer. =20 - @return The load option buffer. Caller is responsible to free the memory= . + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. **/ -VOID * +EFI_DEVICE_PATH_PROTOCOL * BmExpandUsbDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize, - IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode + IN EFI_DEVICE_PATH_PROTOCOL *FullPath, IN =20 + EFI_DEVICE_PATH_PROTOCOL *ShortformNode ) { UINTN ParentDevicePathSize; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; - EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextFullPath; EFI_HANDLE *Handles; UINTN HandleCount; UINTN Index; - VOID *FileBuffer; + BOOLEAN GetNext; =20 + NextFullPath =3D NULL; + GetNext =3D (BOOLEAN)(FullPath =3D=3D NULL); ParentDevicePathSize =3D (UINTN) ShortformNode - (UINTN) FilePath; RemainingDevicePath =3D NextDevicePathNode (ShortformNode); - FileBuffer =3D NULL; Handles =3D BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCoun= t); =20 - for (Index =3D 0; (Index < HandleCount) && (FileBuffer =3D=3D NULL); Ind= ex++) { - FullDevicePath =3D AppendDevicePath (DevicePathFromHandle (Handles[Ind= ex]), RemainingDevicePath); - FileBuffer =3D EfiBootManagerGetLoadOptionBuffer (FullDevicePath, Full= Path, FileSize); - FreePool (FullDevicePath); + for (Index =3D 0; Index < HandleCount; Index++) { + FilePath =3D AppendDevicePath (DevicePathFromHandle (Handles[Index]), = RemainingDevicePath); + if (FilePath =3D=3D NULL) { + // + // Out of memory. + // + continue; + } + NextFullPath =3D BmGetNextLoadOptionDevicePath (FilePath, NULL); + FreePool (FilePath); + if (NextFullPath =3D=3D NULL) { + // + // No BlockIo or SimpleFileSystem under FilePath. + // + continue; + } + if (GetNext) { + break; + } else { + GetNext =3D (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDeviceP= athSize (NextFullPath)) =3D=3D 0); + FreePool (NextFullPath); + NextFullPath =3D NULL; + } } =20 if (Handles !=3D NULL) { FreePool (Handles); } =20 - return FileBuffer; + return NextFullPath; } =20 /** @@ -602,18 +612,16 @@ BmExpandUsbDevicePath ( =20 @param FilePath The device path pointing to a load option. It could be a short-form device path. - @param FullPath Return the full device path of the load option afte= r - short-form device path expanding. - Caller is responsible to free it. - @param FileSize Return the load option size. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. =20 - @return The load option buffer. Caller is responsible to free the memory= . + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. **/ -VOID * +EFI_DEVICE_PATH_PROTOCOL * BmExpandFileDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + IN EFI_DEVICE_PATH_PROTOCOL *FullPath ) { EFI_STATUS Status; @@ -622,9 +630,8 @@ BmExpandFileDevicePath ( EFI_HANDLE *Handles; EFI_BLOCK_IO_PROTOCOL *BlockIo; UINTN MediaType; - EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; - VOID *FileBuffer; - UINT32 AuthenticationStatus; + EFI_DEVICE_PATH_PROTOCOL *NextFullPath; + BOOLEAN GetNext; =20 EfiBootManagerConnectAll (); Status =3D gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemPro= tocolGuid, NULL, &HandleCount, &Handles); @@ -633,6 +640,8 @@ BmExpandFileD= evicePath ( Handles =3D NULL; } =20 + GetNext =3D (BOOLEAN)(FullPath =3D=3D NULL); NextFullPath =3D NULL; // // Enumerate all removable media devices followed by all fixed media dev= ices, // followed by media devices which don't layer on block io. @@ -647,24 +656,26 @@ BmExpandFileDevicePath ( (MediaType =3D=3D 1 && BlockIo !=3D NULL && !BlockIo->Media->Rem= ovableMedia) || (MediaType =3D=3D 2 && BlockIo =3D=3D NULL) ) { - FullDevicePath =3D AppendDevicePath (DevicePathFromHandle (Handles= [Index]), FilePath); - FileBuffer =3D GetFileBufferByFilePath (TRUE, FullDevicePath, File= Size, &AuthenticationStatus); - if (FileBuffer !=3D NULL) { - *FullPath =3D FullDevicePath; - FreePool (Handles); - return FileBuffer; + NextFullPath =3D AppendDevicePath (DevicePathFromHandle (Handles[I= ndex]), FilePath); + if (GetNext) { + break; + } else { + GetNext =3D (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDev= icePathSize (NextFullPath)) =3D=3D 0); + FreePool (NextFullPath); + NextFullPath =3D NULL; } - FreePool (FullDevicePath); } } + if (NextFullPath !=3D NULL) { + break; + } } =20 if (Handles !=3D NULL) { FreePool (Handles); } =20 - *FullPath =3D NULL; - return NULL; + return NextFullPath; } =20 /** @@ -672,25 +683,25 @@ BmExpandFileDevicePath ( =20 @param FilePath The device path pointing to a load option. It could be a short-form device path. - @param FullPath Return the full device path of the load option afte= r - short-form device path expanding. - Caller is responsible to free it. - @param FileSize Return the load option size. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. =20 - @return The load option buffer. Caller is responsible to free the memory= . + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. **/ -VOID * +EFI_DEVICE_PATH_PROTOCOL * BmExpandUriDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + IN EFI_DEVICE_PATH_PROTOCOL *FullPath ) { EFI_STATUS Status; UINTN Index; UINTN HandleCount; EFI_HANDLE *Handles; - VOID *FileBuffer; + EFI_DEVICE_PATH_PROTOCOL *NextFullPath; + EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; + BOOLEAN GetNext; =20 EfiBootManagerConnectAll (); Status =3D gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGui= d, NULL, &HandleCount, &Handles); @@ -699,11 +710,29 @@ BmExpandUriDevicePa= th ( Handles =3D NULL; } =20 - FileBuffer =3D NULL; + NextFullPath =3D NULL; + GetNext =3D (BOOLEAN)(FullPath =3D=3D NULL); for (Index =3D 0; Index < HandleCount; Index++) { - FileBuffer =3D BmGetFileBufferFromLoadFile (Handles[Index], FilePath, = FullPath, FileSize); - if (FileBuffer !=3D NULL) { + NextFullPath =3D BmExpandLoadFile (Handles[Index], FilePath); + + if (NextFullPath =3D=3D NULL) { + continue; + } + + if (GetNext) { break; + } else { + GetNext =3D (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDeviceP= athSize (NextFullPath)) =3D=3D 0); + // + // Free the resource occupied by the RAM disk. + // + RamDiskDevicePath =3D BmGetRamDiskDevicePath (NextFullPath); + if (RamDiskDevicePath !=3D NULL) { + BmDestroyRamDisk (RamDiskDevicePath); + FreePool (RamDiskDevicePath); + } + FreePool (NextFullPath); + NextFullPath =3D NULL; } } =20 @@ -711,7 +740,7 @@ BmExpandUriDevicePath ( FreePool (Handles); } =20 - return FileBuffer; + return NextFullPath; } =20 /** @@ -781,35 +810,28 @@ BmCachePartitionDevicePath ( =20 @param FilePath The device path pointing to a load option. It could be a short-form device path. - @param FullPath Return the full device path of the load option afte= r - short-form device path expanding. - Caller is responsible to free it. - @param FileSize Return the load option size. =20 - @return The load option buffer. Caller is responsible to free the memory= . + @return The full device path pointing to the load option. **/ -VOID * +EFI_DEVICE_PATH_PROTOCOL * BmExpandPartitionDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; UINTN BlockIoHandleCount; EFI_HANDLE *BlockIoBuffer; - VOID *FileBuffer; EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FullPath; UINTN CachedDevicePathSize; BOOLEAN NeedAdjust; EFI_DEVICE_PATH_PROTOCOL *Instance; UINTN Size; =20 - FileBuffer =3D NULL; // // Check if there is prestore 'HDDP' variable. // If exist, search the front path which point to partition node in the = variable instants. @@ -833,6 +855,7 @@ BmExpandPartitionDevicePath ( ASSERT_EFI_ERROR (Status); } =20 + FullPath =3D NULL; if (CachedDevicePath !=3D NULL) { TempNewDevicePath =3D CachedDevicePath; NeedAdjust =3D FALSE; @@ -851,10 +874,20 @@ BmExpandPartitionDevicePath ( Status =3D EfiBootManagerConnectDevicePath (Instance, NULL); if (!EFI_ERROR (Status)) { TempDevicePath =3D AppendDevicePath (Instance, NextDevicePathNod= e (FilePath)); - FileBuffer =3D EfiBootManagerGetLoadOptionBuffer (TempDevicePath= , FullPath, FileSize); + // + // TempDevicePath =3D ACPI()/PCI()/ATA()/Partition() + // or =3D ACPI()/PCI()/ATA()/Partition()/.../A.EFI + // + // When TempDevicePath =3D ACPI()/PCI()/ATA()/Partition(), + // it may expand to two potienal full paths (nested partition, r= arely happen): + // 1. ACPI()/PCI()/ATA()/Partition()/Partition(A1)/EFI/BootX64= .EFI + // 2. ACPI()/PCI()/ATA()/Partition()/Partition(A2)/EFI/BootX64= .EFI + // For simplicity, only #1 is returned. + // + FullPath =3D BmGetNextLoadOptionDevicePath (TempDevicePath,=20 + NULL); FreePool (TempDevicePath); =20 - if (FileBuffer !=3D NULL) { + if (FullPath !=3D NULL) { // // Adjust the 'HDDP' instances sequence if the matched one is = not first one. // @@ -875,7 +908,7 @@ BmExpandPartitionDevicePath ( =20 FreePool (Instance); FreePool (CachedDevicePath); - return FileBuffer; + return FullPath; } } } @@ -911,10 +944,10 @@ BmExpandPartitionDevicePath ( // Find the matched partition device path // TempDevicePath =3D AppendDevicePath (BlockIoDevicePath, NextDevicePa= thNode (FilePath)); - FileBuffer =3D EfiBootManagerGetLoadOptionBuffer (TempDevicePath, Fu= llPath, FileSize); + FullPath =3D BmGetNextLoadOptionDevicePath (TempDevicePath, NULL); FreePool (TempDevicePath); =20 - if (FileBuffer !=3D NULL) { + if (FullPath !=3D NULL) { BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath); =20 // @@ -940,7 +973,7 @@ BmExpandPartitionDevicePath ( if (BlockIoBuffer !=3D NULL) { FreePool (BlockIoBuffer); } - return FileBuffer; + return FullPath; } =20 /** @@ -948,16 +981,16 @@ BmExpandPartitionDevicePath ( by appending EFI_REMOVABLE_MEDIA_FILE_NAME. =20 @param DevicePath The media device path pointing to a BlockIo or Simple= FileSystem instance. - @param FullPath Return the full device path pointing to the load opti= on. - @param FileSize Return the size of the load option. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. =20 - @return The load option buffer. + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. **/ -VOID * +EFI_DEVICE_PATH_PROTOCOL * BmExpandMediaDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + IN EFI_DEVICE_PATH_PROTOCOL *FullPath ) { EFI_STATUS Status; @@ -965,14 +998,15 @@ BmExpandMediaDevicePath ( EFI_BLOCK_IO_PROTOCOL *BlockIo; VOID *Buffer; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextFullPath; UINTN Size; UINTN TempSize; EFI_HANDLE *SimpleFileSystemHandles; UINTN NumberSimpleFileSystemHandles; UINTN Index; - VOID *FileBuffer; - UINT32 AuthenticationStatus; + BOOLEAN GetNext; =20 + GetNext =3D (BOOLEAN)(FullPath =3D=3D NULL); // // Check whether the device is connected // @@ -981,14 +1015,16 @@ BmExpandMediaDevicePath ( if (!EFI_ERROR (Status)) { ASSERT (IsDevicePathEnd (TempDevicePath)); =20 - TempDevicePath =3D FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NA= ME); - FileBuffer =3D GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize= , &AuthenticationStatus); - if (FileBuffer =3D=3D NULL) { - FreePool (TempDevicePath); - TempDevicePath =3D NULL; + NextFullPath =3D FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME= ); + // + // For device path pointing to simple file system, it only expands to = one full path. + // + if (GetNext) { + return NextFullPath; + } else { + FreePool (NextFullPath); + return NULL; } - *FullPath =3D TempDevicePath; - return FileBuffer; } =20 Status =3D gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDeviceP= ath, &Handle); @@ -1025,8 +1061,7 @@ BmExpandMediaDevicePath ( // // Detect the the default boot file from removable Media // - FileBuffer =3D NULL; - *FullPath =3D NULL; + NextFullPath =3D NULL; Size =3D GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH; gBS->LocateHandleBuffer ( ByProtocol, @@ -1045,13 +1080,14 @@ BmExpandMediaDevicePath ( // Check whether the device path of boot option is part of the SimpleF= ileSystem handle's device path // if ((Size <=3D TempSize) && (CompareMem (TempDevicePath, DevicePath, S= ize) =3D=3D 0)) { - TempDevicePath =3D FileDevicePath (SimpleFileSystemHandles[Index], E= FI_REMOVABLE_MEDIA_FILE_NAME); - FileBuffer =3D GetFileBufferByFilePath (TRUE, TempDevicePath, FileSi= ze, &AuthenticationStatus); - if (FileBuffer !=3D NULL) { - *FullPath =3D TempDevicePath; + NextFullPath =3D FileDevicePath (SimpleFileSystemHandles[Index], EFI= _REMOVABLE_MEDIA_FILE_NAME); + if (GetNext) { break; + } else { + GetNext =3D (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevic= ePathSize (NextFullPath)) =3D=3D 0); + FreePool (NextFullPath); + NextFullPath =3D NULL; } - FreePool (TempDevicePath); } } =20 @@ -1059,7 +1095,7 @@ BmExpandMediaDevicePath ( FreePool (SimpleFileSystemHandles); } =20 - return FileBuffer; + return NextFullPath; } =20 /** @@ -1098,17 +1134,14 @@ BmMatchHttpBootDevicePath ( Get the file buffer from the file system produced by Load File instance. =20 @param LoadFileHandle The handle of LoadFile instance. - @param FullPath Return the full device path pointing to the load o= ption. - @param FileSize Return the size of the load option. @param RamDiskHandle Return the RAM Disk handle. =20 - @return The load option buffer. + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. **/ -VOID * -BmGetFileBufferFromLoadFileSystem ( +EFI_DEVICE_PATH_PROTOCOL * +BmExpandNetworkFileSystem ( IN EFI_HANDLE LoadFileHandle, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize, OUT EFI_HANDLE *RamDiskHandle ) { @@ -1138,6 +1171,9 @@ BmGetFileBufferFromLoadFileSystem ( if (!EFI_ERROR (Status) && (Handle =3D=3D LoadFileHandle) && (DevicePathType (Node) =3D=3D MEDIA_DEVICE_PATH) && (DevicePathSub= Type (Node) =3D=3D MEDIA_RAM_DISK_DP)) { + // + // Find the BlockIo instance populated from the LoadFile. + // Handle =3D Handles[Index]; break; } @@ -1154,13 +1190,16 @@ BmGetFileBufferFromLoadFileSystem ( *RamDiskHandle =3D Handle; =20 if (Handle !=3D NULL) { - return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPat= h, FileSize); + // + // Re-use BmExpandMediaDevicePath() to get the full device path of loa= d option. + // But assume only one SimpleFileSystem can be found under the BlockIo= . + // + return BmExpandMediaDevicePath (DevicePathFromHandle (Handle),=20 + NULL); } else { return NULL; } } =20 - /** Return the RAM Disk device path created by LoadFile. =20 @@ -1274,27 +1313,21 @@ BmDestroyRamDisk ( =20 @param LoadFileHandle The specified Load File instance. @param FilePath The file path which will pass to LoadFile(). - @param FullPath Return the full device path pointing to the load o= ption. - @param FileSize Return the size of the load option. =20 - @return The load option buffer or NULL if fails. + @return The full device path pointing to the load option buffer. **/ -VOID * -BmGetFileBufferFromLoadFile ( +EFI_DEVICE_PATH_PROTOCOL * +BmExpandLoadFile ( IN EFI_HANDLE LoadFileHandle, - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; EFI_LOAD_FILE_PROTOCOL *LoadFile; VOID *FileBuffer; - BOOLEAN LoadFileSystem; EFI_HANDLE RamDiskHandle; UINTN BufferSize; - - *FileSize =3D 0; + EFI_DEVICE_PATH_PROTOCOL *FullPath; =20 Status =3D gBS->OpenProtocol ( LoadFileHandle, @@ -1313,52 +1346,60 @@ BmGetFileBufferFromLoadFile ( return NULL; } =20 - LoadFileSystem =3D (BOOLEAN) (Status =3D=3D EFI_WARN_FILE_SYSTEM); - FileBuffer =3D LoadFileSystem ? AllocateReservedPages (EFI_SIZE_TO_PAGES= (BufferSize)) : AllocatePool (BufferSize); + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { + // + // The load option buffer is directly returned by LoadFile. + // + return DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle)); =20 + } + + // + // The load option resides in a RAM disk. + // + FileBuffer =3D AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize)); if (FileBuffer =3D=3D NULL) { return NULL; } =20 Status =3D LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, Fi= leBuffer); if (EFI_ERROR (Status)) { - if (LoadFileSystem) { - FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize)); - } else { - FreePool (FileBuffer); - } + FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize)); return NULL; } =20 - if (LoadFileSystem) { - FileBuffer =3D BmGetFileBufferFromLoadFileSystem (LoadFileHandle, Full= Path, FileSize, &RamDiskHandle); - if (FileBuffer =3D=3D NULL) { - // - // If there is no bootable executable in the populated - // - BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle)); - } - } else { - *FileSize =3D BufferSize; - *FullPath =3D DuplicateDevicePath (DevicePathFromHandle (LoadFileHandl= e)); + FullPath =3D BmExpandNetworkFileSystem (LoadFileHandle,=20 + &RamDiskHandle); if (FullPath =3D=3D NULL) { + // + // Free the memory occupied by the RAM disk if there is no BlockIo or = SimpleFileSystem instance. + // + BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle)); } =20 - return FileBuffer; + return FullPath; } =20 /** - Get the file buffer from all the Load File instances. + Return the full device path pointing to the load option. + + FilePath may: + 1. Exactly matches to a LoadFile instance. + 2. Cannot match to any LoadFile instance. Wide match is required. + In either case, the routine may return: + 1. A copy of FilePath when FilePath matches to a LoadFile instance and + the LoadFile returns a load option buffer. + 2. A new device path with IP and URI information updated when wide match + happens. + 3. A new device path pointing to a load option in RAM disk. + In either case, only one full device path is returned for a specified =20 + FilePath. =20 @param FilePath The media device path pointing to a LoadFile instance= . - @param FullPath Return the full device path pointing to the load opti= on. - @param FileSize Return the size of the load option. =20 @return The load option buffer. **/ -VOID * -BmGetFileBufferFromLoadFiles ( - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize +EFI_DEVICE_PATH_PROTOCOL * +BmExpandLoadFiles ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; @@ -1411,7 +1452,7 @@ BmGetFileBufferFromLoadFiles ( return NULL; } =20 - return BmGetFileBufferFromLoadFile (Handle, FilePath, FullPath, FileSize= ); + return BmExpandLoadFile (Handle, FilePath); } =20 /** @@ -1434,19 +1475,37 @@ EfiBootManagerGetLoadOptionBuffer ( OUT UINTN *FileSize ) { + *FullPath =3D NULL; + + EfiBootManagerConnectDevicePath (FilePath, NULL); + return BmGetNextLoadOptionBuffer (LoadOptionTypeMax, FilePath,=20 +FullPath, FileSize); } + +/** + Get the next possible full path pointing to the load option. + The routine doesn't guarantee the returned full path points to an=20 +existing + file, and it also doesn't guarantee the existing file is a valid load op= tion. + BmGetNextLoadOptionBuffer() guarantees. + + @param FilePath The device path pointing to a load option. + It could be a short-form device path. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. + + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. +**/ +EFI_DEVICE_PATH_PROTOCOL * +BmGetNextLoadOptionDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN EFI_DEVICE_PATH_PROTOCOL *FullPath + ) +{ EFI_HANDLE Handle; - VOID *FileBuffer; - UINT32 AuthenticationStatus; EFI_DEVICE_PATH_PROTOCOL *Node; EFI_STATUS Status; =20 - ASSERT ((FilePath !=3D NULL) && (FullPath !=3D NULL) && (FileSize !=3D N= ULL)); - - EfiBootManagerConnectDevicePath (FilePath, NULL); - - *FullPath =3D NULL; - *FileSize =3D 0; - FileBuffer =3D NULL; + ASSERT (FilePath !=3D NULL); =20 // // Boot from media device by adding a default file name \EFI\BOOT\BOOT{m= achine type short-name}.EFI @@ -1458,7 +1517,7 @@ EfiBootManagerGetLoadOpti= onBuffer ( } =20 if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) { - return BmExpandMediaDevicePath (FilePath, FullPath, FileSize); + return BmExpandMediaDevicePath (FilePath, FullPath); } =20 // @@ -1469,19 +1528,23 @@ EfiBootManagerGetLoadOptionBuffer ( // // Expand the Harddrive device path // - return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize); + if (FullPath =3D=3D NULL) { + return BmExpandPartitionDevicePath (FilePath); + } else { + return NULL; + } } else if ((DevicePathType (FilePath) =3D=3D MEDIA_DEVICE_PATH) && (DevicePathSubType (FilePath) =3D=3D MEDIA_FILEPATH_DP)) { // // Expand the File-path device path // - return BmExpandFileDevicePath (FilePath, FullPath, FileSize); + return BmExpandFileDevicePath (FilePath, FullPath); } else if ((DevicePathType (FilePath) =3D=3D MESSAGING_DEVICE_PATH) && (DevicePathSubType (FilePath) =3D=3D MSG_URI_DP)) { // // Expand the URI device path // - return BmExpandUriDevicePath (FilePath, FullPath, FileSize); + return BmExpandUriDevicePath (FilePath, FullPath); } else { for (Node =3D FilePath; !IsDevicePathEnd (Node); Node =3D NextDevicePa= thNode (Node)) { if ((DevicePathType (Node) =3D=3D MESSAGING_DEVICE_PATH) && @@ -1490= ,45 +1553,50 @@ EfiBootManagerGetLoadOptionBuffer ( } } =20 + // + // Expand the USB WWID/Class device path + // if (!IsDevicePathEnd (Node)) { - // - // Expand the USB WWID/Class device path - // - FileBuffer =3D BmExpandUsbDevicePath (FilePath, FullPath, FileSize, = Node); - if ((FileBuffer =3D=3D NULL) && (FilePath =3D=3D Node)) { + if (FilePath =3D=3D Node) { // // Boot Option device path starts with USB Class or USB WWID devic= e path. // For Boot Option device path which doesn't begin with the USB Cl= ass or // USB WWID device path, it's not needed to connect again here. // BmConnectUsbShortFormDevicePath (FilePath); - FileBuffer =3D BmExpandUsbDevicePath (FilePath, FullPath, FileSize= , Node); } - return FileBuffer; + return BmExpandUsbDevicePath (FilePath, FullPath, Node); } } =20 // - // Get file buffer from FV file path. + // For the below cases, FilePath only expands to one Full path. + // So just handle the case when FullPath =3D=3D NULL. + // + if (FullPath !=3D NULL) { + return NULL; + } + + // + // Load option resides in FV. // if (BmIsFvFilePath (FilePath)) { - return BmGetFileBufferByFvFilePath (FilePath, FullPath, FileSize); + return BmAdjustFvFilePath (FilePath); } =20 // - // Get file buffer from simple file system. + // Load option resides in Simple File System. // Node =3D FilePath; Status =3D gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &No= de, &Handle); if (!EFI_ERROR (Status)) { - FileBuffer =3D GetFileBufferByFilePath (TRUE, FilePath, FileSize, &Aut= henticationStatus); - if (FileBuffer !=3D NULL) { - *FullPath =3D DuplicateDevicePath (FilePath); - } - return FileBuffer; + return DuplicateDevicePath (FilePath); } =20 - return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize); + // + // Last chance to try: Load option may be loaded through LoadFile. + // + return BmExpandLoadFiles (FilePath); } =20 /** @@ -1686,21 +1754,13 @@ EfiBootManagerBoot ( ImageHandle =3D NULL; RamDiskDevicePath =3D NULL; if (DevicePathType (BootOption->FilePath) !=3D BBS_DEVICE_PATH) { - Status =3D EFI_NOT_FOUND; - FileBuffer =3D EfiBootManagerGetLoadOptionBuffer (BootOption->FilePath= , &FilePath, &FileSize); + Status =3D EFI_NOT_FOUND; + FilePath =3D NULL; + EfiBootManagerConnectDevicePath (BootOption->FilePath, NULL); + FileBuffer =3D BmGetNextLoadOptionBuffer (LoadOptionTypeBoot,=20 + BootOption->FilePath, &FilePath, &FileSize); if (FileBuffer !=3D NULL) { RamDiskDevicePath =3D BmGetRamDiskDevicePath (FilePath); - } - DEBUG_CODE ( - if (FileBuffer !=3D NULL && CompareMem (BootOption->FilePath, FilePa= th, GetDevicePathSize (FilePath)) !=3D 0) { - DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: ")); - BmPrintDp (BootOption->FilePath); - DEBUG ((EFI_D_INFO, " -> ")); - BmPrintDp (FilePath); - DEBUG ((EFI_D_INFO, "\n")); - } - ); - if (BmIsLoadOptionPeHeaderValid (BootOption->OptionType, FileBuffer, F= ileSize)) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLo= aderLoad)); Status =3D gBS->LoadImage ( TRUE, diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeMo= dulePkg/Library/UefiBootManagerLib/BmLoadOption.c index 116cf28..b0a3505 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c @@ -1167,6 +1167,10 @@ EfiBootManagerFreeLoadOptions ( Return whether the PE header of the load option is valid or not. =20 @param[in] Type The load option type. + It's used to check whether the load option is vali= d. + When it's LoadOptionTypeMax, the routine only guar= antees + the load option is a valid PE image but doesn't gu= arantee + the PE's subsystem type is valid. @param[in] FileBuffer The PE file buffer of the load option. @param[in] FileSize The size of the load option file. =20 @@ -1217,7 +1221,8 @@ BmIsLoadOptionPeHeaderValid ( // SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### m= ust be of type Application // Subsystem =3D OptionalHeader->Subsystem; - if ((Type =3D=3D LoadOptionTypeDriver && Subsystem =3D=3D EFI_IMAG= E_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || + if ((Type =3D=3D LoadOptionTypeMax) || + (Type =3D=3D LoadOptionTypeDriver && Subsystem =3D=3D=20 + EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || (Type =3D=3D LoadOptionTypeDriver && Subsystem =3D=3D EFI_IMAG= E_SUBSYSTEM_EFI_RUNTIME_DRIVER) || (Type =3D=3D LoadOptionTypeSysPrep && Subsystem =3D=3D EFI_IMA= GE_SUBSYSTEM_EFI_APPLICATION) || (Type =3D=3D LoadOptionTypeBoot && Subsystem =3D=3D EFI_IMAGE_= SUBSYSTEM_EFI_APPLICATION) || @@ -1233,6 +1238,91 @@ BmIsLoadOptionPeHeader= Valid ( } =20 /** + Return the next matched load option buffer. + The routine keeps calling BmGetNextLoadOptionDevicePath() until a=20 + valid load option is read. + + @param Type The load option type. + It's used to check whether the load option is valid. + When it's LoadOptionTypeMax, the routine only guarantee= s + the load option is a valid PE image but doesn't guarant= ee + the PE's subsystem type is valid. + @param FilePath The device path pointing to a load option. + It could be a short-form device path. + @param FullPath Return the next full device path of the load option aft= er + short-form device path expanding. + Caller is responsible to free it. + NULL to return the first matched full device path. + @param FileSize Return the load option size. + + @return The load option buffer. Caller is responsible to free the memory= . +**/ +VOID * +BmGetNextLoadOptionBuffer ( + IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, + OUT UINTN *FileSize + ) +{ + VOID *FileBuffer; + EFI_DEVICE_PATH_PROTOCOL *PreFullPath; + EFI_DEVICE_PATH_PROTOCOL *CurFullPath; + UINTN LocalFileSize; + UINT32 AuthenticationStatus; + EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; + + LocalFileSize =3D 0; + FileBuffer =3D NULL; + CurFullPath =3D *FullPath; + do { + PreFullPath =3D CurFullPath; + CurFullPath =3D BmGetNextLoadOptionDevicePath (FilePath, CurFullPath); + // + // Only free the full path created *inside* this routine + // + if ((PreFullPath !=3D NULL) && (PreFullPath !=3D *FullPath)) { + FreePool (PreFullPath); + } + if (CurFullPath =3D=3D NULL) { + break; + } + FileBuffer =3D GetFileBufferByFilePath (TRUE, CurFullPath, &LocalFileS= ize, &AuthenticationStatus); + if ((FileBuffer !=3D NULL) && !BmIsLoadOptionPeHeaderValid (Type, File= Buffer, LocalFileSize)) { + // + // Free the RAM disk file system if the load option is invalid. + // + RamDiskDevicePath =3D BmGetRamDiskDevicePath (FilePath); + if (RamDiskDevicePath !=3D NULL) { + BmDestroyRamDisk (RamDiskDevicePath); + FreePool (RamDiskDevicePath); + } + + // + // Free the invalid load option buffer. + // + FreePool (FileBuffer); + FileBuffer =3D NULL; + } + } while (FileBuffer =3D=3D NULL); + + if (FileBuffer =3D=3D NULL) { + CurFullPath =3D NULL; + LocalFileSize =3D 0; + } + + DEBUG ((DEBUG_INFO, "[Bds] Expand ")); BmPrintDp (FilePath); DEBUG=20 + ((DEBUG_INFO, " -> ")); BmPrintDp (CurFullPath); DEBUG ((DEBUG_INFO,=20 + "\n")); + + *FullPath =3D CurFullPath; + *FileSize =3D LocalFileSize; + return FileBuffer; +} + +/** Process (load and execute) the load option. =20 @param LoadOption Pointer to the load option. @@ -1249,7 +1339,8 @@ EfiBootManagerProcessLoadOption ( ) { EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_DEVICE_PATH_PROTOCOL *PreFullPath; + EFI_DEVICE_PATH_PROTOCOL *CurFullPath; EFI_HANDLE ImageHandle; EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; VOID *FileBuffer; @@ -1271,8 +1362,6 @@ EfiBootManagerProcessLoadOption ( return EFI_SUCCESS; } =20 - Status =3D EFI_INVALID_PARAMETER; - // // Load and start the load option. // @@ -1282,54 +1371,62 @@ EfiBootManagerProcessLoadOption ( LoadOption->Description )); ImageHandle =3D NULL; - FileBuffer =3D EfiBootManagerGetLoadOptionBuffer (LoadOption->FilePath, = &FilePath, &FileSize); - DEBUG_CODE ( - if (FileBuffer !=3D NULL && CompareMem (LoadOption->FilePath, FilePath= , GetDevicePathSize (FilePath)) !=3D 0) { - DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: ")); - BmPrintDp (LoadOption->FilePath); - DEBUG ((EFI_D_INFO, " -> ")); - BmPrintDp (FilePath); - DEBUG ((EFI_D_INFO, "\n")); + CurFullPath =3D NULL; + EfiBootManagerConnectDevicePath (LoadOption->FilePath, NULL); + + // + // while() loop is to keep starting next matched load option if the Plat= formRecovery#### returns failure status. + // + while (TRUE) { + Status =3D EFI_INVALID_PARAMETER; + PreFullPath =3D CurFullPath; + FileBuffer =3D BmGetNextLoadOptionBuffer (LoadOption->OptionType, Loa= dOption->FilePath, &CurFullPath, &FileSize); + if (PreFullPath !=3D NULL) { + FreePool (PreFullPath); + } + if (FileBuffer =3D=3D NULL) { + break; } - ); - if (BmIsLoadOptionPeHeaderValid (LoadOption->OptionType, FileBuffer, Fil= eSize)) { Status =3D gBS->LoadImage ( FALSE, gImageHandle, - FilePath, + CurFullPath, FileBuffer, FileSize, &ImageHandle ); - } - if (FilePath !=3D NULL) { - FreePool (FilePath); - } - if (FileBuffer !=3D NULL) { FreePool (FileBuffer); - } =20 - if (!EFI_ERROR (Status)) { - Status =3D gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolG= uid, (VOID **) &ImageInfo); - ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + Status =3D gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtoco= lGuid, (VOID **)&ImageInfo); + ASSERT_EFI_ERROR (Status); =20 - ImageInfo->LoadOptionsSize =3D LoadOption->OptionalDataSize; - ImageInfo->LoadOptions =3D LoadOption->OptionalData; - // - // Before calling the image, enable the Watchdog Timer for the 5-minut= e period - // - gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL); + ImageInfo->LoadOptionsSize =3D LoadOption->OptionalDataSize; + ImageInfo->LoadOptions =3D LoadOption->OptionalData; + // + // Before calling the image, enable the Watchdog Timer for the 5-min= ute period + // + gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL); =20 - LoadOption->Status =3D gBS->StartImage (ImageHandle, &LoadOption->Exit= DataSize, &LoadOption->ExitData); - DEBUG (( - DEBUG_INFO | DEBUG_LOAD, "%s%04x Return Status =3D %r\n", - mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber,= LoadOption->Status + LoadOption->Status =3D gBS->StartImage (ImageHandle, &LoadOption->Ex= itDataSize, &LoadOption->ExitData); + DEBUG (( + DEBUG_INFO | DEBUG_LOAD, "%s%04x Return Status =3D %r\n", + mBmLoadOptionName[LoadOption->OptionType],=20 + LoadOption->OptionNumber, LoadOption->Status )); =20 - // - // Clear the Watchdog Timer after the image returns - // - gBS->SetWatchdogTimer (0, 0, 0, NULL); + // + // Clear the Watchdog Timer after the image returns + // + gBS->SetWatchdogTimer (0, 0, 0, NULL); + + if ((LoadOption->OptionType !=3D LoadOptionTypePlatformRecovery) || = (LoadOption->Status =3D=3D EFI_SUCCESS)) { + break; + } + } + } + + if (CurFullPath !=3D NULL) { + FreePool (CurFullPath); } =20 return Status; diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModu= lePkg/Library/UefiBootManagerLib/InternalBm.h index 8d7215a..ef09050 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -310,23 +310,6 @@ BmSetVariableAndReportStatusCodeOnError ( ); =20 /** - Return whether the PE header of the load option is valid or not. - - @param[in] Type The load option type. - @param[in] FileBuffer The PE file buffer of the load option. - @param[in] FileSize The size of the load option file. - - @retval TRUE The PE header of the load option is valid. - @retval FALSE The PE header of the load option is not valid. -**/ -BOOLEAN -BmIsLoadOptionPeHeaderValid ( - IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type, - IN VOID *FileBuffer, - IN UINTN FileSize - ); - -/** Function compares a device path data structure to that of all the nodes = of a second device path instance. =20 @@ -425,16 +408,83 @@ BmMakeBootOptionDescriptionUnique ( =20 @param LoadFileHandle The specified Load File instance. @param FilePath The file path which will pass to LoadFile(). - @param FullPath Return the full device path pointing to the load o= ption. - @param FileSize Return the size of the load option. =20 - @return The load option buffer or NULL if fails. + @return The full device path pointing to the load option buffer. +**/ +EFI_DEVICE_PATH_PROTOCOL * +BmExpandLoadFile ( + IN EFI_HANDLE LoadFileHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + +/** + Return the RAM Disk device path created by LoadFile. + + @param FilePath The source file path. + + @return Callee-to-free RAM Disk device path **/=20 +EFI_DEVICE_PATH_PROTOCOL * BmGetRamDiskDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + +/** + Destroy the RAM Disk. + + The destroy operation includes to call RamDisk.Unregister to =20 + unregister the RAM DISK from RAM DISK driver, free the memory =20 + allocated for the RAM Disk. + + @param RamDiskDevicePath RAM Disk device path. +**/ +VOID +BmDestroyRamDisk ( + IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath + ); + +/** + Get the next possible full path pointing to the load option. + + @param FilePath The device path pointing to a load option. + It could be a short-form device path. + @param FullPath The full path returned by the routine in last call. + Set to NULL in first call. + + @return The next possible full path pointing to the load option. + Caller is responsible to free the memory. +**/ +EFI_DEVICE_PATH_PROTOCOL * +BmGetNextLoadOptionDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN EFI_DEVICE_PATH_PROTOCOL *FullPath + ); + +/** + Return the next matched load option buffer. + The routine keeps calling BmGetNextLoadOptionDevicePath() until a=20 +valid + load option is read. + + @param Type The load option type. + It's used to check whether the load option is valid. + When it's LoadOptionTypeMax, the routine only guarantee= s + the load option is a valid PE image but doesn't guarant= ee + the PE's subsystem type is valid. + @param FilePath The device path pointing to a load option. + It could be a short-form device path. + @param FullPath Return the next full device path of the load option aft= er + short-form device path expanding. + Caller is responsible to free it. + NULL to return the first matched full device path. + @param FileSize Return the load option size. + + @return The load option buffer. Caller is responsible to free the memory= . **/ VOID * -BmGetFileBufferFromLoadFile ( - EFI_HANDLE LoadFileHandle, - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize +BmGetNextLoadOptionBuffer ( + IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, + OUT UINTN *FileSize ); #endif // _INTERNAL_BM_H_ -- 2.9.0.windows.1