]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
IntelFrameworkModulePkg/Csm: Add code to bypass NULL pointer detection
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyBootSupport.c
CommitLineData
bcecde14 1/** @file\r
2\r
aa5f60ae 3Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
bcecde14 4\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The\r
8full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "LegacyBiosInterface.h"\r
17#include <IndustryStandard/Pci.h>\r
18\r
19#define BOOT_LEGACY_OS 0\r
20#define BOOT_EFI_OS 1\r
21#define BOOT_UNCONVENTIONAL_DEVICE 2\r
22\r
23UINT32 mLoadOptionsSize = 0;\r
24UINTN mBootMode = BOOT_LEGACY_OS;\r
25VOID *mLoadOptions = NULL;\r
26BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr = NULL;\r
27BBS_BBS_DEVICE_PATH mBbsDevicePathNode;\r
28UDC_ATTRIBUTES mAttributes = { 0, 0, 0, 0 };\r
29UINTN mBbsEntry = 0;\r
30VOID *mBeerData = NULL;\r
31VOID *mServiceAreaData = NULL;\r
32UINT64 mLowWater = 0xffffffffffffffffULL;\r
33\r
34extern BBS_TABLE *mBbsTable;\r
35\r
b6823730
EL
36extern VOID *mRuntimeSmbiosEntryPoint;\r
37extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint;\r
38extern EFI_PHYSICAL_ADDRESS mStructureTableAddress;\r
39\r
bcecde14 40/**\r
41 Print the BBS Table.\r
42\r
43 @param BbsTable The BBS table.\r
44\r
45\r
46**/\r
47VOID\r
48PrintBbsTable (\r
49 IN BBS_TABLE *BbsTable\r
50 )\r
51{\r
52 UINT16 Index;\r
53 UINT16 SubIndex;\r
54 CHAR8 *String;\r
55\r
56 DEBUG ((EFI_D_INFO, "\n"));\r
57 DEBUG ((EFI_D_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:mfgo dess:deso\n"));\r
58 DEBUG ((EFI_D_INFO, "=================================================================\n"));\r
59 for (Index = 0; Index < MAX_BBS_ENTRIES; Index++) {\r
60 //\r
61 // Filter\r
62 //\r
63 if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
64 continue;\r
65 }\r
66\r
67 DEBUG ((\r
68 EFI_D_INFO,\r
69 " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x",\r
70 (UINTN) Index,\r
71 (UINTN) BbsTable[Index].BootPriority,\r
72 (UINTN) BbsTable[Index].Bus,\r
73 (UINTN) BbsTable[Index].Device,\r
74 (UINTN) BbsTable[Index].Function,\r
75 (UINTN) BbsTable[Index].Class,\r
76 (UINTN) BbsTable[Index].SubClass,\r
77 (UINTN) BbsTable[Index].DeviceType,\r
78 (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags\r
79 ));\r
80 DEBUG ((\r
81 EFI_D_INFO,\r
82 " %04x:%04x %04x:%04x %04x:%04x",\r
83 (UINTN) BbsTable[Index].BootHandlerSegment,\r
84 (UINTN) BbsTable[Index].BootHandlerOffset,\r
85 (UINTN) BbsTable[Index].MfgStringSegment,\r
86 (UINTN) BbsTable[Index].MfgStringOffset,\r
87 (UINTN) BbsTable[Index].DescStringSegment,\r
88 (UINTN) BbsTable[Index].DescStringOffset\r
89 ));\r
90\r
91 //\r
92 // Print DescString\r
93 //\r
aa5f60ae 94 String = (CHAR8 *)(((UINTN)BbsTable[Index].DescStringSegment << 4) + BbsTable[Index].DescStringOffset);\r
bcecde14 95 if (String != NULL) {\r
96 DEBUG ((EFI_D_INFO," ("));\r
97 for (SubIndex = 0; String[SubIndex] != 0; SubIndex++) {\r
98 DEBUG ((EFI_D_INFO, "%c", String[SubIndex]));\r
99 }\r
100 DEBUG ((EFI_D_INFO,")"));\r
101 }\r
102 DEBUG ((EFI_D_INFO,"\n"));\r
103 }\r
104\r
105 DEBUG ((EFI_D_INFO, "\n"));\r
106\r
107 return ;\r
108}\r
109\r
110/**\r
111 Print the BBS Table.\r
112\r
113 @param HddInfo The HddInfo table.\r
114\r
115\r
116**/\r
117VOID\r
118PrintHddInfo (\r
119 IN HDD_INFO *HddInfo\r
120 )\r
121{\r
122 UINTN Index;\r
123\r
124 DEBUG ((EFI_D_INFO, "\n"));\r
125 for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
126 DEBUG ((EFI_D_INFO, "Index - %04x\n", Index));\r
127 DEBUG ((EFI_D_INFO, " Status - %04x\n", (UINTN)HddInfo[Index].Status));\r
128 DEBUG ((EFI_D_INFO, " B/D/F - %02x/%02x/%02x\n", (UINTN)HddInfo[Index].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function));\r
129 DEBUG ((EFI_D_INFO, " Command - %04x\n", HddInfo[Index].CommandBaseAddress));\r
130 DEBUG ((EFI_D_INFO, " Control - %04x\n", HddInfo[Index].ControlBaseAddress));\r
131 DEBUG ((EFI_D_INFO, " BusMaster - %04x\n", HddInfo[Index].BusMasterAddress));\r
132 DEBUG ((EFI_D_INFO, " HddIrq - %02x\n", HddInfo[Index].HddIrq));\r
133 DEBUG ((EFI_D_INFO, " IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[0].Raw[0]));\r
134 DEBUG ((EFI_D_INFO, " IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index].IdentifyDrive[1].Raw[0]));\r
135 }\r
136\r
137 DEBUG ((EFI_D_INFO, "\n"));\r
138\r
139 return ;\r
140}\r
141\r
7dad86fc
RN
142/**\r
143 Print the PCI Interrupt Line and Interrupt Pin registers.\r
144**/\r
145VOID\r
146PrintPciInterruptRegister (\r
147 VOID\r
148 )\r
149{\r
150 EFI_STATUS Status;\r
151 UINTN Index;\r
152 EFI_HANDLE *Handles;\r
153 UINTN HandleNum;\r
154 EFI_PCI_IO_PROTOCOL *PciIo;\r
155 UINT8 Interrupt[2];\r
156 UINTN Segment;\r
157 UINTN Bus;\r
158 UINTN Device;\r
159 UINTN Function;\r
160\r
161 gBS->LocateHandleBuffer (\r
162 ByProtocol,\r
163 &gEfiPciIoProtocolGuid,\r
164 NULL,\r
165 &HandleNum,\r
166 &Handles\r
167 );\r
168\r
169 Bus = 0;\r
170 Device = 0;\r
171 Function = 0;\r
172\r
173 DEBUG ((EFI_D_INFO, "\n"));\r
174 DEBUG ((EFI_D_INFO, " bb/dd/ff interrupt line interrupt pin\n"));\r
175 DEBUG ((EFI_D_INFO, "======================================\n"));\r
176 for (Index = 0; Index < HandleNum; Index++) {\r
177 Status = gBS->HandleProtocol (Handles[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
178 if (!EFI_ERROR (Status)) {\r
179 Status = PciIo->Pci.Read (\r
180 PciIo,\r
181 EfiPciIoWidthUint8,\r
182 PCI_INT_LINE_OFFSET,\r
183 2,\r
184 Interrupt\r
185 );\r
186 }\r
187 if (!EFI_ERROR (Status)) {\r
188 Status = PciIo->GetLocation (\r
189 PciIo,\r
190 &Segment,\r
191 &Bus,\r
192 &Device,\r
193 &Function\r
194 );\r
195 }\r
196 if (!EFI_ERROR (Status)) {\r
197 DEBUG ((EFI_D_INFO, " %02x/%02x/%02x 0x%02x 0x%02x\n",\r
198 Bus, Device, Function, Interrupt[0], Interrupt[1]));\r
199 }\r
200 }\r
201 DEBUG ((EFI_D_INFO, "\n"));\r
202\r
203 if (Handles != NULL) {\r
204 FreePool (Handles);\r
205 }\r
206}\r
207\r
bcecde14 208/**\r
209 Identify drive data must be updated to actual parameters before boot.\r
210\r
211 @param IdentifyDriveData ATA Identify Data\r
212\r
213**/\r
214VOID\r
215UpdateIdentifyDriveData (\r
216 IN UINT8 *IdentifyDriveData\r
217 );\r
218\r
219/**\r
220 Update SIO data.\r
221\r
222 @param Private Legacy BIOS Instance data\r
223\r
224 @retval EFI_SUCCESS Removable media not present\r
225\r
226**/\r
227EFI_STATUS\r
228UpdateSioData (\r
229 IN LEGACY_BIOS_INSTANCE *Private\r
230 )\r
231{\r
232 EFI_STATUS Status;\r
233 UINTN Index;\r
234 UINTN Index1;\r
235 UINT8 LegacyInterrupts[16];\r
236 EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable;\r
237 UINTN RoutingTableEntries;\r
238 EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable;\r
239 UINTN NumberPriorityEntries;\r
240 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
241 UINT8 HddIrq;\r
242 UINT16 LegacyInt;\r
243 UINT16 LegMask;\r
244 UINT32 Register;\r
245 UINTN HandleCount;\r
246 EFI_HANDLE *HandleBuffer;\r
247 EFI_ISA_IO_PROTOCOL *IsaIo;\r
248\r
249 LegacyInt = 0;\r
250 HandleBuffer = NULL;\r
251\r
252 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
253 LegacyBiosBuildSioData (Private);\r
254 SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0);\r
255\r
256 //\r
257 // Create list of legacy interrupts.\r
258 //\r
259 for (Index = 0; Index < 4; Index++) {\r
260 LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Serial[Index].Irq;\r
261 }\r
262\r
263 for (Index = 4; Index < 7; Index++) {\r
264 LegacyInterrupts[Index] = EfiToLegacy16BootTable->SioData.Parallel[Index - 4].Irq;\r
265 }\r
266\r
267 LegacyInterrupts[7] = EfiToLegacy16BootTable->SioData.Floppy.Irq;\r
268\r
269 //\r
270 // Get Legacy Hdd IRQs. If native mode treat as PCI\r
271 //\r
272 for (Index = 0; Index < 2; Index++) {\r
273 HddIrq = EfiToLegacy16BootTable->HddInfo[Index].HddIrq;\r
274 if ((HddIrq != 0) && ((HddIrq == 15) || (HddIrq == 14))) {\r
275 LegacyInterrupts[Index + 8] = HddIrq;\r
276 }\r
277 }\r
278\r
279 Private->LegacyBiosPlatform->GetRoutingTable (\r
280 Private->LegacyBiosPlatform,\r
281 (VOID *) &RoutingTable,\r
282 &RoutingTableEntries,\r
283 NULL,\r
284 NULL,\r
285 (VOID **) &IrqPriorityTable,\r
286 &NumberPriorityEntries\r
287 );\r
288 //\r
289 // Remove legacy interrupts from the list of PCI interrupts available.\r
290 //\r
291 for (Index = 0; Index <= 0x0b; Index++) {\r
292 for (Index1 = 0; Index1 <= NumberPriorityEntries; Index1++) {\r
293 if (LegacyInterrupts[Index] != 0) {\r
294 LegacyInt = (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index]));\r
295 if (LegacyInterrupts[Index] == IrqPriorityTable[Index1].Irq) {\r
296 IrqPriorityTable[Index1].Used = LEGACY_USED;\r
297 }\r
298 }\r
299 }\r
300 }\r
301\r
302 Private->Legacy8259->GetMask (\r
303 Private->Legacy8259,\r
304 &LegMask,\r
305 NULL,\r
306 NULL,\r
307 NULL\r
308 );\r
309\r
310 //\r
311 // Set SIO interrupts and disable mouse. Let mouse driver\r
312 // re-enable it.\r
313 //\r
314 LegMask = (UINT16) ((LegMask &~LegacyInt) | 0x1000);\r
315 Private->Legacy8259->SetMask (\r
316 Private->Legacy8259,\r
317 &LegMask,\r
318 NULL,\r
319 NULL,\r
320 NULL\r
321 );\r
322\r
323 //\r
324 // Disable mouse in keyboard controller\r
325 //\r
326 Register = 0xA7;\r
327 Status = gBS->LocateHandleBuffer (\r
328 ByProtocol,\r
329 &gEfiIsaIoProtocolGuid,\r
330 NULL,\r
331 &HandleCount,\r
332 &HandleBuffer\r
333 );\r
334 if (EFI_ERROR (Status)) {\r
335 return Status;\r
336 }\r
337\r
338 for (Index = 0; Index < HandleCount; Index++) {\r
339 Status = gBS->HandleProtocol (\r
340 HandleBuffer[Index],\r
341 &gEfiIsaIoProtocolGuid,\r
342 (VOID **) &IsaIo\r
343 );\r
344 ASSERT_EFI_ERROR (Status);\r
345 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register);\r
346\r
347 }\r
348\r
349 if (HandleBuffer != NULL) {\r
350 FreePool (HandleBuffer);\r
351 }\r
352\r
353 return EFI_SUCCESS;\r
354\r
355}\r
356\r
357/**\r
358 Identify drive data must be updated to actual parameters before boot.\r
359 This requires updating the checksum, if it exists.\r
360\r
361 @param IdentifyDriveData ATA Identify Data\r
362 @param Checksum checksum of the ATA Identify Data\r
363\r
364 @retval EFI_SUCCESS checksum calculated\r
365 @retval EFI_SECURITY_VIOLATION IdentifyData invalid\r
366\r
367**/\r
368EFI_STATUS\r
369CalculateIdentifyDriveChecksum (\r
370 IN UINT8 *IdentifyDriveData,\r
371 OUT UINT8 *Checksum\r
372 )\r
373{\r
374 UINTN Index;\r
375 UINT8 LocalChecksum;\r
376 LocalChecksum = 0;\r
377 *Checksum = 0;\r
378 if (IdentifyDriveData[510] != 0xA5) {\r
379 return EFI_SECURITY_VIOLATION;\r
380 }\r
381\r
382 for (Index = 0; Index < 512; Index++) {\r
383 LocalChecksum = (UINT8) (LocalChecksum + IdentifyDriveData[Index]);\r
384 }\r
385\r
386 *Checksum = LocalChecksum;\r
387 return EFI_SUCCESS;\r
388}\r
389\r
390\r
391/**\r
392 Identify drive data must be updated to actual parameters before boot.\r
393\r
394 @param IdentifyDriveData ATA Identify Data\r
395\r
396\r
397**/\r
398VOID\r
399UpdateIdentifyDriveData (\r
400 IN UINT8 *IdentifyDriveData\r
401 )\r
402{\r
403 UINT16 NumberCylinders;\r
404 UINT16 NumberHeads;\r
405 UINT16 NumberSectorsTrack;\r
406 UINT32 CapacityInSectors;\r
407 UINT8 OriginalChecksum;\r
408 UINT8 FinalChecksum;\r
409 EFI_STATUS Status;\r
410 ATAPI_IDENTIFY *ReadInfo;\r
411\r
412 //\r
413 // Status indicates if Integrity byte is correct. Checksum should be\r
414 // 0 if valid.\r
415 //\r
416 ReadInfo = (ATAPI_IDENTIFY *) IdentifyDriveData;\r
417 Status = CalculateIdentifyDriveChecksum (IdentifyDriveData, &OriginalChecksum);\r
418 if (OriginalChecksum != 0) {\r
419 Status = EFI_SECURITY_VIOLATION;\r
420 }\r
421 //\r
422 // If NumberCylinders = 0 then do data(Controller present but don drive attached).\r
423 //\r
424 NumberCylinders = ReadInfo->Raw[1];\r
425 if (NumberCylinders != 0) {\r
426 ReadInfo->Raw[54] = NumberCylinders;\r
427\r
428 NumberHeads = ReadInfo->Raw[3];\r
429 ReadInfo->Raw[55] = NumberHeads;\r
430\r
431 NumberSectorsTrack = ReadInfo->Raw[6];\r
432 ReadInfo->Raw[56] = NumberSectorsTrack;\r
433\r
434 //\r
435 // Copy Multisector info and set valid bit.\r
436 //\r
437 ReadInfo->Raw[59] = (UINT16) (ReadInfo->Raw[47] + 0x100);\r
438 CapacityInSectors = (UINT32) ((UINT32) (NumberCylinders) * (UINT32) (NumberHeads) * (UINT32) (NumberSectorsTrack));\r
439 ReadInfo->Raw[57] = (UINT16) (CapacityInSectors >> 16);\r
440 ReadInfo->Raw[58] = (UINT16) (CapacityInSectors & 0xffff);\r
441 if (Status == EFI_SUCCESS) {\r
442 //\r
443 // Forece checksum byte to 0 and get new checksum.\r
444 //\r
445 ReadInfo->Raw[255] &= 0xff;\r
446 CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum);\r
447\r
448 //\r
449 // Force new checksum such that sum is 0.\r
450 //\r
451 FinalChecksum = (UINT8) ((UINT8)0 - FinalChecksum);\r
452 ReadInfo->Raw[255] = (UINT16) (ReadInfo->Raw[255] | (FinalChecksum << 8));\r
453 }\r
454 }\r
455}\r
456\r
457/**\r
458 Identify drive data must be updated to actual parameters before boot.\r
459 Do for all drives.\r
460\r
461 @param Private Legacy BIOS Instance data\r
462\r
463\r
464**/\r
465VOID\r
466UpdateAllIdentifyDriveData (\r
467 IN LEGACY_BIOS_INSTANCE *Private\r
468 )\r
469{\r
470 UINTN Index;\r
471 HDD_INFO *HddInfo;\r
472\r
473 HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];\r
474\r
475 for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
476 //\r
477 // Each controller can have 2 devices. Update for each device\r
478 //\r
479 if ((HddInfo[Index].Status & HDD_MASTER_IDE) != 0) {\r
480 UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0].Raw[0]));\r
481 }\r
482\r
483 if ((HddInfo[Index].Status & HDD_SLAVE_IDE) != 0) {\r
484 UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1].Raw[0]));\r
485 }\r
486 }\r
487}\r
488\r
489/**\r
490 Enable ide controller. This gets disabled when LegacyBoot.c is about\r
491 to run the Option ROMs.\r
492\r
493 @param Private Legacy BIOS Instance data\r
494\r
495\r
496**/\r
497VOID\r
498EnableIdeController (\r
499 IN LEGACY_BIOS_INSTANCE *Private\r
500 )\r
501{\r
502 EFI_PCI_IO_PROTOCOL *PciIo;\r
503 EFI_STATUS Status;\r
504 EFI_HANDLE IdeController;\r
505 UINT8 ByteBuffer;\r
506 UINTN HandleCount;\r
507 EFI_HANDLE *HandleBuffer;\r
508\r
509 Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
510 Private->LegacyBiosPlatform,\r
511 EfiGetPlatformIdeHandle,\r
512 0,\r
513 &HandleBuffer,\r
514 &HandleCount,\r
515 NULL\r
516 );\r
517 if (!EFI_ERROR (Status)) {\r
518 IdeController = HandleBuffer[0];\r
519 Status = gBS->HandleProtocol (\r
520 IdeController,\r
521 &gEfiPciIoProtocolGuid,\r
522 (VOID **) &PciIo\r
523 );\r
524 ByteBuffer = 0x1f;\r
525 if (!EFI_ERROR (Status)) {\r
526 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer);\r
527 }\r
528 }\r
529}\r
530\r
531\r
532/**\r
533 Enable ide controller. This gets disabled when LegacyBoot.c is about\r
534 to run the Option ROMs.\r
535\r
536 @param Private Legacy BIOS Instance data\r
537\r
538\r
539**/\r
540VOID\r
541EnableAllControllers (\r
542 IN LEGACY_BIOS_INSTANCE *Private\r
543 )\r
544{\r
545 UINTN HandleCount;\r
546 EFI_HANDLE *HandleBuffer;\r
547 UINTN Index;\r
548 EFI_PCI_IO_PROTOCOL *PciIo;\r
549 PCI_TYPE01 PciConfigHeader;\r
550 EFI_STATUS Status;\r
551\r
552 //\r
553 //\r
554 //\r
555 EnableIdeController (Private);\r
556\r
557 //\r
558 // Assumption is table is built from low bus to high bus numbers.\r
559 //\r
560 Status = gBS->LocateHandleBuffer (\r
561 ByProtocol,\r
562 &gEfiPciIoProtocolGuid,\r
563 NULL,\r
564 &HandleCount,\r
565 &HandleBuffer\r
566 );\r
567 ASSERT_EFI_ERROR (Status);\r
568\r
569 for (Index = 0; Index < HandleCount; Index++) {\r
570 Status = gBS->HandleProtocol (\r
571 HandleBuffer[Index],\r
572 &gEfiPciIoProtocolGuid,\r
573 (VOID **) &PciIo\r
574 );\r
575 ASSERT_EFI_ERROR (Status);\r
576\r
577 PciIo->Pci.Read (\r
578 PciIo,\r
579 EfiPciIoWidthUint32,\r
580 0,\r
581 sizeof (PciConfigHeader) / sizeof (UINT32),\r
582 &PciConfigHeader\r
583 );\r
584\r
585 //\r
586 // We do not enable PPB here. This is for HotPlug Consideration.\r
587 // The Platform HotPlug Driver is responsible for Padding enough hot plug\r
588 // resources. It is also responsible for enable this bridge. If it\r
589 // does not pad it. It will cause some early Windows fail to installation.\r
590 // If the platform driver does not pad resource for PPB, PPB should be in\r
591 // un-enabled state to let Windows know that this PPB is not configured by\r
592 // BIOS. So Windows will allocate default resource for PPB.\r
593 //\r
594 // The reason for why we enable the command register is:\r
595 // The CSM will use the IO bar to detect some IRQ status, if the command\r
596 // is disabled, the IO resource will be out of scope.\r
597 // For example:\r
598 // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ\r
599 // comes up, the handle will check the IO space to identify is the\r
600 // controller generated the IRQ source.\r
601 // If the IO command is not enabled, the IRQ handler will has wrong\r
602 // information. It will cause IRQ storm when the correctly IRQ handler fails\r
603 // to run.\r
604 //\r
605 if (!(IS_PCI_VGA (&PciConfigHeader) ||\r
606 IS_PCI_OLD_VGA (&PciConfigHeader) ||\r
607 IS_PCI_IDE (&PciConfigHeader) ||\r
608 IS_PCI_P2P (&PciConfigHeader) ||\r
609 IS_PCI_P2P_SUB (&PciConfigHeader) ||\r
610 IS_PCI_LPC (&PciConfigHeader) )) {\r
611\r
612 PciConfigHeader.Hdr.Command |= 0x1f;\r
613\r
614 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader.Hdr.Command);\r
615 }\r
616 }\r
617}\r
618\r
619/**\r
620 The following routines are identical in operation, so combine\r
621 for code compaction:\r
622 EfiGetPlatformBinaryGetMpTable\r
623 EfiGetPlatformBinaryGetOemIntData\r
624 EfiGetPlatformBinaryGetOem32Data\r
625 EfiGetPlatformBinaryGetOem16Data\r
626\r
627 @param This Protocol instance pointer.\r
628 @param Id Table/Data identifier\r
629\r
630 @retval EFI_SUCCESS Success\r
631 @retval EFI_INVALID_PARAMETER Invalid ID\r
632 @retval EFI_OUT_OF_RESOURCES no resource to get data or table\r
633\r
634**/\r
635EFI_STATUS\r
636LegacyGetDataOrTable (\r
637 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
638 IN EFI_GET_PLATFORM_INFO_MODE Id\r
639 )\r
640{\r
641 VOID *Table;\r
642 UINT32 TablePtr;\r
643 UINTN TableSize;\r
644 UINTN Alignment;\r
645 UINTN Location;\r
646 EFI_STATUS Status;\r
647 EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
648 EFI_COMPATIBILITY16_TABLE *Legacy16Table;\r
649 EFI_IA32_REGISTER_SET Regs;\r
650 LEGACY_BIOS_INSTANCE *Private;\r
651\r
652 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
653\r
654 LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
655 Legacy16Table = Private->Legacy16Table;\r
656\r
657 //\r
658 // Phase 1 - get an address allocated in 16-bit code\r
659 //\r
660 while (TRUE) {\r
661 switch (Id) {\r
662 case EfiGetPlatformBinaryMpTable:\r
663 case EfiGetPlatformBinaryOemIntData:\r
664 case EfiGetPlatformBinaryOem32Data:\r
665 case EfiGetPlatformBinaryOem16Data:\r
666 {\r
667 Status = LegacyBiosPlatform->GetPlatformInfo (\r
668 LegacyBiosPlatform,\r
669 Id,\r
670 (VOID *) &Table,\r
671 &TableSize,\r
672 &Location,\r
673 &Alignment,\r
674 0,\r
675 0\r
676 );\r
677 DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)Id, Status));\r
678 DEBUG ((EFI_D_INFO, " Table - %x, Size - %x, Location - %x, Alignment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Alignment));\r
679 break;\r
680 }\r
681\r
682 default:\r
683 {\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
686 }\r
687\r
688 if (EFI_ERROR (Status)) {\r
689 return Status;\r
690 }\r
691\r
692 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
693 Regs.X.AX = Legacy16GetTableAddress;\r
694 Regs.X.CX = (UINT16) TableSize;\r
695 Regs.X.BX = (UINT16) Location;\r
696 Regs.X.DX = (UINT16) Alignment;\r
697 Private->LegacyBios.FarCall86 (\r
698 This,\r
699 Private->Legacy16CallSegment,\r
700 Private->Legacy16CallOffset,\r
701 &Regs,\r
702 NULL,\r
703 0\r
704 );\r
705\r
706 if (Regs.X.AX != 0) {\r
707 DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id));\r
708 return EFI_OUT_OF_RESOURCES;\r
709 } else {\r
710 break;\r
711 }\r
712 }\r
713 //\r
714 // Phase 2 Call routine second time with address to allow address adjustment\r
715 //\r
716 Status = LegacyBiosPlatform->GetPlatformInfo (\r
717 LegacyBiosPlatform,\r
718 Id,\r
719 (VOID *) &Table,\r
720 &TableSize,\r
721 &Location,\r
722 &Alignment,\r
723 Regs.X.DS,\r
724 Regs.X.BX\r
725 );\r
726 switch (Id) {\r
727 case EfiGetPlatformBinaryMpTable:\r
728 {\r
729 Legacy16Table->MpTablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
730 Legacy16Table->MpTableLength = (UINT32)TableSize;\r
731 DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legacy16Table->MpTablePtr));\r
732 break;\r
733 }\r
734\r
735 case EfiGetPlatformBinaryOemIntData:\r
736 {\r
737\r
738 Legacy16Table->OemIntSegment = Regs.X.DS;\r
739 Legacy16Table->OemIntOffset = Regs.X.BX;\r
740 DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset));\r
741 break;\r
742 }\r
743\r
744 case EfiGetPlatformBinaryOem32Data:\r
745 {\r
746 Legacy16Table->Oem32Segment = Regs.X.DS;\r
747 Legacy16Table->Oem32Offset = Regs.X.BX;\r
748 DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset));\r
749 break;\r
750 }\r
751\r
752 case EfiGetPlatformBinaryOem16Data:\r
753 {\r
754 //\r
755 // Legacy16Table->Oem16Segment = Regs.X.DS;\r
756 // Legacy16Table->Oem16Offset = Regs.X.BX;\r
757 DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (UINTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset));\r
758 break;\r
759 }\r
760\r
761 default:\r
762 {\r
763 return EFI_INVALID_PARAMETER;\r
764 }\r
765 }\r
766\r
767 if (EFI_ERROR (Status)) {\r
768 return Status;\r
769 }\r
770 //\r
771 // Phase 3 Copy table to final location\r
772 //\r
773 TablePtr = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
774\r
775 CopyMem (\r
776 (VOID *) (UINTN)TablePtr,\r
777 Table,\r
778 TableSize\r
779 );\r
780\r
781 return EFI_SUCCESS;\r
782}\r
783\r
b6823730
EL
784/**\r
785 Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot.\r
786\r
787**/\r
788VOID\r
789CreateSmbiosTableInReservedMemory (\r
790 VOID\r
791 )\r
792{\r
793 SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;\r
794 \r
795 if ((mRuntimeSmbiosEntryPoint == NULL) || \r
796 (mReserveSmbiosEntryPoint == 0) || \r
797 (mStructureTableAddress == 0)) {\r
798 return;\r
799 }\r
800 \r
801 EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint;\r
802 \r
803 //\r
804 // Copy SMBIOS Entry Point Structure\r
805 //\r
806 CopyMem (\r
807 (VOID *)(UINTN) mReserveSmbiosEntryPoint,\r
808 EntryPointStructure,\r
809 EntryPointStructure->EntryPointLength\r
810 );\r
811 \r
812 //\r
813 // Copy SMBIOS Structure Table into EfiReservedMemoryType memory\r
814 //\r
815 CopyMem (\r
816 (VOID *)(UINTN) mStructureTableAddress,\r
817 (VOID *)(UINTN) EntryPointStructure->TableAddress,\r
818 EntryPointStructure->TableLength\r
819 );\r
820 \r
821 //\r
822 // Update TableAddress in Entry Point Structure\r
823 //\r
824 EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbiosEntryPoint;\r
825 EntryPointStructure->TableAddress = (UINT32)(UINTN) mStructureTableAddress;\r
826 \r
827 //\r
828 // Fixup checksums in the Entry Point Structure\r
829 //\r
830 EntryPointStructure->IntermediateChecksum = 0;\r
831 EntryPointStructure->EntryPointStructureChecksum = 0;\r
832\r
833 EntryPointStructure->IntermediateChecksum = \r
834 CalculateCheckSum8 (\r
835 (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString), \r
836 EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)\r
837 );\r
838 EntryPointStructure->EntryPointStructureChecksum =\r
839 CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength);\r
840}\r
bcecde14 841\r
842/**\r
843 Assign drive number to legacy HDD drives prior to booting an EFI\r
844 aware OS so the OS can access drives without an EFI driver.\r
845 Note: BBS compliant drives ARE NOT available until this call by\r
846 either shell or EFI.\r
847\r
848 @param This Protocol instance pointer.\r
849\r
850 @retval EFI_SUCCESS Drive numbers assigned\r
851\r
852**/\r
853EFI_STATUS\r
854GenericLegacyBoot (\r
855 IN EFI_LEGACY_BIOS_PROTOCOL *This\r
856 )\r
857{\r
858 EFI_STATUS Status;\r
859 LEGACY_BIOS_INSTANCE *Private;\r
860 EFI_IA32_REGISTER_SET Regs;\r
861 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
862 EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
863 UINTN CopySize;\r
864 VOID *AcpiPtr;\r
865 HDD_INFO *HddInfo;\r
866 HDD_INFO *LocalHddInfo;\r
867 UINTN Index;\r
868 EFI_COMPATIBILITY16_TABLE *Legacy16Table;\r
869 UINT32 *BdaPtr;\r
870 UINT16 HddCount;\r
871 UINT16 BbsCount;\r
872 BBS_TABLE *LocalBbsTable;\r
873 UINT32 *BaseVectorMaster;\r
874 EFI_TIME BootTime;\r
875 UINT32 LocalTime;\r
876 EFI_HANDLE IdeController;\r
877 UINTN HandleCount;\r
878 EFI_HANDLE *HandleBuffer;\r
bcecde14 879 VOID *AcpiTable;\r
880 UINTN ShadowAddress;\r
881 UINT32 Granularity;\r
bcecde14 882\r
883 LocalHddInfo = NULL;\r
884 HddCount = 0;\r
885 BbsCount = 0;\r
886 LocalBbsTable = NULL;\r
bcecde14 887\r
888 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
889 DEBUG_CODE (\r
890 DEBUG ((EFI_D_ERROR, "Start of legacy boot\n"));\r
891 );\r
892\r
893 Legacy16Table = Private->Legacy16Table;\r
894 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
895 HddInfo = &EfiToLegacy16BootTable->HddInfo[0];\r
896\r
897 LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
898\r
899 EfiToLegacy16BootTable->MajorVersion = EFI_TO_LEGACY_MAJOR_VERSION;\r
900 EfiToLegacy16BootTable->MinorVersion = EFI_TO_LEGACY_MINOR_VERSION;\r
bcecde14 901 \r
902 //\r
903 // If booting to a legacy OS then force HDD drives to the appropriate\r
904 // boot mode by calling GetIdeHandle.\r
905 // A reconnect -r can force all HDDs back to native mode.\r
906 //\r
907 IdeController = NULL;\r
908 if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
909 Status = LegacyBiosPlatform->GetPlatformHandle (\r
910 Private->LegacyBiosPlatform,\r
911 EfiGetPlatformIdeHandle,\r
912 0,\r
913 &HandleBuffer,\r
914 &HandleCount,\r
915 NULL\r
916 );\r
917 if (!EFI_ERROR (Status)) {\r
918 IdeController = HandleBuffer[0];\r
919 } \r
920 }\r
921 //\r
922 // Unlock the Legacy BIOS region\r
923 //\r
924 Private->LegacyRegion->UnLock (\r
925 Private->LegacyRegion,\r
926 0xE0000,\r
927 0x20000,\r
928 &Granularity\r
929 );\r
930\r
931 //\r
932 // Reconstruct the Legacy16 boot memory map\r
933 //\r
934 LegacyBiosBuildE820 (Private, &CopySize);\r
935 if (CopySize > Private->Legacy16Table->E820Length) {\r
936 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
937 Regs.X.AX = Legacy16GetTableAddress;\r
938 Regs.X.CX = (UINT16) CopySize;\r
939 Private->LegacyBios.FarCall86 (\r
940 &Private->LegacyBios,\r
941 Private->Legacy16Table->Compatibility16CallSegment,\r
942 Private->Legacy16Table->Compatibility16CallOffset,\r
943 &Regs,\r
944 NULL,\r
945 0\r
946 );\r
947\r
948 Private->Legacy16Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
949 Private->Legacy16Table->E820Length = (UINT32) CopySize;\r
950 if (Regs.X.AX != 0) {\r
951 DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n"));\r
952 } else {\r
953 CopyMem (\r
954 (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,\r
955 Private->E820Table,\r
956 CopySize\r
957 );\r
958 }\r
959 } else {\r
960 CopyMem (\r
961 (VOID *)(UINTN) Private->Legacy16Table->E820Pointer,\r
962 Private->E820Table,\r
963 CopySize\r
964 );\r
965 Private->Legacy16Table->E820Length = (UINT32) CopySize;\r
966 }\r
b6823730 967\r
bcecde14 968 //\r
969 // We do not ASSERT if SmbiosTable not found. It is possbile that a platform does not produce SmbiosTable.\r
970 //\r
b6823730 971 if (mReserveSmbiosEntryPoint == 0) {\r
bcecde14 972 DEBUG ((EFI_D_INFO, "Smbios table is not found!\n"));\r
973 }\r
b6823730
EL
974 CreateSmbiosTableInReservedMemory ();\r
975 EfiToLegacy16BootTable->SmbiosTable = (UINT32)(UINTN)mReserveSmbiosEntryPoint;\r
bcecde14 976\r
977 AcpiTable = NULL;\r
978 Status = EfiGetSystemConfigurationTable (\r
979 &gEfiAcpi20TableGuid,\r
980 &AcpiTable\r
981 );\r
982 if (EFI_ERROR (Status)) {\r
983 Status = EfiGetSystemConfigurationTable (\r
984 &gEfiAcpi10TableGuid,\r
985 &AcpiTable\r
986 );\r
987 }\r
988 //\r
989 // We do not ASSERT if AcpiTable not found. It is possbile that a platform does not produce AcpiTable.\r
990 //\r
991 if (AcpiTable == NULL) {\r
992 DEBUG ((EFI_D_INFO, "ACPI table is not found!\n"));\r
993 }\r
994 EfiToLegacy16BootTable->AcpiTable = (UINT32)(UINTN)AcpiTable;\r
995\r
996 //\r
997 // Get RSD Ptr table rev at offset 15 decimal\r
998 // Rev = 0 Length is 20 decimal\r
999 // Rev != 0 Length is UINT32 at offset 20 decimal\r
1000 //\r
1001 if (AcpiTable != NULL) {\r
1002\r
1003 AcpiPtr = AcpiTable;\r
1004 if (*((UINT8 *) AcpiPtr + 15) == 0) {\r
1005 CopySize = 20;\r
1006 } else {\r
1007 AcpiPtr = ((UINT8 *) AcpiPtr + 20);\r
1008 CopySize = (*(UINT32 *) AcpiPtr);\r
1009 }\r
1010\r
1011 CopyMem (\r
1012 (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer,\r
1013 AcpiTable,\r
1014 CopySize\r
1015 );\r
1016 }\r
1017 //\r
1018 // Make sure all PCI Interrupt Line register are programmed to match 8259\r
1019 //\r
1020 PciProgramAllInterruptLineRegisters (Private);\r
1021\r
1022 //\r
1023 // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters\r
1024 // can lock it.\r
1025 //\r
1026 Private->LegacyRegion->UnLock (\r
1027 Private->LegacyRegion,\r
1028 Private->BiosStart,\r
1029 Private->LegacyBiosImageSize,\r
1030 &Granularity\r
1031 );\r
1032\r
1033 //\r
1034 // Configure Legacy Device Magic\r
1035 //\r
1036 // Only do this code if booting legacy OS\r
1037 //\r
1038 if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
1039 UpdateSioData (Private);\r
1040 }\r
1041 //\r
1042 // Setup BDA and EBDA standard areas before Legacy Boot\r
1043 //\r
1044 LegacyBiosCompleteBdaBeforeBoot (Private);\r
1045 LegacyBiosCompleteStandardCmosBeforeBoot (Private);\r
1046\r
1047 //\r
1048 // We must build IDE data, if it hasn't been done, before PciShadowRoms\r
1049 // to insure EFI drivers are connected.\r
1050 //\r
1051 LegacyBiosBuildIdeData (Private, &HddInfo, 1);\r
1052 UpdateAllIdentifyDriveData (Private);\r
1053\r
1054 //\r
1055 // Clear IO BAR, if IDE controller in legacy mode.\r
1056 //\r
1057 InitLegacyIdeController (IdeController);\r
1058\r
1059 //\r
1060 // Generate number of ticks since midnight for BDA. DOS requires this\r
1061 // for its time. We have to make assumptions as to how long following\r
1062 // code takes since after PciShadowRoms PciIo is gone. Place result in\r
1063 // 40:6C-6F\r
1064 //\r
1065 // Adjust value by 1 second.\r
1066 //\r
1067 gRT->GetTime (&BootTime, NULL);\r
1068 LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;\r
1069 LocalTime += 1;\r
1070\r
1071 //\r
1072 // Multiply result by 18.2 for number of ticks since midnight.\r
1073 // Use 182/10 to avoid floating point math.\r
1074 //\r
1075 LocalTime = (LocalTime * 182) / 10;\r
d057d8c4 1076 DisableNullDetection ();\r
bcecde14 1077 BdaPtr = (UINT32 *) (UINTN)0x46C;\r
1078 *BdaPtr = LocalTime;\r
d057d8c4 1079 EnableNullDetection ();\r
bcecde14 1080\r
1081 //\r
1082 // Shadow PCI ROMs. We must do this near the end since this will kick\r
1083 // of Native EFI drivers that may be needed to collect info for Legacy16\r
1084 //\r
1085 // WARNING: PciIo is gone after this call.\r
1086 //\r
1087 PciShadowRoms (Private);\r
1088\r
1089 //\r
1090 // Shadow PXE base code, BIS etc.\r
1091 //\r
1092 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity);\r
1093 ShadowAddress = Private->OptionRom;\r
1094 Private->LegacyBiosPlatform->PlatformHooks (\r
1095 Private->LegacyBiosPlatform,\r
1096 EfiPlatformHookShadowServiceRoms,\r
1097 0,\r
1098 0,\r
1099 &ShadowAddress,\r
1100 Legacy16Table,\r
1101 NULL\r
1102 );\r
1103 Private->OptionRom = (UINT32)ShadowAddress;\r
1104 //\r
1105 // Register Legacy SMI Handler\r
1106 //\r
1107 LegacyBiosPlatform->SmmInit (\r
1108 LegacyBiosPlatform,\r
1109 EfiToLegacy16BootTable\r
1110 );\r
1111\r
1112 //\r
1113 // Let platform code know the boot options\r
1114 //\r
1115 LegacyBiosGetBbsInfo (\r
1116 This,\r
1117 &HddCount,\r
1118 &LocalHddInfo,\r
1119 &BbsCount,\r
1120 &LocalBbsTable\r
1121 );\r
1122\r
7dad86fc
RN
1123 DEBUG_CODE (\r
1124 PrintPciInterruptRegister ();\r
1125 PrintBbsTable (LocalBbsTable);\r
1126 PrintHddInfo (LocalHddInfo);\r
1127 );\r
bcecde14 1128 //\r
1129 // If drive wasn't spun up then BuildIdeData may have found new drives.\r
1130 // Need to update BBS boot priority.\r
1131 //\r
1132 for (Index = 0; Index < MAX_IDE_CONTROLLER; Index++) {\r
1133 if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] != 0) &&\r
1134 (LocalBbsTable[2 * Index + 1].BootPriority == BBS_IGNORE_ENTRY)\r
1135 ) {\r
1136 LocalBbsTable[2 * Index + 1].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
1137 }\r
1138\r
1139 if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] != 0) &&\r
1140 (LocalBbsTable[2 * Index + 2].BootPriority == BBS_IGNORE_ENTRY)\r
1141 ) {\r
1142 LocalBbsTable[2 * Index + 2].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
1143 }\r
1144 }\r
1145\r
1146 Private->LegacyRegion->UnLock (\r
1147 Private->LegacyRegion,\r
1148 0xc0000,\r
1149 0x40000,\r
1150 &Granularity\r
1151 );\r
1152\r
1153 LegacyBiosPlatform->PrepareToBoot (\r
1154 LegacyBiosPlatform,\r
1155 mBbsDevicePathPtr,\r
1156 mBbsTable,\r
1157 mLoadOptionsSize,\r
1158 mLoadOptions,\r
1159 (VOID *) &Private->IntThunk->EfiToLegacy16BootTable\r
1160 );\r
1161\r
1162 //\r
1163 // If no boot device return to BDS\r
1164 //\r
1165 if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
1166 for (Index = 0; Index < BbsCount; Index++){\r
1167 if ((LocalBbsTable[Index].BootPriority != BBS_DO_NOT_BOOT_FROM) &&\r
1168 (LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&\r
1169 (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY)) {\r
1170 break;\r
1171 }\r
1172 }\r
1173 if (Index == BbsCount) {\r
1174 return EFI_DEVICE_ERROR;\r
1175 }\r
1176 }\r
1177 //\r
1178 // Let the Legacy16 code know the device path type for legacy boot\r
1179 //\r
1180 EfiToLegacy16BootTable->DevicePathType = mBbsDevicePathPtr->DeviceType;\r
1181\r
1182 //\r
1183 // Copy MP table, if it exists.\r
1184 //\r
1185 LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable);\r
1186\r
1187 if (!Private->LegacyBootEntered) {\r
1188 //\r
1189 // Copy OEM INT Data, if it exists. Note: This code treats any data\r
1190 // as a bag of bits and knows nothing of the contents nor cares.\r
1191 // Contents are IBV specific.\r
1192 //\r
1193 LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData);\r
1194\r
1195 //\r
1196 // Copy OEM16 Data, if it exists.Note: This code treats any data\r
1197 // as a bag of bits and knows nothing of the contents nor cares.\r
1198 // Contents are IBV specific.\r
1199 //\r
1200 LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data);\r
1201\r
1202 //\r
1203 // Copy OEM32 Data, if it exists.Note: This code treats any data\r
1204 // as a bag of bits and knows nothing of the contents nor cares.\r
1205 // Contents are IBV specific.\r
1206 //\r
1207 LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data);\r
1208 }\r
1209\r
1210 //\r
1211 // Call into Legacy16 code to prepare for INT 19h\r
1212 //\r
1213 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
1214 Regs.X.AX = Legacy16PrepareToBoot;\r
1215\r
1216 //\r
1217 // Pass in handoff data\r
1218 //\r
81c0d6e9 1219 Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable);\r
1220 Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINTN)EfiToLegacy16BootTable);\r
bcecde14 1221\r
1222 Private->LegacyBios.FarCall86 (\r
1223 This,\r
1224 Private->Legacy16CallSegment,\r
1225 Private->Legacy16CallOffset,\r
1226 &Regs,\r
1227 NULL,\r
1228 0\r
1229 );\r
1230\r
1231 if (Regs.X.AX != 0) {\r
1232 return EFI_DEVICE_ERROR;\r
1233 }\r
1234 //\r
1235 // Lock the Legacy BIOS region\r
1236 //\r
1237 Private->LegacyRegion->Lock (\r
1238 Private->LegacyRegion,\r
1239 0xc0000,\r
1240 0x40000,\r
1241 &Granularity\r
1242 );\r
ff247afd
DW
1243\r
1244 if ((Private->Legacy16Table->TableLength >= OFFSET_OF (EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) &&\r
1245 ((Private->Legacy16Table->UmaAddress != 0) && (Private->Legacy16Table->UmaSize != 0))) {\r
1246 //\r
1247 // Here we could reduce UmaAddress down as far as Private->OptionRom, taking into\r
1248 // account the granularity of the access control.\r
1249 //\r
1250 DEBUG((EFI_D_INFO, "Unlocking UMB RAM region 0x%x-0x%x\n", Private->Legacy16Table->UmaAddress,\r
1251 Private->Legacy16Table->UmaAddress + Private->Legacy16Table->UmaSize));\r
1252\r
1253 Private->LegacyRegion->UnLock (\r
1254 Private->LegacyRegion,\r
1255 Private->Legacy16Table->UmaAddress,\r
1256 Private->Legacy16Table->UmaSize,\r
1257 &Granularity\r
1258 );\r
1259 }\r
1260\r
bcecde14 1261 //\r
1262 // Lock attributes of the Legacy Region if chipset supports\r
1263 //\r
1264 Private->LegacyRegion->BootLock (\r
1265 Private->LegacyRegion,\r
1266 0xc0000,\r
1267 0x40000,\r
1268 &Granularity\r
1269 );\r
1270\r
1271 //\r
1272 // Call into Legacy16 code to do the INT 19h\r
1273 //\r
1274 EnableAllControllers (Private);\r
1275 if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
c8a2836a
EL
1276\r
1277 //\r
1278 // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT\r
1279 //\r
1280 EfiSignalEventLegacyBoot ();\r
1281\r
cb38c322 1282 //\r
c8a2836a 1283 // Report Status Code to indicate legacy boot event was signalled\r
cb38c322 1284 //\r
1285 REPORT_STATUS_CODE (\r
1286 EFI_PROGRESS_CODE,\r
1287 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT)\r
1288 );\r
1289\r
bcecde14 1290 DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n"));\r
3512efa9 1291\r
1292 //\r
1293 // Disable DXE Timer while executing in real mode\r
bcecde14 1294 //\r
3512efa9 1295 Private->Timer->SetTimerPeriod (Private->Timer, 0);\r
1296 \r
bcecde14 1297 //\r
3512efa9 1298 // Save and disable interrupt of debug timer\r
1299 //\r
1300 SaveAndSetDebugTimerInterrupt (FALSE);\r
1301\r
bcecde14 1302\r
1303 //\r
1304 // Put the 8259 into its legacy mode by reprogramming the vector bases\r
1305 //\r
1306 Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE);\r
1307 //\r
1308 // PC History\r
1309 // The original PC used INT8-F for master PIC. Since these mapped over\r
1310 // processor exceptions TIANO moved the master PIC to INT68-6F.\r
1311 // We need to set these back to the Legacy16 unexpected interrupt(saved\r
1312 // in LegacyBios.c) since some OS see that these have values different from\r
1313 // what is expected and invoke them. Since the legacy OS corrupts EFI\r
1314 // memory, there is no handler for these interrupts and OS blows up.\r
1315 //\r
1316 // We need to save the TIANO values for the rare case that the Legacy16\r
1317 // code cannot boot but knows memory hasn't been destroyed.\r
1318 //\r
1319 // To compound the problem, video takes over one of these INTS and must be\r
1320 // be left.\r
1321 // @bug - determine if video hooks INT(in which case we must find new\r
1322 // set of TIANO vectors) or takes it over.\r
1323 //\r
1324 //\r
d057d8c4 1325 DisableNullDetection ();\r
bcecde14 1326 BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
1327 for (Index = 0; Index < 8; Index++) {\r
1328 Private->ThunkSavedInt[Index] = BaseVectorMaster[Index];\r
1329 if (Private->ThunkSeg == (UINT16) (BaseVectorMaster[Index] >> 16)) {\r
1330 BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt);\r
1331 }\r
1332 }\r
d057d8c4 1333 EnableNullDetection ();\r
bcecde14 1334\r
1335 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
1336 Regs.X.AX = Legacy16Boot;\r
1337\r
1338 Private->LegacyBios.FarCall86 (\r
1339 This,\r
1340 Private->Legacy16CallSegment,\r
1341 Private->Legacy16CallOffset,\r
1342 &Regs,\r
1343 NULL,\r
1344 0\r
1345 );\r
1346\r
d057d8c4 1347 DisableNullDetection ();\r
bcecde14 1348 BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
1349 for (Index = 0; Index < 8; Index++) {\r
1350 BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];\r
1351 }\r
d057d8c4 1352 EnableNullDetection ();\r
bcecde14 1353 }\r
1354 Private->LegacyBootEntered = TRUE;\r
1355 if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {\r
1356 //\r
1357 // Should never return unless never passed control to 0:7c00(first stage\r
1358 // OS loader) and only then if no bootable device found.\r
1359 //\r
1360 return EFI_DEVICE_ERROR;\r
1361 } else {\r
1362 //\r
1363 // If boot to EFI then expect to return to caller\r
1364 //\r
1365 return EFI_SUCCESS;\r
1366 }\r
1367}\r
1368\r
1369\r
1370/**\r
1371 Assign drive number to legacy HDD drives prior to booting an EFI\r
1372 aware OS so the OS can access drives without an EFI driver.\r
1373 Note: BBS compliant drives ARE NOT available until this call by\r
1374 either shell or EFI.\r
1375\r
1376 @param This Protocol instance pointer.\r
1377 @param BbsCount Number of BBS_TABLE structures\r
1378 @param BbsTable List BBS entries\r
1379\r
1380 @retval EFI_SUCCESS Drive numbers assigned\r
1381\r
1382**/\r
1383EFI_STATUS\r
1384EFIAPI\r
1385LegacyBiosPrepareToBootEfi (\r
1386 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
1387 OUT UINT16 *BbsCount,\r
1388 OUT BBS_TABLE **BbsTable\r
1389 )\r
1390{\r
1391 EFI_STATUS Status;\r
1392 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
1393 LEGACY_BIOS_INSTANCE *Private;\r
1394\r
1395 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
1396 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
1397 mBootMode = BOOT_EFI_OS;\r
1398 mBbsDevicePathPtr = NULL;\r
1399 Status = GenericLegacyBoot (This);\r
1400 *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
1401 *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));\r
1402 return Status;\r
1403}\r
1404\r
1405/**\r
1406 To boot from an unconventional device like parties and/or execute HDD diagnostics.\r
1407\r
1408 @param This Protocol instance pointer.\r
1409 @param Attributes How to interpret the other input parameters\r
1410 @param BbsEntry The 0-based index into the BbsTable for the parent\r
1411 device.\r
1412 @param BeerData Pointer to the 128 bytes of ram BEER data.\r
1413 @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The\r
1414 caller must provide a pointer to the specific Service\r
1415 Area and not the start all Service Areas.\r
1416\r
1417 @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error.\r
1418\r
1419***/\r
1420EFI_STATUS\r
1421EFIAPI\r
1422LegacyBiosBootUnconventionalDevice (\r
1423 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
1424 IN UDC_ATTRIBUTES Attributes,\r
1425 IN UINTN BbsEntry,\r
1426 IN VOID *BeerData,\r
1427 IN VOID *ServiceAreaData\r
1428 )\r
1429{\r
1430 EFI_STATUS Status;\r
1431 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
1432 LEGACY_BIOS_INSTANCE *Private;\r
1433 UD_TABLE *UcdTable;\r
1434 UINTN Index;\r
1435 UINT16 BootPriority;\r
1436 BBS_TABLE *BbsTable;\r
1437\r
1438 BootPriority = 0;\r
1439 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
1440 mBootMode = BOOT_UNCONVENTIONAL_DEVICE;\r
1441 mBbsDevicePathPtr = &mBbsDevicePathNode;\r
1442 mAttributes = Attributes;\r
1443 mBbsEntry = BbsEntry;\r
1444 mBeerData = BeerData, mServiceAreaData = ServiceAreaData;\r
1445\r
1446 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
1447\r
1448 //\r
1449 // Do input parameter checking\r
1450 //\r
1451 if ((Attributes.DirectoryServiceValidity == 0) &&\r
1452 (Attributes.RabcaUsedFlag == 0) &&\r
1453 (Attributes.ExecuteHddDiagnosticsFlag == 0)\r
1454 ) {\r
1455 return EFI_INVALID_PARAMETER;\r
1456 }\r
1457\r
1458 if (((Attributes.DirectoryServiceValidity != 0) && (ServiceAreaData == NULL)) ||\r
1459 (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != 0) && (BeerData == NULL))\r
1460 ) {\r
1461 return EFI_INVALID_PARAMETER;\r
1462 }\r
1463\r
1464 UcdTable = (UD_TABLE *) AllocatePool (\r
1465 sizeof (UD_TABLE)\r
1466 );\r
1467 if (NULL == UcdTable) {\r
1468 return EFI_OUT_OF_RESOURCES;\r
1469 }\r
1470\r
1471 EfiToLegacy16BootTable->UnconventionalDeviceTable = (UINT32)(UINTN)UcdTable;\r
1472 UcdTable->Attributes = Attributes;\r
1473 UcdTable->BbsTableEntryNumberForParentDevice = (UINT8) BbsEntry;\r
1474 //\r
1475 // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM\r
1476 // to assign drive numbers but bot boot from. Only newly created entries\r
1477 // will be valid.\r
1478 //\r
1479 BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;\r
1480 for (Index = 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Index++) {\r
1481 BbsTable[Index].BootPriority = BBS_DO_NOT_BOOT_FROM;\r
1482 }\r
1483 //\r
1484 // If parent is onboard IDE then assign controller & device number\r
1485 // else they are 0.\r
1486 //\r
1487 if (BbsEntry < MAX_IDE_CONTROLLER * 2) {\r
1488 UcdTable->DeviceNumber = (UINT8) ((BbsEntry - 1) % 2);\r
1489 }\r
1490\r
1491 if (BeerData != NULL) {\r
1492 CopyMem (\r
1493 (VOID *) UcdTable->BeerData,\r
1494 BeerData,\r
1495 (UINTN) 128\r
1496 );\r
1497 }\r
1498\r
1499 if (ServiceAreaData != NULL) {\r
1500 CopyMem (\r
1501 (VOID *) UcdTable->ServiceAreaData,\r
1502 ServiceAreaData,\r
1503 (UINTN) 64\r
1504 );\r
1505 }\r
1506 //\r
1507 // For each new entry do the following:\r
1508 // 1. Increment current number of BBS entries\r
1509 // 2. Copy parent entry to new entry.\r
1510 // 3. Zero out BootHandler Offset & segment\r
1511 // 4. Set appropriate device type. BEV(0x80) for HDD diagnostics\r
1512 // and Floppy(0x01) for PARTIES boot.\r
1513 // 5. Assign new priority.\r
1514 //\r
1515 if ((Attributes.ExecuteHddDiagnosticsFlag) != 0) {\r
1516 EfiToLegacy16BootTable->NumberBbsEntries += 1;\r
1517\r
1518 CopyMem (\r
1519 (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,\r
1520 (VOID *) &BbsTable[BbsEntry].BootPriority,\r
1521 sizeof (BBS_TABLE)\r
1522 );\r
1523\r
1524 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0;\r
1525 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;\r
1526 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x80;\r
1527\r
1528 UcdTable->BbsTableEntryNumberForHddDiag = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);\r
1529\r
1530 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;\r
1531 BootPriority += 1;\r
1532\r
1533 //\r
1534 // Set device type as BBS_TYPE_DEV for PARTIES diagnostic\r
1535 //\r
1536 mBbsDevicePathNode.DeviceType = BBS_TYPE_BEV;\r
1537 }\r
1538\r
1539 if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != 0) {\r
1540 EfiToLegacy16BootTable->NumberBbsEntries += 1;\r
1541 CopyMem (\r
1542 (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority,\r
1543 (VOID *) &BbsTable[BbsEntry].BootPriority,\r
1544 sizeof (BBS_TABLE)\r
1545 );\r
1546\r
1547 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = 0;\r
1548 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = 0;\r
1549 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = 0x01;\r
1550 UcdTable->BbsTableEntryNumberForBoot = (UINT8) (EfiToLegacy16BootTable->NumberBbsEntries - 1);\r
1551 BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority = BootPriority;\r
1552\r
1553 //\r
1554 // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy\r
1555 //\r
1556 mBbsDevicePathNode.DeviceType = BBS_TYPE_FLOPPY;\r
1557 }\r
1558 //\r
1559 // Build the BBS Device Path for this boot selection\r
1560 //\r
1561 mBbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
1562 mBbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
1563 SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
1564 mBbsDevicePathNode.StatusFlag = 0;\r
1565 mBbsDevicePathNode.String[0] = 0;\r
1566\r
1567 Status = GenericLegacyBoot (This);\r
1568 return Status;\r
1569}\r
1570\r
1571/**\r
1572 Attempt to legacy boot the BootOption. If the EFI contexted has been\r
1573 compromised this function will not return.\r
1574\r
1575 @param This Protocol instance pointer.\r
1576 @param BbsDevicePath EFI Device Path from BootXXXX variable.\r
1577 @param LoadOptionsSize Size of LoadOption in size.\r
1578 @param LoadOptions LoadOption from BootXXXX variable\r
1579\r
1580 @retval EFI_SUCCESS Removable media not present\r
1581\r
1582**/\r
1583EFI_STATUS\r
1584EFIAPI\r
1585LegacyBiosLegacyBoot (\r
1586 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
1587 IN BBS_BBS_DEVICE_PATH *BbsDevicePath,\r
1588 IN UINT32 LoadOptionsSize,\r
1589 IN VOID *LoadOptions\r
1590 )\r
1591{\r
1592 EFI_STATUS Status;\r
1593\r
1594 mBbsDevicePathPtr = BbsDevicePath;\r
1595 mLoadOptionsSize = LoadOptionsSize;\r
1596 mLoadOptions = LoadOptions;\r
1597 mBootMode = BOOT_LEGACY_OS;\r
1598 Status = GenericLegacyBoot (This);\r
1599\r
1600 return Status;\r
1601}\r
1602\r
1603/**\r
1604 Convert EFI Memory Type to E820 Memory Type.\r
1605\r
1606 @param Type EFI Memory Type\r
1607\r
1608 @return ACPI Memory Type for EFI Memory Type\r
1609\r
1610**/\r
1611EFI_ACPI_MEMORY_TYPE\r
1612EfiMemoryTypeToE820Type (\r
1613 IN UINT32 Type\r
1614 )\r
1615{\r
1616 switch (Type) {\r
1617 case EfiLoaderCode:\r
1618 case EfiLoaderData:\r
1619 case EfiBootServicesCode:\r
1620 case EfiBootServicesData:\r
1621 case EfiConventionalMemory:\r
800765aa
EL
1622 //\r
1623 // The memory of EfiRuntimeServicesCode and EfiRuntimeServicesData are\r
8e822856 1624 // usable memory for legacy OS, because legacy OS is not aware of EFI runtime concept.\r
800765aa
EL
1625 // In ACPI specification, EfiRuntimeServiceCode and EfiRuntimeServiceData\r
1626 // should be mapped to AddressRangeReserved. This statement is for UEFI OS, not for legacy OS.\r
1627 //\r
bcecde14 1628 case EfiRuntimeServicesCode:\r
1629 case EfiRuntimeServicesData:\r
1630 return EfiAcpiAddressRangeMemory;\r
1631\r
b483e74d
LG
1632 case EfiPersistentMemory:\r
1633 return EfiAddressRangePersistentMemory;\r
1634\r
bcecde14 1635 case EfiACPIReclaimMemory:\r
1636 return EfiAcpiAddressRangeACPI;\r
1637\r
1638 case EfiACPIMemoryNVS:\r
1639 return EfiAcpiAddressRangeNVS;\r
1640\r
1641 //\r
1642 // All other types map to reserved.\r
1643 // Adding the code just waists FLASH space.\r
1644 //\r
1645 // case EfiReservedMemoryType:\r
1646 // case EfiUnusableMemory:\r
1647 // case EfiMemoryMappedIO:\r
1648 // case EfiMemoryMappedIOPortSpace:\r
1649 // case EfiPalCode:\r
1650 //\r
1651 default:\r
1652 return EfiAcpiAddressRangeReserved;\r
1653 }\r
1654}\r
1655\r
1656/**\r
1657 Build the E820 table.\r
1658\r
1659 @param Private Legacy BIOS Instance data\r
1660 @param Size Size of E820 Table\r
1661\r
1662 @retval EFI_SUCCESS It should always work.\r
1663\r
1664**/\r
1665EFI_STATUS\r
1666LegacyBiosBuildE820 (\r
1667 IN LEGACY_BIOS_INSTANCE *Private,\r
1668 OUT UINTN *Size\r
1669 )\r
1670{\r
1671 EFI_STATUS Status;\r
1672 EFI_E820_ENTRY64 *E820Table;\r
1673 EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;\r
1674 EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;\r
1675 EFI_MEMORY_DESCRIPTOR *EfiEntry;\r
1676 EFI_MEMORY_DESCRIPTOR *NextEfiEntry;\r
1677 EFI_MEMORY_DESCRIPTOR TempEfiEntry;\r
1678 UINTN EfiMemoryMapSize;\r
1679 UINTN EfiMapKey;\r
1680 UINTN EfiDescriptorSize;\r
1681 UINT32 EfiDescriptorVersion;\r
1682 UINTN Index;\r
1683 EFI_PEI_HOB_POINTERS Hob;\r
1684 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
1685 UINTN TempIndex;\r
1686 UINTN IndexSort;\r
1687 UINTN TempNextIndex;\r
1688 EFI_E820_ENTRY64 TempE820;\r
1689 EFI_ACPI_MEMORY_TYPE TempType;\r
1690 BOOLEAN ChangedFlag;\r
1691 UINTN Above1MIndex;\r
1692 UINT64 MemoryBlockLength;\r
1693\r
1694 E820Table = (EFI_E820_ENTRY64 *) Private->E820Table;\r
1695\r
1696 //\r
1697 // Get the EFI memory map.\r
1698 //\r
1699 EfiMemoryMapSize = 0;\r
1700 EfiMemoryMap = NULL;\r
1701 Status = gBS->GetMemoryMap (\r
1702 &EfiMemoryMapSize,\r
1703 EfiMemoryMap,\r
1704 &EfiMapKey,\r
1705 &EfiDescriptorSize,\r
1706 &EfiDescriptorVersion\r
1707 );\r
1708 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
1709\r
1710 do {\r
1711 //\r
1712 // Use size returned back plus 1 descriptor for the AllocatePool.\r
1713 // We don't just multiply by 2 since the "for" loop below terminates on\r
1714 // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize\r
1715 // we process bogus entries and create bogus E820 entries.\r
1716 //\r
1717 EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);\r
1718 ASSERT (EfiMemoryMap != NULL);\r
1719 Status = gBS->GetMemoryMap (\r
1720 &EfiMemoryMapSize,\r
1721 EfiMemoryMap,\r
1722 &EfiMapKey,\r
1723 &EfiDescriptorSize,\r
1724 &EfiDescriptorVersion\r
1725 );\r
1726 if (EFI_ERROR (Status)) {\r
1727 FreePool (EfiMemoryMap);\r
1728 }\r
1729 } while (Status == EFI_BUFFER_TOO_SMALL);\r
1730\r
1731 ASSERT_EFI_ERROR (Status);\r
1732\r
1733 //\r
1734 // Punch in the E820 table for memory less than 1 MB.\r
1735 // Assume ZeroMem () has been done on data structure.\r
1736 //\r
1737 //\r
1738 // First entry is 0 to (640k - EBDA)\r
1739 //\r
d057d8c4 1740 DisableNullDetection ();\r
bcecde14 1741 E820Table[0].BaseAddr = 0;\r
1742 E820Table[0].Length = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);\r
1743 E820Table[0].Type = EfiAcpiAddressRangeMemory;\r
d057d8c4 1744 EnableNullDetection ();\r
bcecde14 1745\r
1746 //\r
1747 // Second entry is (640k - EBDA) to 640k\r
1748 //\r
1749 E820Table[1].BaseAddr = E820Table[0].Length;\r
1750 E820Table[1].Length = (UINT64) ((640 * 1024) - E820Table[0].Length);\r
1751 E820Table[1].Type = EfiAcpiAddressRangeReserved;\r
1752\r
1753 //\r
1754 // Third Entry is legacy BIOS\r
1755 // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas\r
1756 // to page in memory under 1MB.\r
1757 // Omit region from 0xE0000 to start of BIOS, if any. This can be\r
1758 // used for a multiple reasons including OPROMS.\r
1759 //\r
1760\r
1761 //\r
1762 // The CSM binary image size is not the actually size that CSM binary used,\r
1763 // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CSM binary.\r
1764 //\r
1765 E820Table[2].BaseAddr = 0xE0000;\r
1766 E820Table[2].Length = 0x20000;\r
1767 E820Table[2].Type = EfiAcpiAddressRangeReserved;\r
1768\r
1769 Above1MIndex = 2;\r
1770\r
1771 //\r
1772 // Process the EFI map to produce E820 map;\r
1773 //\r
1774\r
1775 //\r
1776 // Sort memory map from low to high\r
1777 //\r
1778 EfiEntry = EfiMemoryMap;\r
1779 NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
1780 EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);\r
1781 while (EfiEntry < EfiMemoryMapEnd) {\r
1782 while (NextEfiEntry < EfiMemoryMapEnd) {\r
1783 if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {\r
1784 CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
1785 CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
1786 CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
1787 }\r
1788\r
1789 NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);\r
1790 }\r
1791\r
1792 EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
1793 NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
1794 }\r
1795\r
1796 EfiEntry = EfiMemoryMap;\r
1797 EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);\r
1798 for (Index = Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EFI_MAX_E820_ENTRY - 1); ) {\r
1799 MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));\r
1800 if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) {\r
1801 //\r
1802 // Skip the memory block is under 1MB\r
1803 //\r
1804 } else {\r
1805 if (EfiEntry->PhysicalStart < 0x100000) {\r
1806 //\r
1807 // When the memory block spans below 1MB, ensure the memory block start address is at least 1MB\r
1808 //\r
1809 MemoryBlockLength -= 0x100000 - EfiEntry->PhysicalStart;\r
1810 EfiEntry->PhysicalStart = 0x100000;\r
1811 }\r
1812\r
1813 //\r
1814 // Convert memory type to E820 type\r
1815 //\r
1816 TempType = EfiMemoryTypeToE820Type (EfiEntry->Type);\r
1817\r
1818 if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) {\r
1819 //\r
1820 // Grow an existing entry\r
1821 //\r
1822 E820Table[Index].Length += MemoryBlockLength;\r
1823 } else {\r
1824 //\r
1825 // Make a new entry\r
1826 //\r
1827 ++Index;\r
1828 E820Table[Index].BaseAddr = EfiEntry->PhysicalStart;\r
1829 E820Table[Index].Length = MemoryBlockLength;\r
1830 E820Table[Index].Type = TempType;\r
1831 }\r
1832 }\r
1833 EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);\r
1834 }\r
1835\r
1836 FreePool (EfiMemoryMap);\r
1837\r
1838 //\r
1839 // Process the reserved memory map to produce E820 map ;\r
1840 //\r
1841 for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
1842 if (Hob.Raw != NULL && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
1843 ResourceHob = Hob.ResourceDescriptor;\r
1844 if (((ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO) ||\r
1845 (ResourceHob->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE) ||\r
1846 (ResourceHob->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) ) &&\r
1847 (ResourceHob->PhysicalStart > 0x100000) &&\r
1848 (Index < EFI_MAX_E820_ENTRY - 1)) {\r
1849 ++Index;\r
1850 E820Table[Index].BaseAddr = ResourceHob->PhysicalStart;\r
1851 E820Table[Index].Length = ResourceHob->ResourceLength;\r
1852 E820Table[Index].Type = EfiAcpiAddressRangeReserved;\r
1853 }\r
1854 }\r
1855 }\r
1856\r
1857 Index ++;\r
1858 Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;\r
1859 Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;\r
1860 Private->NumberE820Entries = (UINT32)Index;\r
1861 *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));\r
1862\r
1863 //\r
1864 // Sort E820Table from low to high\r
1865 //\r
1866 for (TempIndex = 0; TempIndex < Index; TempIndex++) {\r
1867 ChangedFlag = FALSE;\r
1868 for (TempNextIndex = 1; TempNextIndex < Index - TempIndex; TempNextIndex++) {\r
1869 if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex].BaseAddr) {\r
1870 ChangedFlag = TRUE;\r
1871 TempE820.BaseAddr = E820Table[TempNextIndex - 1].BaseAddr;\r
1872 TempE820.Length = E820Table[TempNextIndex - 1].Length;\r
1873 TempE820.Type = E820Table[TempNextIndex - 1].Type;\r
1874\r
1875 E820Table[TempNextIndex - 1].BaseAddr = E820Table[TempNextIndex].BaseAddr;\r
1876 E820Table[TempNextIndex - 1].Length = E820Table[TempNextIndex].Length;\r
1877 E820Table[TempNextIndex - 1].Type = E820Table[TempNextIndex].Type;\r
1878\r
1879 E820Table[TempNextIndex].BaseAddr = TempE820.BaseAddr;\r
1880 E820Table[TempNextIndex].Length = TempE820.Length;\r
1881 E820Table[TempNextIndex].Type = TempE820.Type;\r
1882 }\r
1883 }\r
1884\r
1885 if (!ChangedFlag) {\r
1886 break;\r
1887 }\r
1888 }\r
1889\r
1890 //\r
1891 // Remove the overlap range\r
1892 //\r
1893 for (TempIndex = 1; TempIndex < Index; TempIndex++) {\r
1894 if (E820Table[TempIndex - 1].BaseAddr <= E820Table[TempIndex].BaseAddr &&\r
1895 ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Length) >=\r
1896 (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) {\r
1897 //\r
1898 //Overlap range is found\r
1899 //\r
1900 ASSERT (E820Table[TempIndex - 1].Type == E820Table[TempIndex].Type);\r
1901\r
1902 if (TempIndex == Index - 1) {\r
1903 E820Table[TempIndex].BaseAddr = 0;\r
1904 E820Table[TempIndex].Length = 0;\r
1905 E820Table[TempIndex].Type = (EFI_ACPI_MEMORY_TYPE) 0;\r
1906 Index--;\r
1907 break;\r
1908 } else {\r
1909 for (IndexSort = TempIndex; IndexSort < Index - 1; IndexSort ++) {\r
1910 E820Table[IndexSort].BaseAddr = E820Table[IndexSort + 1].BaseAddr;\r
1911 E820Table[IndexSort].Length = E820Table[IndexSort + 1].Length;\r
1912 E820Table[IndexSort].Type = E820Table[IndexSort + 1].Type;\r
1913 }\r
1914 Index--;\r
1915 }\r
1916 }\r
1917 }\r
1918\r
1919\r
1920\r
1921 Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries = (UINT32)Index;\r
1922 Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries = (UINT32)Index;\r
1923 Private->NumberE820Entries = (UINT32)Index;\r
1924 *Size = (UINTN) (Index * sizeof (EFI_E820_ENTRY64));\r
1925\r
1926 //\r
1927 // Determine OS usable memory above 1Mb\r
1928 //\r
1929 Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb = 0x0000;\r
1930 for (TempIndex = Above1MIndex; TempIndex < Index; TempIndex++) {\r
1931 if (E820Table[TempIndex].BaseAddr >= 0x100000 && E820Table[TempIndex].BaseAddr < 0x100000000ULL) { // not include above 4G memory\r
1932 //\r
1933 // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dumps all ACPI tables.\r
1934 //\r
1935 if ((E820Table[TempIndex].Type == EfiAcpiAddressRangeMemory) || (E820Table[TempIndex].Type == EfiAcpiAddressRangeACPI)) {\r
1936 Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb += (UINT32) (E820Table[TempIndex].Length);\r
1937 } else {\r
1938 break; // break at first not normal memory, because SMM may use reserved memory.\r
1939 }\r
1940 }\r
1941 }\r
1942\r
1943 Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb = Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb;\r
1944\r
1945 //\r
1946 // Print DEBUG information\r
1947 //\r
1948 for (TempIndex = 0; TempIndex < Index; TempIndex++) {\r
1949 DEBUG((EFI_D_INFO, "E820[%2d]: 0x%16lx ---- 0x%16lx, Type = 0x%x \n",\r
1950 TempIndex,\r
1951 E820Table[TempIndex].BaseAddr,\r
1952 (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length),\r
1953 E820Table[TempIndex].Type\r
1954 ));\r
1955 }\r
1956\r
1957 return EFI_SUCCESS;\r
1958}\r
1959\r
1960\r
1961/**\r
1962 Fill in the standard BDA and EBDA stuff prior to legacy Boot\r
1963\r
1964 @param Private Legacy BIOS Instance data\r
1965\r
1966 @retval EFI_SUCCESS It should always work.\r
1967\r
1968**/\r
1969EFI_STATUS\r
1970LegacyBiosCompleteBdaBeforeBoot (\r
1971 IN LEGACY_BIOS_INSTANCE *Private\r
1972 )\r
1973{\r
1974 BDA_STRUC *Bda;\r
1975 UINT16 MachineConfig;\r
1976 DEVICE_PRODUCER_DATA_HEADER *SioPtr;\r
1977\r
d057d8c4
JW
1978 DisableNullDetection ();\r
1979\r
bcecde14 1980 Bda = (BDA_STRUC *) ((UINTN) 0x400);\r
1981 MachineConfig = 0;\r
1982\r
1983 SioPtr = &(Private->IntThunk->EfiToLegacy16BootTable.SioData);\r
1984 Bda->Com1 = SioPtr->Serial[0].Address;\r
1985 Bda->Com2 = SioPtr->Serial[1].Address;\r
1986 Bda->Com3 = SioPtr->Serial[2].Address;\r
1987 Bda->Com4 = SioPtr->Serial[3].Address;\r
1988\r
1989 if (SioPtr->Serial[0].Address != 0x00) {\r
1990 MachineConfig += 0x200;\r
1991 }\r
1992\r
1993 if (SioPtr->Serial[1].Address != 0x00) {\r
1994 MachineConfig += 0x200;\r
1995 }\r
1996\r
1997 if (SioPtr->Serial[2].Address != 0x00) {\r
1998 MachineConfig += 0x200;\r
1999 }\r
2000\r
2001 if (SioPtr->Serial[3].Address != 0x00) {\r
2002 MachineConfig += 0x200;\r
2003 }\r
2004\r
2005 Bda->Lpt1 = SioPtr->Parallel[0].Address;\r
2006 Bda->Lpt2 = SioPtr->Parallel[1].Address;\r
2007 Bda->Lpt3 = SioPtr->Parallel[2].Address;\r
2008\r
2009 if (SioPtr->Parallel[0].Address != 0x00) {\r
2010 MachineConfig += 0x4000;\r
2011 }\r
2012\r
2013 if (SioPtr->Parallel[1].Address != 0x00) {\r
2014 MachineConfig += 0x4000;\r
2015 }\r
2016\r
2017 if (SioPtr->Parallel[2].Address != 0x00) {\r
2018 MachineConfig += 0x4000;\r
2019 }\r
2020\r
2021 Bda->NumberOfDrives = (UINT8) (Bda->NumberOfDrives + Private->IdeDriveCount);\r
2022 if (SioPtr->Floppy.NumberOfFloppy != 0x00) {\r
2023 MachineConfig = (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy.NumberOfFloppy - 1) * 0x40);\r
2024 Bda->FloppyXRate = 0x07;\r
2025 }\r
2026\r
2027 Bda->Lpt1_2Timeout = 0x1414;\r
2028 Bda->Lpt3_4Timeout = 0x1414;\r
2029 Bda->Com1_2Timeout = 0x0101;\r
2030 Bda->Com3_4Timeout = 0x0101;\r
2031\r
2032 //\r
2033 // Force VGA and Coprocessor, indicate 101/102 keyboard\r
2034 //\r
2035 MachineConfig = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));\r
2036 Bda->MachineConfig = MachineConfig;\r
2037\r
d057d8c4
JW
2038 EnableNullDetection ();\r
2039\r
bcecde14 2040 return EFI_SUCCESS;\r
2041}\r
2042\r
2043/**\r
2044 Fill in the standard BDA for Keyboard LEDs\r
2045\r
2046 @param This Protocol instance pointer.\r
2047 @param Leds Current LED status\r
2048\r
2049 @retval EFI_SUCCESS It should always work.\r
2050\r
2051**/\r
2052EFI_STATUS\r
2053EFIAPI\r
2054LegacyBiosUpdateKeyboardLedStatus (\r
2055 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
2056 IN UINT8 Leds\r
2057 )\r
2058{\r
2059 LEGACY_BIOS_INSTANCE *Private;\r
2060 BDA_STRUC *Bda;\r
2061 UINT8 LocalLeds;\r
2062 EFI_IA32_REGISTER_SET Regs;\r
2063\r
bcecde14 2064 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
d057d8c4
JW
2065\r
2066 DisableNullDetection ();\r
2067\r
2068 Bda = (BDA_STRUC *) ((UINTN) 0x400);\r
bcecde14 2069 LocalLeds = Leds;\r
2070 Bda->LedStatus = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds);\r
2071 LocalLeds = (UINT8) (LocalLeds << 4);\r
2072 Bda->ShiftStatus = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds);\r
2073 LocalLeds = (UINT8) (Leds & 0x20);\r
2074 Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds);\r
d057d8c4
JW
2075\r
2076 EnableNullDetection ();\r
2077\r
bcecde14 2078 //\r
2079 // Call into Legacy16 code to allow it to do any processing\r
2080 //\r
2081 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
2082 Regs.X.AX = Legacy16SetKeyboardLeds;\r
2083 Regs.H.CL = Leds;\r
2084\r
2085 Private->LegacyBios.FarCall86 (\r
2086 &Private->LegacyBios,\r
2087 Private->Legacy16Table->Compatibility16CallSegment,\r
2088 Private->Legacy16Table->Compatibility16CallOffset,\r
2089 &Regs,\r
2090 NULL,\r
2091 0\r
2092 );\r
2093\r
2094 return EFI_SUCCESS;\r
2095}\r
2096\r
2097\r
2098/**\r
2099 Fill in the standard CMOS stuff prior to legacy Boot\r
2100\r
2101 @param Private Legacy BIOS Instance data\r
2102\r
2103 @retval EFI_SUCCESS It should always work.\r
2104\r
2105**/\r
2106EFI_STATUS\r
2107LegacyBiosCompleteStandardCmosBeforeBoot (\r
2108 IN LEGACY_BIOS_INSTANCE *Private\r
2109 )\r
2110{\r
2111 UINT8 Bda;\r
2112 UINT8 Floppy;\r
2113 UINT32 Size;\r
2114\r
2115 //\r
2116 // Update CMOS locations\r
2117 // 10 floppy\r
2118 // 12,19,1A - ignore as OS don't use them and there is no standard due\r
2119 // to large capacity drives\r
2120 // CMOS 14 = BDA 40:10 plus bit 3(display enabled)\r
2121 //\r
d057d8c4 2122 DisableNullDetection ();\r
bcecde14 2123 Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);\r
d057d8c4 2124 EnableNullDetection ();\r
bcecde14 2125\r
2126 //\r
2127 // Force display enabled\r
2128 //\r
2129 Floppy = 0x00;\r
2130 if ((Bda & BIT0) != 0) {\r
2131 Floppy = BIT6;\r
2132 }\r
2133\r
2134 //\r
2135 // Check if 2.88MB floppy set\r
2136 //\r
2137 if ((Bda & (BIT7 | BIT6)) != 0) {\r
2138 Floppy = (UINT8)(Floppy | BIT1);\r
2139 }\r
2140\r
2141 LegacyWriteStandardCmos (CMOS_10, Floppy);\r
2142 LegacyWriteStandardCmos (CMOS_14, Bda);\r
2143\r
2144 //\r
2145 // Force Status Register A to set rate selection bits and divider\r
2146 //\r
2147 LegacyWriteStandardCmos (CMOS_0A, 0x26);\r
2148\r
2149 //\r
2150 // redo memory size since it can change\r
2151 //\r
de2eccc4 2152 Size = (15 * SIZE_1MB) >> 10;\r
bcecde14 2153 if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * SIZE_1MB)) {\r
2154 Size = Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >> 10;\r
2155 }\r
2156\r
2157 LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF));\r
2158 LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF));\r
2159 LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8));\r
2160 LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8));\r
2161\r
2162 LegacyCalculateWriteStandardCmosChecksum ();\r
2163\r
2164 return EFI_SUCCESS;\r
2165}\r
2166\r
2167/**\r
2168 Relocate this image under 4G memory for IPF.\r
2169\r
2170 @param ImageHandle Handle of driver image.\r
2171 @param SystemTable Pointer to system table.\r
2172\r
2173 @retval EFI_SUCCESS Image successfully relocated.\r
2174 @retval EFI_ABORTED Failed to relocate image.\r
2175\r
2176**/\r
2177EFI_STATUS\r
2178RelocateImageUnder4GIfNeeded (\r
2179 IN EFI_HANDLE ImageHandle,\r
2180 IN EFI_SYSTEM_TABLE *SystemTable\r
2181 )\r
2182{\r
2183 return EFI_SUCCESS;\r
2184}\r