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