]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c
6b1dd344f3446336caf96d40f3b28058153618c0
[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
148 //
149 // First entry is floppy.
150 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
151 // Next n entries are filled in after each ROM is dispatched.
152 // Entry filled in if follow BBS spec. See LegacyPci.c
153 // Next entries are for non-BBS compliant ROMS. They are filled in by
154 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
155 // occurs after that invocation.
156 //
157 // Floppy
158 // Set default state.
159 //
160 IsHaveMediaInFloppy = HasMediaInFloppy ();
161 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {
162 BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;
163 } else {
164 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {
165 BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;
166 } else {
167 BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;
168 }
169 }
170
171 BbsTable[0].Bus = 0xff;
172 BbsTable[0].Device = 0xff;
173 BbsTable[0].Function = 0xff;
174 BbsTable[0].DeviceType = BBS_FLOPPY;
175 BbsTable[0].Class = 01;
176 BbsTable[0].SubClass = 02;
177 BbsTable[0].StatusFlags.OldPosition = 0;
178 BbsTable[0].StatusFlags.Reserved1 = 0;
179 BbsTable[0].StatusFlags.Enabled = 0;
180 BbsTable[0].StatusFlags.Failed = 0;
181 BbsTable[0].StatusFlags.MediaPresent = 0;
182 BbsTable[0].StatusFlags.Reserved2 = 0;
183
184 //
185 // Onboard HDD - Note Each HDD controller controls 2 drives
186 // Master & Slave
187 //
188 HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
189 //
190 // Get IDE Drive Info
191 //
192 LegacyBiosBuildIdeData (Private, &HddInfo, 0);
193
194 for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {
195
196 BbsIndex = HddIndex * 2 + 1;
197 for (Index = 0; Index < 2; ++Index) {
198
199 BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;
200 BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;
201 BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;
202 BbsTable[BbsIndex + Index].Class = 01;
203 BbsTable[BbsIndex + Index].SubClass = 01;
204 BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;
205 BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;
206 BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;
207 BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;
208 BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;
209 BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;
210
211 //
212 // If no controller found or no device found set to ignore
213 // else set to unprioritized and set device type
214 //
215 if (HddInfo[HddIndex].CommandBaseAddress == 0) {
216 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
217 } else {
218 if (Index == 0) {
219 if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {
220 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
221 if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {
222 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
223 } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {
224 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
225 } else {
226 //
227 // for ZIPDISK
228 //
229 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
230 }
231 } else {
232 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
233 }
234 } else {
235 if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {
236 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
237 if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {
238 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
239 } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {
240 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
241 } else {
242 //
243 // for ZIPDISK
244 //
245 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
246 }
247 } else {
248 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
249 }
250 }
251 }
252 }
253 }
254
255 return EFI_SUCCESS;
256
257 }
258
259
260 /**
261 Get all BBS info
262
263 @param This Protocol instance pointer.
264 @param HddCount Number of HDD_INFO structures
265 @param HddInfo Onboard IDE controller information
266 @param BbsCount Number of BBS_TABLE structures
267 @param BbsTable List BBS entries
268
269 @retval EFI_SUCCESS Tables returned
270 @retval EFI_NOT_FOUND resource not found
271 @retval EFI_DEVICE_ERROR can not get BBS table
272
273 **/
274 EFI_STATUS
275 EFIAPI
276 LegacyBiosGetBbsInfo (
277 IN EFI_LEGACY_BIOS_PROTOCOL *This,
278 OUT UINT16 *HddCount,
279 OUT HDD_INFO **HddInfo,
280 OUT UINT16 *BbsCount,
281 OUT BBS_TABLE **BbsTable
282 )
283 {
284 LEGACY_BIOS_INSTANCE *Private;
285 EFI_IA32_REGISTER_SET Regs;
286 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
287 // HDD_INFO *LocalHddInfo;
288 // IN BBS_TABLE *LocalBbsTable;
289 UINTN NumHandles;
290 EFI_HANDLE *HandleBuffer;
291 UINTN Index;
292 UINTN TempData;
293 UINT32 Granularity;
294
295 HandleBuffer = NULL;
296
297 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
298 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
299 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
300 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
301
302 if (!mBbsTableDoneFlag) {
303 mBbsTable = Private->BbsTablePtr;
304
305 //
306 // Always enable disk controllers so 16-bit CSM code has valid information for all
307 // drives.
308 //
309 //
310 // Get PciRootBridgeIO protocol
311 //
312 gBS->LocateHandleBuffer (
313 ByProtocol,
314 &gEfiPciRootBridgeIoProtocolGuid,
315 NULL,
316 &NumHandles,
317 &HandleBuffer
318 );
319
320 if (NumHandles == 0) {
321 return EFI_NOT_FOUND;
322 }
323
324 mBbsTableDoneFlag = TRUE;
325 for (Index = 0; Index < NumHandles; Index++) {
326 //
327 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
328 // PCI bus driver enumerate all subsequent handles
329 //
330 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
331
332 }
333
334 LegacyBiosBuildBbs (Private, mBbsTable);
335
336 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
337
338 //
339 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
340 //
341 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
342 Regs.X.AX = Legacy16UpdateBbs;
343
344 //
345 // Pass in handoff data
346 //
347 TempData = (UINTN) EfiToLegacy16BootTable;
348 Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData);
349 Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData);
350
351 Private->LegacyBios.FarCall86 (
352 This,
353 Private->Legacy16CallSegment,
354 Private->Legacy16CallOffset,
355 &Regs,
356 NULL,
357 0
358 );
359
360 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
361 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
362
363 if (Regs.X.AX != 0) {
364 return EFI_DEVICE_ERROR;
365 }
366 }
367
368 if (HandleBuffer != NULL) {
369 FreePool (HandleBuffer);
370 }
371
372 *HddCount = MAX_IDE_CONTROLLER;
373 *HddInfo = EfiToLegacy16BootTable->HddInfo;
374 *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
375 *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
376 return EFI_SUCCESS;
377 }