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