PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/edk2/Clover/OsxBdsDxe/BootMngr/BootManager.c

https://gitlab.com/envieidoc/Clover
C | 412 lines | 256 code | 51 blank | 105 comment | 37 complexity | ee549d8310433b6ed2361108d31c6f80 MD5 | raw file
  1. /** @file
  2. The platform boot manager reference implementation
  3. Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
  4. This program and the accompanying materials
  5. are licensed and made available under the terms and conditions of the BSD License
  6. which accompanies this distribution. The full text of the license may be found at
  7. http://opensource.org/licenses/bsd-license.php
  8. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #include "BootManager.h"
  12. UINT16 mKeyInput;
  13. LIST_ENTRY mBootOptionsList;
  14. BDS_COMMON_OPTION *gOption;
  15. CHAR16 *mDeviceTypeStr[] = {
  16. L"Legacy BEV",
  17. L"Legacy Floppy",
  18. L"Legacy Hard Drive",
  19. L"Legacy CD ROM",
  20. L"Legacy PCMCIA",
  21. L"Legacy USB",
  22. L"Legacy Embedded Network",
  23. L"Legacy Unknown Device"
  24. };
  25. HII_VENDOR_DEVICE_PATH mBootManagerHiiVendorDevicePath = {
  26. {
  27. {
  28. HARDWARE_DEVICE_PATH,
  29. HW_VENDOR_DP,
  30. {
  31. (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
  32. (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  33. }
  34. },
  35. BOOT_MANAGER_FORMSET_GUID
  36. },
  37. {
  38. END_DEVICE_PATH_TYPE,
  39. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  40. {
  41. (UINT8) (END_DEVICE_PATH_LENGTH),
  42. (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
  43. }
  44. }
  45. };
  46. BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
  47. BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
  48. NULL,
  49. NULL,
  50. {
  51. FakeExtractConfig,
  52. FakeRouteConfig,
  53. BootManagerCallback
  54. }
  55. };
  56. /**
  57. This call back function is registered with Boot Manager formset.
  58. When user selects a boot option, this call back function will
  59. be triggered. The boot option is saved for later processing.
  60. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  61. @param Action Specifies the type of action taken by the browser.
  62. @param QuestionId A unique value which is sent to the original exporting driver
  63. so that it can identify the type of data to expect.
  64. @param Type The type of value for the question.
  65. @param Value A pointer to the data being sent to the original exporting driver.
  66. @param ActionRequest On return, points to the action requested by the callback function.
  67. @retval EFI_SUCCESS The callback successfully handled the action.
  68. @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
  69. **/
  70. EFI_STATUS
  71. EFIAPI
  72. BootManagerCallback (
  73. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  74. IN EFI_BROWSER_ACTION Action,
  75. IN EFI_QUESTION_ID QuestionId,
  76. IN UINT8 Type,
  77. IN EFI_IFR_TYPE_VALUE *Value,
  78. OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
  79. )
  80. {
  81. BDS_COMMON_OPTION *Option;
  82. LIST_ENTRY *Link;
  83. UINT16 KeyCount;
  84. if (Action == EFI_BROWSER_ACTION_CHANGED) {
  85. if ((Value == NULL) || (ActionRequest == NULL)) {
  86. return EFI_INVALID_PARAMETER;
  87. }
  88. //
  89. // Initialize the key count
  90. //
  91. KeyCount = 0;
  92. for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
  93. Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
  94. KeyCount++;
  95. gOption = Option;
  96. //
  97. // Is this device the one chosen?
  98. //
  99. if (KeyCount == QuestionId) {
  100. //
  101. // Assigning the returned Key to a global allows the original routine to know what was chosen
  102. //
  103. mKeyInput = QuestionId;
  104. //
  105. // Request to exit SendForm(), so that we could boot the selected option
  106. //
  107. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
  108. break;
  109. }
  110. }
  111. return EFI_SUCCESS;
  112. }
  113. //
  114. // All other action return unsupported.
  115. //
  116. return EFI_UNSUPPORTED;
  117. }
  118. /**
  119. Registers HII packages for the Boot Manger to HII Database.
  120. It also registers the browser call back function.
  121. @retval EFI_SUCCESS HII packages for the Boot Manager were registered successfully.
  122. @retval EFI_OUT_OF_RESOURCES HII packages for the Boot Manager failed to be registered.
  123. **/
  124. EFI_STATUS
  125. InitializeBootManager (
  126. VOID
  127. )
  128. {
  129. EFI_STATUS Status;
  130. //
  131. // Install Device Path Protocol and Config Access protocol to driver handle
  132. //
  133. Status = gBS->InstallMultipleProtocolInterfaces (
  134. &gBootManagerPrivate.DriverHandle,
  135. &gEfiDevicePathProtocolGuid,
  136. &mBootManagerHiiVendorDevicePath,
  137. &gEfiHiiConfigAccessProtocolGuid,
  138. &gBootManagerPrivate.ConfigAccess,
  139. NULL
  140. );
  141. ASSERT_EFI_ERROR (Status);
  142. //
  143. // Publish our HII data
  144. //
  145. gBootManagerPrivate.HiiHandle = HiiAddPackages (
  146. &gBootManagerFormSetGuid,
  147. gBootManagerPrivate.DriverHandle,
  148. BootManagerVfrBin,
  149. BdsDxeStrings,
  150. NULL
  151. );
  152. if (gBootManagerPrivate.HiiHandle == NULL) {
  153. Status = EFI_OUT_OF_RESOURCES;
  154. } else {
  155. Status = EFI_SUCCESS;
  156. }
  157. return Status;
  158. }
  159. /**
  160. This function invokes Boot Manager. If all devices have not a chance to be connected,
  161. the connect all will be triggered. It then enumerate all boot options. If
  162. a boot option from the Boot Manager page is selected, Boot Manager will boot
  163. from this boot option.
  164. **/
  165. VOID
  166. CallBootManager (
  167. VOID
  168. )
  169. {
  170. EFI_STATUS Status;
  171. BDS_COMMON_OPTION *Option;
  172. LIST_ENTRY *Link;
  173. CHAR16 *ExitData;
  174. UINTN ExitDataSize;
  175. EFI_STRING_ID Token;
  176. EFI_INPUT_KEY Key;
  177. CHAR16 *HelpString;
  178. EFI_STRING_ID HelpToken;
  179. UINT16 *TempStr;
  180. EFI_HII_HANDLE HiiHandle;
  181. EFI_BROWSER_ACTION_REQUEST ActionRequest;
  182. UINTN TempSize;
  183. VOID *StartOpCodeHandle;
  184. VOID *EndOpCodeHandle;
  185. EFI_IFR_GUID_LABEL *StartLabel;
  186. EFI_IFR_GUID_LABEL *EndLabel;
  187. UINT16 DeviceType;
  188. BOOLEAN IsLegacyOption;
  189. BOOLEAN NeedEndOp;
  190. DeviceType = (UINT16) -1;
  191. gOption = NULL;
  192. InitializeListHead (&mBootOptionsList);
  193. //
  194. // Connect all prior to entering the platform setup menu.
  195. //
  196. if (!gConnectAllHappened) {
  197. BdsLibConnectAllDriversToAllControllers ();
  198. gConnectAllHappened = TRUE;
  199. }
  200. BdsLibEnumerateAllBootOption (&mBootOptionsList);
  201. //
  202. // Group the legacy boot options for the same device type
  203. //
  204. GroupMultipleLegacyBootOption4SameType ();
  205. InitializeListHead (&mBootOptionsList);
  206. BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder");
  207. HiiHandle = gBootManagerPrivate.HiiHandle;
  208. //
  209. // Allocate space for creation of UpdateData Buffer
  210. //
  211. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  212. // ASSERT (StartOpCodeHandle != NULL);
  213. if (!StartOpCodeHandle) {
  214. return;
  215. }
  216. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  217. // ASSERT (EndOpCodeHandle != NULL);
  218. if (!EndOpCodeHandle) {
  219. return;
  220. }
  221. //
  222. // Create Hii Extend Label OpCode as the start opcode
  223. //
  224. StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  225. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  226. StartLabel->Number = LABEL_BOOT_OPTION;
  227. //
  228. // Create Hii Extend Label OpCode as the end opcode
  229. //
  230. EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  231. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  232. EndLabel->Number = LABEL_BOOT_OPTION_END;
  233. mKeyInput = 0;
  234. NeedEndOp = FALSE;
  235. for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) {
  236. Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
  237. //
  238. // At this stage we are creating a menu entry, thus the Keys are reproduceable
  239. //
  240. mKeyInput++;
  241. //
  242. // Don't display the hidden/inactive boot option
  243. //
  244. if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) {
  245. continue;
  246. }
  247. //
  248. // Group the legacy boot option in the sub title created dynamically
  249. //
  250. IsLegacyOption = (BOOLEAN) (
  251. (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&
  252. (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)
  253. );
  254. if (!IsLegacyOption && NeedEndOp) {
  255. NeedEndOp = FALSE;
  256. HiiCreateEndOpCode (StartOpCodeHandle);
  257. }
  258. if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) {
  259. if (NeedEndOp) {
  260. HiiCreateEndOpCode (StartOpCodeHandle);
  261. }
  262. DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType;
  263. Token = HiiSetString (
  264. HiiHandle,
  265. 0,
  266. mDeviceTypeStr[
  267. MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1)
  268. ],
  269. NULL
  270. );
  271. HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1);
  272. NeedEndOp = TRUE;
  273. }
  274. // ASSERT (Option->Description != NULL);
  275. if (!Option->Description) {
  276. return;
  277. }
  278. Token = HiiSetString (HiiHandle, 0, Option->Description, NULL);
  279. TempStr = FileDevicePathToStr (Option->DevicePath);
  280. TempSize = StrSize (TempStr);
  281. HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
  282. // ASSERT (HelpString != NULL);
  283. if (!HelpString) {
  284. return;
  285. }
  286. StrCat (HelpString, L"Device Path : ");
  287. StrCat (HelpString, TempStr);
  288. HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL);
  289. HiiCreateActionOpCode (
  290. StartOpCodeHandle,
  291. mKeyInput,
  292. Token,
  293. HelpToken,
  294. EFI_IFR_FLAG_CALLBACK,
  295. 0
  296. );
  297. }
  298. if (NeedEndOp) {
  299. HiiCreateEndOpCode (StartOpCodeHandle);
  300. }
  301. HiiUpdateForm (
  302. HiiHandle,
  303. &gBootManagerFormSetGuid,
  304. BOOT_MANAGER_FORM_ID,
  305. StartOpCodeHandle,
  306. EndOpCodeHandle
  307. );
  308. HiiFreeOpCodeHandle (StartOpCodeHandle);
  309. HiiFreeOpCodeHandle (EndOpCodeHandle);
  310. ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
  311. Status = gFormBrowser2->SendForm (
  312. gFormBrowser2,
  313. &HiiHandle,
  314. 1,
  315. &gBootManagerFormSetGuid,
  316. 0,
  317. NULL,
  318. &ActionRequest
  319. );
  320. if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
  321. EnableResetRequired ();
  322. }
  323. if (gOption == NULL) {
  324. return ;
  325. }
  326. //
  327. // Will leave browser, check any reset required change is applied? if yes, reset system
  328. //
  329. SetupResetReminder ();
  330. //
  331. // Restore to original mode before launching boot option.
  332. //
  333. BdsSetConsoleMode (FALSE);
  334. //
  335. // parse the selected option
  336. //
  337. Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
  338. if (!EFI_ERROR (Status)) {
  339. gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
  340. PlatformBdsBootSuccess (gOption);
  341. } else {
  342. gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
  343. PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
  344. gST->ConOut->OutputString (
  345. gST->ConOut,
  346. GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
  347. );
  348. gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
  349. }
  350. }