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