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
HasMediaInFloppy(VOID)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
LegacyBiosBuildBbs(IN LEGACY_BIOS_INSTANCE * Private,IN BBS_TABLE * BbsTable)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
LegacyBiosGetBbsInfo(IN EFI_LEGACY_BIOS_PROTOCOL * This,OUT UINT16 * HddCount,OUT HDD_INFO ** HddInfo,OUT UINT16 * BbsCount,OUT BBS_TABLE ** BbsTable)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 }
378