]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c
OvmfPkg/LegacyBbs: Add boot entries for VirtIO and NVME devices
[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 // Update blockio in case the floppy is inserted in during BdsTimeout
90 //
91 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
92
93 if (EFI_ERROR (Status)) {
94 continue;
95 }
96
97 Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
98
99 if (EFI_ERROR (Status)) {
100 continue;
101 }
102
103 Status = gBS->HandleProtocol (
104 HandleBuffer[Index],
105 &gEfiBlockIoProtocolGuid,
106 (VOID **) &BlkIo
107 );
108 if (EFI_ERROR (Status)) {
109 continue;
110 }
111
112 if (BlkIo->Media->MediaPresent) {
113 FreePool (HandleBuffer);
114 return FLOPPY_PRESENT_WITH_MEDIA;
115 } else {
116 FreePool (HandleBuffer);
117 return FLOPPY_PRESENT_NO_MEDIA;
118 }
119 }
120
121 FreePool (HandleBuffer);
122
123 return FLOPPY_NOT_PRESENT;
124
125 }
126
127
128 /**
129 Complete build of BBS TABLE.
130
131 @param Private Legacy BIOS Instance data
132 @param BbsTable BBS Table passed to 16-bit code
133
134 @retval EFI_SUCCESS Removable media not present
135
136 **/
137 EFI_STATUS
138 LegacyBiosBuildBbs (
139 IN LEGACY_BIOS_INSTANCE *Private,
140 IN BBS_TABLE *BbsTable
141 )
142 {
143 UINTN BbsIndex;
144 HDD_INFO *HddInfo;
145 UINTN HddIndex;
146 UINTN Index;
147 EFI_HANDLE *BlockIoHandles;
148 UINTN NumberBlockIoHandles;
149 UINTN BlockIndex;
150 EFI_STATUS Status;
151
152 //
153 // First entry is floppy.
154 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
155 // Next n entries are filled in after each ROM is dispatched.
156 // Entry filled in if follow BBS spec. See LegacyPci.c
157 // Next entries are for non-BBS compliant ROMS. They are filled in by
158 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
159 // occurs after that invocation.
160 //
161 // Floppy
162 // Set default state.
163 //
164 IsHaveMediaInFloppy = HasMediaInFloppy ();
165 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {
166 BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;
167 } else {
168 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {
169 BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;
170 } else {
171 BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;
172 }
173 }
174
175 BbsTable[0].Bus = 0xff;
176 BbsTable[0].Device = 0xff;
177 BbsTable[0].Function = 0xff;
178 BbsTable[0].DeviceType = BBS_FLOPPY;
179 BbsTable[0].Class = 01;
180 BbsTable[0].SubClass = 02;
181 BbsTable[0].StatusFlags.OldPosition = 0;
182 BbsTable[0].StatusFlags.Reserved1 = 0;
183 BbsTable[0].StatusFlags.Enabled = 0;
184 BbsTable[0].StatusFlags.Failed = 0;
185 BbsTable[0].StatusFlags.MediaPresent = 0;
186 BbsTable[0].StatusFlags.Reserved2 = 0;
187
188 //
189 // Onboard HDD - Note Each HDD controller controls 2 drives
190 // Master & Slave
191 //
192 HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
193 //
194 // Get IDE Drive Info
195 //
196 LegacyBiosBuildIdeData (Private, &HddInfo, 0);
197
198 for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {
199
200 BbsIndex = HddIndex * 2 + 1;
201 for (Index = 0; Index < 2; ++Index) {
202
203 BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;
204 BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;
205 BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;
206 BbsTable[BbsIndex + Index].Class = 01;
207 BbsTable[BbsIndex + Index].SubClass = 01;
208 BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;
209 BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;
210 BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;
211 BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;
212 BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;
213 BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;
214
215 //
216 // If no controller found or no device found set to ignore
217 // else set to unprioritized and set device type
218 //
219 if (HddInfo[HddIndex].CommandBaseAddress == 0) {
220 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
221 } else {
222 if (Index == 0) {
223 if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {
224 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
225 if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {
226 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
227 } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {
228 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
229 } else {
230 //
231 // for ZIPDISK
232 //
233 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
234 }
235 } else {
236 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
237 }
238 } else {
239 if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {
240 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
241 if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {
242 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
243 } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {
244 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
245 } else {
246 //
247 // for ZIPDISK
248 //
249 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
250 }
251 } else {
252 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
253 }
254 }
255 }
256 }
257 }
258
259 //
260 // Add non-IDE block devices
261 //
262 BbsIndex = HddIndex * 2 + 1;
263
264 Status = gBS->LocateHandleBuffer (
265 ByProtocol,
266 &gEfiBlockIoProtocolGuid,
267 NULL,
268 &NumberBlockIoHandles,
269 &BlockIoHandles
270 );
271
272 if (!EFI_ERROR (Status)) {
273 UINTN Removable;
274 EFI_BLOCK_IO_PROTOCOL *BlkIo;
275 EFI_PCI_IO_PROTOCOL *PciIo;
276 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
277 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
278 EFI_HANDLE PciHandle;
279 UINTN SegNum;
280 UINTN BusNum;
281 UINTN DevNum;
282 UINTN FuncNum;
283
284 for (Removable = 0; Removable < 2; Removable++) {
285 for (BlockIndex = 0; BlockIndex < NumberBlockIoHandles; BlockIndex++) {
286 Status = gBS->HandleProtocol (
287 BlockIoHandles[BlockIndex],
288 &gEfiBlockIoProtocolGuid,
289 (VOID **) &BlkIo
290 );
291
292 if (EFI_ERROR (Status)) {
293 continue;
294 }
295
296 //
297 // Skip the logical partitions
298 //
299 if (BlkIo->Media->LogicalPartition) {
300 continue;
301 }
302
303 //
304 // Skip the fixed block io then the removable block io
305 //
306 if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {
307 continue;
308 }
309
310 //
311 // Get Device Path
312 //
313 Status = gBS->HandleProtocol (
314 BlockIoHandles[BlockIndex],
315 &gEfiDevicePathProtocolGuid,
316 (VOID **) &DevicePath
317 );
318 if (EFI_ERROR (Status)) {
319 continue;
320 }
321
322 //
323 // Skip ATA devices as they have already been handled
324 //
325 DevicePathNode = DevicePath;
326 while (!IsDevicePathEnd (DevicePathNode)) {
327 if (DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH &&
328 DevicePathSubType (DevicePathNode) == MSG_ATAPI_DP) {
329 break;
330 }
331 DevicePathNode = NextDevicePathNode (DevicePathNode);
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 ((DEBUG_WARN, "CSM cannot use PCI devices in segment %Lu\n",
371 (UINT64) SegNum));
372 continue;
373 }
374
375 DEBUG ((DEBUG_INFO, "Add Legacy Bbs entry for PCI %d/%d/%d\n",
376 BusNum, DevNum, FuncNum));
377
378 BbsTable[BbsIndex].Bus = BusNum;
379 BbsTable[BbsIndex].Device = DevNum;
380 BbsTable[BbsIndex].Function = FuncNum;
381 BbsTable[BbsIndex].Class = 1;
382 BbsTable[BbsIndex].SubClass = 0x80;
383 BbsTable[BbsIndex].StatusFlags.OldPosition = 0;
384 BbsTable[BbsIndex].StatusFlags.Reserved1 = 0;
385 BbsTable[BbsIndex].StatusFlags.Enabled = 0;
386 BbsTable[BbsIndex].StatusFlags.Failed = 0;
387 BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;
388 BbsTable[BbsIndex].StatusFlags.Reserved2 = 0;
389 BbsTable[BbsIndex].DeviceType = BBS_HARDDISK;
390 BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY;
391 BbsIndex++;
392
393 if (BbsIndex == MAX_BBS_ENTRIES) {
394 Removable = 2;
395 break;
396 }
397 }
398 }
399
400 FreePool (BlockIoHandles);
401 }
402
403 return EFI_SUCCESS;
404 }
405
406
407 /**
408 Get all BBS info
409
410 @param This Protocol instance pointer.
411 @param HddCount Number of HDD_INFO structures
412 @param HddInfo Onboard IDE controller information
413 @param BbsCount Number of BBS_TABLE structures
414 @param BbsTable List BBS entries
415
416 @retval EFI_SUCCESS Tables returned
417 @retval EFI_NOT_FOUND resource not found
418 @retval EFI_DEVICE_ERROR can not get BBS table
419
420 **/
421 EFI_STATUS
422 EFIAPI
423 LegacyBiosGetBbsInfo (
424 IN EFI_LEGACY_BIOS_PROTOCOL *This,
425 OUT UINT16 *HddCount,
426 OUT HDD_INFO **HddInfo,
427 OUT UINT16 *BbsCount,
428 OUT BBS_TABLE **BbsTable
429 )
430 {
431 LEGACY_BIOS_INSTANCE *Private;
432 EFI_IA32_REGISTER_SET Regs;
433 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
434 // HDD_INFO *LocalHddInfo;
435 // IN BBS_TABLE *LocalBbsTable;
436 UINTN NumHandles;
437 EFI_HANDLE *HandleBuffer;
438 UINTN Index;
439 UINTN TempData;
440 UINT32 Granularity;
441
442 HandleBuffer = NULL;
443
444 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
445 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
446 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
447 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
448
449 if (!mBbsTableDoneFlag) {
450 mBbsTable = Private->BbsTablePtr;
451
452 //
453 // Always enable disk controllers so 16-bit CSM code has valid information for all
454 // drives.
455 //
456 //
457 // Get PciRootBridgeIO protocol
458 //
459 gBS->LocateHandleBuffer (
460 ByProtocol,
461 &gEfiPciRootBridgeIoProtocolGuid,
462 NULL,
463 &NumHandles,
464 &HandleBuffer
465 );
466
467 if (NumHandles == 0) {
468 return EFI_NOT_FOUND;
469 }
470
471 mBbsTableDoneFlag = TRUE;
472 for (Index = 0; Index < NumHandles; Index++) {
473 //
474 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
475 // PCI bus driver enumerate all subsequent handles
476 //
477 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
478
479 }
480
481 LegacyBiosBuildBbs (Private, mBbsTable);
482
483 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
484
485 //
486 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
487 //
488 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
489 Regs.X.AX = Legacy16UpdateBbs;
490
491 //
492 // Pass in handoff data
493 //
494 TempData = (UINTN) EfiToLegacy16BootTable;
495 Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData);
496 Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData);
497
498 Private->LegacyBios.FarCall86 (
499 This,
500 Private->Legacy16CallSegment,
501 Private->Legacy16CallOffset,
502 &Regs,
503 NULL,
504 0
505 );
506
507 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
508 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
509
510 if (Regs.X.AX != 0) {
511 return EFI_DEVICE_ERROR;
512 }
513 }
514
515 if (HandleBuffer != NULL) {
516 FreePool (HandleBuffer);
517 }
518
519 *HddCount = MAX_IDE_CONTROLLER;
520 *HddInfo = EfiToLegacy16BootTable->HddInfo;
521 *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
522 *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
523 return EFI_SUCCESS;
524 }