1 /** @file
2
3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "LegacyBiosInterface.h"
17 #include <IndustryStandard/Pci.h>
18
19 // Give floppy 3 states
20 // FLOPPY_PRESENT_WITH_MEDIA = Floppy controller present and media is inserted
21 // FLOPPY_NOT_PRESENT = No floppy controller present
22 // FLOPPY_PRESENT_NO_MEDIA = Floppy controller present but no media inserted
23 //
24 #define FLOPPY_NOT_PRESENT 0
25 #define FLOPPY_PRESENT_WITH_MEDIA 1
26 #define FLOPPY_PRESENT_NO_MEDIA 2
27
28 BBS_TABLE *mBbsTable;
29 BOOLEAN mBbsTableDoneFlag = FALSE;
30 BOOLEAN IsHaveMediaInFloppy = TRUE;
31
32 /**
33 Checks the state of the floppy and if media is inserted.
34
35 This routine checks the state of the floppy and if media is inserted.
36 There are 3 cases:
37 No floppy present - Set BBS entry to ignore
38 Floppy present & no media - Set BBS entry to lowest priority. We cannot
39 set it to ignore since 16-bit CSM will
40 indicate no floppy and thus drive A: is
41 unusable. CSM-16 will not try floppy since
42 lowest priority and thus not incur boot
43 time penality.
44 Floppy present & media - Set BBS entry to some priority.
45
46 @return State of floppy media
47
48 **/
49 UINT8
HasMediaInFloppy(VOID)50 HasMediaInFloppy (
51 VOID
52 )
53 {
54 EFI_STATUS Status;
55 UINTN HandleCount;
56 EFI_HANDLE *HandleBuffer;
57 UINTN Index;
58 EFI_ISA_IO_PROTOCOL *IsaIo;
59 EFI_BLOCK_IO_PROTOCOL *BlkIo;
60
61 HandleBuffer = NULL;
62 HandleCount = 0;
63
64 gBS->LocateHandleBuffer (
65 ByProtocol,
66 &gEfiIsaIoProtocolGuid,
67 NULL,
68 &HandleCount,
69 &HandleBuffer
70 );
71
72 //
73 // If don't find any ISA/IO protocol assume no floppy. Need for floppy
74 // free system
75 //
76 if (HandleCount == 0) {
77 return FLOPPY_NOT_PRESENT;
78 }
79
80 ASSERT (HandleBuffer != NULL);
81
82 for (Index = 0; Index < HandleCount; Index++) {
83 Status = gBS->HandleProtocol (
84 HandleBuffer[Index],
85 &gEfiIsaIoProtocolGuid,
86 (VOID **) &IsaIo
87 );
88 if (EFI_ERROR (Status)) {
89 continue;
90 }
91
92 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
93 continue;
94 }
95 //
96 // Update blockio in case the floppy is inserted in during BdsTimeout
97 //
98 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
99
100 if (EFI_ERROR (Status)) {
101 continue;
102 }
103
104 Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
105
106 if (EFI_ERROR (Status)) {
107 continue;
108 }
109
110 Status = gBS->HandleProtocol (
111 HandleBuffer[Index],
112 &gEfiBlockIoProtocolGuid,
113 (VOID **) &BlkIo
114 );
115 if (EFI_ERROR (Status)) {
116 continue;
117 }
118
119 if (BlkIo->Media->MediaPresent) {
120 FreePool (HandleBuffer);
121 return FLOPPY_PRESENT_WITH_MEDIA;
122 } else {
123 FreePool (HandleBuffer);
124 return FLOPPY_PRESENT_NO_MEDIA;
125 }
126 }
127
128 FreePool (HandleBuffer);
129
130 return FLOPPY_NOT_PRESENT;
131
132 }
133
134
135 /**
136 Complete build of BBS TABLE.
137
138 @param Private Legacy BIOS Instance data
139 @param BbsTable BBS Table passed to 16-bit code
140
141 @retval EFI_SUCCESS Removable media not present
142
143 **/
144 EFI_STATUS
LegacyBiosBuildBbs(IN LEGACY_BIOS_INSTANCE * Private,IN BBS_TABLE * BbsTable)145 LegacyBiosBuildBbs (
146 IN LEGACY_BIOS_INSTANCE *Private,
147 IN BBS_TABLE *BbsTable
148 )
149 {
150 UINTN BbsIndex;
151 HDD_INFO *HddInfo;
152 UINTN HddIndex;
153 UINTN Index;
154
155 //
156 // First entry is floppy.
157 // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE.
158 // Next n entries are filled in after each ROM is dispatched.
159 // Entry filled in if follow BBS spec. See LegacyPci.c
160 // Next entries are for non-BBS compliant ROMS. They are filled in by
161 // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority
162 // occurs after that invocation.
163 //
164 // Floppy
165 // Set default state.
166 //
167 IsHaveMediaInFloppy = HasMediaInFloppy ();
168 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) {
169 BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY;
170 } else {
171 if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) {
172 BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY;
173 } else {
174 BbsTable[0].BootPriority = BBS_IGNORE_ENTRY;
175 }
176 }
177
178 BbsTable[0].Bus = 0xff;
179 BbsTable[0].Device = 0xff;
180 BbsTable[0].Function = 0xff;
181 BbsTable[0].DeviceType = BBS_FLOPPY;
182 BbsTable[0].Class = 01;
183 BbsTable[0].SubClass = 02;
184 BbsTable[0].StatusFlags.OldPosition = 0;
185 BbsTable[0].StatusFlags.Reserved1 = 0;
186 BbsTable[0].StatusFlags.Enabled = 0;
187 BbsTable[0].StatusFlags.Failed = 0;
188 BbsTable[0].StatusFlags.MediaPresent = 0;
189 BbsTable[0].StatusFlags.Reserved2 = 0;
190
191 //
192 // Onboard HDD - Note Each HDD controller controls 2 drives
193 // Master & Slave
194 //
195 HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
196 //
197 // Get IDE Drive Info
198 //
199 LegacyBiosBuildIdeData (Private, &HddInfo, 0);
200
201 for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) {
202
203 BbsIndex = HddIndex * 2 + 1;
204 for (Index = 0; Index < 2; ++Index) {
205
206 BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus;
207 BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device;
208 BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function;
209 BbsTable[BbsIndex + Index].Class = 01;
210 BbsTable[BbsIndex + Index].SubClass = 01;
211 BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0;
212 BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0;
213 BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0;
214 BbsTable[BbsIndex + Index].StatusFlags.Failed = 0;
215 BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0;
216 BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0;
217
218 //
219 // If no controller found or no device found set to ignore
220 // else set to unprioritized and set device type
221 //
222 if (HddInfo[HddIndex].CommandBaseAddress == 0) {
223 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
224 } else {
225 if (Index == 0) {
226 if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) {
227 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
228 if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) {
229 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
230 } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) {
231 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
232 } else {
233 //
234 // for ZIPDISK
235 //
236 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
237 }
238 } else {
239 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
240 }
241 } else {
242 if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) {
243 BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
244 if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) {
245 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
246 } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) {
247 BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM;
248 } else {
249 //
250 // for ZIPDISK
251 //
252 BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK;
253 }
254 } else {
255 BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY;
256 }
257 }
258 }
259 }
260 }
261
262 return EFI_SUCCESS;
263
264 }
265
266
267 /**
268 Get all BBS info
269
270 @param This Protocol instance pointer.
271 @param HddCount Number of HDD_INFO structures
272 @param HddInfo Onboard IDE controller information
273 @param BbsCount Number of BBS_TABLE structures
274 @param BbsTable List BBS entries
275
276 @retval EFI_SUCCESS Tables returned
277 @retval EFI_NOT_FOUND resource not found
278 @retval EFI_DEVICE_ERROR can not get BBS table
279
280 **/
281 EFI_STATUS
282 EFIAPI
LegacyBiosGetBbsInfo(IN EFI_LEGACY_BIOS_PROTOCOL * This,OUT UINT16 * HddCount,OUT HDD_INFO ** HddInfo,OUT UINT16 * BbsCount,OUT BBS_TABLE ** BbsTable)283 LegacyBiosGetBbsInfo (
284 IN EFI_LEGACY_BIOS_PROTOCOL *This,
285 OUT UINT16 *HddCount,
286 OUT HDD_INFO **HddInfo,
287 OUT UINT16 *BbsCount,
288 OUT BBS_TABLE **BbsTable
289 )
290 {
291 LEGACY_BIOS_INSTANCE *Private;
292 EFI_IA32_REGISTER_SET Regs;
293 EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
294 // HDD_INFO *LocalHddInfo;
295 // IN BBS_TABLE *LocalBbsTable;
296 UINTN NumHandles;
297 EFI_HANDLE *HandleBuffer;
298 UINTN Index;
299 UINTN TempData;
300 UINT32 Granularity;
301
302 HandleBuffer = NULL;
303
304 Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
305 EfiToLegacy16BootTable = &Private->IntThunk->EfiToLegacy16BootTable;
306 // LocalHddInfo = EfiToLegacy16BootTable->HddInfo;
307 // LocalBbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
308
309 if (!mBbsTableDoneFlag) {
310 mBbsTable = Private->BbsTablePtr;
311
312 //
313 // Always enable disk controllers so 16-bit CSM code has valid information for all
314 // drives.
315 //
316 //
317 // Get PciRootBridgeIO protocol
318 //
319 gBS->LocateHandleBuffer (
320 ByProtocol,
321 &gEfiPciRootBridgeIoProtocolGuid,
322 NULL,
323 &NumHandles,
324 &HandleBuffer
325 );
326
327 if (NumHandles == 0) {
328 return EFI_NOT_FOUND;
329 }
330
331 mBbsTableDoneFlag = TRUE;
332 for (Index = 0; Index < NumHandles; Index++) {
333 //
334 // Connect PciRootBridgeIO protocol handle with FALSE parameter to let
335 // PCI bus driver enumerate all subsequent handles
336 //
337 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
338
339 }
340
341 LegacyBiosBuildBbs (Private, mBbsTable);
342
343 Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
344
345 //
346 // Call into Legacy16 code to add to BBS table for non BBS compliant OPROMs.
347 //
348 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
349 Regs.X.AX = Legacy16UpdateBbs;
350
351 //
352 // Pass in handoff data
353 //
354 TempData = (UINTN) EfiToLegacy16BootTable;
355 Regs.X.ES = NORMALIZE_EFI_SEGMENT ((UINT32) TempData);
356 Regs.X.BX = NORMALIZE_EFI_OFFSET ((UINT32) TempData);
357
358 Private->LegacyBios.FarCall86 (
359 This,
360 Private->Legacy16CallSegment,
361 Private->Legacy16CallOffset,
362 &Regs,
363 NULL,
364 0
365 );
366
367 Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
368 Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, &Granularity);
369
370 if (Regs.X.AX != 0) {
371 return EFI_DEVICE_ERROR;
372 }
373 }
374
375 if (HandleBuffer != NULL) {
376 FreePool (HandleBuffer);
377 }
378
379 *HddCount = MAX_IDE_CONTROLLER;
380 *HddInfo = EfiToLegacy16BootTable->HddInfo;
381 *BbsTable = (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable;
382 *BbsCount = (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (BBS_TABLE));
383 return EFI_SUCCESS;
384 }
385