]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Csm / LegacyBiosDxe / LegacyBbs.c
1 /** @file
2
3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "LegacyBiosInterface.h"
10 #include <IndustryStandard/Pci.h>
11
12 // Give floppy 3 states
13 // FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted
14 // FLOPPY_NOT_PRESENT = No floppy controller present
15 // FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted
16 //
17 #define FLOPPY_NOT_PRESENT 0
18 #define FLOPPY_PRESENT_WITH_MEDIA 1
19 #define FLOPPY_PRESENT_NO_MEDIA 2
20
21 BBS_TABLE *mBbsTable;
22 BOOLEAN mBbsTableDoneFlag = FALSE;
23 BOOLEAN IsHaveMediaInFloppy = TRUE;
24
25 /**
26 Checks the state of the floppy and if media is inserted.
27
28 This routine checks the state of the floppy and if media is inserted.
29 There are 3 cases:
30 No floppy present - Set BBS entry to ignore
31 Floppy present & no media - Set BBS entry to lowest priority. We cannot
32 set it to ignore since 16-bit CSM will
33 indicate no floppy and thus drive A: is
34 unusable. CSM-16 will not try floppy since
35 lowest priority and thus not incur boot
36 time penality.
37 Floppy present & media - Set BBS entry to some priority.
38
39 @return State of floppy media
40
41 **/
42 UINT8
43 HasMediaInFloppy (
44 VOID
45 )
46 {
47 EFI_STATUS Status;
48 UINTN HandleCount;
49 EFI_HANDLE *HandleBuffer;
50 UINTN Index;
51 EFI_ISA_IO_PROTOCOL *IsaIo;
52 EFI_BLOCK_IO_PROTOCOL *BlkIo;
53
54 HandleBuffer = NULL;
55 HandleCount = 0;
56
57 gBS->LocateHandleBuffer (
58 ByProtocol,
59 &gEfiIsaIoProtocolGuid,
60 NULL,
61 &HandleCount,
62 &HandleBuffer
63 );
64
65 //
66 // If don't find any ISA/IO protocol assume no floppy. Need for floppy
67 // free system
68 //
69 if (HandleCount == 0) {
70 return FLOPPY_NOT_PRESENT;
71 }
72
73 ASSERT (HandleBuffer != NULL);
74
75 for (Index = 0; Index < HandleCount; Index++) {
76 Status = gBS->HandleProtocol (
77 HandleBuffer[Index],
78 &gEfiIsaIoProtocolGuid,
79 (VOID **)&IsaIo
80 );
81 if (EFI_ERROR (Status)) {
82 continue;
83 }
84
85 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
86 continue;
87 }
88
89 //
90 // Update blockio in case the floppy is inserted in during BdsTimeout
91 //
92 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
93
94 if (EFI_ERROR (Status)) {
95 continue;
96 }
97
98 Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
99
100 if (EFI_ERROR (Status)) {
101 continue;
102 }
103
104 Status = gBS->HandleProtocol (
105 HandleBuffer[Index],
106 &gEfiBlockIoProtocolGuid,
107 (VOID **)&BlkIo
108 );
109 if (EFI_ERROR (Status)) {
110 continue;
111 }
112
113 if (BlkIo->Media->MediaPresent) {
114 FreePool (HandleBuffer);
115 return FLOPPY_PRESENT_WITH_MEDIA;
116 } else {
117 FreePool (HandleBuffer);
118 return FLOPPY_PRESENT_NO_MEDIA;
119 }
120 }
121
122 FreePool (HandleBuffer);
123
124 return FLOPPY_NOT_PRESENT;
125 }
126
127 /**
128 Complete build of BBS TABLE.
129
130 @param Private Legacy BIOS Instance data
131 @param BbsTable BBS Table passed to 16-bit code
132
133 @retval EFI_SUCCESS Removable media not present
134
135 **/
136 EFI_STATUS
137 LegacyBiosBuildBbs (
138 IN LEGACY_BIOS_INSTANCE *Private,
139 IN BBS_TABLE *BbsTable
140 )
141 {
142 UINTN BbsIndex;
143 HDD_INFO *HddInfo;
144 UINTN HddIndex;
145 UINTN Index;
146 EFI_HANDLE *BlockIoHandles;
147 UINTN NumberBlockIoHandles;
148 UINTN BlockIndex;
149 EFI_STATUS Status;
150
151 //
152 // First entry is floppy.
153 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
154 // Next n entries are filled in after each ROM is dispatched.
155 // Entry filled in if follow BBS spec. See LegacyPci.c
156 // Next entries are for non-BBS compliant ROMS. They are filled in by
157 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
158 // occurs after that invocation.
159 //
160 // Floppy
161 // Set default state.
162 //
163 IsHaveMediaInFloppy = HasMediaInFloppy ();
164 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {
165 BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;
166 } else {
167 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {
168 BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;
169 } else {
170 BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;
171 }
172 }
173
174 BbsTable[0].Bus = 0xff;
175 BbsTable[0].Device = 0xff;
176 BbsTable[0].Function = 0xff;
177 BbsTable[0].DeviceType = BBS_FLOPPY;
178 BbsTable[0].Class = 01;
179 BbsTable[0].SubClass = 02;
180 BbsTable[0].StatusFlags.OldPosition = 0;
181 BbsTable[0].StatusFlags.Reserved1 = 0;
182 BbsTable[0].StatusFlags.Enabled = 0;
183 BbsTable[0].StatusFlags.Failed = 0;
184 BbsTable[0].StatusFlags.MediaPresent = 0;
185 BbsTable[0].StatusFlags.Reserved2 = 0;
186
187 //
188 // Onboard HDD - Note Each HDD controller controls 2 drives
189 // Master & Slave
190 //
191 HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
192 //
193 // Get IDE Drive Info
194 //
195 LegacyBiosBuildIdeData (Private, &HddInfo, 0);
196
197 for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {
198 BbsIndex = HddIndex * 2 + 1;
199 for (Index = 0; Index < 2; ++Index) {
200 BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;
201 BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;
202 BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;
203 BbsTable[BbsIndex + Index].Class = 01;
204 BbsTable[BbsIndex + Index].SubClass = 01;
205 BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;
206 BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;
207 BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;
208 BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;
209 BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;
210 BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;
211
212 //
213 // If no controller found or no device found set to ignore
214 // else set to unprioritized and set device type
215 //
216 if (HddInfo[HddIndex].CommandBaseAddress == 0) {
217 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
218 } else {
219 if (Index == 0) {
220 if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {
221 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
222 if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {
223 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
224 } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {
225 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
226 } else {
227 //
228 // for ZIPDISK
229 //
230 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
231 }
232 } else {
233 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
234 }
235 } else {
236 if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {
237 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
238 if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {
239 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
240 } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {
241 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
242 } else {
243 //
244 // for ZIPDISK
245 //
246 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
247 }
248 } else {
249 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
250 }
251 }
252 }
253 }
254 }
255
256 //
257 // Add non-IDE block devices
258 //
259 BbsIndex = HddIndex * 2 + 1;
260
261 Status = gBS->LocateHandleBuffer (
262 ByProtocol,
263 &gEfiBlockIoProtocolGuid,
264 NULL,
265 &NumberBlockIoHandles,
266 &BlockIoHandles
267 );
268
269 if (!EFI_ERROR (Status)) {
270 UINTN Removable;
271 EFI_BLOCK_IO_PROTOCOL *BlkIo;
272 EFI_PCI_IO_PROTOCOL *PciIo;
273 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
274 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
275 EFI_HANDLE PciHandle;
276 UINTN SegNum;
277 UINTN BusNum;
278 UINTN DevNum;
279 UINTN FuncNum;
280
281 for (Removable = 0; Removable < 2; Removable++) {
282 for (BlockIndex = 0; BlockIndex < NumberBlockIoHandles; BlockIndex++) {
283 Status = gBS->HandleProtocol (
284 BlockIoHandles[BlockIndex],
285 &gEfiBlockIoProtocolGuid,
286 (VOID **)&BlkIo
287 );
288
289 if (EFI_ERROR (Status)) {
290 continue;
291 }
292
293 //
294 // Skip the logical partitions
295 //
296 if (BlkIo->Media->LogicalPartition) {
297 continue;
298 }
299
300 //
301 // Skip the fixed block io then the removable block io
302 //
303 if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {
304 continue;
305 }
306
307 //
308 // Get Device Path
309 //
310 Status = gBS->HandleProtocol (
311 BlockIoHandles[BlockIndex],
312 &gEfiDevicePathProtocolGuid,
313 (VOID **)&DevicePath
314 );
315 if (EFI_ERROR (Status)) {
316 continue;
317 }
318
319 //
320 // Skip ATA devices as they have already been handled
321 //
322 DevicePathNode = DevicePath;
323 while (!IsDevicePathEnd (DevicePathNode)) {
324 if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
325 (DevicePathSubType (DevicePathNode) == MSG_ATAPI_DP))
326 {
327 break;
328 }
329
330 DevicePathNode = NextDevicePathNode (DevicePathNode);
331 }
332
333 if (!IsDevicePathEnd (DevicePathNode)) {
334 continue;
335 }
336
337 //
338 // Locate which PCI device
339 //
340 Status = gBS->LocateDevicePath (
341 &gEfiPciIoProtocolGuid,
342 &DevicePath,
343 &PciHandle
344 );
345 if (EFI_ERROR (Status)) {
346 continue;
347 }
348
349 Status = gBS->HandleProtocol (
350 PciHandle,
351 &gEfiPciIoProtocolGuid,
352 (VOID **)&PciIo
353 );
354 if (EFI_ERROR (Status)) {
355 continue;
356 }
357
358 Status = PciIo->GetLocation (
359 PciIo,
360 &SegNum,
361 &BusNum,
362 &DevNum,
363 &FuncNum
364 );
365 if (EFI_ERROR (Status)) {
366 continue;
367 }
368
369 if (SegNum != 0) {
370 DEBUG ((
371 DEBUG_WARN,
372 "CSM cannot use PCI devices in segment %Lu\n",
373 (UINT64)SegNum
374 ));
375 continue;
376 }
377
378 DEBUG ((
379 DEBUG_INFO,
380 "Add Legacy Bbs entry for PCI %d/%d/%d\n",
381 BusNum,
382 DevNum,
383 FuncNum
384 ));
385
386 BbsTable[BbsIndex].Bus = BusNum;
387 BbsTable[BbsIndex].Device = DevNum;
388 BbsTable[BbsIndex].Function = FuncNum;
389 BbsTable[BbsIndex].Class = 1;
390 BbsTable[BbsIndex].SubClass = 0x80;
391 BbsTable[BbsIndex].StatusFlags.OldPosition = 0;
392 BbsTable[BbsIndex].StatusFlags.Reserved1 = 0;
393 BbsTable[BbsIndex].StatusFlags.Enabled = 0;
394 BbsTable[BbsIndex].StatusFlags.Failed = 0;
395 BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;
396 BbsTable[BbsIndex].StatusFlags.Reserved2 = 0;
397 BbsTable[BbsIndex].DeviceType = BBS_HARDDISK;
398 BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY;
399 BbsIndex++;
400
401 if (BbsIndex == MAX_BBS_ENTRIES) {
402 Removable = 2;
403 break;
404 }
405 }
406 }
407
408 FreePool (BlockIoHandles);
409 }
410
411 return EFI_SUCCESS;
412 }
413
414 /**
415 Get all BBS info
416
417 @param This Protocol instance pointer.
418 @param HddCount Number of HDD_INFO structures
419 @param HddInfo Onboard IDE controller information
420 @param BbsCount Number of BBS_TABLE structures
421 @param BbsTable List BBS entries
422
423 @retval EFI_SUCCESS Tables returned
424 @retval EFI_NOT_FOUND resource not found
425 @retval EFI_DEVICE_ERROR can not get BBS table
426
427 **/
428 EFI_STATUS
429 EFIAPI
430 LegacyBiosGetBbsInfo (
431 IN EFI_LEGACY_BIOS_PROTOCOL *This,
432 OUT UINT16 *HddCount,
433 OUT HDD_INFO **HddInfo,
434 OUT UINT16 *BbsCount,
435 OUT BBS_TABLE **BbsTable
436 )
437 {
438 LEGACY_BIOS_INSTANCE *Private;
439 EFI_IA32_REGISTER_SET Regs;
440 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
441 // HDD_INFO *LocalHddInfo;
442 // IN BBS_TABLE *LocalBbsTable;
443 UINTN NumHandles;
444 EFI_HANDLE *HandleBuffer;
445 UINTN Index;
446 UINTN TempData;
447 UINT32 Granularity;
448
449 HandleBuffer = NULL;
450
451 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
452 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
453 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
454 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
455
456 if (!mBbsTableDoneFlag) {
457 mBbsTable = Private->BbsTablePtr;
458
459 //
460 // Always enable disk controllers so 16-bit CSM code has valid information for all
461 // drives.
462 //
463 //
464 // Get PciRootBridgeIO protocol
465 //
466 gBS->LocateHandleBuffer (
467 ByProtocol,
468 &gEfiPciRootBridgeIoProtocolGuid,
469 NULL,
470 &NumHandles,
471 &HandleBuffer
472 );
473
474 if (NumHandles == 0) {
475 return EFI_NOT_FOUND;
476 }
477
478 mBbsTableDoneFlag = TRUE;
479 for (Index = 0; Index < NumHandles; Index++) {
480 //
481 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
482 // PCI bus driver enumerate all subsequent handles
483 //
484 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
485 }
486
487 LegacyBiosBuildBbs (Private, mBbsTable);
488
489 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
490
491 //
492 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
493 //
494 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
495 Regs.X.AX = Legacy16UpdateBbs;
496
497 //
498 // Pass in handoff data
499 //
500 TempData = (UINTN)EfiToLegacy16BootTable;
501 Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32)TempData);
502 Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32)TempData);
503
504 Private->LegacyBios.FarCall86 (
505 This,
506 Private->Legacy16CallSegment,
507 Private->Legacy16CallOffset,
508 &Regs,
509 NULL,
510 0
511 );
512
513 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
514 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
515
516 if (Regs.X.AX != 0) {
517 return EFI_DEVICE_ERROR;
518 }
519 }
520
521 if (HandleBuffer != NULL) {
522 FreePool (HandleBuffer);
523 }
524
525 *HddCount = MAX_IDE_CONTROLLER;
526 *HddInfo = EfiToLegacy16BootTable->HddInfo;
527 *BbsTable = (BBS_TABLE *)(UINTN)EfiToLegacy16BootTable->BbsTable;
528 *BbsCount = (UINT16)(sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
529 return EFI_SUCCESS;
530 }