OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ReloadOptionRoms.c
Go to the documentation of this file.
1
18#include <Uefi.h>
19
20#include <Library/BaseLib.h>
21#include <Library/DebugLib.h>
22#include <Library/DevicePathLib.h>
23#include <Library/IoLib.h>
24#include <Library/MemoryAllocationLib.h>
26#include <Library/PrintLib.h>
27#include <Library/UefiBootServicesTableLib.h>
28#include <IndustryStandard/Pci23.h>
29#include <IndustryStandard/PeImage2.h>
30#include <Protocol/Decompress.h>
31#include <Protocol/PciIo.h>
32
33#include "HandleParsingMin.h"
34
47STATIC
48EFI_STATUS
50 IN VOID *RomBar,
51 IN UINTN RomSize,
52 IN CONST CHAR16 *FileName
53 )
54{
55 VOID *ImageBuffer;
56 VOID *DecompressedImageBuffer;
57 UINTN ImageIndex;
58 UINTN RomBarOffset;
59 UINT8 *Scratch;
60 UINT16 ImageOffset;
61 UINT32 ImageSize;
62 UINT32 ScratchSize;
63 UINT32 ImageLength;
64 UINT32 DestinationSize;
65 UINT32 InitializationSize;
66 BOOLEAN LoadROM;
67 EFI_STATUS Status;
68 EFI_HANDLE ImageHandle;
69 PCI_DATA_STRUCTURE *Pcir;
70 EFI_DECOMPRESS_PROTOCOL *Decompress;
71 EFI_DEVICE_PATH_PROTOCOL *FilePath;
72 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
73 CHAR16 RomFileName[32];
74
75 ImageIndex = 0;
76 Status = EFI_NOT_FOUND;
77 RomBarOffset = (UINTN)RomBar;
78
79 do {
80 LoadROM = FALSE;
81 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *)(UINTN)RomBarOffset;
82
83 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
84 return EFI_VOLUME_CORRUPTED;
85 }
86
87 //
88 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
89 // The PCI Data Structure must be DWORD aligned.
90 //
91 if ( (EfiRomHeader->PcirOffset == 0)
92 || ((EfiRomHeader->PcirOffset & 3) != 0)
93 || (RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize))
94 {
95 break;
96 }
97
98 Pcir = (PCI_DATA_STRUCTURE *)(UINTN)(RomBarOffset + EfiRomHeader->PcirOffset);
99
100 //
101 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
102 //
103 if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
104 break;
105 }
106
107 ImageSize = Pcir->ImageLength * 512;
108
109 if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {
110 break;
111 }
112
113 if ( (Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE)
114 && (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)
115 && ( (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
116 || (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)))
117 {
118 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
119 InitializationSize = EfiRomHeader->InitializationSize * 512;
120
121 if ((InitializationSize <= ImageSize) && (ImageOffset < InitializationSize)) {
122 ImageBuffer = (VOID *)(UINTN)(RomBarOffset + ImageOffset);
123 ImageLength = InitializationSize - ImageOffset;
124 DecompressedImageBuffer = NULL;
125
126 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
127 Status = gBS->LocateProtocol (
128 &gEfiDecompressProtocolGuid,
129 NULL,
130 (VOID **)&Decompress
131 );
132
133 if (!EFI_ERROR (Status)) {
134 Status = Decompress->GetInfo (
136 ImageBuffer,
137 ImageLength,
138 &DestinationSize,
139 &ScratchSize
140 );
141
142 if (!EFI_ERROR (Status)) {
143 DecompressedImageBuffer = AllocateZeroPool (DestinationSize);
144 if (ImageBuffer != NULL) {
145 Scratch = AllocateZeroPool (ScratchSize);
146 if (Scratch != NULL) {
147 Status = Decompress->Decompress (
149 ImageBuffer,
150 ImageLength,
151 DecompressedImageBuffer,
152 DestinationSize,
153 Scratch,
154 ScratchSize
155 );
156
157 if (!EFI_ERROR (Status)) {
158 LoadROM = TRUE;
159 ImageBuffer = DecompressedImageBuffer;
160 ImageLength = DestinationSize;
161 }
162
163 FreePool (Scratch);
164 }
165 }
166 }
167 }
168 }
169
170 if (LoadROM) {
171 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
172 FilePath = FileDevicePath (NULL, RomFileName);
173 Status = gBS->LoadImage (
174 TRUE,
176 FilePath,
177 ImageBuffer,
178 ImageLength,
179 &ImageHandle
180 );
181
182 if (!EFI_ERROR (Status)) {
183 gBS->StartImage (ImageHandle, NULL, NULL);
184 } else if (Status == EFI_SECURITY_VIOLATION) {
185 gBS->UnloadImage (ImageHandle);
186 }
187 }
188
189 if (DecompressedImageBuffer != NULL) {
190 FreePool (DecompressedImageBuffer);
191 }
192 }
193 }
194
195 RomBarOffset = RomBarOffset + ImageSize;
196 ImageIndex++;
197 } while ((Pcir->Indicator & 0x80) == 0x00 && RomBarOffset - (UINTN)RomBar < RomSize);
198
199 return Status;
200}
201
202EFI_STATUS
204 VOID
205 )
206{
207 UINTN Index;
208 UINTN HandleIndex;
209 UINTN HandleArrayCount;
210 UINTN BindingHandleCount;
211 EFI_HANDLE *HandleArray;
212 EFI_HANDLE *BindingHandleBuffer;
213 EFI_STATUS ReturnStatus;
214 EFI_STATUS Status;
215 EFI_PCI_IO_PROTOCOL *PciIo;
216 CHAR16 RomFileName[16];
217
218 ReturnStatus = EFI_LOAD_ERROR;
219
220 Status = gBS->LocateHandleBuffer (
221 ByProtocol,
222 &gEfiPciIoProtocolGuid,
223 NULL,
224 &HandleArrayCount,
225 &HandleArray
226 );
227
228 if (EFI_ERROR (Status)) {
229 return EFI_PROTOCOL_ERROR;
230 }
231
232 for (Index = 0; Index < HandleArrayCount; Index++) {
233 Status = gBS->HandleProtocol (
234 HandleArray[Index],
235 &gEfiPciIoProtocolGuid,
236 (void **)&PciIo
237 );
238
239 if (!EFI_ERROR (Status) && (PciIo->RomImage != NULL) && (PciIo->RomSize > 0)) {
240 BindingHandleBuffer = NULL;
241 BindingHandleCount = 0;
243 HandleArray[Index],
244 &BindingHandleCount,
245 &BindingHandleBuffer
246 );
247
248 if (BindingHandleCount == 0) {
249 HandleIndex = InternalConvertHandleToHandleIndex (HandleArray[Index]);
250 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"Handle%X", HandleIndex);
251 Status = ReloadPciRom (PciIo->RomImage, (UINTN)PciIo->RomSize, RomFileName);
252 if (EFI_ERROR (ReturnStatus)) {
253 ReturnStatus = Status;
254 }
255 }
256
257 if (BindingHandleBuffer != NULL) {
258 FreePool (BindingHandleBuffer);
259 }
260 }
261 }
262
263 FreePool (HandleArray);
264
265 return ReturnStatus;
266}
EFI_STATUS Decompress(IN RUNLIST *Runlist, IN UINT64 Offset, IN UINTN Length, OUT UINT8 *Dest)
UINTN EFIAPI InternalConvertHandleToHandleIndex(IN CONST EFI_HANDLE TheHandle)
#define PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ControllerHandle, Count, Buffer)
DMG_FILEPATH_DEVICE_PATH FilePath
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
STATIC EFI_STATUS ReloadPciRom(IN VOID *RomBar, IN UINTN RomSize, IN CONST CHAR16 *FileName)
EFI_STATUS OcReloadOptionRoms(VOID)