LegacyBbs.c 16 KB

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