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