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.

2081 lines
46 KiB

  1. /*++
  2. Module Name:
  3. nvrio.c
  4. Abstract:
  5. Access function to r/w environment variables from NVRAM
  6. Author:
  7. Mudit Vats (v-muditv) 12-13-99
  8. Revision History:
  9. --*/
  10. #include <precomp.h>
  11. #define FIELD_OFFSET(type, field) ((UINT32)(UINTN)&(((type *)0)->field))
  12. #define ALIGN_DOWN(length, type) \
  13. ((UINT32)(length) & ~(sizeof(type) - 1))
  14. #define ALIGN_UP(length, type) \
  15. (ALIGN_DOWN(((UINT32)(length) + sizeof(type) - 1), type))
  16. #define EFI_ATTR EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
  17. VOID* LoadOptions [MAXBOOTVARS];
  18. UINT64 LoadOptionsSize [MAXBOOTVARS];
  19. VOID* BootOrder;
  20. UINT64 BootOrderCount;
  21. UINT64 OsBootOptionCount;
  22. #define LOAD_OPTION_ACTIVE 0x00000001
  23. INT32
  24. SafeWcslen (
  25. CHAR16 *String,
  26. CHAR16 *Max
  27. )
  28. {
  29. CHAR16 *p = String;
  30. while ( (p < Max) && (*p != 0) ) {
  31. p++;
  32. }
  33. if ( p < Max ) {
  34. return(UINT32)(p - String);
  35. }
  36. return -1;
  37. } // SafeWclen
  38. #define ISWINDOWSOSCHECK_DEBUG 0
  39. BOOLEAN
  40. isWindowsOsBootOption(
  41. char* elo,
  42. UINT64 eloSize
  43. )
  44. //
  45. // Purpose: determine if the EFI_LOAD_OPTION structure in question is referring to
  46. // a Windows OS boot option
  47. //
  48. // Return:
  49. //
  50. // TRUE elo refers to a Windows OS option
  51. //
  52. {
  53. CHAR16 *max;
  54. INT32 l;
  55. UINTN length;
  56. PEFI_LOAD_OPTION pElo;
  57. char* devicePath;
  58. char* osOptions;
  59. PWINDOWS_OS_OPTIONS pOsOptions;
  60. char* aOsOptions;
  61. BOOLEAN status;
  62. status = TRUE;
  63. aOsOptions = NULL;
  64. pElo = (EFI_LOAD_OPTION*)elo;
  65. if ( eloSize < sizeof(EFI_LOAD_OPTION) ) {
  66. status = FALSE;
  67. goto Done;
  68. }
  69. #if ISWINDOWSOSCHECK_DEBUG
  70. Print( L"Is %s a Windows OS boot option?\n", pElo->Description );
  71. #endif
  72. //
  73. // Is the description properly terminated?
  74. //
  75. max = (CHAR16 *)(elo + eloSize);
  76. l = SafeWcslen( pElo->Description, max );
  77. if ( l < 0 ) {
  78. #if ISWINDOWSOSCHECK_DEBUG
  79. Print (L"Failed: SafeWcslen( pElo->Description, max )\n");
  80. #endif
  81. status = FALSE;
  82. goto Done;
  83. }
  84. //
  85. // get the WINDOWS_OS_OPTIONS structure from the OptionalData field
  86. //
  87. osOptions = elo +
  88. FIELD_OFFSET(EFI_LOAD_OPTION,Description) +
  89. StrSize(pElo->Description) +
  90. pElo->FilePathListLength;
  91. length = (UINTN)eloSize;
  92. length -= (UINTN)(osOptions - elo);
  93. #if ISWINDOWSOSCHECK_DEBUG
  94. Print (L"length = %x\n", length);
  95. #endif
  96. //
  97. // make sure osOptions are atleast the size of the
  98. // WINDOWS_OS_OPTIONS header
  99. //
  100. //
  101. if ( length < FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions) ) {
  102. #if ISWINDOWSOSCHECK_DEBUG
  103. Print (L"Failed: invalid length: %x\n", length);
  104. #endif
  105. status = FALSE;
  106. goto Done;
  107. }
  108. //
  109. // align the os options
  110. //
  111. aOsOptions = GetAlignedOsOptions(elo, eloSize);
  112. pOsOptions = (WINDOWS_OS_OPTIONS*)aOsOptions;
  113. #if ISWINDOWSOSCHECK_DEBUG
  114. DisplayOsOptions(aOsOptions);
  115. #endif
  116. //
  117. // Does the OsOptions structure look like a WINDOWS_OS_OPTIONS structure?
  118. //
  119. if ( (length != pOsOptions->Length) ||
  120. (WINDOWS_OS_OPTIONS_VERSION != pOsOptions->Version) ||
  121. (strcmpa(pOsOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) != 0) ) {
  122. #if ISWINDOWSOSCHECK_DEBUG
  123. Print (L"Failed: OsOptions doesn't look like WINDOWS_OS_OPTIONS structure.\n");
  124. Print (L"test1: %x\n", length != pOsOptions->Length);
  125. Print (L"test2: %x\n", WINDOWS_OS_OPTIONS_VERSION != pOsOptions->Version);
  126. Print (L"test3: %x\n", strcmpa(pOsOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) != 0 );
  127. #endif
  128. status = FALSE;
  129. goto Done;
  130. }
  131. //
  132. // Is the OsLoadOptions string properly terminated?
  133. //
  134. //
  135. // create a new max ptr to accomodate the fact that we are
  136. // now using an aligned copy of OsOptions from the Pool
  137. //
  138. max = (CHAR16*)(aOsOptions + pOsOptions->Length);
  139. #if ISWINDOWSOSCHECK_DEBUG
  140. Print (L"max = %x, osloadoptions = %x, diff = %x, strsize=%x\n",
  141. max,
  142. pOsOptions->OsLoadOptions,
  143. (char*)max - (char*)pOsOptions->OsLoadOptions,
  144. StrSize(pOsOptions->OsLoadOptions)
  145. );
  146. #endif
  147. l = SafeWcslen( pOsOptions->OsLoadOptions, max );
  148. if ( l < 0 ) {
  149. #if ISWINDOWSOSCHECK_DEBUG
  150. Print (L"Failed: SafeWcslen( osLoadOptions, max ) = %x\n", l);
  151. #endif
  152. status = FALSE;
  153. goto Done;
  154. }
  155. Done:
  156. //
  157. // we are done with the os options
  158. //
  159. if (aOsOptions != NULL) {
  160. FreePool(aOsOptions);
  161. }
  162. return status;
  163. }
  164. #define GETBOOTVARS_DEBUG 0
  165. VOID
  166. GetBootManagerVars(
  167. )
  168. {
  169. UINT32 i,j;
  170. CHAR16 szTemp[10];
  171. VOID* bootvar;
  172. UINT64 BootOrderSize = 0;
  173. //
  174. // Initialize EFI LoadOptions.
  175. //
  176. BootOrderSize = 0;
  177. BootOrderCount = 0;
  178. OsBootOptionCount = 0;
  179. BootOrder = NULL;
  180. #if 0
  181. ZeroMem( LoadOptions, sizeof(VOID*) * MAXBOOTVARS );
  182. ZeroMem( LoadOptionsSize, sizeof(UINT64) * MAXBOOTVARS );
  183. #endif
  184. //
  185. // Ensure that the Load Options have been freed
  186. //
  187. ASSERT(BootOrderCount == 0);
  188. //
  189. // Get BootOrder.
  190. //
  191. BootOrder = LibGetVariableAndSize( L"BootOrder", &VenEfi, &BootOrderSize );
  192. if ( BootOrder ) {
  193. BootOrderCount = BootOrderSize / sizeof(CHAR16);
  194. #if GETBOOTVARS_DEBUG
  195. Print (L"BootOrderCount = %x\n", BootOrderCount);
  196. #endif
  197. //
  198. // Get the boot options.
  199. //
  200. for ( i=0; i<BootOrderCount; i++ ) {
  201. SPrint( szTemp, sizeof(szTemp), L"Boot%04x", ((CHAR16*) BootOrder)[i] );
  202. ASSERT(LoadOptions[i] == NULL);
  203. ASSERT(LoadOptionsSize[i] == 0);
  204. LoadOptions[i] = LibGetVariableAndSize( szTemp, &VenEfi, &(LoadOptionsSize[i]) );
  205. #if GETBOOTVARS_DEBUG
  206. Print (L"i = %x, szTemp = %s, BOCnt = %x, LOptions = %x, BSize = %x\n",
  207. i,
  208. szTemp,
  209. OsBootOptionCount,
  210. LoadOptions[i],
  211. LoadOptionsSize[i]
  212. );
  213. #endif
  214. OsBootOptionCount++;
  215. }
  216. }
  217. }
  218. #define ERASEBOOTOPT_DEBUG 0
  219. BOOLEAN
  220. EraseOsBootOption(
  221. UINTN BootVarNum
  222. )
  223. {
  224. UINTN j;
  225. CHAR16 szTemp[10];
  226. CHAR16* tmpBootOrder;
  227. VOID* bootvar;
  228. UINT64 BootOrderSize = 0;
  229. VOID* pDummy;
  230. UINTN dummySize;
  231. //
  232. // Initialize EFI LoadOptions.
  233. //
  234. BootOrderSize = 0;
  235. BootOrderCount = 0;
  236. BootOrder = NULL;
  237. //
  238. // Get BootOrder.
  239. //
  240. BootOrder = LibGetVariableAndSize( L"BootOrder", &VenEfi, &BootOrderSize );
  241. BootOrderCount = BootOrderSize / sizeof(CHAR16);
  242. ASSERT(BootOrderCount == OsBootOptionCount);
  243. ASSERT(BootVarNum < MAXBOOTVARS);
  244. ASSERT(BootOrderCount >= 1);
  245. #if ERASEBOOTOPT_DEBUG
  246. Print (L"BootOrderCount = %x\n", BootOrderCount);
  247. Print (L"BootVarNum = %x\n", BootVarNum);
  248. #endif
  249. //
  250. // if the boot option is populated, then erase it
  251. //
  252. if (LoadOptions[BootVarNum]) {
  253. //
  254. // free the local load option
  255. //
  256. FreePool(LoadOptions[BootVarNum]);
  257. //
  258. // zero the local memory for the load options
  259. //
  260. LoadOptions[BootVarNum] = (VOID*)0;
  261. LoadOptionsSize[BootVarNum] = 0;
  262. //
  263. // Get the boot option
  264. //
  265. SPrint( szTemp, sizeof(szTemp), L"Boot%04x", ((CHAR16*) BootOrder)[BootVarNum] );
  266. #if ERASEBOOTOPT_DEBUG
  267. Print (L"BootXXXX = %s\n", szTemp);
  268. #endif
  269. pDummy = LibGetVariableAndSize( szTemp, &VenEfi, &dummySize );
  270. //
  271. // whack the nvram entry
  272. //
  273. SetVariable(
  274. szTemp,
  275. &VenEfi,
  276. EFI_ATTR,
  277. 0,
  278. NULL
  279. );
  280. #if ERASEBOOTOPT_DEBUG
  281. Print (L"Adjusting boot order [begin]\n");
  282. #endif
  283. //
  284. // adjust the counters for os boot options
  285. //
  286. OsBootOptionCount--;
  287. BootOrderCount--;
  288. //
  289. // Shift the remaining entries in the boot order and the load options
  290. //
  291. tmpBootOrder = (CHAR16*)BootOrder;
  292. for (j = BootVarNum; j < BootOrderCount; j++) {
  293. tmpBootOrder[j] = tmpBootOrder[j + 1];
  294. LoadOptions[j] = LoadOptions[j + 1];
  295. LoadOptionsSize[j] = LoadOptionsSize[j + 1];
  296. }
  297. //
  298. // Set the modified boot order
  299. //
  300. SetVariable(
  301. L"BootOrder",
  302. &VenEfi,
  303. EFI_ATTR,
  304. BootOrderCount * sizeof(CHAR16),
  305. BootOrder
  306. );
  307. #if ERASEBOOTOPT_DEBUG
  308. Print (L"Adjusting boot order [end]\n");
  309. #endif
  310. return TRUE;
  311. }
  312. return FALSE;
  313. }
  314. BOOLEAN
  315. EraseAllOsBootOptions(
  316. )
  317. {
  318. UINT32 i;
  319. UINT64 BootOrderSize = 0;
  320. BOOLEAN status;
  321. UINT64 maxBootCount;
  322. #if ERASEBOOTOPT_DEBUG
  323. CHAR16 szInput[1024];
  324. #endif
  325. //
  326. // Initialize EFI LoadOptions.
  327. //
  328. BootOrderSize = 0;
  329. BootOrderCount = 0;
  330. BootOrder = NULL;
  331. //
  332. // Get BootOrder.
  333. //
  334. BootOrder = LibGetVariableAndSize( L"BootOrder", &VenEfi, &BootOrderSize );
  335. BootOrderCount = BootOrderSize / sizeof(CHAR16);
  336. ASSERT(BootOrderCount == OsBootOptionCount);
  337. //
  338. // Make sure there is atleast one OS boot option
  339. //
  340. if ( BootOrder && OsBootOptionCount) {
  341. maxBootCount = BootOrderCount;
  342. //
  343. // erase invidual boot options.
  344. //
  345. for ( i = 0; i < maxBootCount; i++ ) {
  346. #if ERASEBOOTOPT_DEBUG
  347. Print (L"BootOrderCount = %x, Erasing boot option: %x\n", BootOrderCount, i);
  348. #endif
  349. //
  350. // remove the boot entry at the head of the list
  351. //
  352. status = EraseOsBootOption(0);
  353. #if ERASEBOOTOPT_DEBUG
  354. Input (L"Here!\n", szInput, sizeof(szInput));
  355. Print(L"\n");
  356. #endif
  357. if (status == FALSE) {
  358. Print (L"Error: failed to erase boot entry %x\n", i);
  359. break;
  360. }
  361. }
  362. }
  363. return status;
  364. }
  365. BOOLEAN
  366. PushToTop(
  367. IN UINT32 BootVarNum
  368. )
  369. {
  370. UINT32 i;
  371. CHAR16 szTemp[10];
  372. char* osbootoption;
  373. UINT64 osbootoptionsize;
  374. CHAR16 savBootOption;
  375. CHAR16* tmpBootOrder;
  376. UINT64 BootOrderSize = 0;
  377. i=0;
  378. BootOrderSize = 0;
  379. BootOrder = NULL;
  380. //
  381. // Get BootOrder.
  382. //
  383. BootOrder = LibGetVariableAndSize( L"BootOrder", &VenEfi, &BootOrderSize );
  384. //
  385. // Make sure there is atleast one OS boot option
  386. //
  387. if ( BootOrder && OsBootOptionCount) {
  388. BootOrderCount = BootOrderSize / sizeof(CHAR16);
  389. //
  390. // Get the boot option.
  391. //
  392. tmpBootOrder = (CHAR16*)BootOrder;
  393. savBootOption = tmpBootOrder[BootVarNum];
  394. SPrint( szTemp, sizeof(szTemp), L"Boot%04x", savBootOption );
  395. osbootoption = LibGetVariableAndSize( szTemp, &VenEfi, &osbootoptionsize );
  396. //
  397. // Now adjust the boot order
  398. //
  399. i=BootVarNum;
  400. while (i > 0) {
  401. tmpBootOrder[i] = tmpBootOrder[i-1];
  402. i--;
  403. }
  404. tmpBootOrder[0] = savBootOption;
  405. //
  406. // Set the changed boot order
  407. //
  408. SetVariable(
  409. L"BootOrder",
  410. &VenEfi,
  411. EFI_ATTR,
  412. BootOrderCount * sizeof(CHAR16),
  413. BootOrder
  414. );
  415. return TRUE;
  416. }
  417. return FALSE;
  418. }
  419. VOID
  420. FreeBootManagerVars(
  421. )
  422. {
  423. UINTN i;
  424. for ( i=0; i<BootOrderCount; i++ ) {
  425. if ( LoadOptions[i] )
  426. FreePool( LoadOptions[i] );
  427. }
  428. if ( BootOrder )
  429. FreePool( BootOrder );
  430. //
  431. // zero the local memory for the load options
  432. //
  433. ZeroMem( LoadOptions, sizeof(VOID*) * MAXBOOTVARS );
  434. ZeroMem( LoadOptionsSize, sizeof(UINT64) * MAXBOOTVARS );
  435. }
  436. BOOLEAN
  437. CopyVar(
  438. IN UINT32 VarNum
  439. )
  440. {
  441. CHAR16 i;
  442. if ( VarNum < BootOrderCount ) {
  443. LoadOptions[BootOrderCount] = AllocateZeroPool( LoadOptionsSize[VarNum] );
  444. if ( LoadOptions[BootOrderCount] && LoadOptions[VarNum] ) {
  445. CopyMem( LoadOptions[BootOrderCount], LoadOptions[VarNum], LoadOptionsSize[VarNum] );
  446. LoadOptionsSize[BootOrderCount] = LoadOptionsSize[VarNum];
  447. BootOrder = ReallocatePool(
  448. (VOID*) BootOrder,
  449. BootOrderCount * sizeof(CHAR16),
  450. ( BootOrderCount + 1 ) * sizeof(CHAR16)
  451. );
  452. ((CHAR16*) BootOrder)[BootOrderCount] = FindFreeBootOption();
  453. BootOrderCount++;
  454. OsBootOptionCount++;
  455. return TRUE;
  456. } else
  457. return FALSE;
  458. }
  459. return FALSE;
  460. }
  461. CHAR16
  462. FindFreeBootOption(
  463. )
  464. {
  465. CHAR16 i;
  466. CHAR16 BootOptionBitmap[MAXBOOTVARS];
  467. SetMem( BootOptionBitmap, sizeof(BootOptionBitmap), 0 );
  468. for ( i=0; i<BootOrderCount; i++ ) {
  469. BootOptionBitmap[ ((CHAR16*)BootOrder)[i] ] = 1;
  470. }
  471. for ( i=0; i < MAXBOOTVARS; i++ ) {
  472. if ( BootOptionBitmap[i] == 0 )
  473. return i;
  474. }
  475. return 0xFFFF;
  476. }
  477. BOOLEAN
  478. SetBootManagerVar(
  479. UINTN BootVarNum
  480. )
  481. {
  482. CHAR16 szTemp[50];
  483. BOOLEAN status;
  484. status = TRUE;
  485. SPrint( szTemp, sizeof(szTemp), L"Boot%04x", ((CHAR16*) BootOrder)[BootVarNum] );
  486. if (LoadOptions[BootVarNum]) {
  487. SetVariable(
  488. szTemp,
  489. &VenEfi,
  490. EFI_ATTR,
  491. LoadOptionsSize[BootVarNum],
  492. LoadOptions[BootVarNum]
  493. );
  494. SetVariable(
  495. L"BootOrder",
  496. &VenEfi,
  497. EFI_ATTR,
  498. BootOrderCount * sizeof(CHAR16),
  499. BootOrder
  500. );
  501. }
  502. else
  503. {
  504. status = FALSE;
  505. }
  506. return status;
  507. }
  508. VOID
  509. SetBootManagerVars(
  510. )
  511. {
  512. UINTN BootVarNum;
  513. BOOLEAN status;
  514. for ( BootVarNum = 0; BootVarNum < BootOrderCount; BootVarNum++ ) {
  515. status = SetBootManagerVar(BootVarNum);
  516. if (status == FALSE) {
  517. Print (L"ERROR: Attempt to write non-existent boot option to NVRAM!\n");
  518. }
  519. }
  520. }
  521. UINT64
  522. GetBootOrderCount(
  523. )
  524. {
  525. return BootOrderCount;
  526. }
  527. UINT64
  528. GetOsBootOptionsCount(
  529. )
  530. {
  531. return OsBootOptionCount;
  532. }
  533. VOID
  534. SetEnvVar(
  535. IN CHAR16* szVarName,
  536. IN CHAR16* szVarValue,
  537. IN UINT32 deleteOnly
  538. )
  539. /*
  540. deleteOnly
  541. TRUE - Env var szVarName is deleted from nvr.
  542. FALSE - Env var szVarName overwrites or creates
  543. */
  544. {
  545. EFI_STATUS status;
  546. //
  547. // Erase the previous value
  548. //
  549. SetVariable(
  550. szVarName,
  551. &VenEfi,
  552. 0,
  553. 0,
  554. NULL
  555. );
  556. if ( !deleteOnly ) {
  557. //
  558. // Store the new value
  559. //
  560. status = SetVariable(
  561. szVarName,
  562. &VenEfi,
  563. EFI_ATTR,
  564. StrSize( szVarValue ),
  565. szVarValue
  566. );
  567. }
  568. }
  569. VOID
  570. SubString(
  571. IN OUT char* Dest,
  572. IN UINT32 Start,
  573. IN UINT32 End,
  574. IN char* Src
  575. )
  576. {
  577. UINTN i;
  578. UINTN j=0;
  579. for ( i=Start; i<End; i++ ) {
  580. Dest[ j++ ] = Src[ i ];
  581. }
  582. Dest[ j ] = '\0';
  583. }
  584. VOID
  585. InsertString(
  586. IN OUT char* Dest,
  587. IN UINT32 Start,
  588. IN UINT32 End,
  589. IN char* InsertString
  590. )
  591. {
  592. UINT32 i;
  593. UINT32 j=0;
  594. char first[1024];
  595. char last[1024];
  596. SubString( first, 0, Start, Dest );
  597. SubString( last, End, (UINT32) StrLenA(Dest), Dest );
  598. StrCatA( first, InsertString );
  599. StrCatA( first, last );
  600. StrCpyA( Dest, first );
  601. }
  602. VOID
  603. UtoA(
  604. OUT char* c,
  605. IN CHAR16* u
  606. )
  607. {
  608. UINT32 i = 0;
  609. while ( u[i] ) {
  610. c[i] = u[i] & 0xFF;
  611. i++;
  612. }
  613. c[i] = '\0';
  614. }
  615. VOID
  616. AtoU(
  617. OUT CHAR16* u,
  618. IN char* c
  619. )
  620. {
  621. UINT32 i = 0;
  622. while ( c[i] ) {
  623. u[i] = (CHAR16)c[i];
  624. i++;
  625. }
  626. u[i] = (CHAR16)'\0';
  627. }
  628. VOID
  629. SetFieldFromLoadOption(
  630. IN UINT32 BootVarNum,
  631. IN UINT32 FieldType,
  632. IN VOID* Data
  633. )
  634. {
  635. CHAR16 LoadIdentifier[200];
  636. char OsLoadOptions[200];
  637. char EfiFilePath[1024];
  638. char OsLoadPath[1024];
  639. //
  640. // Make sure it is a valid OS load option
  641. //
  642. if (BootVarNum >= BootOrderCount)
  643. return ;
  644. if (LoadOptions[BootVarNum] == NULL)
  645. return;
  646. GetOsLoadOptionVars(
  647. BootVarNum,
  648. LoadIdentifier,
  649. OsLoadOptions,
  650. EfiFilePath,
  651. OsLoadPath
  652. );
  653. //
  654. // Set the field.
  655. //
  656. switch (FieldType) {
  657. case DESCRIPTION:
  658. StrCpy( LoadIdentifier, Data );
  659. break;
  660. case OSLOADOPTIONS:
  661. StrCpy( (CHAR16*)OsLoadOptions, (CHAR16*)Data );
  662. break;
  663. #if 0
  664. case EFIFILEPATHLIST:
  665. SetFilePathFromShort( (EFI_DEVICE_PATH*) EfiFilePath, (CHAR16*) Data );
  666. break;
  667. case OSFILEPATHLIST: {
  668. PFILE_PATH pFilePath;
  669. pFilePath = (FILE_PATH*)OsLoadPath;
  670. SetFilePathFromShort( (EFI_DEVICE_PATH*) pFilePath->FilePath, (CHAR16*) Data );
  671. break;
  672. }
  673. #endif
  674. default:
  675. break;
  676. }
  677. //
  678. // Pack the new parameters into the the current load option
  679. //
  680. PackLoadOption( BootVarNum,
  681. LoadIdentifier,
  682. (CHAR16*)OsLoadOptions,
  683. EfiFilePath,
  684. OsLoadPath
  685. );
  686. //
  687. // save the new load option into NVRAM
  688. //
  689. SetBootManagerVar(BootVarNum);
  690. }
  691. VOID
  692. GetFilePathShort(
  693. EFI_DEVICE_PATH *FilePath,
  694. CHAR16 *FilePathShort
  695. )
  696. {
  697. UINT32 i, j, End;
  698. EFI_DEVICE_PATH *n = FilePath;
  699. //
  700. // Advance to FilePath node.
  701. //
  702. while (( n->Type != END_DEVICE_PATH_TYPE ) &&
  703. ( n->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE ) ) {
  704. if (( n->Type == MEDIA_DEVICE_PATH ) &&
  705. ( n->SubType == MEDIA_FILEPATH_DP )) {
  706. j = 0;
  707. End = DevicePathNodeLength(n);
  708. for ( i=sizeof(EFI_DEVICE_PATH); i<End; i++ ) {
  709. ((char*) FilePathShort)[j++] = ( (char*) n)[i];
  710. }
  711. break;
  712. }
  713. n = NextDevicePathNode(n);
  714. }
  715. }
  716. VOID
  717. SetFilePathFromShort(
  718. EFI_DEVICE_PATH *FilePath,
  719. CHAR16* FilePathShort
  720. )
  721. {
  722. UINT32 i, j, End;
  723. EFI_DEVICE_PATH *n = FilePath;
  724. UINT64 DevicePathSize;
  725. //
  726. // Advance to FilePath node.
  727. //
  728. while (( n->Type != END_DEVICE_PATH_TYPE ) &&
  729. ( n->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE ) ) {
  730. if (( n->Type == MEDIA_DEVICE_PATH ) &&
  731. ( n->SubType == MEDIA_FILEPATH_DP )) {
  732. j = 0;
  733. End = DevicePathNodeLength(n);
  734. //
  735. // Set the new file path
  736. //
  737. DevicePathSize = GetDevPathSize(n);
  738. for ( i=sizeof(EFI_DEVICE_PATH); i<DevicePathSize; i++ ) {
  739. ((char*) n)[i] = 0;
  740. }
  741. j=sizeof(EFI_DEVICE_PATH);
  742. for ( i=0; i<StrSize(FilePathShort); i++ ) {
  743. ((char*)n)[j++] = ((char*)FilePathShort)[i];
  744. }
  745. SetDevicePathNodeLength( n, StrSize(FilePathShort) + sizeof(EFI_DEVICE_PATH) );
  746. n = NextDevicePathNode(n);
  747. SetDevicePathEndNode(n);
  748. break;
  749. }
  750. n = NextDevicePathNode(n);
  751. }
  752. }
  753. char*
  754. GetAlignedELOFilePath(
  755. char* elo
  756. )
  757. {
  758. UINTN abufSize;
  759. char* abuf;
  760. PEFI_LOAD_OPTION pElo;
  761. pElo = (EFI_LOAD_OPTION*)elo;
  762. abufSize = pElo->FilePathListLength;
  763. abuf = AllocatePool(abufSize);
  764. CopyMem(abuf,
  765. elo +
  766. FIELD_OFFSET(EFI_LOAD_OPTION, Description) +
  767. StrSize(pElo->Description),
  768. abufSize
  769. );
  770. return abuf;
  771. }
  772. char*
  773. GetAlignedOptionalData(
  774. char* elo,
  775. UINT64 eloSize,
  776. UINT64* dataSize
  777. )
  778. {
  779. UINTN abufSize;
  780. char* abuf;
  781. PEFI_LOAD_OPTION pElo;
  782. UINTN offset;
  783. pElo = (EFI_LOAD_OPTION*)elo;
  784. offset = FIELD_OFFSET(EFI_LOAD_OPTION, Description) +
  785. StrSize(pElo->Description) +
  786. pElo->FilePathListLength;
  787. abufSize = eloSize - offset;
  788. abuf = AllocatePool(abufSize);
  789. CopyMem(abuf,
  790. elo + offset,
  791. abufSize
  792. );
  793. *dataSize = abufSize;
  794. return abuf;
  795. }
  796. char*
  797. GetAlignedOsOptions(
  798. char* elo,
  799. UINT64 eloSize
  800. )
  801. {
  802. UINT64 dummy;
  803. char* abuf;
  804. abuf = GetAlignedOptionalData(elo,
  805. eloSize,
  806. &dummy
  807. );
  808. return abuf;
  809. }
  810. char*
  811. GetAlignedOsLoadPath(
  812. IN char* osOptions,
  813. OUT UINTN* osLoadPathSize
  814. )
  815. //
  816. // we need to align the FilePath structure because the load options are
  817. // variable in length, so the FilePath structure may not be aligned
  818. //
  819. {
  820. UINTN abufSize;
  821. char* abuf;
  822. PWINDOWS_OS_OPTIONS pOsOptions;
  823. pOsOptions = (WINDOWS_OS_OPTIONS*)osOptions;
  824. abufSize = pOsOptions->Length -
  825. FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions) -
  826. StrSize(pOsOptions->OsLoadOptions);
  827. abuf = AllocatePool(abufSize);
  828. CopyMem(abuf,
  829. &osOptions[pOsOptions->OsLoadPathOffset],
  830. abufSize
  831. );
  832. *osLoadPathSize = abufSize;
  833. return abuf;
  834. }
  835. VOID
  836. DisplayLoadPath(
  837. char* osLoadPath
  838. )
  839. {
  840. PFILE_PATH pFilePath;
  841. pFilePath = (FILE_PATH*)osLoadPath;
  842. Print (L"osOptions->FILE_PATH->Version = %x\n", pFilePath->Version);
  843. Print (L"osOptions->FILE_PATH->Length = %x\n", pFilePath->Length);
  844. Print (L"osOptions->FILE_PATH->Type = %x\n", pFilePath->Type);
  845. if (pFilePath->Type == FILE_PATH_TYPE_EFI) {
  846. CHAR16 FilePathShort[200];
  847. GetFilePathShort(
  848. (EFI_DEVICE_PATH *)pFilePath->FilePath,
  849. FilePathShort
  850. );
  851. Print (L"osOptions->FILE_PATH->FilePath(EFI:DP:Short) = %s\n", FilePathShort);
  852. }
  853. }
  854. VOID
  855. DisplayOsOptions(
  856. char* osOptions
  857. )
  858. {
  859. PWINDOWS_OS_OPTIONS pOsOptions;
  860. CHAR16 wideSig[256];
  861. char* aOsLoadPath;
  862. UINTN aOsLoadPathSize;
  863. pOsOptions = (WINDOWS_OS_OPTIONS*)osOptions;
  864. Print (L">>>>\n");
  865. //
  866. // display the attributes
  867. //
  868. AtoU(wideSig, pOsOptions->Signature);
  869. Print (L"osOptions->Signature = %s\n", wideSig);
  870. Print (L"osOptions->Version = %x\n", pOsOptions->Version);
  871. Print (L"osOptions->Length = %x\n", pOsOptions->Length);
  872. Print (L"osOptions->OsLoadPathOffset = %x\n", pOsOptions->OsLoadPathOffset);
  873. // display the os load options
  874. Print (L"osOptions->OsLoadOptions = %s\n", pOsOptions->OsLoadOptions);
  875. //
  876. // display the FILE PATH
  877. //
  878. //
  879. // we need to align the FilePath structure because the load options are
  880. // variable in length, so the FilePath structure may not be aligned
  881. //
  882. aOsLoadPath = GetAlignedOsLoadPath(osOptions, &aOsLoadPathSize);
  883. DisplayLoadPath(aOsLoadPath);
  884. FreePool(aOsLoadPath);
  885. Print (L"<<<<\n");
  886. }
  887. VOID
  888. DisplayELO(
  889. char* elo,
  890. UINT64 eloSize
  891. )
  892. {
  893. PEFI_LOAD_OPTION pElo;
  894. #if 0
  895. UINT64 eloSize;
  896. #endif
  897. CHAR16 FilePathShort[200];
  898. char* aOsOptions;
  899. pElo = (EFI_LOAD_OPTION*)elo;
  900. Print (L"elo->Attributes = %x\n", pElo->Attributes);
  901. Print (L"elo->FilePathListLength = %x\n", pElo->FilePathListLength);
  902. Print (L"elo->Description = %s\n", pElo->Description);
  903. GetFilePathShort(
  904. (EFI_DEVICE_PATH *)&elo[FIELD_OFFSET(EFI_LOAD_OPTION, Description) + StrSize(pElo->Description)],
  905. FilePathShort
  906. );
  907. Print (L"elo->FilePath(EFI:DP:SHORT) = %s\n", FilePathShort);
  908. #if 0
  909. eloSize = FIELD_OFFSET(EFI_LOAD_OPTION, Description) + StrSize(pElo->Description) + pElo->FilePathListLength;
  910. DisplayOsOptions(&elo[eloSize]);
  911. #else
  912. aOsOptions = GetAlignedOsOptions(
  913. elo,
  914. eloSize
  915. );
  916. DisplayOsOptions(aOsOptions);
  917. FreePool(aOsOptions);
  918. #endif
  919. }
  920. VOID
  921. BuildNewOsOptions(
  922. IN CHAR16* osLoadOptions,
  923. IN char* osLoadPath,
  924. OUT char** osOptions
  925. )
  926. //
  927. //
  928. // Note: osLoadPath must be aligned
  929. //
  930. {
  931. char* newOsOptions;
  932. PWINDOWS_OS_OPTIONS pNewOsOptions;
  933. UINT32 osLoadOptionsLength;
  934. UINT32 osOptionsLength;
  935. PFILE_PATH pOsLoadPath;
  936. //
  937. // NOTE: aligning the FILE_PATH structure (osLoadPath) works
  938. // by aligning the osLoadOptionsLength because the
  939. // WINDOWS_OS_OPTIONS structure has a UINT32 variable
  940. // before the OsLoadOptions. If anything changes above
  941. // the OsLoadOptions in the WINDOWS_OS_OPTIONS structure
  942. // the alignment method may have to change in this structure.
  943. //
  944. //
  945. //
  946. // determine the size of the os load options (UNICODE) string
  947. //
  948. osLoadOptionsLength = (UINT32)StrSize(osLoadOptions);
  949. osLoadOptionsLength = ALIGN_UP(osLoadOptionsLength, UINT32);
  950. #if DEBUG_PACK
  951. Print (L"osLoadOptionsLength = %x\n", osLoadOptionsLength);
  952. #endif
  953. pOsLoadPath = (FILE_PATH*)osLoadPath;
  954. #if DEBUG_PACK
  955. Print (L"pOsLoadPath->Length = %x\n", pOsLoadPath->Length);
  956. #endif
  957. //
  958. // determine the size of the new WINDOWS_OS_OPTIONS structure
  959. //
  960. osOptionsLength = FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions) + osLoadOptionsLength + pOsLoadPath->Length;
  961. #if DEBUG_PACK
  962. Print (L"osOptionsLength = %x\n", osOptionsLength);
  963. #endif
  964. //
  965. // Allocate memory for the WINDOWS_OS_OPTIONS
  966. //
  967. newOsOptions = AllocatePool(osOptionsLength);
  968. ASSERT(newOsOptions != NULL);
  969. pNewOsOptions = (WINDOWS_OS_OPTIONS*)newOsOptions;
  970. //
  971. // populate the new os options
  972. //
  973. StrCpyA((char *)pNewOsOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE);
  974. pNewOsOptions->Version = WINDOWS_OS_OPTIONS_VERSION;
  975. pNewOsOptions->Length = (UINT32)osOptionsLength;
  976. pNewOsOptions->OsLoadPathOffset = FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions) + osLoadOptionsLength;
  977. StrCpy(pNewOsOptions->OsLoadOptions, osLoadOptions);
  978. CopyMem( &newOsOptions[pNewOsOptions->OsLoadPathOffset], osLoadPath, pOsLoadPath->Length );
  979. *osOptions = newOsOptions;
  980. }
  981. VOID
  982. PackLoadOption(
  983. IN UINT32 BootVarNum,
  984. IN CHAR16* LoadIdentifier,
  985. IN CHAR16* OsLoadOptions,
  986. IN char* EfiFilePath,
  987. IN char* OsLoadPath
  988. )
  989. /*
  990. PackLoadOption
  991. Purpose: To construct an EFI_LOAD_OPTION structure using user arguments
  992. and load the structure into into BootXXXX, where XXXX = BootVarNum.
  993. See EFI spec, ch. 17
  994. Args:
  995. BootVarNum The boot option being written/modified
  996. */
  997. {
  998. PEFI_LOAD_OPTION pOldElo;
  999. PEFI_LOAD_OPTION pElo;
  1000. char* elo;
  1001. char* oldElo;
  1002. UINT64 oldEloSize;
  1003. UINT64 eloSize;
  1004. UINT8* oldEloFilePath;
  1005. UINT64 TempEfiFilePathListSize;
  1006. char* aFilePath;
  1007. #if DEBUG_PACK
  1008. CHAR16 szInput[1024];
  1009. Print (L"BootVarNum = %x\n", BootVarNum);
  1010. Print (L"LoadIdentifier = %s\n", LoadIdentifier);
  1011. Print (L"OsLoadOptions = %s\n", OsLoadOptions);
  1012. Input (L"Here! [Pack begin] \n", szInput, sizeof(szInput));
  1013. Print(L"\n");
  1014. #endif
  1015. oldElo = LoadOptions[BootVarNum];
  1016. oldEloSize = LoadOptionsSize[BootVarNum];
  1017. #if DEBUG_PACK
  1018. DisplayELO(oldElo, oldEloSize);
  1019. Input (L"Here! [Pack begin] \n", szInput, sizeof(szInput));
  1020. Print(L"\n");
  1021. #endif
  1022. //
  1023. // allocate the elo structure with maximal amount of memory allowed for
  1024. // an EFI_LOAD_OPTION
  1025. //
  1026. elo = AllocatePool(MAXBOOTVARSIZE);
  1027. if (elo == NULL) {
  1028. Print (L"PackAndWriteToNvr: AllocatePool\n");
  1029. return;
  1030. }
  1031. pElo = (EFI_LOAD_OPTION*)elo;
  1032. pOldElo = (EFI_LOAD_OPTION*)oldElo;
  1033. //
  1034. // Efi Attribute.
  1035. //
  1036. pElo->Attributes = pOldElo->Attributes;
  1037. eloSize = sizeof(UINT32);
  1038. //
  1039. // FilePathListLength
  1040. //
  1041. pElo->FilePathListLength = pOldElo->FilePathListLength;
  1042. eloSize += sizeof(UINT16);
  1043. //
  1044. // Description.
  1045. //
  1046. StrCpy( pElo->Description, LoadIdentifier );
  1047. eloSize += StrSize(LoadIdentifier);
  1048. //
  1049. // copy the FilePath from the old/existing ELO structure
  1050. //
  1051. // Note: we don't actually need an aligned filepath block for this
  1052. // copy, but there may come a time when we want to modify
  1053. // the filepath, which will require an aligned block.
  1054. //
  1055. aFilePath = GetAlignedELOFilePath(oldElo);
  1056. CopyMem( &elo[eloSize],
  1057. aFilePath,
  1058. pOldElo->FilePathListLength
  1059. );
  1060. eloSize += pOldElo->FilePathListLength;
  1061. FreePool(aFilePath);
  1062. #if DEBUG_PACK
  1063. Print (L"eloSize = %x\n", eloSize);
  1064. Input (L"Here! \n", szInput, sizeof(szInput));
  1065. Print(L"\n");
  1066. #endif
  1067. //
  1068. // add or modify the boot option
  1069. //
  1070. if ( BootVarNum == -1 ) {
  1071. Print(L"Adding currently disabled\n");
  1072. } else {
  1073. char* osOptions;
  1074. char* aOsLoadPath;
  1075. char* aOldOsOptions;
  1076. PWINDOWS_OS_OPTIONS pOldOsOptions;
  1077. PWINDOWS_OS_OPTIONS pOsOptions;
  1078. UINTN aOsLoadPathSize;
  1079. //
  1080. // OptionalData.
  1081. //
  1082. // For a Windows OS boot option, the OptionalData field in the EFI_LOAD_OPTION
  1083. // structure is a WINDOWS_OS_OPTION structure.
  1084. //
  1085. // get the WINDOWS_OS_OPTIONS from the old/existing boot entry
  1086. //
  1087. aOldOsOptions = GetAlignedOsOptions(oldElo, oldEloSize);
  1088. pOldOsOptions = (WINDOWS_OS_OPTIONS*)aOldOsOptions;
  1089. //
  1090. // Get the LoadPath from the old/existing WINDOWS_OS_OPTIONS structure
  1091. //
  1092. // we need to align the FilePath structure because the load options are
  1093. // variable in length, so the FilePath structure may not be aligned
  1094. //
  1095. aOsLoadPath = GetAlignedOsLoadPath(aOldOsOptions, &aOsLoadPathSize);
  1096. FreePool(aOldOsOptions);
  1097. //
  1098. // Construct a new WINDOWS_OS_STRUCTURE with the new values
  1099. //
  1100. BuildNewOsOptions(
  1101. OsLoadOptions,
  1102. aOsLoadPath,
  1103. &osOptions
  1104. );
  1105. FreePool(aOsLoadPath);
  1106. #if DEBUG_PACK
  1107. Input (L"build\n", szInput, sizeof(szInput) );
  1108. Print(L"\n");
  1109. DisplayOsOptions(osOptions);
  1110. Input (L"elo freed\n", szInput, sizeof(szInput) );
  1111. Print(L"\n");
  1112. #endif
  1113. pOsOptions = (WINDOWS_OS_OPTIONS*)osOptions;
  1114. //
  1115. // Copy the new WINDOWS_OS_OPTIONS structure into the new EFI_LOAD_OPTION structure
  1116. //
  1117. CopyMem( &elo[eloSize], osOptions, pOsOptions->Length);
  1118. eloSize += pOsOptions->Length;
  1119. #if DEBUG_PACK
  1120. Print (L"osOptions->Length = %x\n", pOsOptions->Length);
  1121. Print (L"eloSize = %x\n", eloSize);
  1122. #endif
  1123. FreePool(osOptions);
  1124. //
  1125. // Modify current boot options.
  1126. //
  1127. LoadOptions[BootVarNum] = ReallocatePool( LoadOptions[BootVarNum], LoadOptionsSize[BootVarNum], eloSize );
  1128. LoadOptionsSize[BootVarNum] = eloSize;
  1129. CopyMem( LoadOptions[BootVarNum], elo, eloSize );
  1130. }
  1131. FreePool(elo);
  1132. ASSERT(eloSize < MAXBOOTVARSIZE);
  1133. #if DEBUG_PACK
  1134. Input (L"elo freed\n", szInput, sizeof(szInput) );
  1135. Print(L"\n");
  1136. Print (L">>\n");
  1137. DisplayELO((char*)LoadOptions[BootVarNum], LoadOptionsSize[BootVarNum]);
  1138. Print (L"<<\n");
  1139. Input (L"pack done\n", szInput, sizeof(szInput) );
  1140. Print(L"\n");
  1141. #endif
  1142. }
  1143. EFI_STATUS
  1144. AppendEntryToBootOrder(
  1145. UINT16 BootNumber
  1146. )
  1147. {
  1148. EFI_STATUS status;
  1149. UINT64 oldBootOrderSize;
  1150. UINT64 newBootOrderSize;
  1151. VOID* newBootOrder;
  1152. VOID* oldBootOrder;
  1153. newBootOrder = NULL;
  1154. oldBootOrder = NULL;
  1155. //
  1156. // get the existing boot order array
  1157. //
  1158. oldBootOrder = LibGetVariableAndSize( L"BootOrder", &VenEfi, &oldBootOrderSize );
  1159. if ((!oldBootOrder) &&
  1160. (oldBootOrderSize != 0)
  1161. ) {
  1162. Print(L"\nError: Failed to get old boot order array.\n");
  1163. status = EFI_OUT_OF_RESOURCES;
  1164. goto Done;
  1165. }
  1166. //
  1167. // allocate the new boot order array
  1168. //
  1169. newBootOrderSize = oldBootOrderSize + sizeof(BootNumber);
  1170. newBootOrder = AllocatePool( newBootOrderSize );
  1171. if (! newBootOrder) {
  1172. Print(L"\nError: Failed to allocate new boot order array.\n");
  1173. status = EFI_OUT_OF_RESOURCES;
  1174. goto Done;
  1175. }
  1176. //
  1177. // append the new boot entry to the bottom of the list
  1178. //
  1179. CopyMem(
  1180. (CHAR8*)newBootOrder,
  1181. oldBootOrder,
  1182. oldBootOrderSize
  1183. );
  1184. CopyMem(
  1185. (CHAR8*)newBootOrder + oldBootOrderSize,
  1186. &BootNumber,
  1187. sizeof(BootNumber) );
  1188. status = SetVariable(
  1189. L"BootOrder",
  1190. &VenEfi,
  1191. EFI_ATTR,
  1192. newBootOrderSize,
  1193. newBootOrder
  1194. );
  1195. Done:
  1196. if (oldBootOrder) {
  1197. FreePool( oldBootOrder );
  1198. }
  1199. if (newBootOrder) {
  1200. FreePool(newBootOrder);
  1201. }
  1202. return status;
  1203. }
  1204. EFI_STATUS
  1205. WritePackedDataToNvr(
  1206. UINT16 BootNumber,
  1207. VOID *BootOption,
  1208. UINT32 BootSize
  1209. )
  1210. {
  1211. EFI_STATUS status;
  1212. CHAR16 VariableName[10];
  1213. SPrint( VariableName, sizeof(VariableName), L"Boot%04x", BootNumber );
  1214. status = SetVariable(
  1215. VariableName,
  1216. &VenEfi,
  1217. EFI_ATTR,
  1218. BootSize,
  1219. BootOption
  1220. );
  1221. if (status == EFI_SUCCESS) {
  1222. status = AppendEntryToBootOrder(BootNumber);
  1223. if (status != EFI_SUCCESS) {
  1224. Print(L"\nError: Failed to append new boot entry to boot order array\n");
  1225. goto Done;
  1226. }
  1227. } else {
  1228. Print(L"\nError: Failed to set new boot entry variable\n");
  1229. goto Done;
  1230. }
  1231. //
  1232. // repopulate the local info about boot entries
  1233. //
  1234. FreeBootManagerVars();
  1235. GetBootManagerVars();
  1236. Done:
  1237. return status;
  1238. }
  1239. #if DEBUG_PACK
  1240. VOID
  1241. DisplayELOFromLoadOption(
  1242. IN UINT32 OptionNum
  1243. )
  1244. {
  1245. char* elo;
  1246. PEFI_LOAD_OPTION pElo;
  1247. //
  1248. // Make sure it is a valid OS load option
  1249. //
  1250. if (OptionNum > BootOrderCount) {
  1251. return;
  1252. }
  1253. if (LoadOptions[OptionNum] == NULL) {
  1254. return;
  1255. }
  1256. pElo = (EFI_LOAD_OPTION*)LoadOptions[OptionNum];
  1257. elo = (char*)LoadOptions[OptionNum];
  1258. DisplayELO(elo, LoadOptionsSize[OptionNum]);
  1259. }
  1260. #endif
  1261. VOID
  1262. GetFieldFromLoadOption(
  1263. IN UINT32 OptionNum,
  1264. IN UINT32 FieldType,
  1265. OUT VOID* Data,
  1266. OUT UINT64* DataSize
  1267. )
  1268. {
  1269. char* elo;
  1270. PEFI_LOAD_OPTION pElo;
  1271. //
  1272. // Make sure it is a valid OS load option
  1273. //
  1274. if (OptionNum > BootOrderCount) {
  1275. return;
  1276. }
  1277. if (LoadOptions[OptionNum] == NULL) {
  1278. *DataSize = 0;
  1279. return;
  1280. }
  1281. pElo = (EFI_LOAD_OPTION*)LoadOptions[OptionNum];
  1282. elo = (char*)LoadOptions[OptionNum];
  1283. switch ( FieldType ) {
  1284. case ATTRIBUTE: {
  1285. *((UINT32*) Data) = pElo->Attributes;
  1286. *DataSize = sizeof(UINT32);
  1287. break;
  1288. }
  1289. case FILEPATHLISTLENGTH: {
  1290. *((UINT16*) Data) = pElo->FilePathListLength;
  1291. *DataSize = sizeof(UINT16);
  1292. break;
  1293. }
  1294. case DESCRIPTION: {
  1295. StrCpy((CHAR16*)Data, pElo->Description);
  1296. *DataSize = StrSize(pElo->Description);
  1297. break;
  1298. }
  1299. case EFIFILEPATHLIST: {
  1300. char* aFilePath;
  1301. aFilePath = GetAlignedELOFilePath(elo);
  1302. CopyMem(Data,
  1303. aFilePath,
  1304. pElo->FilePathListLength
  1305. );
  1306. FreePool(aFilePath);
  1307. *DataSize = pElo->FilePathListLength;
  1308. break;
  1309. }
  1310. case OPTIONALDATA: {
  1311. char* aOptionalData;
  1312. UINT64 eloSize;
  1313. eloSize = LoadOptionsSize[OptionNum];
  1314. aOptionalData = GetAlignedOptionalData(elo,
  1315. eloSize,
  1316. DataSize
  1317. );
  1318. CopyMem(Data, aOptionalData, *DataSize);
  1319. FreePool(aOptionalData);
  1320. break;
  1321. }
  1322. default:
  1323. *DataSize = 0;
  1324. break;
  1325. }
  1326. }
  1327. BOOLEAN
  1328. GetLoadIdentifier(
  1329. IN UINT32 BootVarNum,
  1330. OUT CHAR16* LoadIdentifier
  1331. )
  1332. {
  1333. UINT64 DataSize = 0;
  1334. GetFieldFromLoadOption(
  1335. BootVarNum,
  1336. DESCRIPTION,
  1337. LoadIdentifier,
  1338. &DataSize
  1339. );
  1340. if (!DataSize)
  1341. return FALSE;
  1342. return TRUE;
  1343. }
  1344. VOID
  1345. GetEfiOsLoaderFilePath(
  1346. IN UINT32 BootVarNum,
  1347. OUT char* FilePath
  1348. )
  1349. {
  1350. UINT64 DataSize = 0;
  1351. GetFieldFromLoadOption(
  1352. BootVarNum,
  1353. EFIFILEPATHLIST,
  1354. FilePath,
  1355. &DataSize
  1356. );
  1357. }
  1358. BOOLEAN
  1359. GetOsLoadOptionVars(
  1360. IN UINT32 BootVarNum,
  1361. OUT CHAR16* LoadIdentifier,
  1362. OUT char* OsLoadOptions,
  1363. OUT char* EfiFilePath,
  1364. OUT char* OsLoadPath
  1365. )
  1366. {
  1367. if (BootVarNum >= BootOrderCount)
  1368. return FALSE;
  1369. if (!LoadOptions[BootVarNum])
  1370. return FALSE;
  1371. GetLoadIdentifier( BootVarNum, LoadIdentifier );
  1372. GetOptionalDataValue( BootVarNum, OSLOADOPTIONS, OsLoadOptions );
  1373. GetEfiOsLoaderFilePath( BootVarNum, EfiFilePath );
  1374. GetOptionalDataValue( BootVarNum, OSLOADPATH, OsLoadPath);
  1375. return TRUE;
  1376. }
  1377. VOID
  1378. GetOptionalDataValue(
  1379. IN UINT32 BootVarNum,
  1380. IN UINT32 Selection,
  1381. OUT char* OptionalDataValue
  1382. )
  1383. {
  1384. char osOptions[MAXBOOTVARSIZE];
  1385. UINT64 osOptionsSize;
  1386. PWINDOWS_OS_OPTIONS pOsOptions;
  1387. if (BootVarNum < MAXBOOTVARS) {
  1388. GetFieldFromLoadOption(
  1389. BootVarNum,
  1390. OPTIONALDATA,
  1391. osOptions,
  1392. &osOptionsSize
  1393. );
  1394. pOsOptions = (PWINDOWS_OS_OPTIONS)osOptions;
  1395. switch (Selection) {
  1396. case OSLOADOPTIONS: {
  1397. StrCpy( (CHAR16*)OptionalDataValue, pOsOptions->OsLoadOptions );
  1398. break;
  1399. }
  1400. case OSLOADPATH: {
  1401. char* aOsLoadPath;
  1402. UINTN aOsLoadPathSize;
  1403. aOsLoadPath = GetAlignedOsLoadPath(osOptions, &aOsLoadPathSize);
  1404. CopyMem(OptionalDataValue,
  1405. aOsLoadPath,
  1406. aOsLoadPathSize
  1407. );
  1408. FreePool(aOsLoadPath);
  1409. break;
  1410. }
  1411. default: {
  1412. break;
  1413. }
  1414. }
  1415. }
  1416. }
  1417. UINTN
  1418. GetDevPathSize(
  1419. IN EFI_DEVICE_PATH *DevPath
  1420. )
  1421. {
  1422. EFI_DEVICE_PATH *Start;
  1423. //
  1424. // Search for the end of the device path structure
  1425. //
  1426. Start = DevPath;
  1427. while (DevPath->Type != END_DEVICE_PATH_TYPE) {
  1428. DevPath = NextDevicePathNode(DevPath);
  1429. }
  1430. //
  1431. // Compute the size
  1432. //
  1433. return(UINTN) ((UINT64) DevPath - (UINT64) Start);
  1434. }
  1435. UINT32
  1436. GetPartitions(
  1437. )
  1438. {
  1439. EFI_HANDLE EspHandles[100],FSPath;
  1440. UINT64 HandleArraySize = 100 * sizeof(EFI_HANDLE);
  1441. UINT64 CachedDevicePaths[100];
  1442. UINTN i, j;
  1443. UINTN CachedDevicePathsCount;
  1444. UINT64 SystemPartitionPathSize;
  1445. EFI_DEVICE_PATH *dp;
  1446. EFI_STATUS Status;
  1447. UINT32 PartitionCount;
  1448. char AlignedNode[1024];
  1449. //
  1450. // Get all handles that supports the block I/O protocol.
  1451. //
  1452. ZeroMem( EspHandles, HandleArraySize );
  1453. Status = LocateHandle (
  1454. ByProtocol,
  1455. &EfiESPProtocol,
  1456. 0,
  1457. (UINTN *) &HandleArraySize,
  1458. EspHandles
  1459. );
  1460. //
  1461. // Cache all of the EFI Device Paths.
  1462. //
  1463. for (i = 0; EspHandles[i] != 0; i++) {
  1464. Status = HandleProtocol (
  1465. EspHandles[i],
  1466. &DevicePathProtocol,
  1467. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  1468. );
  1469. }
  1470. //
  1471. // Save the number of cached Device Paths.
  1472. //
  1473. CachedDevicePathsCount = i;
  1474. PartitionCount = 0;
  1475. //
  1476. // Find the first partition on the first hard drive
  1477. // partition. That is our SystemPartition.
  1478. //
  1479. for ( i=0; i<CachedDevicePathsCount; i++ ) {
  1480. dp = (EFI_DEVICE_PATH*) CachedDevicePaths[i];
  1481. while (( DevicePathType(dp) != END_DEVICE_PATH_TYPE ) &&
  1482. ( DevicePathSubType(dp) != END_ENTIRE_DEVICE_PATH_SUBTYPE )) {
  1483. if (( DevicePathType(dp) == MEDIA_DEVICE_PATH ) &&
  1484. ( DevicePathSubType(dp) == MEDIA_HARDDRIVE_DP )) {
  1485. CopyMem( AlignedNode, dp, DevicePathNodeLength(dp) );
  1486. HandleProtocol (EspHandles[i],&FileSystemProtocol,&FSPath);
  1487. if ( FSPath != NULL) {
  1488. PartitionCount++;
  1489. }
  1490. }
  1491. dp = NextDevicePathNode(dp);
  1492. }
  1493. }
  1494. return PartitionCount;
  1495. }
  1496. EFI_HANDLE
  1497. GetDeviceHandleForPartition(
  1498. )
  1499. {
  1500. EFI_HANDLE EspHandles[100],FSPath;
  1501. UINT64 HandleArraySize = 100 * sizeof(EFI_HANDLE);
  1502. UINT64 CachedDevicePaths[100];
  1503. UINTN i, j;
  1504. UINTN CachedDevicePathsCount;
  1505. UINT64 SystemPartitionPathSize;
  1506. EFI_DEVICE_PATH *dp;
  1507. EFI_STATUS Status;
  1508. char AlignedNode[1024];
  1509. //
  1510. // Get all handles that supports the block I/O protocol.
  1511. //
  1512. ZeroMem( EspHandles, HandleArraySize );
  1513. Status = LocateHandle (
  1514. ByProtocol,
  1515. &EfiESPProtocol,
  1516. 0,
  1517. (UINTN *) &HandleArraySize,
  1518. EspHandles
  1519. );
  1520. //
  1521. // Cache all of the EFI Device Paths.
  1522. //
  1523. for (i = 0; EspHandles[i] != 0; i++) {
  1524. Status = HandleProtocol (
  1525. EspHandles[i],
  1526. &DevicePathProtocol,
  1527. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  1528. );
  1529. }
  1530. //
  1531. // Save the number of cached Device Paths.
  1532. //
  1533. CachedDevicePathsCount = i;
  1534. //
  1535. // Find the first ESP partition on the first hard drive
  1536. // partition. That is our SystemPartition.
  1537. //
  1538. for ( i=0; i<CachedDevicePathsCount; i++ ) {
  1539. dp = (EFI_DEVICE_PATH*) CachedDevicePaths[i];
  1540. while (( DevicePathType(dp) != END_DEVICE_PATH_TYPE ) &&
  1541. ( DevicePathSubType(dp) != END_ENTIRE_DEVICE_PATH_SUBTYPE )) {
  1542. if (( DevicePathType(dp) == MEDIA_DEVICE_PATH ) &&
  1543. ( DevicePathSubType(dp) == MEDIA_HARDDRIVE_DP )) {
  1544. CopyMem( AlignedNode, dp, DevicePathNodeLength(dp) );
  1545. HandleProtocol (EspHandles[i],&FileSystemProtocol,&FSPath);
  1546. if ( FSPath != NULL) {
  1547. //
  1548. // Found the correct device path partition.
  1549. // Return the device handle.
  1550. //
  1551. return( EspHandles[i] );
  1552. }
  1553. }
  1554. dp = NextDevicePathNode(dp);
  1555. }
  1556. }
  1557. return NULL;
  1558. }
  1559. /*
  1560. ** BUGBUG: These functions need to be eventually placed in lib\str.c
  1561. */
  1562. INTN
  1563. RUNTIMEFUNCTION
  1564. StrCmpA (
  1565. IN CHAR8 *s1,
  1566. IN CHAR8 *s2
  1567. )
  1568. /* compare strings */
  1569. {
  1570. while (*s1) {
  1571. if (*s1 != *s2) {
  1572. break;
  1573. }
  1574. s1 += 1;
  1575. s2 += 1;
  1576. }
  1577. return *s1 - *s2;
  1578. }
  1579. VOID
  1580. RUNTIMEFUNCTION
  1581. StrCpyA (
  1582. IN CHAR8 *Dest,
  1583. IN CHAR8 *Src
  1584. )
  1585. /* copy strings */
  1586. {
  1587. while (*Src) {
  1588. *(Dest++) = *(Src++);
  1589. }
  1590. *Dest = 0;
  1591. }
  1592. VOID
  1593. RUNTIMEFUNCTION
  1594. StrCatA (
  1595. IN CHAR8 *Dest,
  1596. IN CHAR8 *Src
  1597. )
  1598. {
  1599. StrCpyA(Dest+StrLenA(Dest), Src);
  1600. }
  1601. UINTN
  1602. RUNTIMEFUNCTION
  1603. StrLenA (
  1604. IN CHAR8 *s1
  1605. )
  1606. /* string length */
  1607. {
  1608. UINTN len;
  1609. for (len=0; *s1; s1+=1, len+=1) ;
  1610. return len;
  1611. }
  1612. UINTN
  1613. RUNTIMEFUNCTION
  1614. StrSizeA (
  1615. IN CHAR8 *s1
  1616. )
  1617. /* string size */
  1618. {
  1619. UINTN len;
  1620. for (len=0; *s1; s1+=1, len+=1) ;
  1621. return(len + 1) * sizeof(CHAR8);
  1622. }