Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

585 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. menu.c
  5. Abstract:
  6. Revision History:
  7. Jeff Sigman 05/01/00 Created
  8. Jeff Sigman 05/10/00 Version 1.5 released
  9. Jeff Sigman 10/18/00 Fix for Soft81 bug(s)
  10. --*/
  11. #include "precomp.h"
  12. ADVANCEDBOOT_OPTIONS AdvancedBootOptions[] =
  13. {
  14. {BL_MENU_ITEM, BL_SAFEBOOT_OPTION1, BL_SAFEBOOT_OPTION1M},
  15. {BL_MENU_ITEM, BL_SAFEBOOT_OPTION2, BL_SAFEBOOT_OPTION2M},
  16. {BL_MENU_ITEM, BL_SAFEBOOT_OPTION4, BL_SAFEBOOT_OPTION4M},
  17. {BL_MENU_BLANK_LINE, NULL, NULL},
  18. {BL_MENU_ITEM, BL_BOOTLOG, BL_BOOTLOGM},
  19. {BL_MENU_ITEM, BL_BASEVIDEO, BL_BASEVIDEOM},
  20. {BL_MENU_ITEM, BL_LASTKNOWNGOOD_OPTION, NULL},
  21. {BL_MENU_ITEM, BL_SAFEBOOT_OPTION6, BL_SAFEBOOT_OPTION6M},
  22. {BL_MENU_ITEM, BL_DEBUG_OPTION, BL_DEBUG_OPTIONM},
  23. {BL_MENU_BLANK_LINE, NULL, NULL},
  24. {BL_MENU_ITEM, BL_MSG_BOOT_NORMALLY, NULL},
  25. {BL_MENU_ITEM, BL_MSG_OSCHOICES_MENU, NULL}
  26. };
  27. #define MaxAdvancedBootOptions (sizeof(AdvancedBootOptions)/sizeof(ADVANCEDBOOT_OPTIONS))
  28. //
  29. //
  30. //
  31. char*
  32. FindAdvLoadOptions(
  33. IN char* String
  34. )
  35. {
  36. char* find = NULL;
  37. UINTN i;
  38. for (i = 0; i < MaxAdvancedBootOptions; i++)
  39. {
  40. if (!AdvancedBootOptions[i].LoadOptions)
  41. {
  42. continue;
  43. }
  44. if (find = strstr(String, AdvancedBootOptions[i].LoadOptions))
  45. {
  46. if (*(find - 1) == SPACEC)
  47. {
  48. find--;
  49. break;
  50. }
  51. else
  52. {
  53. find = NULL;
  54. continue;
  55. }
  56. }
  57. }
  58. return find;
  59. }
  60. //
  61. //
  62. //
  63. void
  64. MenuEraseLine(
  65. IN UINTN x,
  66. IN UINTN y,
  67. IN UINTN* Width
  68. )
  69. {
  70. UINTN i;
  71. ST->ConOut->SetCursorPosition(ST->ConOut, x, y);
  72. for (i = 0; i < *Width; i++)
  73. {
  74. Print(L" ");
  75. }
  76. ST->ConOut->SetCursorPosition(ST->ConOut, x, y);
  77. return;
  78. }
  79. //
  80. //
  81. //
  82. void
  83. MenuHighlightOn(
  84. )
  85. {
  86. ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_LIGHTGRAY);
  87. return;
  88. }
  89. //
  90. //
  91. //
  92. void
  93. MenuHighlightOff(
  94. )
  95. {
  96. ST->ConOut->SetAttribute(ST->ConOut,
  97. EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK));
  98. ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_BLACK);
  99. return;
  100. }
  101. //
  102. //
  103. //
  104. void
  105. MenuHighlight(
  106. IN UINTN Flag,
  107. IN UINTN* Highlight,
  108. IN UINTN* Width,
  109. IN UINT16 Key,
  110. IN VOID* hBootData
  111. )
  112. {
  113. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  114. do
  115. {
  116. if (Flag == HIGHLT_MAIN_INIT)
  117. {
  118. MenuHighlightOn();
  119. Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight],
  120. pBootData->pszShort[*Highlight]);
  121. MenuHighlightOff();
  122. break;
  123. }
  124. else if (Flag == HIGHLT_MAIN_LOOP)
  125. {
  126. MenuEraseLine(0, (*Highlight) + 5, Width);
  127. Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight],
  128. pBootData->pszShort[*Highlight]);
  129. switch (Key)
  130. {
  131. case SCAN_UP:
  132. if (*Highlight == 0)
  133. {
  134. *Highlight = pBootData->dwIndex;
  135. }
  136. else
  137. {
  138. (*Highlight)--;
  139. }
  140. break;
  141. case SCAN_DOWN:
  142. if (*Highlight == pBootData->dwIndex)
  143. {
  144. *Highlight = 0;
  145. }
  146. else
  147. {
  148. (*Highlight)++;
  149. }
  150. break;
  151. }
  152. MenuEraseLine(0, (*Highlight) + 5, Width);
  153. MenuHighlightOn();
  154. Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight],
  155. pBootData->pszShort[*Highlight]);
  156. MenuHighlightOff();
  157. break;
  158. }
  159. else if (Flag == HIGHLT_ADVND_INIT)
  160. {
  161. MenuHighlightOn();
  162. Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId);
  163. MenuHighlightOff();
  164. break;
  165. }
  166. else if (Flag == HIGHLT_ADVND_LOOP)
  167. {
  168. MenuEraseLine(0, (*Highlight) + 4, Width);
  169. Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId);
  170. switch (Key)
  171. {
  172. case SCAN_UP:
  173. if (*Highlight == 0)
  174. {
  175. *Highlight = MaxAdvancedBootOptions - 1;
  176. }
  177. else
  178. {
  179. (*Highlight)--;
  180. }
  181. //
  182. // Check for space
  183. //
  184. if (AdvancedBootOptions[*Highlight].MsgId == NULL)
  185. {
  186. if (*Highlight == 0)
  187. {
  188. *Highlight = MaxAdvancedBootOptions - 1;
  189. }
  190. else
  191. {
  192. (*Highlight)--;
  193. }
  194. }
  195. break;
  196. case SCAN_DOWN:
  197. if (*Highlight == MaxAdvancedBootOptions - 1)
  198. {
  199. *Highlight =0;
  200. }
  201. else
  202. {
  203. (*Highlight)++;
  204. }
  205. //
  206. // Check for space
  207. //
  208. if (AdvancedBootOptions[*Highlight].MsgId == NULL)
  209. {
  210. if (*Highlight == MaxAdvancedBootOptions - 1)
  211. {
  212. *Highlight = 0;
  213. }
  214. else
  215. {
  216. (*Highlight)++;
  217. }
  218. }
  219. break;
  220. }
  221. MenuEraseLine(0, (*Highlight) + 4, Width);
  222. MenuHighlightOn();
  223. Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId);
  224. MenuHighlightOff();
  225. break;
  226. }
  227. } while (FALSE);
  228. return;
  229. }
  230. //
  231. //
  232. //
  233. UINTN
  234. DrawAdvancedBoot(
  235. IN UINTN* Width,
  236. IN VOID* hBootData
  237. )
  238. {
  239. UINTN i,
  240. Highlight = 0,
  241. Exit = 0;
  242. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  243. EFI_INPUT_KEY Key;
  244. //
  245. // Clear the screen
  246. //
  247. ST->ConOut->ClearScreen(ST->ConOut);
  248. Print(L"\n%s\n\n", BL_ADVANCEDBOOT_TITLE);
  249. for (i = 0; i < MaxAdvancedBootOptions; i++)
  250. {
  251. if (i == Highlight)
  252. {
  253. MenuHighlight(HIGHLT_ADVND_INIT, &Highlight, NULL, 0, pBootData);
  254. continue;
  255. }
  256. if (!(AdvancedBootOptions[i].MsgId))
  257. {
  258. Print(L"\n");
  259. continue;
  260. }
  261. Print(L" %s\n", AdvancedBootOptions[i].MsgId);
  262. }
  263. Print(L"\n%s%c%s%c%s\n", BL_MOVE_HIGHLIGHT1, ARROW_UP,
  264. BL_MOVE_HIGHLIGHT2, ARROW_DOWN, BL_MOVE_HIGHLIGHT3);
  265. //
  266. // Loop through menu options until user hits enter/esc
  267. //
  268. while (!Exit)
  269. {
  270. WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
  271. ST->ConIn->ReadKeyStroke(ST->ConIn, &Key);
  272. switch (Key.UnicodeChar)
  273. {
  274. case CHAR_CARRIAGE_RETURN:
  275. Exit = 1;
  276. continue;
  277. case 0:
  278. switch (Key.ScanCode)
  279. {
  280. case SCAN_UP:
  281. MenuHighlight(
  282. HIGHLT_ADVND_LOOP,
  283. &Highlight,
  284. Width,
  285. SCAN_UP,
  286. pBootData);
  287. break;
  288. case SCAN_DOWN:
  289. MenuHighlight(
  290. HIGHLT_ADVND_LOOP,
  291. &Highlight,
  292. Width,
  293. SCAN_DOWN,
  294. pBootData);
  295. break;
  296. case SCAN_ESC:
  297. Highlight = 11;
  298. Exit = 1;
  299. continue;
  300. }
  301. }
  302. }
  303. return Highlight;
  304. }
  305. //
  306. //
  307. //
  308. void
  309. DrawChoices(
  310. IN UINTN* Highlight,
  311. IN VOID* hBootData
  312. )
  313. {
  314. int i;
  315. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  316. //
  317. // Clear the screen
  318. //
  319. ST->ConOut->ClearScreen(ST->ConOut);
  320. Print(L"\n\n%s\n\n\n", BL_SELECT_OS);
  321. for (i = 0; i <= pBootData->dwIndex; i++)
  322. {
  323. if (*Highlight == i)
  324. {
  325. MenuHighlight(HIGHLT_MAIN_INIT, Highlight, NULL, 0, pBootData);
  326. continue;
  327. }
  328. Print(L" %a (%a)\n", pBootData->pszIdent[i],
  329. pBootData->pszShort[i]);
  330. }
  331. Print(L"\n%s%c%s%c%s\n", BL_MOVE_HIGHLIGHT1, ARROW_UP,
  332. BL_MOVE_HIGHLIGHT2, ARROW_DOWN, BL_MOVE_HIGHLIGHT3);
  333. return;
  334. }
  335. //
  336. //
  337. //
  338. void
  339. EnableAdvOpt(
  340. IN VOID* hBootData,
  341. IN UINTN* Index
  342. )
  343. {
  344. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  345. if (AdvancedBootOptions[*Index].LoadOptions)
  346. {
  347. pBootData->pszLoadOpt =
  348. RutlStrDup(AdvancedBootOptions[*Index].LoadOptions);
  349. }
  350. else
  351. {
  352. pBootData->dwLastKnown = 1;
  353. }
  354. return;
  355. }
  356. //
  357. //
  358. //
  359. void
  360. DisableAdvOpt(
  361. IN VOID* hBootData
  362. )
  363. {
  364. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  365. if (pBootData->pszLoadOpt)
  366. pBootData->pszLoadOpt = RutlFree(pBootData->pszLoadOpt);
  367. pBootData->dwLastKnown = 0;
  368. return;
  369. }
  370. //
  371. //
  372. //
  373. UINTN
  374. DisplayMenu(
  375. IN VOID* hBootData
  376. )
  377. {
  378. int i;
  379. UINTN j,
  380. Highlight = 0,
  381. Width = 0,
  382. Height = 0,
  383. Exit = 0,
  384. Advanced = 0;
  385. BOOT_DATA* pBootData = (BOOT_DATA*) hBootData;
  386. EFI_STATUS Status;
  387. EFI_INPUT_KEY Key;
  388. //
  389. // Set the screen to 80 x 25 mode
  390. //
  391. ST->ConOut->SetMode(ST->ConOut, 0);
  392. //
  393. // Get the height and width of the screen
  394. //
  395. ST->ConOut->QueryMode(ST->ConOut, ST->ConOut->Mode->Mode, &Width, &Height);
  396. //
  397. // Disable the cursor
  398. //
  399. ST->ConOut->EnableCursor(ST->ConOut, FALSE);
  400. DrawChoices(&Highlight, pBootData);
  401. Print(L"%s", BL_TIMEOUT_COUNTDOWN);
  402. for (i = (int)pBootData->dwCount; i >= 0; i--)
  403. {
  404. Print(L"\n\n\n%s", BL_ADVANCED_BOOT_MESSAGE);
  405. ST->ConOut->SetCursorPosition(
  406. ST->ConOut,
  407. StrLen(BL_TIMEOUT_COUNTDOWN),
  408. BL_NUMBER_OF_LINES + pBootData->dwIndex - 1);
  409. Print(L"%d ", i);
  410. //
  411. // Wait 1 second, stop waiting if a key is pressed
  412. //
  413. Status = WaitForSingleEvent(ST->ConIn->WaitForKey, 10000000);
  414. //
  415. // Get the key from the buffer
  416. //
  417. ST->ConIn->ReadKeyStroke(ST->ConIn, &Key);
  418. if (Status == EFI_TIMEOUT)
  419. {
  420. Exit = 1;
  421. continue;
  422. }
  423. else
  424. {
  425. Exit = 0;
  426. //
  427. // Erase the the timeout message
  428. //
  429. MenuEraseLine(
  430. 0,
  431. BL_NUMBER_OF_LINES + pBootData->dwIndex - 1,
  432. &Width);
  433. break;
  434. }
  435. }
  436. //
  437. // Loop through menu options until user hits enter
  438. //
  439. while (!Exit)
  440. {
  441. switch (Key.UnicodeChar)
  442. {
  443. case CHAR_CARRIAGE_RETURN:
  444. Exit = 1;
  445. continue;
  446. case 0:
  447. switch (Key.ScanCode)
  448. {
  449. case SCAN_UP:
  450. MenuHighlight(
  451. HIGHLT_MAIN_LOOP,
  452. &Highlight,
  453. &Width,
  454. SCAN_UP,
  455. pBootData);
  456. break;
  457. case SCAN_DOWN:
  458. MenuHighlight(
  459. HIGHLT_MAIN_LOOP,
  460. &Highlight,
  461. &Width,
  462. SCAN_DOWN,
  463. pBootData);
  464. break;
  465. case SCAN_F8:
  466. Advanced = DrawAdvancedBoot(&Width, pBootData);
  467. //
  468. // If user already selected another option, we kill it
  469. //
  470. DisableAdvOpt(pBootData);
  471. if (Advanced == 10)
  472. {
  473. Exit = 1;
  474. continue;
  475. }
  476. else
  477. {
  478. DrawChoices(&Highlight, pBootData);
  479. Print(L"\n\n\n%s", BL_ADVANCED_BOOT_MESSAGE);
  480. if (Advanced < 9)
  481. {
  482. EnableAdvOpt(pBootData, &Advanced);
  483. ST->ConOut->SetAttribute(ST->ConOut,
  484. EFI_TEXT_ATTR(EFI_LIGHTBLUE, EFI_BLACK));
  485. Print(L"\n\n%s", AdvancedBootOptions[Advanced].MsgId);
  486. MenuHighlightOff();
  487. break;
  488. }
  489. }
  490. break;
  491. }
  492. }
  493. WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
  494. ST->ConIn->ReadKeyStroke(ST->ConIn, &Key);
  495. }
  496. //
  497. // Clear the screen
  498. //
  499. ST->ConOut->ClearScreen(ST->ConOut);
  500. //
  501. // Re-enable the cursor
  502. //
  503. ST->ConOut->EnableCursor(ST->ConOut, TRUE);
  504. return Highlight;
  505. }