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