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