]> code.delx.au - refind/blob - EfiLib/BdsHelper.c
New files to support legacy BIOS boots on UEFI-based PCs
[refind] / EfiLib / BdsHelper.c
1 /*
2 * EfiLib/BdsHelper.c
3 * Functions to call legacy BIOS API.
4 *
5 */
6
7
8 #include "BdsHelper.h"
9
10 /**
11 Internal helper function.
12
13 Update the BBS Table so that devices of DeviceType have their boot priority
14 updated to a high/bootable value.
15
16 See "DeviceType values" in
17 http://www.intel.com/content/dam/doc/reference-guide/efi-compatibility-support-module-specification-v097.pdf
18
19 NOTE: This function should probably be refactored! Currently, all devices of
20 type are enabled. This should be updated so that only a specific device is
21 enabled. The wrong device could boot if there are multiple targets of the same
22 type.
23
24 @param DeviceType The device type that we wish to enable
25 **/
26 VOID
27 UpdateBbsTable (
28 IN UINT16 DeviceType
29 )
30 {
31 UINT16 Idx;
32 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
33 EFI_GUID EfiLegacyBootProtocolGuid = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
34 EFI_STATUS Status;
35 UINT16 HddCount = 0;
36 HDD_INFO *HddInfo = NULL;
37 UINT16 BbsCount = 0;
38 BBS_TABLE *LocalBbsTable = NULL;
39
40 Status = gBS->LocateProtocol (&EfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios);
41 if (EFI_ERROR (Status)) {
42 return;
43 }
44
45 Status = LegacyBios->GetBbsInfo (LegacyBios, &HddCount, &HddInfo, &BbsCount, &LocalBbsTable);
46
47 //Print (L"\n");
48 //Print (L" NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n");
49 //Print (L"=============================================\n");
50
51 for (Idx = 0; Idx < BbsCount; Idx++)
52 {
53 if(LocalBbsTable[Idx].DeviceType == 0){
54 continue;
55 }
56
57 // Set devices of a particular type to BootPriority of 0. I believe 0 is the highest priority
58 if(LocalBbsTable[Idx].DeviceType == DeviceType){
59 LocalBbsTable[Idx].BootPriority = 0;
60 }
61
62 /*
63 Print (
64 L" %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
65 (UINTN) Idx,
66 (UINTN) LocalBbsTable[Idx].BootPriority,
67 (UINTN) LocalBbsTable[Idx].Bus,
68 (UINTN) LocalBbsTable[Idx].Device,
69 (UINTN) LocalBbsTable[Idx].Function,
70 (UINTN) LocalBbsTable[Idx].Class,
71 (UINTN) LocalBbsTable[Idx].SubClass,
72 (UINTN) LocalBbsTable[Idx].DeviceType,
73 (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
74 (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
75 (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
76 (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
77 (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset)
78 );
79 */
80 }
81
82 //Print(L"\n");
83 }
84
85 // Internal helper function
86 BOOLEAN ArrayContains(UINT16* Arr, UINT8 ArrLen, UINT8 Target)
87 {
88 UINT8 i;
89 for(i = 0; i < ArrLen; i++)
90 {
91 if(Arr[i] == Target)
92 return TRUE;
93 }
94
95 return FALSE;
96 }
97
98 /**
99 True if the DeviceType is supported by rEFInd, false otherwise.
100 */
101 BOOLEAN IsBbsDeviceTypeSupported(UINT16 DeviceType)
102 {
103 return ArrayContains(SupportedLegacyDevices, sizeof(SupportedLegacyDevices), DeviceType);
104 }
105
106 /**
107 Boot the legacy system with the boot option
108
109 @param Option The legacy boot option which have BBS device path
110
111 @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support
112 legacy boot.
113 @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot ().
114
115 **/
116 EFI_STATUS
117 BdsLibDoLegacyBoot (
118 IN BDS_COMMON_OPTION *Option
119 )
120 {
121 EFI_STATUS Status;
122 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
123 EFI_GUID EfiLegacyBootProtocolGuid = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
124 EFI_GUID EfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
125 BBS_BBS_DEVICE_PATH *OptionBBS;
126
127 Status = gBS->LocateProtocol (&EfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios);
128 if (EFI_ERROR (Status)) {
129 return EFI_UNSUPPORTED;
130 }
131 OptionBBS = (BBS_BBS_DEVICE_PATH *) Option->DevicePath;
132
133 //Print(L"\n\n");
134 //Print(L"Option->Name='%s'\n", Option->OptionName);
135 //Print(L"Option->Number='%d'\n", Option->OptionNumber);
136 //Print(L"Option->Description='%s'\n", Option->Description);
137 //Print(L"Option->LoadOptionsSize='%d'\n",Option->LoadOptionsSize);
138 //Print(L"Option->BootCurrent='%d'\n",Option->BootCurrent);
139 //Print(L"Option->DevicePath->Type= '%d'\n", Option->DevicePath->Type);
140 //Print(L"Option->DevicePath->SubType= '%d'\n", Option->DevicePath->SubType);
141 //Print(L"Option->DevicePath->Length[0]= '%d'\n", Option->DevicePath->Length[0]);
142 //Print(L"Option->DevicePath->Length[1]= '%d'\n", Option->DevicePath->Length[1]);
143 //Print(L"OptionBBS->DeviceType='%d'\n",OptionBBS->DeviceType);
144 //Print(L"OptionBBS->StatusFlag='%d'\n",OptionBBS->StatusFlag);
145 //Print(L"OptionBBS->String[0]='%c'\n",OptionBBS->String[0]);
146 //Print(L"About to legacy boot!\n");
147 //PauseForKey();
148
149 UpdateBbsTable(OptionBBS->DeviceType);
150
151 return LegacyBios->LegacyBoot (LegacyBios, (BBS_BBS_DEVICE_PATH *) Option->DevicePath, Option->LoadOptionsSize, Option->LoadOptions);
152 }
153