FirmwareUpdate.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /** @file
  2. Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "FirmwareUpdate.h"
  6. EFI_HII_HANDLE HiiHandle;
  7. //
  8. // MinnowMax Flash Layout
  9. //
  10. //Start (hex) End (hex) Length (hex) Area Name
  11. //----------- --------- ------------ ---------
  12. //00000000 007FFFFF 00800000 Flash Image
  13. //
  14. //00000000 00000FFF 00001000 Descriptor Region
  15. //00001000 003FFFFF 003FF000 TXE Region
  16. //00500000 007FFFFF 00400000 BIOS Region
  17. //
  18. FV_REGION_INFO mRegionInfo[] = {
  19. {FixedPcdGet32 (PcdFlashDescriptorBase), FixedPcdGet32 (PcdFlashDescriptorSize), TRUE},
  20. {FixedPcdGet32 (PcdTxeRomBase), FixedPcdGet32 (PcdTxeRomSize), TRUE},
  21. {FixedPcdGet32 (PcdBiosRomBase), FixedPcdGet32 (PcdBiosRomSize), TRUE}
  22. };
  23. UINTN mRegionInfoCount = ARRAY_SIZE (mRegionInfo);
  24. FV_INPUT_DATA mInputData = {0};
  25. EFI_SPI_PROTOCOL *mSpiProtocol;
  26. EFI_STATUS
  27. GetRegionIndex (
  28. IN EFI_PHYSICAL_ADDRESS Address,
  29. OUT UINTN *RegionIndex
  30. )
  31. {
  32. UINTN Index;
  33. for (Index = 0; Index < mRegionInfoCount; Index++) {
  34. if (Address >= mRegionInfo[Index].Base &&
  35. Address < (mRegionInfo[Index].Base + mRegionInfo[Index].Size)
  36. ) {
  37. break;
  38. }
  39. }
  40. *RegionIndex = Index;
  41. if (Index >= mRegionInfoCount) {
  42. return EFI_NOT_FOUND;
  43. }
  44. return EFI_SUCCESS;
  45. }
  46. BOOLEAN
  47. UpdateBlock (
  48. IN EFI_PHYSICAL_ADDRESS Address
  49. )
  50. {
  51. EFI_STATUS Status;
  52. UINTN Index;
  53. if (mInputData.FullFlashUpdate) {
  54. return TRUE;
  55. }
  56. Status = GetRegionIndex (Address, &Index);
  57. if ((!EFI_ERROR(Status)) && mRegionInfo[Index].Update) {
  58. return TRUE;
  59. }
  60. return FALSE;
  61. }
  62. EFI_STATUS
  63. MarkRegionState (
  64. IN EFI_PHYSICAL_ADDRESS Address,
  65. IN BOOLEAN Update
  66. )
  67. {
  68. EFI_STATUS Status;
  69. UINTN Index;
  70. Status = GetRegionIndex (Address, &Index);
  71. if (!EFI_ERROR(Status)) {
  72. mRegionInfo[Index].Update = Update;
  73. }
  74. return Status;
  75. }
  76. UINTN
  77. InternalPrintToken (
  78. IN CONST CHAR16 *Format,
  79. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console,
  80. IN VA_LIST Marker
  81. )
  82. {
  83. EFI_STATUS Status;
  84. UINTN Return;
  85. CHAR16 *Buffer;
  86. UINTN BufferSize;
  87. ASSERT (Format != NULL);
  88. ASSERT (((UINTN) Format & BIT0) == 0);
  89. ASSERT (Console != NULL);
  90. BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);
  91. Buffer = (CHAR16 *) AllocatePool(BufferSize);
  92. ASSERT (Buffer != NULL);
  93. Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker);
  94. if (Console != NULL && Return > 0) {
  95. //
  96. // To be extra safe make sure Console has been initialized.
  97. //
  98. Status = Console->OutputString (Console, Buffer);
  99. if (EFI_ERROR (Status)) {
  100. Return = 0;
  101. }
  102. }
  103. FreePool (Buffer);
  104. return Return;
  105. }
  106. UINTN
  107. EFIAPI
  108. PrintToken (
  109. IN UINT16 Token,
  110. IN EFI_HII_HANDLE Handle,
  111. ...
  112. )
  113. {
  114. VA_LIST Marker;
  115. UINTN Return;
  116. CHAR16 *Format;
  117. VA_START (Marker, Handle);
  118. Format = HiiGetString (Handle, Token, NULL);
  119. ASSERT (Format != NULL);
  120. Return = InternalPrintToken (Format, gST->ConOut, Marker);
  121. FreePool (Format);
  122. VA_END (Marker);
  123. return Return;
  124. }
  125. EFI_STATUS
  126. ParseCommandLine (
  127. IN UINTN Argc,
  128. IN CHAR16 **Argv
  129. )
  130. {
  131. EFI_STATUS Status;
  132. UINTN Index;
  133. //
  134. // Check to make sure that the command line has enough arguments for minimal
  135. // operation. The minimum is just the file name.
  136. //
  137. if (Argc < 2 || Argc > 4) {
  138. return EFI_INVALID_PARAMETER;
  139. }
  140. //
  141. // Loop through command line arguments.
  142. //
  143. for (Index = 1; Index < Argc; Index++) {
  144. //
  145. // Make sure the string is valid.
  146. //
  147. if (StrLen (Argv[Index]) == 0) {;
  148. PrintToken (STRING_TOKEN (STR_FWUPDATE_ZEROLENGTH_ARG), HiiHandle);
  149. return EFI_INVALID_PARAMETER;
  150. }
  151. //
  152. // Check to see if this is an option or the file name.
  153. //
  154. if ((Argv[Index])[0] == L'-' || (Argv[Index])[0] == L'/') {
  155. //
  156. // Parse the arguments.
  157. //
  158. if ((StrCmp (Argv[Index], L"-h") == 0) ||
  159. (StrCmp (Argv[Index], L"--help") == 0) ||
  160. (StrCmp (Argv[Index], L"/?") == 0) ||
  161. (StrCmp (Argv[Index], L"/h") == 0)) {
  162. //
  163. // Print Help Information.
  164. //
  165. return EFI_INVALID_PARAMETER;
  166. } else if (StrCmp (Argv[Index], L"-m") == 0) {
  167. //
  168. // Parse the MAC address here.
  169. //
  170. Status = ConvertMac(Argv[Index+1]);
  171. if (EFI_ERROR(Status)) {
  172. PrintToken (STRING_TOKEN (STR_FWUPDATE_INVAILD_MAC), HiiHandle);
  173. return Status;
  174. }
  175. //
  176. // Save the MAC address to mInputData.MacValue.
  177. //
  178. mInputData.UpdateMac= TRUE;
  179. Index++;
  180. } else {
  181. //
  182. // Invalid option was provided.
  183. //
  184. return EFI_INVALID_PARAMETER;
  185. }
  186. }
  187. if ((Index == Argc - 1) && (StrCmp (Argv[Index - 1], L"-m") != 0)) {
  188. //
  189. // The only parameter that is not an option is the firmware image. Check
  190. // to make sure that the file exists.
  191. //
  192. Status = ShellIsFile (Argv[Index]);
  193. if (EFI_ERROR (Status)) {
  194. PrintToken (STRING_TOKEN (STR_FWUPDATE_FILE_NOT_FOUND_ERROR), HiiHandle, Argv[Index]);
  195. return EFI_INVALID_PARAMETER;
  196. }
  197. if (StrLen (Argv[Index]) > INPUT_STRING_LEN) {
  198. PrintToken (STRING_TOKEN (STR_FWUPDATE_PATH_ERROR), HiiHandle, Argv[Index]);
  199. return EFI_INVALID_PARAMETER;
  200. }
  201. StrCpyS (mInputData.FileName, sizeof (mInputData.FileName) / sizeof (CHAR16), Argv[Index]);
  202. mInputData.UpdateFromFile = TRUE;
  203. }
  204. }
  205. return EFI_SUCCESS;
  206. }
  207. INTN
  208. EFIAPI
  209. ShellAppMain (
  210. IN UINTN Argc,
  211. IN CHAR16 **Argv
  212. )
  213. {
  214. EFI_STATUS Status;
  215. UINTN Index;
  216. UINT32 FileSize;
  217. UINT32 BufferSize;
  218. UINT8 *FileBuffer;
  219. UINT8 *Buffer;
  220. EFI_PHYSICAL_ADDRESS Address;
  221. UINTN CountOfBlocks;
  222. EFI_TPL OldTpl;
  223. BOOLEAN ResetRequired;
  224. BOOLEAN FlashError;
  225. Index = 0;
  226. FileSize = 0;
  227. BufferSize = 0;
  228. FileBuffer = NULL;
  229. Buffer = NULL;
  230. Address = 0;
  231. CountOfBlocks = 0;
  232. ResetRequired = FALSE;
  233. FlashError = FALSE;
  234. Status = EFI_SUCCESS;
  235. mInputData.FullFlashUpdate = TRUE;
  236. //
  237. // Publish our HII data.
  238. //
  239. HiiHandle = HiiAddPackages (
  240. &gEfiCallerIdGuid,
  241. NULL,
  242. FirmwareUpdateStrings,
  243. NULL
  244. );
  245. if (HiiHandle == NULL) {
  246. Status = EFI_OUT_OF_RESOURCES;
  247. goto Done;
  248. }
  249. //
  250. // Locate the SPI protocol.
  251. //
  252. Status = gBS->LocateProtocol (
  253. &gEfiSpiProtocolGuid,
  254. NULL,
  255. (VOID **)&mSpiProtocol
  256. );
  257. if (EFI_ERROR (Status)) {
  258. PrintToken (STRING_TOKEN (STR_SPI_NOT_FOUND), HiiHandle);
  259. return EFI_DEVICE_ERROR;
  260. }
  261. //
  262. // Parse the command line.
  263. //
  264. Status = ParseCommandLine (Argc, Argv);
  265. if (EFI_ERROR (Status)) {
  266. PrintHelpInfo ();
  267. Status = EFI_SUCCESS;
  268. goto Done;
  269. }
  270. //
  271. // Display sign-on information.
  272. //
  273. PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle);
  274. PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle);
  275. PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle);
  276. //
  277. // Test to see if the firmware needs to be updated.
  278. //
  279. if (mInputData.UpdateFromFile) {
  280. //
  281. // Get the file to use in the update.
  282. //
  283. PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE), HiiHandle, mInputData.FileName);
  284. Status = ReadFileData (mInputData.FileName, &FileBuffer, &FileSize);
  285. if (EFI_ERROR (Status)) {
  286. PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE_ERROR), HiiHandle, mInputData.FileName);
  287. goto Done;
  288. }
  289. //
  290. // Check that the file and flash sizes match.
  291. //
  292. if (FileSize != PcdGet32 (PcdFlashChipSize)) {
  293. PrintToken (STRING_TOKEN (STR_FWUPDATE_SIZE), HiiHandle);
  294. Status = EFI_UNSUPPORTED;
  295. goto Done;
  296. }
  297. //
  298. // Display flash update information.
  299. //
  300. PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATING_FIRMWARE), HiiHandle);
  301. //
  302. // Update it.
  303. //
  304. Buffer = FileBuffer;
  305. BufferSize = FileSize;
  306. Address = PcdGet32 (PcdFlashChipBase);
  307. CountOfBlocks = (UINTN) (BufferSize / BLOCK_SIZE);
  308. //
  309. // Raise TPL to TPL_NOTIFY to block any event handler,
  310. // while still allowing RaiseTPL(TPL_NOTIFY) within
  311. // output driver during Print().
  312. //
  313. OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
  314. for (Index = 0; Index < CountOfBlocks; Index++) {
  315. //
  316. // Handle block based on address and contents.
  317. //
  318. if (!UpdateBlock (Address)) {
  319. DEBUG((EFI_D_INFO, "Skipping block at 0x%lx\n", Address));
  320. } else if (!EFI_ERROR (InternalCompareBlock (Address, Buffer))) {
  321. DEBUG((EFI_D_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));
  322. } else {
  323. //
  324. // Display a dot for each block being updated.
  325. //
  326. Print (L".");
  327. //
  328. // Flag that the flash image will be changed and the system must be rebooted
  329. // to use the change.
  330. //
  331. ResetRequired = TRUE;
  332. //
  333. // Make updating process uninterruptable,
  334. // so that the flash memory area is not accessed by other entities
  335. // which may interfere with the updating process.
  336. //
  337. Status = InternalEraseBlock (Address);
  338. ASSERT_EFI_ERROR(Status);
  339. if (EFI_ERROR (Status)) {
  340. gBS->RestoreTPL (OldTpl);
  341. FlashError = TRUE;
  342. goto Done;
  343. }
  344. Status = InternalWriteBlock (
  345. Address,
  346. Buffer,
  347. (BufferSize > BLOCK_SIZE ? BLOCK_SIZE : BufferSize)
  348. );
  349. if (EFI_ERROR (Status)) {
  350. gBS->RestoreTPL (OldTpl);
  351. FlashError = TRUE;
  352. goto Done;
  353. }
  354. }
  355. //
  356. // Move to next block to update.
  357. //
  358. Address += BLOCK_SIZE;
  359. Buffer += BLOCK_SIZE;
  360. if (BufferSize > BLOCK_SIZE) {
  361. BufferSize -= BLOCK_SIZE;
  362. } else {
  363. BufferSize = 0;
  364. }
  365. }
  366. gBS->RestoreTPL (OldTpl);
  367. //
  368. // Print result of update.
  369. //
  370. if (!FlashError) {
  371. if (ResetRequired) {
  372. Print (L"\n");
  373. PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_SUCCESS), HiiHandle);
  374. } else {
  375. PrintToken (STRING_TOKEN (STR_FWUPDATE_NO_RESET), HiiHandle);
  376. }
  377. } else {
  378. goto Done;
  379. }
  380. }
  381. //
  382. // All flash updates are done so see if the system needs to be reset.
  383. //
  384. if (ResetRequired && !FlashError) {
  385. //
  386. // Update successful.
  387. //
  388. for (Index = 5; Index > 0; Index--) {
  389. PrintToken (STRING_TOKEN (STR_FWUPDATE_SHUTDOWN), HiiHandle, Index);
  390. gBS->Stall (1000000);
  391. }
  392. gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
  393. PrintToken (STRING_TOKEN (STR_FWUPDATE_MANUAL_RESET), HiiHandle);
  394. CpuDeadLoop ();
  395. }
  396. Done:
  397. //
  398. // Print flash update failure message if error detected.
  399. //
  400. if (FlashError) {
  401. PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_FAILED), HiiHandle, Index);
  402. }
  403. //
  404. // Do cleanup.
  405. //
  406. if (HiiHandle != NULL) {
  407. HiiRemovePackages (HiiHandle);
  408. }
  409. if (FileBuffer) {
  410. gBS->FreePool (FileBuffer);
  411. }
  412. return Status;
  413. }
  414. STATIC
  415. EFI_STATUS
  416. InternalEraseBlock (
  417. IN EFI_PHYSICAL_ADDRESS BaseAddress
  418. )
  419. /*++
  420. Routine Description:
  421. Erase the whole block.
  422. Arguments:
  423. BaseAddress - Base address of the block to be erased.
  424. Returns:
  425. EFI_SUCCESS - The command completed successfully.
  426. Other - Device error or wirte-locked, operation failed.
  427. --*/
  428. {
  429. EFI_STATUS Status;
  430. UINTN NumBytes;
  431. NumBytes = BLOCK_SIZE;
  432. Status = SpiFlashBlockErase ((UINTN) BaseAddress, &NumBytes);
  433. return Status;
  434. }
  435. #if 0
  436. STATIC
  437. EFI_STATUS
  438. InternalReadBlock (
  439. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  440. OUT VOID *ReadBuffer
  441. )
  442. {
  443. EFI_STATUS Status;
  444. UINT32 BlockSize;
  445. BlockSize = BLOCK_SIZE;
  446. Status = SpiFlashRead ((UINTN) BaseAddress, &BlockSize, ReadBuffer);
  447. return Status;
  448. }
  449. #endif
  450. STATIC
  451. EFI_STATUS
  452. InternalCompareBlock (
  453. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  454. IN UINT8 *Buffer
  455. )
  456. {
  457. EFI_STATUS Status;
  458. VOID *CompareBuffer;
  459. UINT32 NumBytes;
  460. INTN CompareResult;
  461. NumBytes = BLOCK_SIZE;
  462. CompareBuffer = AllocatePool (NumBytes);
  463. if (CompareBuffer == NULL) {
  464. Status = EFI_OUT_OF_RESOURCES;
  465. goto Done;
  466. }
  467. Status = SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer);
  468. if (EFI_ERROR (Status)) {
  469. goto Done;
  470. }
  471. CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);
  472. if (CompareResult != 0) {
  473. Status = EFI_VOLUME_CORRUPTED;
  474. }
  475. Done:
  476. if (CompareBuffer != NULL) {
  477. FreePool (CompareBuffer);
  478. }
  479. return Status;
  480. }
  481. STATIC
  482. EFI_STATUS
  483. InternalWriteBlock (
  484. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  485. IN UINT8 *Buffer,
  486. IN UINT32 BufferSize
  487. )
  488. /*++
  489. Routine Description:
  490. Write a block of data.
  491. Arguments:
  492. BaseAddress - Base address of the block.
  493. Buffer - Data buffer.
  494. BufferSize - Size of the buffer.
  495. Returns:
  496. EFI_SUCCESS - The command completed successfully.
  497. EFI_INVALID_PARAMETER - Invalid parameter, can not proceed.
  498. Other - Device error or wirte-locked, operation failed.
  499. --*/
  500. {
  501. EFI_STATUS Status;
  502. Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer);
  503. ASSERT_EFI_ERROR(Status);
  504. if (EFI_ERROR (Status)) {
  505. DEBUG((EFI_D_ERROR, "\nFlash write error."));
  506. return Status;
  507. }
  508. WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE);
  509. Status = InternalCompareBlock (BaseAddress, Buffer);
  510. if (EFI_ERROR (Status)) {
  511. DEBUG((EFI_D_ERROR, "\nError when writing to BaseAddress %lx with different at offset %x.", BaseAddress, Status));
  512. } else {
  513. DEBUG((EFI_D_INFO, "\nVerified data written to Block at %lx is correct.", BaseAddress));
  514. }
  515. return Status;
  516. }
  517. STATIC
  518. EFI_STATUS
  519. ReadFileData (
  520. IN CHAR16 *FileName,
  521. OUT UINT8 **Buffer,
  522. OUT UINT32 *BufferSize
  523. )
  524. {
  525. EFI_STATUS Status;
  526. SHELL_FILE_HANDLE FileHandle;
  527. UINT64 Size;
  528. VOID *NewBuffer;
  529. UINTN ReadSize;
  530. FileHandle = NULL;
  531. NewBuffer = NULL;
  532. Size = 0;
  533. Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
  534. if (EFI_ERROR (Status)) {
  535. goto Done;
  536. }
  537. Status = FileHandleIsDirectory (FileHandle);
  538. if (!EFI_ERROR (Status)) {
  539. Status = EFI_NOT_FOUND;
  540. goto Done;
  541. }
  542. Status = FileHandleGetSize (FileHandle, &Size);
  543. if (EFI_ERROR (Status)) {
  544. goto Done;
  545. }
  546. NewBuffer = AllocatePool ((UINTN) Size);
  547. ReadSize = (UINTN) Size;
  548. Status = FileHandleRead (FileHandle, &ReadSize, NewBuffer);
  549. if (EFI_ERROR (Status)) {
  550. goto Done;
  551. } else if (ReadSize != (UINTN) Size) {
  552. Status = EFI_INVALID_PARAMETER;
  553. goto Done;
  554. }
  555. Done:
  556. if (FileHandle != NULL) {
  557. ShellCloseFile (&FileHandle);
  558. }
  559. if (EFI_ERROR (Status)) {
  560. if (NewBuffer != NULL) {
  561. FreePool (NewBuffer);
  562. }
  563. } else {
  564. *Buffer = NewBuffer;
  565. *BufferSize = (UINT32) Size;
  566. }
  567. return Status;
  568. }
  569. STATIC
  570. VOID
  571. PrintHelpInfo (
  572. VOID
  573. )
  574. /*++
  575. Routine Description:
  576. Print out help information.
  577. Arguments:
  578. None.
  579. Returns:
  580. None.
  581. --*/
  582. {
  583. PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle);
  584. PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle);
  585. PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle);
  586. Print (L"\n");
  587. PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE), HiiHandle);
  588. PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_1), HiiHandle);
  589. PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_2), HiiHandle);
  590. PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_3), HiiHandle);
  591. PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_4), HiiHandle);
  592. Print (L"\n");
  593. }
  594. /**
  595. Read NumBytes bytes of data from the address specified by
  596. PAddress into Buffer.
  597. @param[in] Address The starting physical address of the read.
  598. @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
  599. of bytes actually read.
  600. @param[out] Buffer The destination data buffer for the read.
  601. @retval EFI_SUCCESS Opertion is successful.
  602. @retval EFI_DEVICE_ERROR If there is any device errors.
  603. **/
  604. EFI_STATUS
  605. EFIAPI
  606. SpiFlashRead (
  607. IN UINTN Address,
  608. IN OUT UINT32 *NumBytes,
  609. OUT UINT8 *Buffer
  610. )
  611. {
  612. EFI_STATUS Status = EFI_SUCCESS;
  613. UINTN Offset = 0;
  614. ASSERT ((NumBytes != NULL) && (Buffer != NULL));
  615. Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);
  616. Status = mSpiProtocol->Execute (
  617. mSpiProtocol,
  618. 1, //SPI_READ,
  619. 0, //SPI_WREN,
  620. TRUE,
  621. TRUE,
  622. FALSE,
  623. Offset,
  624. BLOCK_SIZE,
  625. Buffer,
  626. EnumSpiRegionAll
  627. );
  628. return Status;
  629. }
  630. /**
  631. Write NumBytes bytes of data from Buffer to the address specified by
  632. PAddresss.
  633. @param[in] Address The starting physical address of the write.
  634. @param[in,out] NumBytes On input, the number of bytes to write. On output,
  635. the actual number of bytes written.
  636. @param[in] Buffer The source data buffer for the write.
  637. @retval EFI_SUCCESS Opertion is successful.
  638. @retval EFI_DEVICE_ERROR If there is any device errors.
  639. **/
  640. EFI_STATUS
  641. EFIAPI
  642. SpiFlashWrite (
  643. IN UINTN Address,
  644. IN OUT UINT32 *NumBytes,
  645. IN UINT8 *Buffer
  646. )
  647. {
  648. EFI_STATUS Status;
  649. UINTN Offset;
  650. UINT32 Length;
  651. UINT32 RemainingBytes;
  652. ASSERT ((NumBytes != NULL) && (Buffer != NULL));
  653. ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));
  654. Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);
  655. ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));
  656. Status = EFI_SUCCESS;
  657. RemainingBytes = *NumBytes;
  658. while (RemainingBytes > 0) {
  659. if (RemainingBytes > SIZE_4KB) {
  660. Length = SIZE_4KB;
  661. } else {
  662. Length = RemainingBytes;
  663. }
  664. Status = mSpiProtocol->Execute (
  665. mSpiProtocol,
  666. SPI_PROG,
  667. SPI_WREN,
  668. TRUE,
  669. TRUE,
  670. TRUE,
  671. (UINT32) Offset,
  672. Length,
  673. Buffer,
  674. EnumSpiRegionAll
  675. );
  676. if (EFI_ERROR (Status)) {
  677. break;
  678. }
  679. RemainingBytes -= Length;
  680. Offset += Length;
  681. Buffer += Length;
  682. }
  683. //
  684. // Actual number of bytes written.
  685. //
  686. *NumBytes -= RemainingBytes;
  687. return Status;
  688. }
  689. /**
  690. Erase the block starting at Address.
  691. @param[in] Address The starting physical address of the block to be erased.
  692. This library assume that caller garantee that the PAddress
  693. is at the starting address of this block.
  694. @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
  695. On output, the actual number of bytes erased.
  696. @retval EFI_SUCCESS. Opertion is successful.
  697. @retval EFI_DEVICE_ERROR If there is any device errors.
  698. **/
  699. EFI_STATUS
  700. EFIAPI
  701. SpiFlashBlockErase (
  702. IN UINTN Address,
  703. IN UINTN *NumBytes
  704. )
  705. {
  706. EFI_STATUS Status;
  707. UINTN Offset;
  708. UINTN RemainingBytes;
  709. ASSERT (NumBytes != NULL);
  710. ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));
  711. Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);
  712. ASSERT ((*NumBytes % SIZE_4KB) == 0);
  713. ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));
  714. Status = EFI_SUCCESS;
  715. RemainingBytes = *NumBytes;
  716. while (RemainingBytes > 0) {
  717. Status = mSpiProtocol->Execute (
  718. mSpiProtocol,
  719. SPI_SERASE,
  720. SPI_WREN,
  721. FALSE,
  722. TRUE,
  723. FALSE,
  724. (UINT32) Offset,
  725. 0,
  726. NULL,
  727. EnumSpiRegionAll
  728. );
  729. if (EFI_ERROR (Status)) {
  730. break;
  731. }
  732. RemainingBytes -= SIZE_4KB;
  733. Offset += SIZE_4KB;
  734. }
  735. //
  736. // Actual number of bytes erased.
  737. //
  738. *NumBytes -= RemainingBytes;
  739. return Status;
  740. }
  741. EFI_STATUS
  742. EFIAPI
  743. ConvertMac (
  744. CHAR16 *Str
  745. )
  746. {
  747. UINTN Index;
  748. UINT8 Temp[MAC_ADD_STR_LEN];
  749. if (Str == NULL)
  750. return EFI_INVALID_PARAMETER;
  751. if (StrLen(Str) != MAC_ADD_STR_LEN)
  752. return EFI_INVALID_PARAMETER;
  753. for (Index = 0; Index < MAC_ADD_STR_LEN; Index++) {
  754. if (Str[Index] >= 0x30 && Str[Index] <= 0x39) {
  755. Temp[Index] = (UINT8)Str[Index] - 0x30;
  756. } else if (Str[Index] >= 0x41 && Str[Index] <= 0x46) {
  757. Temp[Index] = (UINT8)Str[Index] - 0x37;
  758. } else if (Str[Index] >= 0x61 && Str[Index] <= 0x66) {
  759. Temp[Index] = (UINT8)Str[Index] - 0x57;
  760. } else {
  761. return EFI_INVALID_PARAMETER;
  762. }
  763. }
  764. for (Index = 0; Index < MAC_ADD_BYTE_COUNT; Index++) {
  765. mInputData.MacValue[Index] = (Temp[2 * Index] << 4) + Temp[2 * Index + 1];
  766. }
  767. return EFI_SUCCESS;
  768. }