]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
IntelFrameworkModulePkg: Refine casting expression result to bigger size
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / LegacyBiosDxe / LegacyBios.c
CommitLineData
bcecde14 1/** @file\r
2\r
aa5f60ae 3Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
bcecde14 4\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The\r
8full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "LegacyBiosInterface.h"\r
17\r
18#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address))\r
19\r
20//\r
21// define maximum number of HDD system supports\r
22//\r
23#define MAX_HDD_ENTRIES 0x30\r
24\r
25//\r
26// Module Global:\r
27// Since this driver will only ever produce one instance of the Private Data\r
28// protocol you are not required to dynamically allocate the PrivateData.\r
29//\r
30LEGACY_BIOS_INSTANCE mPrivateData;\r
31\r
b6823730
EL
32//\r
33// The SMBIOS table in EfiRuntimeServicesData memory\r
34//\r
35VOID *mRuntimeSmbiosEntryPoint = NULL;\r
36\r
37//\r
38// The SMBIOS table in EfiReservedMemoryType memory\r
39//\r
40EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0;\r
41EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0;\r
42UINTN mStructureTablePages = 0;\r
43\r
bcecde14 44/**\r
45 Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode\r
46 memory.\r
47\r
48 @param AllocateType Allocated Legacy Memory Type\r
49 @param StartPageAddress Start address of range\r
50 @param Pages Number of pages to allocate\r
51 @param Result Result of allocation\r
52\r
53 @retval EFI_SUCCESS Legacy16 code loaded\r
54 @retval Other No protocol installed, unload driver.\r
55\r
56**/\r
57EFI_STATUS\r
58AllocateLegacyMemory (\r
59 IN EFI_ALLOCATE_TYPE AllocateType,\r
60 IN EFI_PHYSICAL_ADDRESS StartPageAddress,\r
61 IN UINTN Pages,\r
62 OUT EFI_PHYSICAL_ADDRESS *Result\r
63 )\r
64{\r
65 EFI_STATUS Status;\r
66 EFI_PHYSICAL_ADDRESS MemPage;\r
67\r
68 //\r
69 // Allocate Pages of memory less <= StartPageAddress\r
70 //\r
71 MemPage = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress;\r
72 Status = gBS->AllocatePages (\r
73 AllocateType,\r
74 EfiBootServicesCode,\r
75 Pages,\r
76 &MemPage\r
77 );\r
78 //\r
79 // Do not ASSERT on Status error but let caller decide since some cases\r
80 // memory is already taken but that is ok.\r
81 //\r
82 if (!EFI_ERROR (Status)) {\r
83 *Result = (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage;\r
84 }\r
85 //\r
86 // If reach here the status = EFI_SUCCESS\r
87 //\r
88 return Status;\r
89}\r
90\r
91\r
92/**\r
93 This function is called when EFI needs to reserve an area in the 0xE0000 or 0xF0000\r
94 64 KB blocks.\r
95\r
96 Note: inconsistency with the Framework CSM spec. Per the spec, this function may be\r
97 invoked only once. This limitation is relaxed to allow multiple calls in this implemenation.\r
98\r
99 @param This Protocol instance pointer.\r
100 @param LegacyMemorySize Size of required region\r
101 @param Region Region to use. 00 = Either 0xE0000 or 0xF0000\r
102 block Bit0 = 1 0xF0000 block Bit1 = 1 0xE0000\r
103 block\r
104 @param Alignment Address alignment. Bit mapped. First non-zero\r
105 bit from right is alignment.\r
106 @param LegacyMemoryAddress Region Assigned\r
107\r
108 @retval EFI_SUCCESS Region assigned\r
109 @retval EFI_ACCESS_DENIED Procedure previously invoked\r
110 @retval Other Region not assigned\r
111\r
112**/\r
113EFI_STATUS\r
114EFIAPI\r
115LegacyBiosGetLegacyRegion (\r
116 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
117 IN UINTN LegacyMemorySize,\r
118 IN UINTN Region,\r
119 IN UINTN Alignment,\r
120 OUT VOID **LegacyMemoryAddress\r
121 )\r
122{\r
123\r
124 LEGACY_BIOS_INSTANCE *Private;\r
125 EFI_IA32_REGISTER_SET Regs;\r
126 EFI_STATUS Status;\r
127 UINT32 Granularity;\r
128\r
129 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
130 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
131\r
132 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
133 Regs.X.AX = Legacy16GetTableAddress;\r
134 Regs.X.BX = (UINT16) Region;\r
135 Regs.X.CX = (UINT16) LegacyMemorySize;\r
136 Regs.X.DX = (UINT16) Alignment;\r
137 Private->LegacyBios.FarCall86 (\r
138 &Private->LegacyBios,\r
139 Private->Legacy16CallSegment,\r
140 Private->Legacy16CallOffset,\r
141 &Regs,\r
142 NULL,\r
143 0\r
144 );\r
145\r
146 if (Regs.X.AX == 0) {\r
aa5f60ae 147 *LegacyMemoryAddress = (VOID *) (((UINTN) Regs.X.DS << 4) + Regs.X.BX);\r
bcecde14 148 Status = EFI_SUCCESS;\r
149 } else {\r
150 Status = EFI_OUT_OF_RESOURCES;\r
151 }\r
152\r
153 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
154 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
155\r
156 return Status;\r
157}\r
158\r
159\r
160/**\r
161 This function is called when copying data to the region assigned by\r
162 EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion().\r
163\r
164 @param This Protocol instance pointer.\r
165 @param LegacyMemorySize Size of data to copy\r
166 @param LegacyMemoryAddress Legacy Region destination address Note: must\r
167 be in region assigned by\r
168 LegacyBiosGetLegacyRegion\r
169 @param LegacyMemorySourceAddress Source of data\r
170\r
171 @retval EFI_SUCCESS The data was copied successfully.\r
172 @retval EFI_ACCESS_DENIED Either the starting or ending address is out of bounds.\r
173**/\r
174EFI_STATUS\r
175EFIAPI\r
176LegacyBiosCopyLegacyRegion (\r
177 IN EFI_LEGACY_BIOS_PROTOCOL *This,\r
178 IN UINTN LegacyMemorySize,\r
179 IN VOID *LegacyMemoryAddress,\r
180 IN VOID *LegacyMemorySourceAddress\r
181 )\r
182{\r
183\r
184 LEGACY_BIOS_INSTANCE *Private;\r
185 UINT32 Granularity;\r
186\r
187 if ((LegacyMemoryAddress < (VOID *)(UINTN)0xE0000 ) ||\r
188 ((UINTN) LegacyMemoryAddress + LegacyMemorySize > (UINTN) 0x100000)\r
189 ) {\r
190 return EFI_ACCESS_DENIED;\r
191 }\r
192 //\r
193 // There is no protection from writes over lapping if this function is\r
194 // called multiple times.\r
195 //\r
196 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
197 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
198 CopyMem (LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySize);\r
199\r
200 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);\r
201 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &Granularity);\r
202\r
203 return EFI_SUCCESS;\r
204}\r
205\r
206\r
207/**\r
208 Find Legacy16 BIOS image in the FLASH device and shadow it into memory. Find\r
209 the $EFI table in the shadow area. Thunk into the Legacy16 code after it had\r
210 been shadowed.\r
211\r
212 @param Private Legacy BIOS context data\r
213\r
214 @retval EFI_SUCCESS Legacy16 code loaded\r
215 @retval Other No protocol installed, unload driver.\r
216\r
217**/\r
218EFI_STATUS\r
219ShadowAndStartLegacy16 (\r
220 IN LEGACY_BIOS_INSTANCE *Private\r
221 )\r
222{\r
223 EFI_STATUS Status;\r
224 UINT8 *Ptr;\r
225 UINT8 *PtrEnd;\r
226 BOOLEAN Done;\r
227 EFI_COMPATIBILITY16_TABLE *Table;\r
228 UINT8 CheckSum;\r
229 EFI_IA32_REGISTER_SET Regs;\r
230 EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;\r
231 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;\r
232 VOID *LegacyBiosImage;\r
233 UINTN LegacyBiosImageSize;\r
234 UINTN E820Size;\r
235 UINT32 *ClearPtr;\r
236 BBS_TABLE *BbsTable;\r
237 LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable;\r
238 UINTN Index;\r
239 UINT32 TpmPointer;\r
240 VOID *TpmBinaryImage;\r
241 UINTN TpmBinaryImageSize;\r
242 UINTN Location;\r
243 UINTN Alignment;\r
244 UINTN TempData;\r
245 EFI_PHYSICAL_ADDRESS Address;\r
246 UINT16 OldMask;\r
247 UINT16 NewMask;\r
248 UINT32 Granularity;\r
249 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
250\r
251 Location = 0;\r
252 Alignment = 0;\r
253\r
254 //\r
255 // we allocate the C/D/E/F segment as RT code so no one will use it any more.\r
256 //\r
257 Address = 0xC0000;\r
258 gDS->GetMemorySpaceDescriptor (Address, &Descriptor);\r
259 if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
260 //\r
261 // If it is already reserved, we should be safe, or else we allocate it.\r
262 //\r
263 Status = gBS->AllocatePages (\r
264 AllocateAddress,\r
265 EfiRuntimeServicesCode,\r
266 0x40000/EFI_PAGE_SIZE,\r
267 &Address\r
268 );\r
269 if (EFI_ERROR (Status)) {\r
270 //\r
271 // Bugbug: need to figure out whether C/D/E/F segment should be marked as reserved memory.\r
272 // \r
273 DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = %r", Status));\r
274 }\r
275 }\r
276\r
277 //\r
278 // start testtest\r
279 // GetTimerValue (&Ticker);\r
280 //\r
281 // gRT->SetVariable (L"StartLegacy",\r
282 // &gEfiGlobalVariableGuid,\r
283 // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
284 // sizeof (UINT64),\r
285 // (VOID *)&Ticker\r
286 // );\r
287 // end testtest\r
288 //\r
289 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;\r
290 Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
291 Private->LegacyBiosPlatform,\r
292 EfiGetPlatformBinarySystemRom,\r
293 &LegacyBiosImage,\r
294 &LegacyBiosImageSize,\r
295 &Location,\r
296 &Alignment,\r
297 0,\r
298 0\r
299 );\r
300 if (EFI_ERROR (Status)) {\r
301 return Status;\r
302 }\r
303\r
304 Private->BiosStart = (UINT32) (0x100000 - LegacyBiosImageSize);\r
305 Private->OptionRom = 0xc0000;\r
306 Private->LegacyBiosImageSize = (UINT32) LegacyBiosImageSize;\r
307\r
308 //\r
309 // Can only shadow into memory allocated for legacy useage.\r
310 //\r
311 ASSERT (Private->BiosStart > Private->OptionRom);\r
312\r
313 //\r
314 // Shadow Legacy BIOS. Turn on memory and copy image\r
315 //\r
316 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, &Granularity);\r
317\r
318 ClearPtr = (VOID *) ((UINTN) 0xc0000);\r
319\r
320 //\r
321 // Initialize region from 0xc0000 to start of BIOS to all ffs. This allows unused\r
322 // regions to be used by EMM386 etc.\r
323 //\r
324 SetMem ((VOID *) ClearPtr, (UINTN) (0x40000 - LegacyBiosImageSize), 0xff);\r
325\r
326 TempData = Private->BiosStart;\r
327\r
328 CopyMem (\r
329 (VOID *) TempData,\r
330 LegacyBiosImage,\r
331 (UINTN) LegacyBiosImageSize\r
332 );\r
333\r
334 Private->Cpu->FlushDataCache (Private->Cpu, 0xc0000, 0x40000, EfiCpuFlushTypeWriteBackInvalidate);\r
335\r
336 //\r
337 // Search for Legacy16 table in Shadowed ROM\r
338 //\r
339 Done = FALSE;\r
340 Table = NULL;\r
341 for (Ptr = (UINT8 *) TempData; Ptr < (UINT8 *) ((UINTN) 0x100000) && !Done; Ptr += 0x10) {\r
342 if (*(UINT32 *) Ptr == SIGNATURE_32 ('I', 'F', 'E', '$')) {\r
343 Table = (EFI_COMPATIBILITY16_TABLE *) Ptr;\r
344 PtrEnd = Ptr + Table->TableLength;\r
345 for (CheckSum = 0; Ptr < PtrEnd; Ptr++) {\r
346 CheckSum = (UINT8) (CheckSum +*Ptr);\r
347 }\r
348\r
349 Done = TRUE;\r
350 }\r
351 }\r
352\r
353 if (Table == NULL) {\r
354 DEBUG ((EFI_D_ERROR, "No Legacy16 table found\n"));\r
355 return EFI_NOT_FOUND;\r
356 }\r
357\r
358 if (!Done) {\r
359 //\r
360 // Legacy16 table header checksum error.\r
361 //\r
362 DEBUG ((EFI_D_ERROR, "Legacy16 table found with bad talbe header checksum\n"));\r
363 }\r
364\r
365 //\r
366 // Remember location of the Legacy16 table\r
367 //\r
368 Private->Legacy16Table = Table;\r
369 Private->Legacy16CallSegment = Table->Compatibility16CallSegment;\r
370 Private->Legacy16CallOffset = Table->Compatibility16CallOffset;\r
371 EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable;\r
372 Private->Legacy16InitPtr = EfiToLegacy16InitTable;\r
373 Private->Legacy16BootPtr = &Private->IntThunk->EfiToLegacy16BootTable;\r
374 Private->InternalIrqRoutingTable = NULL;\r
375 Private->NumberIrqRoutingEntries = 0;\r
376 Private->BbsTablePtr = NULL;\r
377 Private->LegacyEfiHddTable = NULL;\r
378 Private->DiskEnd = 0;\r
379 Private->Disk4075 = 0;\r
380 Private->HddTablePtr = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo;\r
381 Private->NumberHddControllers = MAX_IDE_CONTROLLER;\r
382 Private->Dump[0] = 'D';\r
383 Private->Dump[1] = 'U';\r
384 Private->Dump[2] = 'M';\r
385 Private->Dump[3] = 'P';\r
386\r
387 ZeroMem (\r
388 Private->Legacy16BootPtr,\r
389 sizeof (EFI_TO_COMPATIBILITY16_BOOT_TABLE)\r
390 );\r
391\r
392 //\r
393 // Store away a copy of the EFI System Table\r
394 //\r
395 Table->EfiSystemTable = (UINT32) (UINTN) gST;\r
396\r
bcecde14 397 //\r
398 // IPF CSM integration -Bug\r
399 //\r
400 // Construct the Legacy16 boot memory map. This sets up number of\r
401 // E820 entries.\r
402 //\r
403 LegacyBiosBuildE820 (Private, &E820Size);\r
404 //\r
405 // Initialize BDA and EBDA standard values needed to load Legacy16 code\r
406 //\r
407 LegacyBiosInitBda (Private);\r
408 LegacyBiosInitCmos (Private);\r
409\r
410 //\r
411 // All legacy interrupt should be masked when do initialization work from legacy 16 code.\r
412 //\r
413 Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL);\r
414 NewMask = 0xFFFF;\r
415 Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, NULL);\r
416 \r
417 //\r
418 // Call into Legacy16 code to do an INIT\r
419 //\r
420 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
421 Regs.X.AX = Legacy16InitializeYourself;\r
422 Regs.X.ES = EFI_SEGMENT (*((UINT32 *) &EfiToLegacy16InitTable));\r
423 Regs.X.BX = EFI_OFFSET (*((UINT32 *) &EfiToLegacy16InitTable));\r
424\r
425 Private->LegacyBios.FarCall86 (\r
426 &Private->LegacyBios,\r
427 Table->Compatibility16CallSegment,\r
428 Table->Compatibility16CallOffset,\r
429 &Regs,\r
430 NULL,\r
431 0\r
432 );\r
433\r
434 //\r
435 // Restore original legacy interrupt mask value\r
436 //\r
437 Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, NULL);\r
438 \r
439 if (Regs.X.AX != 0) {\r
440 return EFI_DEVICE_ERROR;\r
441 }\r
442\r
443 //\r
444 // start testtest\r
445 // GetTimerValue (&Ticker);\r
446 //\r
447 // gRT->SetVariable (L"BackFromInitYourself",\r
448 // &gEfiGlobalVariableGuid,\r
449 // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
450 // sizeof (UINT64),\r
451 // (VOID *)&Ticker\r
452 // );\r
453 // end testtest\r
454 //\r
455 // Copy E820 table after InitializeYourself is completed\r
456 //\r
457 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
458 Regs.X.AX = Legacy16GetTableAddress;\r
459 Regs.X.CX = (UINT16) E820Size;\r
460 Regs.X.DX = 1;\r
461 Private->LegacyBios.FarCall86 (\r
462 &Private->LegacyBios,\r
463 Table->Compatibility16CallSegment,\r
464 Table->Compatibility16CallOffset,\r
465 &Regs,\r
466 NULL,\r
467 0\r
468 );\r
469\r
470 Table->E820Pointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
471 Table->E820Length = (UINT32) E820Size;\r
472 if (Regs.X.AX != 0) {\r
473 DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n"));\r
474 } else {\r
475 TempData = Table->E820Pointer;\r
476 CopyMem ((VOID *) TempData, Private->E820Table, E820Size);\r
477 }\r
478 //\r
479 // Get PnPInstallationCheck Info.\r
480 //\r
481 Private->PnPInstallationCheckSegment = Table->PnPInstallationCheckSegment;\r
482 Private->PnPInstallationCheckOffset = Table->PnPInstallationCheckOffset;\r
483\r
484 //\r
485 // Check if PCI Express is supported. If yes, Save base address.\r
486 //\r
487 Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
488 Private->LegacyBiosPlatform,\r
489 EfiGetPlatformPciExpressBase,\r
490 NULL,\r
491 NULL,\r
492 &Location,\r
493 &Alignment,\r
494 0,\r
495 0\r
496 );\r
497 if (!EFI_ERROR (Status)) {\r
498 Private->Legacy16Table->PciExpressBase = (UINT32)Location;\r
499 Location = 0;\r
500 }\r
501 //\r
502 // Check if TPM is supported. If yes get a region in E0000,F0000 to copy it\r
503 // into, copy it and update pointer to binary image. This needs to be\r
504 // done prior to any OPROM for security purposes.\r
505 //\r
506 Status = Private->LegacyBiosPlatform->GetPlatformInfo (\r
507 Private->LegacyBiosPlatform,\r
508 EfiGetPlatformBinaryTpmBinary,\r
509 &TpmBinaryImage,\r
510 &TpmBinaryImageSize,\r
511 &Location,\r
512 &Alignment,\r
513 0,\r
514 0\r
515 );\r
516 if (!EFI_ERROR (Status)) {\r
517\r
518 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));\r
519 Regs.X.AX = Legacy16GetTableAddress;\r
520 Regs.X.CX = (UINT16) TpmBinaryImageSize;\r
521 Regs.X.DX = 1;\r
522 Private->LegacyBios.FarCall86 (\r
523 &Private->LegacyBios,\r
524 Table->Compatibility16CallSegment,\r
525 Table->Compatibility16CallOffset,\r
526 &Regs,\r
527 NULL,\r
528 0\r
529 );\r
530\r
531 TpmPointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);\r
532 if (Regs.X.AX != 0) {\r
533 DEBUG ((EFI_D_ERROR, "TPM cannot be loaded\n"));\r
534 } else {\r
535 CopyMem ((VOID *) (UINTN)TpmPointer, TpmBinaryImage, TpmBinaryImageSize);\r
536 Table->TpmSegment = Regs.X.DS;\r
537 Table->TpmOffset = Regs.X.BX;\r
538\r
539 }\r
540 }\r
541 //\r
542 // Lock the Legacy BIOS region\r
543 //\r
544 Private->Cpu->FlushDataCache (Private->Cpu, Private->BiosStart, (UINT32) LegacyBiosImageSize, EfiCpuFlushTypeWriteBackInvalidate);\r
545 Private->LegacyRegion->Lock (Private->LegacyRegion, Private->BiosStart, (UINT32) LegacyBiosImageSize, &Granularity);\r
546\r
547 //\r
548 // Get the BbsTable from LOW_MEMORY_THUNK\r
549 //\r
550 BbsTable = (BBS_TABLE *)(UINTN)Private->IntThunk->BbsTable;\r
551 ZeroMem ((VOID *)BbsTable, sizeof (Private->IntThunk->BbsTable));\r
552\r
553 EfiToLegacy16BootTable->BbsTable = (UINT32)(UINTN)BbsTable;\r
554 Private->BbsTablePtr = (VOID *) BbsTable;\r
555 //\r
556 // Skip Floppy and possible onboard IDE drives\r
557 //\r
558 EfiToLegacy16BootTable->NumberBbsEntries = 1 + 2 * MAX_IDE_CONTROLLER;\r
559\r
560 for (Index = 0; Index < (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE)); Index++) {\r
561 BbsTable[Index].BootPriority = BBS_IGNORE_ENTRY;\r
562 }\r
563 //\r
564 // Allocate space for Legacy HDD table\r
565 //\r
566 LegacyEfiHddTable = (LEGACY_EFI_HDD_TABLE *) AllocateZeroPool ((UINTN) MAX_HDD_ENTRIES * sizeof (LEGACY_EFI_HDD_TABLE));\r
567 ASSERT (LegacyEfiHddTable);\r
568\r
569 Private->LegacyEfiHddTable = LegacyEfiHddTable;\r
570 Private->LegacyEfiHddTableIndex = 0x00;\r
571\r
572 //\r
573 // start testtest\r
574 // GetTimerValue (&Ticker);\r
575 //\r
576 // gRT->SetVariable (L"EndOfLoadFv",\r
577 // &gEfiGlobalVariableGuid,\r
578 // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
579 // sizeof (UINT64),\r
580 // (VOID *)&Ticker\r
581 // );\r
582 // end testtest\r
583 //\r
584 return EFI_SUCCESS;\r
585}\r
586\r
587/**\r
588 Shadow all legacy16 OPROMs that haven't been shadowed.\r
589 Warning: Use this with caution. This routine disconnects all EFI\r
590 drivers. If used externally then caller must re-connect EFI\r
591 drivers.\r
592\r
593 @param This Protocol instance pointer.\r
594\r
595 @retval EFI_SUCCESS OPROMs shadowed\r
596\r
597**/\r
598EFI_STATUS\r
599EFIAPI\r
600LegacyBiosShadowAllLegacyOproms (\r
601 IN EFI_LEGACY_BIOS_PROTOCOL *This\r
602 )\r
603{\r
604 LEGACY_BIOS_INSTANCE *Private;\r
605\r
606 //\r
607 // EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;\r
608 // EFI_LEGACY16_TABLE *Legacy16Table;\r
609 //\r
610 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);\r
611\r
612 //\r
613 // LegacyBiosPlatform = Private->LegacyBiosPlatform;\r
614 // Legacy16Table = Private->Legacy16Table;\r
615 //\r
616 // Shadow PCI ROMs. We must do this near the end since this will kick\r
617 // of Native EFI drivers that may be needed to collect info for Legacy16\r
618 //\r
619 // WARNING: PciIo is gone after this call.\r
620 //\r
621 PciProgramAllInterruptLineRegisters (Private);\r
622\r
623 PciShadowRoms (Private);\r
624\r
625 //\r
626 // Shadow PXE base code, BIS etc.\r
627 //\r
628 // LegacyBiosPlatform->ShadowServiceRoms (LegacyBiosPlatform,\r
629 // &Private->OptionRom,\r
630 // Legacy16Table);\r
631 //\r
632 return EFI_SUCCESS;\r
633}\r
634\r
635/**\r
636 Get the PCI BIOS interface version.\r
637\r
638 @param Private Driver private data.\r
639\r
640 @return The PCI interface version number in Binary Coded Decimal (BCD) format.\r
641 E.g.: 0x0210 indicates 2.10, 0x0300 indicates 3.00\r
642\r
643**/\r
644UINT16\r
645GetPciInterfaceVersion (\r
646 IN LEGACY_BIOS_INSTANCE *Private\r
647 )\r
648{\r
649 EFI_IA32_REGISTER_SET Reg;\r
650 BOOLEAN ThunkFailed;\r
651 UINT16 PciInterfaceVersion;\r
652\r
653 PciInterfaceVersion = 0;\r
654 \r
655 Reg.X.AX = 0xB101;\r
656 Reg.E.EDI = 0;\r
657\r
658 ThunkFailed = Private->LegacyBios.Int86 (&Private->LegacyBios, 0x1A, &Reg);\r
659 if (!ThunkFailed) {\r
660 //\r
661 // From PCI Firmware 3.0 Specification:\r
662 // If the CARRY FLAG [CF] is cleared and AH is set to 00h, it is still necessary to examine the\r
663 // contents of [EDX] for the presence of the string "PCI" + (trailing space) to fully validate the\r
664 // presence of the PCI function set. [BX] will further indicate the version level, with enough\r
665 // granularity to allow for incremental changes in the code that don't affect the function interface.\r
666 // Version numbers are stored as Binary Coded Decimal (BCD) values. For example, Version 2.10\r
667 // would be returned as a 02h in the [BH] registers and 10h in the [BL] registers.\r
668 //\r
669 if ((Reg.X.Flags.CF == 0) && (Reg.H.AH == 0) && (Reg.E.EDX == SIGNATURE_32 ('P', 'C', 'I', ' '))) {\r
670 PciInterfaceVersion = Reg.X.BX;\r
671 }\r
672 }\r
673 return PciInterfaceVersion;\r
674}\r
675\r
b6823730
EL
676/**\r
677 Callback function to calculate SMBIOS table size, and allocate memory for SMBIOS table.\r
678 SMBIOS table will be copied into EfiReservedMemoryType memory in legacy boot path.\r
679\r
680 @param Event Event whose notification function is being invoked.\r
681 @param Context The pointer to the notification function's context,\r
682 which is implementation-dependent.\r
683\r
684**/\r
685VOID\r
686EFIAPI\r
687InstallSmbiosEventCallback (\r
688 IN EFI_EVENT Event,\r
689 IN VOID *Context\r
690 )\r
691{\r
692 EFI_STATUS Status;\r
693 SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;\r
694 \r
695 //\r
696 // Get SMBIOS table from EFI configuration table\r
697 //\r
698 Status = EfiGetSystemConfigurationTable (\r
699 &gEfiSmbiosTableGuid,\r
700 &mRuntimeSmbiosEntryPoint\r
701 );\r
ad793176 702 if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint == NULL)) {\r
b6823730
EL
703 return;\r
704 }\r
705 \r
706 EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntryPoint;\r
707\r
708 //\r
709 // Allocate memory for SMBIOS Entry Point Structure.\r
710 // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIBILITY16_BOOT_TABLE.\r
711 //\r
712 if (mReserveSmbiosEntryPoint == 0) {\r
713 //\r
714 // Entrypoint structure with fixed size is allocated only once.\r
715 //\r
716 mReserveSmbiosEntryPoint = SIZE_4GB - 1;\r
717 Status = gBS->AllocatePages (\r
718 AllocateMaxAddress,\r
719 EfiReservedMemoryType,\r
720 EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)),\r
721 &mReserveSmbiosEntryPoint\r
722 );\r
723 if (EFI_ERROR (Status)) {\r
724 mReserveSmbiosEntryPoint = 0;\r
725 return;\r
726 }\r
727 DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\n"));\r
728 }\r
729 \r
730 if ((mStructureTableAddress != 0) && \r
aa5f60ae 731 (mStructureTablePages < EFI_SIZE_TO_PAGES ((UINT32)EntryPointStructure->TableLength))) {\r
b6823730
EL
732 //\r
733 // If original buffer is not enough for the new SMBIOS table, free original buffer and re-allocate\r
734 //\r
735 gBS->FreePages (mStructureTableAddress, mStructureTablePages);\r
736 mStructureTableAddress = 0;\r
737 mStructureTablePages = 0;\r
738 DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memory.\n"));\r
739 }\r
740 \r
741 if (mStructureTableAddress == 0) {\r
742 //\r
743 // Allocate reserved memory below 4GB.\r
744 // Smbios spec requires the structure table is below 4GB.\r
745 //\r
746 mStructureTableAddress = SIZE_4GB - 1;\r
747 mStructureTablePages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
748 Status = gBS->AllocatePages (\r
749 AllocateMaxAddress,\r
750 EfiReservedMemoryType,\r
751 mStructureTablePages,\r
752 &mStructureTableAddress\r
753 );\r
754 if (EFI_ERROR (Status)) {\r
755 gBS->FreePages (\r
756 mReserveSmbiosEntryPoint, \r
757 EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength))\r
758 );\r
759 mReserveSmbiosEntryPoint = 0;\r
760 mStructureTableAddress = 0;\r
761 mStructureTablePages = 0;\r
762 return;\r
763 }\r
764 DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n"));\r
765 }\r
766}\r
767\r
bcecde14 768/**\r
769 Install Driver to produce Legacy BIOS protocol.\r
770\r
771 @param ImageHandle Handle of driver image.\r
772 @param SystemTable Pointer to system table.\r
773\r
774 @retval EFI_SUCCESS Legacy BIOS protocol installed\r
775 @retval No protocol installed, unload driver.\r
776\r
777**/\r
778EFI_STATUS\r
779EFIAPI\r
780LegacyBiosInstall (\r
781 IN EFI_HANDLE ImageHandle,\r
782 IN EFI_SYSTEM_TABLE *SystemTable\r
783 )\r
784{\r
785 EFI_STATUS Status;\r
786 LEGACY_BIOS_INSTANCE *Private;\r
787 EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;\r
788 EFI_PHYSICAL_ADDRESS MemoryAddress;\r
3e5eb447 789 EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress;\r
bcecde14 790 VOID *MemoryPtr;\r
791 EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB;\r
792 UINTN Index;\r
793 UINT32 *BaseVectorMaster;\r
794 EFI_PHYSICAL_ADDRESS StartAddress;\r
795 UINT32 *ClearPtr;\r
796 EFI_PHYSICAL_ADDRESS MemStart;\r
797 UINT32 IntRedirCode;\r
798 UINT32 Granularity;\r
799 BOOLEAN DecodeOn;\r
800 UINT32 MemorySize;\r
801 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
802 UINT64 Length;\r
0f8b0298 803 UINT8 *SecureBoot;\r
b6823730 804 EFI_EVENT InstallSmbiosEvent;\r
bcecde14 805\r
806 //\r
807 // Load this driver's image to memory\r
808 //\r
809 Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);\r
810 if (EFI_ERROR (Status)) {\r
811 return Status;\r
812 }\r
813\r
0f8b0298 814 //\r
815 // When UEFI Secure Boot is enabled, CSM module will not start any more.\r
816 //\r
817 SecureBoot = NULL;\r
818 GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
819 if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) {\r
820 FreePool (SecureBoot);\r
821 return EFI_SECURITY_VIOLATION;\r
822 }\r
823 \r
824 if (SecureBoot != NULL) {\r
825 FreePool (SecureBoot);\r
826 }\r
827\r
bcecde14 828 Private = &mPrivateData;\r
829 ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE));\r
830\r
831 //\r
832 // Grab a copy of all the protocols we depend on. Any error would\r
833 // be a dispatcher bug!.\r
834 //\r
835 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Private->Cpu);\r
836 ASSERT_EFI_ERROR (Status);\r
837\r
f767f990 838 Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Private->Timer);\r
839 ASSERT_EFI_ERROR (Status);\r
840\r
bcecde14 841 Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Private->LegacyRegion);\r
842 ASSERT_EFI_ERROR (Status);\r
843\r
844 Status = gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NULL, (VOID **) &Private->LegacyBiosPlatform);\r
845 ASSERT_EFI_ERROR (Status);\r
846\r
847 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &Private->Legacy8259);\r
848 ASSERT_EFI_ERROR (Status);\r
849\r
850 Status = gBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, (VOID **) &Private->LegacyInterrupt);\r
851 ASSERT_EFI_ERROR (Status);\r
852\r
853 //\r
854 // Locate Memory Test Protocol if exists\r
855 //\r
856 Status = gBS->LocateProtocol (\r
857 &gEfiGenericMemTestProtocolGuid,\r
858 NULL,\r
859 (VOID **) &Private->GenericMemoryTest\r
860 );\r
861 ASSERT_EFI_ERROR (Status);\r
862\r
863 //\r
864 // Make sure all memory from 0-640K is tested\r
865 //\r
866 for (StartAddress = 0; StartAddress < 0xa0000; ) {\r
867 gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor);\r
868 if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {\r
869 StartAddress = Descriptor.BaseAddress + Descriptor.Length;\r
870 continue;\r
871 }\r
872 Length = MIN (Descriptor.Length, 0xa0000 - StartAddress);\r
873 Private->GenericMemoryTest->CompatibleRangeTest (\r
874 Private->GenericMemoryTest,\r
875 StartAddress,\r
876 Length\r
877 );\r
878 StartAddress = StartAddress + Length;\r
879 }\r
880 //\r
881 // Make sure all memory from 1MB to 16MB is tested and added to memory map\r
882 //\r
883 for (StartAddress = BASE_1MB; StartAddress < BASE_16MB; ) {\r
884 gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor);\r
885 if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {\r
886 StartAddress = Descriptor.BaseAddress + Descriptor.Length;\r
887 continue;\r
888 }\r
889 Length = MIN (Descriptor.Length, BASE_16MB - StartAddress);\r
890 Private->GenericMemoryTest->CompatibleRangeTest (\r
891 Private->GenericMemoryTest,\r
892 StartAddress,\r
893 Length\r
894 );\r
895 StartAddress = StartAddress + Length;\r
896 }\r
897\r
898 Private->Signature = LEGACY_BIOS_INSTANCE_SIGNATURE;\r
899\r
900 Private->LegacyBios.Int86 = LegacyBiosInt86;\r
901 Private->LegacyBios.FarCall86 = LegacyBiosFarCall86;\r
902 Private->LegacyBios.CheckPciRom = LegacyBiosCheckPciRom;\r
903 Private->LegacyBios.InstallPciRom = LegacyBiosInstallPciRom;\r
904 Private->LegacyBios.LegacyBoot = LegacyBiosLegacyBoot;\r
905 Private->LegacyBios.UpdateKeyboardLedStatus = LegacyBiosUpdateKeyboardLedStatus;\r
906 Private->LegacyBios.GetBbsInfo = LegacyBiosGetBbsInfo;\r
907 Private->LegacyBios.ShadowAllLegacyOproms = LegacyBiosShadowAllLegacyOproms;\r
908 Private->LegacyBios.PrepareToBootEfi = LegacyBiosPrepareToBootEfi;\r
909 Private->LegacyBios.GetLegacyRegion = LegacyBiosGetLegacyRegion;\r
910 Private->LegacyBios.CopyLegacyRegion = LegacyBiosCopyLegacyRegion;\r
911 Private->LegacyBios.BootUnconventionalDevice = LegacyBiosBootUnconventionalDevice;\r
912\r
913 Private->ImageHandle = ImageHandle;\r
914\r
915 //\r
916 // Enable read attribute of legacy region.\r
917 //\r
918 DecodeOn = TRUE;\r
919 Private->LegacyRegion->Decode (\r
920 Private->LegacyRegion,\r
921 0xc0000,\r
922 0x40000,\r
923 &Granularity,\r
924 &DecodeOn\r
925 );\r
926 //\r
927 // Set Cachebility for legacy region\r
928 // BUGBUG: Comments about this legacy region cacheability setting\r
929 // This setting will make D865GCHProduction CSM Unhappy\r
930 //\r
931 if (PcdGetBool (PcdLegacyBiosCacheLegacyRegion)) {\r
932 gDS->SetMemorySpaceAttributes (\r
933 0x0,\r
934 0xA0000,\r
935 EFI_MEMORY_WB\r
936 );\r
937 gDS->SetMemorySpaceAttributes (\r
938 0xc0000,\r
939 0x40000,\r
940 EFI_MEMORY_WB\r
941 );\r
942 }\r
943\r
944 gDS->SetMemorySpaceAttributes (\r
945 0xA0000,\r
946 0x20000,\r
947 EFI_MEMORY_UC\r
948 );\r
949\r
950 //\r
951 // Allocate 0 - 4K for real mode interupt vectors and BDA.\r
952 //\r
953 AllocateLegacyMemory (\r
954 AllocateAddress,\r
955 0,\r
956 1,\r
957 &MemoryAddress\r
958 );\r
959 ASSERT (MemoryAddress == 0x000000000);\r
960\r
961 ClearPtr = (VOID *) ((UINTN) 0x0000);\r
962\r
963 //\r
964 // Initialize region from 0x0000 to 4k. This initializes interrupt vector\r
965 // range.\r
966 //\r
967 gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);\r
968 ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);\r
969\r
970 //\r
971 // Allocate pages for OPROM usage\r
972 //\r
973 MemorySize = PcdGet32 (PcdEbdaReservedMemorySize);\r
974 ASSERT ((MemorySize & 0xFFF) == 0);\r
975\r
976 Status = AllocateLegacyMemory (\r
977 AllocateAddress,\r
978 CONVENTIONAL_MEMORY_TOP - MemorySize,\r
979 EFI_SIZE_TO_PAGES (MemorySize),\r
980 &MemoryAddress\r
981 );\r
982 ASSERT_EFI_ERROR (Status);\r
983\r
984 ZeroMem ((VOID *) ((UINTN) MemoryAddress), MemorySize);\r
985\r
986 //\r
987 // Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that\r
988 // don't use PMM but look for zeroed memory. Note that various non-BBS\r
3e5eb447 989 // OpROMs expect different areas to be free\r
bcecde14 990 //\r
3e5eb447 991 EbdaReservedBaseAddress = MemoryAddress;\r
992 MemoryAddress = PcdGet32 (PcdOpromReservedMemoryBase);\r
993 MemorySize = PcdGet32 (PcdOpromReservedMemorySize);\r
994 //\r
995 // Check if base address and size for reserved memory are 4KB aligned.\r
996 //\r
997 ASSERT ((MemoryAddress & 0xFFF) == 0);\r
998 ASSERT ((MemorySize & 0xFFF) == 0);\r
999 //\r
1000 // Check if the reserved memory is below EBDA reserved range.\r
1001 //\r
1002 ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + MemorySize - 1) < EbdaReservedBaseAddress));\r
1003 for (MemStart = MemoryAddress; MemStart < MemoryAddress + MemorySize; MemStart += 0x1000) {\r
bcecde14 1004 Status = AllocateLegacyMemory (\r
1005 AllocateAddress,\r
1006 MemStart,\r
1007 1,\r
79966a6f 1008 &StartAddress\r
bcecde14 1009 );\r
1010 if (!EFI_ERROR (Status)) {\r
79966a6f 1011 MemoryPtr = (VOID *) ((UINTN) StartAddress);\r
bcecde14 1012 ZeroMem (MemoryPtr, 0x1000);\r
1013 } else {\r
1014 DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI card - %x\n", MemStart));\r
1015 }\r
1016 }\r
1017\r
1018 //\r
befbc4f3 1019 // Allocate low PMM memory and zero it out\r
bcecde14 1020 //\r
befbc4f3 1021 MemorySize = PcdGet32 (PcdLowPmmMemorySize);\r
1022 ASSERT ((MemorySize & 0xFFF) == 0); \r
bcecde14 1023 Status = AllocateLegacyMemory (\r
1024 AllocateMaxAddress,\r
1025 CONVENTIONAL_MEMORY_TOP,\r
befbc4f3 1026 EFI_SIZE_TO_PAGES (MemorySize),\r
bcecde14 1027 &MemoryAddressUnder1MB\r
1028 );\r
1029 ASSERT_EFI_ERROR (Status);\r
1030\r
befbc4f3 1031 ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), MemorySize);\r
bcecde14 1032\r
1033 //\r
1034 // Allocate space for thunker and Init Thunker\r
1035 //\r
1036 Status = AllocateLegacyMemory (\r
1037 AllocateMaxAddress,\r
1038 CONVENTIONAL_MEMORY_TOP,\r
1039 (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2,\r
1040 &MemoryAddress\r
1041 );\r
1042 ASSERT_EFI_ERROR (Status);\r
1043 Private->IntThunk = (LOW_MEMORY_THUNK *) (UINTN) MemoryAddress;\r
1044 EfiToLegacy16InitTable = &Private->IntThunk->EfiToLegacy16InitTable;\r
1045 EfiToLegacy16InitTable->ThunkStart = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress;\r
1046 EfiToLegacy16InitTable->ThunkSizeInBytes = (UINT32) (sizeof (LOW_MEMORY_THUNK));\r
1047\r
1048 Status = LegacyBiosInitializeThunk (Private);\r
1049 ASSERT_EFI_ERROR (Status);\r
1050\r
1051 //\r
1052 // Init the legacy memory map in memory < 1 MB.\r
1053 //\r
1054 EfiToLegacy16InitTable->BiosLessThan1MB = (UINT32) MemoryAddressUnder1MB;\r
1055 EfiToLegacy16InitTable->LowPmmMemory = (UINT32) MemoryAddressUnder1MB;\r
befbc4f3 1056 EfiToLegacy16InitTable->LowPmmMemorySizeInBytes = MemorySize;\r
bcecde14 1057\r
74dee931 1058 MemorySize = PcdGet32 (PcdHighPmmMemorySize);\r
1059 ASSERT ((MemorySize & 0xFFF) == 0);\r
bcecde14 1060 //\r
befbc4f3 1061 // Allocate high PMM Memory under 16 MB\r
74dee931 1062 // \r
bcecde14 1063 Status = AllocateLegacyMemory (\r
1064 AllocateMaxAddress,\r
1065 0x1000000,\r
befbc4f3 1066 EFI_SIZE_TO_PAGES (MemorySize),\r
bcecde14 1067 &MemoryAddress\r
1068 );\r
74dee931 1069 if (EFI_ERROR (Status)) {\r
1070 //\r
1071 // If it fails, allocate high PMM Memory under 4GB\r
1072 // \r
1073 Status = AllocateLegacyMemory (\r
1074 AllocateMaxAddress,\r
1075 0xFFFFFFFF,\r
1076 EFI_SIZE_TO_PAGES (MemorySize),\r
1077 &MemoryAddress\r
1078 ); \r
1079 }\r
bcecde14 1080 if (!EFI_ERROR (Status)) {\r
1081 EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress;\r
befbc4f3 1082 EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize;\r
74dee931 1083 } \r
bcecde14 1084\r
1085 //\r
1086 // ShutdownAPs();\r
1087 //\r
1088 // Start the Legacy BIOS;\r
1089 //\r
1090 Status = ShadowAndStartLegacy16 (Private);\r
1091 if (EFI_ERROR (Status)) {\r
1092 return Status;\r
1093 }\r
1094 //\r
1095 // Initialize interrupt redirection code and entries;\r
1096 // IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.\r
1097 //\r
1098 CopyMem (\r
1099 Private->IntThunk->InterruptRedirectionCode,\r
1100 (VOID *) (UINTN) InterruptRedirectionTemplate,\r
1101 sizeof (Private->IntThunk->InterruptRedirectionCode)\r
1102 );\r
1103\r
1104 //\r
1105 // Save Unexpected interrupt vector so can restore it just prior to boot\r
1106 //\r
1107 BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);\r
1108 Private->BiosUnexpectedInt = BaseVectorMaster[0];\r
1109 IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;\r
1110 for (Index = 0; Index < 8; Index++) {\r
1111 BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);\r
1112 }\r
1113 //\r
1114 // Save EFI value\r
1115 //\r
1116 Private->ThunkSeg = (UINT16) (EFI_SEGMENT (IntRedirCode));\r
b6823730
EL
1117 \r
1118 //\r
1119 // Allocate reserved memory for SMBIOS table used in legacy boot if SMBIOS table exists\r
1120 //\r
1121 InstallSmbiosEventCallback (NULL, NULL);\r
1122\r
1123 //\r
1124 // Create callback function to update the size of reserved memory after LegacyBiosDxe starts\r
1125 //\r
1126 Status = gBS->CreateEventEx (\r
1127 EVT_NOTIFY_SIGNAL,\r
1128 TPL_NOTIFY,\r
1129 InstallSmbiosEventCallback,\r
1130 NULL,\r
1131 &gEfiSmbiosTableGuid,\r
1132 &InstallSmbiosEvent\r
1133 );\r
1134 ASSERT_EFI_ERROR (Status); \r
bcecde14 1135\r
1136 //\r
1137 // Make a new handle and install the protocol\r
1138 //\r
1139 Private->Handle = NULL;\r
1140 Status = gBS->InstallProtocolInterface (\r
1141 &Private->Handle,\r
1142 &gEfiLegacyBiosProtocolGuid,\r
1143 EFI_NATIVE_INTERFACE,\r
1144 &Private->LegacyBios\r
1145 );\r
1146 Private->Csm16PciInterfaceVersion = GetPciInterfaceVersion (Private);\r
1147 \r
1148 DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", \r
1149 (UINT8) (Private->Csm16PciInterfaceVersion >> 8), \r
1150 (UINT8) Private->Csm16PciInterfaceVersion\r
1151 ));\r
1152 ASSERT (Private->Csm16PciInterfaceVersion != 0);\r
1153 return Status;\r
1154}\r