FmpDeviceLib.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /**
  2. Copyright (c) Microsoft Corporation.<BR>
  3. Copyright (c) 2019, Intel Corporation. All rights reserved.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiDxe.h>
  7. #include <LastAttemptStatus.h>
  8. #include <Guid/SystemResourceTable.h>
  9. #include <Library/FmpDeviceLib.h>
  10. #include <Library/DebugLib.h>
  11. #include <Library/BaseLib.h>
  12. #include <Library/BaseMemoryLib.h>
  13. #include <Library/MemoryAllocationLib.h>
  14. #include <Library/UefiBootServicesTableLib.h>
  15. #include <Library/PlatformFlashAccessLib.h>
  16. //#include <Protocol/FirmwareManagement.h>
  17. //#include <Guid/SystemResourceTable.h>
  18. typedef struct {
  19. PLATFORM_FIRMWARE_TYPE FirmwareType;
  20. FLASH_ADDRESS_TYPE AddressType;
  21. EFI_PHYSICAL_ADDRESS BaseAddress;
  22. UINTN Length;
  23. UINTN ImageOffset;
  24. } UPDATE_CONFIG_DATA;
  25. UPDATE_CONFIG_DATA mUpdateConfigData[] = {
  26. { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeRelativeAddress, 0x00400000, 0x00040000, 0x00400000 },
  27. { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeRelativeAddress, 0x004C0000, 0x00050000, 0x004C0000 },
  28. { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeRelativeAddress, 0x00510000, 0x00210000, 0x00510000 },
  29. { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeRelativeAddress, 0x00720000, 0x00070000, 0x00720000 },
  30. { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeRelativeAddress, 0x00790000, 0x00070000, 0x00790000 }
  31. };
  32. /**
  33. Used to pass the FMP install function to this lib. This allows the library to
  34. have control of the handle that the FMP instance is installed on. This allows
  35. the library to use DriverBinding protocol model to locate its device(s) in the
  36. system.
  37. @param[in] Func Function pointer to FMP install function.
  38. @retval EFI_SUCCESS Library has saved function pointer and will call
  39. function pointer on each DriverBinding Start.
  40. @retval EFI_UNSUPPORTED Library doesn't use driver binding and only supports
  41. a single instance.
  42. @retval other error Error occurred. Don't install FMP
  43. **/
  44. EFI_STATUS
  45. EFIAPI
  46. RegisterFmpInstaller (
  47. IN FMP_DEVICE_LIB_REGISTER_FMP_INSTALLER Func
  48. )
  49. {
  50. //
  51. // This is a system firmware update that does not use Driver Binding Protocol
  52. //
  53. return EFI_UNSUPPORTED;
  54. }
  55. /**
  56. Provide a function to uninstall the Firmware Management Protocol instance from a
  57. device handle when the device is managed by a driver that follows the UEFI
  58. Driver Model. If the device is not managed by a driver that follows the UEFI
  59. Driver Model, then EFI_UNSUPPORTED is returned.
  60. @param[in] FmpUninstaller Function that installs the Firmware Management
  61. Protocol.
  62. @retval EFI_SUCCESS The device is managed by a driver that follows the
  63. UEFI Driver Model. FmpUinstaller must be called on
  64. each Driver Binding Stop().
  65. @retval EFI_UNSUPPORTED The device is not managed by a driver that follows
  66. the UEFI Driver Model.
  67. @retval other The Firmware Management Protocol for this firmware
  68. device is not installed. The firmware device is
  69. still locked using FmpDeviceLock().
  70. **/
  71. EFI_STATUS
  72. EFIAPI
  73. RegisterFmpUninstaller (
  74. IN FMP_DEVICE_LIB_REGISTER_FMP_UNINSTALLER FmpUninstaller
  75. )
  76. {
  77. //
  78. // This is a system firmware update that does not use Driver Binding Protocol
  79. //
  80. return EFI_UNSUPPORTED;
  81. }
  82. /**
  83. Set the device context for the FmpDeviceLib services when the device is
  84. managed by a driver that follows the UEFI Driver Model. If the device is not
  85. managed by a driver that follows the UEFI Driver Model, then EFI_UNSUPPORTED
  86. is returned. Once a device context is set, the FmpDeviceLib services
  87. operate on the currently set device context.
  88. @param[in] Handle Device handle for the FmpDeviceLib services.
  89. If Handle is NULL, then Context is freed.
  90. @param[in, out] Context Device context for the FmpDeviceLib services.
  91. If Context is NULL, then a new context is allocated
  92. for Handle and the current device context is set and
  93. returned in Context. If Context is not NULL, then
  94. the current device context is set.
  95. @retval EFI_SUCCESS The device is managed by a driver that follows the
  96. UEFI Driver Model.
  97. @retval EFI_UNSUPPORTED The device is not managed by a driver that follows
  98. the UEFI Driver Model.
  99. @retval other The Firmware Management Protocol for this firmware
  100. device is not installed. The firmware device is
  101. still locked using FmpDeviceLock().
  102. **/
  103. EFI_STATUS
  104. EFIAPI
  105. FmpDeviceSetContext (
  106. IN EFI_HANDLE Handle,
  107. IN OUT VOID **Context
  108. )
  109. {
  110. //
  111. // This is a system firmware update that does not use Driver Binding Protocol
  112. //
  113. return EFI_UNSUPPORTED;
  114. }
  115. /**
  116. Returns the size, in bytes, of the firmware image currently stored in the
  117. firmware device. This function is used to by the GetImage() and
  118. GetImageInfo() services of the Firmware Management Protocol. If the image
  119. size can not be determined from the firmware device, then 0 must be returned.
  120. @param[out] Size Pointer to the size, in bytes, of the firmware image
  121. currently stored in the firmware device.
  122. @retval EFI_SUCCESS The size of the firmware image currently
  123. stored in the firmware device was returned.
  124. @retval EFI_INVALID_PARAMETER Size is NULL.
  125. @retval EFI_UNSUPPORTED The firmware device does not support reporting
  126. the size of the currently stored firmware image.
  127. @retval EFI_DEVICE_ERROR An error occured attempting to determine the
  128. size of the firmware image currently stored in
  129. in the firmware device.
  130. **/
  131. EFI_STATUS
  132. EFIAPI
  133. FmpDeviceGetSize (
  134. IN UINTN *Size
  135. )
  136. {
  137. if (Size == NULL) {
  138. return EFI_INVALID_PARAMETER;
  139. }
  140. *Size = PcdGet32 (PcdBiosRomSize);
  141. return EFI_SUCCESS;
  142. }
  143. /**
  144. Used to return a library supplied guid that will be the ImageTypeId guid of
  145. the FMP descriptor. This is optional but can be used if at runtime the guid
  146. needs to be determined.
  147. @param[out] Guid Double Guid Ptr that will be updated to point to guid.
  148. This should be from static memory and will not be freed.
  149. @return EFI_UNSUPPORTED Library instance doesn't need dynamic guid.
  150. @return Error Any error will cause the wrapper to use the GUID
  151. defined by PCD.
  152. @return EFI_SUCCESS Guid ptr should be updated to point to static memeory
  153. which contains a valid guid.
  154. **/
  155. EFI_STATUS
  156. EFIAPI
  157. FmpDeviceGetImageTypeIdGuidPtr (
  158. OUT EFI_GUID **Guid
  159. )
  160. {
  161. return EFI_UNSUPPORTED;
  162. }
  163. /**
  164. Returns values used to fill in the AttributesSupported and AttributesSettings
  165. fields of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the
  166. GetImageInfo() service of the Firmware Management Protocol. The following
  167. bit values from the Firmware Management Protocol may be combined:
  168. IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
  169. IMAGE_ATTRIBUTE_RESET_REQUIRED
  170. IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
  171. IMAGE_ATTRIBUTE_IN_USE
  172. IMAGE_ATTRIBUTE_UEFI_IMAGE
  173. @param[out] Supported Attributes supported by this firmware device.
  174. @param[out] Setting Attributes settings for this firmware device.
  175. @retval EFI_SUCCESS The attributes supported by the firmware
  176. device were returned.
  177. @retval EFI_INVALID_PARAMETER Supported is NULL.
  178. @retval EFI_INVALID_PARAMETER Setting is NULL.
  179. **/
  180. EFI_STATUS
  181. EFIAPI
  182. FmpDeviceGetAttributes (
  183. IN OUT UINT64 *Supported,
  184. IN OUT UINT64 *Setting
  185. )
  186. {
  187. if (Supported == NULL || Setting == NULL) {
  188. return EFI_INVALID_PARAMETER;
  189. }
  190. *Supported = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
  191. IMAGE_ATTRIBUTE_RESET_REQUIRED |
  192. IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
  193. IMAGE_ATTRIBUTE_IN_USE
  194. );
  195. *Setting = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
  196. IMAGE_ATTRIBUTE_RESET_REQUIRED |
  197. IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
  198. IMAGE_ATTRIBUTE_IN_USE
  199. );
  200. return EFI_SUCCESS;
  201. }
  202. /**
  203. Gets the current Lowest Supported Version.
  204. This is a protection mechanism so that a previous version with known issue is
  205. not applied. ONLY implement this if your running firmware has a method to
  206. return this at runtime. If EFI_UNSUPPORTED is returned, then the Lowest
  207. Supported Version is stored in a UEFI Variable.
  208. @param[out] Version On return this value represents the current Lowest
  209. Supported Version (in same format as GetVersion).
  210. @retval EFI_SUCCESS The Lowest Supported Version was correctly retrieved
  211. @retval EFI_UNSUPPORTED Device firmware doesn't support reporting LSV
  212. @retval EFI_DEVICE_ERROR Error occurred when trying to get the LSV
  213. **/
  214. EFI_STATUS
  215. EFIAPI
  216. FmpDeviceGetLowestSupportedVersion (
  217. IN OUT UINT32 *LowestSupportedVersion
  218. )
  219. {
  220. //
  221. // Retrieve the lowest support version from a PCD
  222. // NOTE: This method of using a PCD can only be used for the system firmware
  223. // FMP instance that is updated every time the system firmware is
  224. // updated. If system firmware updates support partial updates that
  225. // would not include the system firmware FMP instance, then a PCD can
  226. // not be used and the value must come from the currently running system
  227. // firmware image.
  228. //
  229. *LowestSupportedVersion = PcdGet32 (PcdSystemFirmwareFmpLowestSupportedVersion);
  230. return EFI_SUCCESS;
  231. }
  232. /**
  233. Returns the Null-terminated Unicode string that is used to fill in the
  234. VersionName field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is
  235. returned by the GetImageInfo() service of the Firmware Management Protocol.
  236. The returned string must be allocated using EFI_BOOT_SERVICES.AllocatePool().
  237. @note It is recommended that all firmware devices support a method to report
  238. the VersionName string from the currently stored firmware image.
  239. @param[out] VersionString The version string retrieved from the currently
  240. stored firmware image.
  241. @retval EFI_SUCCESS The version string of currently stored
  242. firmware image was returned in Version.
  243. @retval EFI_INVALID_PARAMETER VersionString is NULL.
  244. @retval EFI_UNSUPPORTED The firmware device does not support a method
  245. to report the version string of the currently
  246. stored firmware image.
  247. @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the
  248. version string of the currently stored
  249. firmware image.
  250. @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the
  251. buffer for the version string of the currently
  252. stored firmware image.
  253. **/
  254. EFI_STATUS
  255. EFIAPI
  256. FmpDeviceGetVersionString (
  257. OUT CHAR16 **VersionString
  258. )
  259. {
  260. if (VersionString == NULL) {
  261. return EFI_INVALID_PARAMETER;
  262. }
  263. //
  264. // Retrieve the version string from a PCD
  265. // NOTE: This method of using a PCD can only be used for the system firmware
  266. // FMP instance that is updated every time the system firmware is
  267. // updated. If system firmware updates support partial updates that
  268. // would not include the system firmware FMP instance, then a PCD can
  269. // not be used and the value must come from the currently running system
  270. // firmware image.
  271. //
  272. *VersionString = (CHAR16 *)AllocateCopyPool (
  273. PcdGetSize (PcdSystemFirmwareFmpVersionString),
  274. PcdGetPtr (PcdSystemFirmwareFmpVersionString)
  275. );
  276. if (*VersionString == NULL) {
  277. return EFI_OUT_OF_RESOURCES;
  278. }
  279. return EFI_SUCCESS;
  280. }
  281. /**
  282. Gets the current running version.
  283. ONLY implement this if your running firmware has a method to return this at
  284. runtime.
  285. @param[out] Version On return this value represents the current running
  286. version.
  287. @retval EFI_SUCCESS The version was correctly retrieved.
  288. @retval EFI_UNSUPPORTED Device firmware doesn't support reporting current
  289. version.
  290. @retval EFI_DEVICE_ERROR Error occurred when trying to get the version.
  291. **/
  292. EFI_STATUS
  293. EFIAPI
  294. FmpDeviceGetVersion (
  295. IN OUT UINT32 *Version
  296. )
  297. {
  298. //
  299. // Retrieve the version string from a PCD
  300. // NOTE: This method of using a PCD can only be used for the system firmware
  301. // FMP instance that is updated every time the system firmware is
  302. // updated. If system firmware updates support partial updates that
  303. // would not include the system firmware FMP instance, then a PCD can
  304. // not be used and the value must come from the currently running system
  305. // firmware image.
  306. //
  307. *Version = PcdGet32 (PcdSystemFirmwareFmpVersion);
  308. return EFI_SUCCESS;
  309. }
  310. /**
  311. Returns the value used to fill in the HardwareInstance field of the
  312. EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
  313. service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then
  314. the firmware device supports a method to report the HardwareInstance value.
  315. If the value can not be reported for the firmware device, then EFI_UNSUPPORTED
  316. must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting
  317. to retrieve the HardwareInstance value for the firmware device.
  318. @param[out] HardwareInstance The hardware instance value for the firmware
  319. device.
  320. @retval EFI_SUCCESS The hardware instance for the current firmware
  321. devide is returned in HardwareInstance.
  322. @retval EFI_UNSUPPORTED The firmware device does not support a method to
  323. report the hardware instance value.
  324. @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the hardware
  325. instance value.
  326. **/
  327. EFI_STATUS
  328. EFIAPI
  329. FmpDeviceGetHardwareInstance (
  330. OUT UINT64 *HardwareInstance
  331. )
  332. {
  333. return EFI_UNSUPPORTED;
  334. }
  335. /**
  336. Retrieves a copy of the current firmware image of the device.
  337. This function allows a copy of the current firmware image to be created and
  338. saved. The saved copy could later been used, for example, in firmware image
  339. recovery or rollback.
  340. @param[out] Image Points to the buffer where the current image is copied
  341. to.
  342. @param[out] ImageSize On entry, points to the size of the buffer pointed to
  343. by Image, in bytes. On return, points to the length of
  344. the image, in bytes.
  345. @retval EFI_SUCCESS The image was successfully read from the device.
  346. @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small
  347. to hold the image. The current buffer size
  348. needed to hold the image is returned in
  349. ImageSize.
  350. @retval EFI_INVALID_PARAMETER The Image was NULL.
  351. @retval EFI_NOT_FOUND The current image is not copied to the buffer.
  352. @retval EFI_UNSUPPORTED The operation is not supported.
  353. **/
  354. EFI_STATUS
  355. EFIAPI
  356. FmpDeviceGetImage (
  357. IN OUT VOID *Image,
  358. IN OUT UINTN *ImageSize
  359. )
  360. {
  361. //
  362. // Check for invalid p;arameters
  363. //
  364. if (Image == NULL || ImageSize == NULL) {
  365. return EFI_INVALID_PARAMETER;
  366. }
  367. //
  368. // Make sure the buffer is big enough to hold the device image
  369. //
  370. if (*ImageSize < PcdGet32 (PcdBiosRomSize)) {
  371. *ImageSize = PcdGet32 (PcdBiosRomSize);
  372. return EFI_BUFFER_TOO_SMALL;
  373. }
  374. //
  375. // Copy the device image to the buffer
  376. //
  377. *ImageSize = PcdGet32 (PcdBiosRomSize);
  378. CopyMem (
  379. Image,
  380. (VOID *)(UINTN)PcdGet32 (PcdBiosRomBase),
  381. *ImageSize
  382. );
  383. return EFI_SUCCESS;
  384. }
  385. /**
  386. Updates a firmware device with a new firmware image. This function returns
  387. EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
  388. is updatable, the function should perform the following minimal validations
  389. before proceeding to do the firmware image update.
  390. - Validate that the image is a supported image for this firmware device.
  391. Return EFI_ABORTED if the image is not supported. Additional details
  392. on why the image is not a supported image may be returned in AbortReason.
  393. - Validate the data from VendorCode if is not NULL. Firmware image
  394. validation must be performed before VendorCode data validation.
  395. VendorCode data is ignored or considered invalid if image validation
  396. fails. Return EFI_ABORTED if the VendorCode data is invalid.
  397. VendorCode enables vendor to implement vendor-specific firmware image update
  398. policy. Null if the caller did not specify the policy or use the default
  399. policy. As an example, vendor can implement a policy to allow an option to
  400. force a firmware image update when the abort reason is due to the new firmware
  401. image version is older than the current firmware image version or bad image
  402. checksum. Sensitive operations such as those wiping the entire firmware image
  403. and render the device to be non-functional should be encoded in the image
  404. itself rather than passed with the VendorCode. AbortReason enables vendor to
  405. have the option to provide a more detailed description of the abort reason to
  406. the caller.
  407. @param[in] Image Points to the new firmware image.
  408. @param[in] ImageSize Size, in bytes, of the new firmware image.
  409. @param[in] VendorCode This enables vendor to implement vendor-specific
  410. firmware image update policy. NULL indicates
  411. the caller did not specify the policy or use the
  412. default policy.
  413. @param[in] Progress A function used to report the progress of
  414. updating the firmware device with the new
  415. firmware image.
  416. @param[in] CapsuleFwVersion The version of the new firmware image from the
  417. update capsule that provided the new firmware
  418. image.
  419. @param[out] AbortReason A pointer to a pointer to a Null-terminated
  420. Unicode string providing more details on an
  421. aborted operation. The buffer is allocated by
  422. this function with
  423. EFI_BOOT_SERVICES.AllocatePool(). It is the
  424. caller's responsibility to free this buffer with
  425. EFI_BOOT_SERVICES.FreePool().
  426. @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt
  427. status to report back to the ESRT table in case
  428. of error. This value will only be checked when this
  429. function returns an error.
  430. The return status code must fall in the range of
  431. LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
  432. LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
  433. If the value falls outside this range, it will be converted
  434. to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
  435. @retval EFI_SUCCESS The firmware device was successfully updated
  436. with the new firmware image.
  437. @retval EFI_ABORTED The operation is aborted. Additional details
  438. are provided in AbortReason.
  439. @retval EFI_INVALID_PARAMETER The Image was NULL.
  440. @retval EFI_INVALID_PARAMETER LastAttemptStatus was NULL.
  441. @retval EFI_UNSUPPORTED The operation is not supported.
  442. **/
  443. EFI_STATUS
  444. EFIAPI
  445. FmpDeviceSetImageWithStatus (
  446. IN CONST VOID *Image,
  447. IN UINTN ImageSize,
  448. IN CONST VOID *VendorCode, OPTIONAL
  449. IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
  450. IN UINT32 CapsuleFwVersion,
  451. OUT CHAR16 **AbortReason,
  452. OUT UINT32 *LastAttemptStatus
  453. )
  454. {
  455. EFI_STATUS Status;
  456. UINT32 Updateable;
  457. UINTN Percentage;
  458. UINTN Index;
  459. UPDATE_CONFIG_DATA *ConfigData;
  460. UINTN TotalSize;
  461. UINTN BytesWritten;
  462. Updateable = 0;
  463. Status = FmpDeviceCheckImageWithStatus (Image, ImageSize, &Updateable, LastAttemptStatus);
  464. if (EFI_ERROR (Status)) {
  465. DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Check Image failed with %r.\n", Status));
  466. return Status;
  467. }
  468. if (Updateable != IMAGE_UPDATABLE_VALID) {
  469. DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Check Image returned that the Image was not valid for update. Updatable value = 0x%X.\n", Updateable));
  470. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  471. return EFI_ABORTED;
  472. }
  473. if (Progress == NULL) {
  474. DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Invalid progress callback\n"));
  475. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  476. return EFI_INVALID_PARAMETER;
  477. }
  478. Status = Progress (15);
  479. if (EFI_ERROR (Status)) {
  480. DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));
  481. }
  482. //
  483. // Write the image to the firmware device
  484. //
  485. Progress (20);
  486. if (EFI_ERROR (Status)) {
  487. DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));
  488. }
  489. //
  490. // Simulate update with delays between progress updates
  491. //
  492. for (Percentage = 20; Percentage <= 100; Percentage++) {
  493. //
  494. // Wait 0.05 seconds
  495. //
  496. // gBS->Stall (50000);
  497. // Progress (Percentage);
  498. // if (EFI_ERROR (Status)) {
  499. // DEBUG((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Progress Callback failed with Status %r.\n", Status));
  500. // }
  501. }
  502. DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %d Images ...\n", ARRAY_SIZE (mUpdateConfigData)));
  503. if (ARRAY_SIZE (mUpdateConfigData) == 0) {
  504. DEBUG((DEBUG_INFO, "PlatformUpdate: BaseAddress - 0x%lx ImageOffset - 0x%x Length - 0x%x\n", 0, 0, ImageSize));
  505. Status = PerformFlashWriteWithProgress (
  506. PlatformFirmwareTypeSystemFirmware, // FirmwareType
  507. 0x00000000, // FlashAddress
  508. FlashAddressTypeRelativeAddress, // FlashAddressType
  509. (VOID *)(UINTN)Image, // Buffer
  510. ImageSize, // BufferLength
  511. Progress, // Progress
  512. 20, // StartPercentage
  513. 100 // EndPercentage
  514. );
  515. }
  516. //
  517. // Compute total size of update
  518. //
  519. for (Index = 0, TotalSize = 0; Index < ARRAY_SIZE (mUpdateConfigData); Index++) {
  520. TotalSize += mUpdateConfigData[Index].Length;
  521. }
  522. BytesWritten = 0;
  523. for (Index = 0, ConfigData = mUpdateConfigData; Index < ARRAY_SIZE (mUpdateConfigData); Index++, ConfigData++) {
  524. DEBUG((DEBUG_INFO, "PlatformUpdate(%d): BaseAddress - 0x%lx ImageOffset - 0x%x Length - 0x%x\n",
  525. Index,
  526. ConfigData->BaseAddress,
  527. ConfigData->ImageOffset,
  528. ConfigData->Length
  529. ));
  530. Status = PerformFlashWriteWithProgress (
  531. ConfigData->FirmwareType, // FirmwareType
  532. ConfigData->BaseAddress, // FlashAddress
  533. ConfigData->AddressType, // FlashAddressType
  534. (VOID *)((UINTN)Image + (UINTN)ConfigData->ImageOffset), // Buffer
  535. ConfigData->Length, // BufferLength
  536. Progress, // Progress
  537. 20 + (BytesWritten * 80) / TotalSize, // StartPercentage
  538. 20 + ((BytesWritten + ConfigData->Length) * 80) / TotalSize // EndPercentage
  539. );
  540. if (EFI_ERROR(Status)) {
  541. break;
  542. }
  543. BytesWritten += ConfigData->Length;
  544. }
  545. DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %r\n", Status));
  546. if (EFI_ERROR (Status)) {
  547. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  548. }
  549. return Status;
  550. }
  551. /**
  552. Updates the firmware image of the device.
  553. This function updates the hardware with the new firmware image. This function
  554. returns EFI_UNSUPPORTED if the firmware image is not updatable. If the
  555. firmware image is updatable, the function should perform the following minimal
  556. validations before proceeding to do the firmware image update.
  557. - Validate the image is a supported image for this device. The function
  558. returns EFI_ABORTED if the image is unsupported. The function can
  559. optionally provide more detailed information on why the image is not a
  560. supported image.
  561. - Validate the data from VendorCode if not null. Image validation must be
  562. performed before VendorCode data validation. VendorCode data is ignored
  563. or considered invalid if image validation failed. The function returns
  564. EFI_ABORTED if the data is invalid.
  565. VendorCode enables vendor to implement vendor-specific firmware image update
  566. policy. Null if the caller did not specify the policy or use the default
  567. policy. As an example, vendor can implement a policy to allow an option to
  568. force a firmware image update when the abort reason is due to the new firmware
  569. image version is older than the current firmware image version or bad image
  570. checksum. Sensitive operations such as those wiping the entire firmware image
  571. and render the device to be non-functional should be encoded in the image
  572. itself rather than passed with the VendorCode. AbortReason enables vendor to
  573. have the option to provide a more detailed description of the abort reason to
  574. the caller.
  575. @param[in] Image Points to the new image.
  576. @param[in] ImageSize Size of the new image in bytes.
  577. @param[in] VendorCode This enables vendor to implement vendor-specific
  578. firmware image update policy. Null indicates the
  579. caller did not specify the policy or use the
  580. default policy.
  581. @param[in] Progress A function used by the driver to report the
  582. progress of the firmware update.
  583. @param[in] CapsuleFwVersion FMP Payload Header version of the image.
  584. @param[out] AbortReason A pointer to a pointer to a null-terminated
  585. string providing more details for the aborted
  586. operation. The buffer is allocated by this
  587. function with AllocatePool(), and it is the
  588. caller's responsibility to free it with a call
  589. to FreePool().
  590. @retval EFI_SUCCESS The device was successfully updated with the
  591. new image.
  592. @retval EFI_ABORTED The operation is aborted.
  593. @retval EFI_INVALID_PARAMETER The Image was NULL.
  594. @retval EFI_UNSUPPORTED The operation is not supported.
  595. **/
  596. EFI_STATUS
  597. EFIAPI
  598. FmpDeviceSetImage (
  599. IN CONST VOID *Image,
  600. IN UINTN ImageSize,
  601. IN CONST VOID *VendorCode,
  602. IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
  603. IN UINT32 CapsuleFwVersion,
  604. OUT CHAR16 **AbortReason
  605. )
  606. {
  607. UINT32 LastAttemptStatus;
  608. return FmpDeviceSetImageWithStatus (
  609. Image,
  610. ImageSize,
  611. VendorCode,
  612. Progress,
  613. CapsuleFwVersion,
  614. AbortReason,
  615. &LastAttemptStatus
  616. );
  617. }
  618. /**
  619. Checks if a new firmware image is valid for the firmware device. This
  620. function allows firmware update operation to validate the firmware image
  621. before FmpDeviceSetImage() is called.
  622. @param[in] Image Points to a new firmware image.
  623. @param[in] ImageSize Size, in bytes, of a new firmware image.
  624. @param[out] ImageUpdatable Indicates if a new firmware image is valid for
  625. a firmware update to the firmware device. The
  626. following values from the Firmware Management
  627. Protocol are supported:
  628. IMAGE_UPDATABLE_VALID
  629. IMAGE_UPDATABLE_INVALID
  630. IMAGE_UPDATABLE_INVALID_TYPE
  631. IMAGE_UPDATABLE_INVALID_OLD
  632. IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
  633. @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt
  634. status to report back to the ESRT table in case
  635. of error. This value will only be checked when this
  636. function returns an error.
  637. The return status code must fall in the range of
  638. LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
  639. LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
  640. If the value falls outside this range, it will be converted
  641. to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
  642. @retval EFI_SUCCESS The image was successfully checked. Additional
  643. status information is returned in
  644. ImageUpdatable.
  645. @retval EFI_INVALID_PARAMETER Image is NULL.
  646. @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
  647. @retval EFI_INVALID_PARAMETER LastAttemptStatus is NULL.
  648. **/
  649. EFI_STATUS
  650. EFIAPI
  651. FmpDeviceCheckImageWithStatus (
  652. IN CONST VOID *Image,
  653. IN UINTN ImageSize,
  654. OUT UINT32 *ImageUpdatable,
  655. OUT UINT32 *LastAttemptStatus
  656. )
  657. {
  658. if (LastAttemptStatus == NULL) {
  659. DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer Parameter is NULL.\n"));
  660. return EFI_INVALID_PARAMETER;
  661. }
  662. *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
  663. if (ImageUpdatable == NULL) {
  664. DEBUG((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Parameter is NULL.\n"));
  665. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  666. return EFI_INVALID_PARAMETER;
  667. }
  668. //
  669. //Set to valid and then if any tests fail it will update this flag.
  670. //
  671. *ImageUpdatable = IMAGE_UPDATABLE_VALID;
  672. if (Image == NULL) {
  673. DEBUG((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter is NULL.\n"));
  674. //
  675. // Not sure if this is needed
  676. //
  677. *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
  678. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  679. return EFI_INVALID_PARAMETER;
  680. }
  681. //
  682. // Make sure the image size is correct
  683. //
  684. if (ImageSize != PcdGet32 (PcdBiosRomSize)) {
  685. *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
  686. *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
  687. return EFI_INVALID_PARAMETER;
  688. }
  689. return EFI_SUCCESS;
  690. }
  691. /**
  692. Checks if the firmware image is valid for the device.
  693. This function allows firmware update application to validate the firmware image without
  694. invoking the SetImage() first.
  695. @param[in] Image Points to the new image.
  696. @param[in] ImageSize Size of the new image in bytes.
  697. @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
  698. if available, additional information if the image is invalid.
  699. @retval EFI_SUCCESS The image was successfully checked.
  700. @retval EFI_INVALID_PARAMETER The Image was NULL.
  701. **/
  702. EFI_STATUS
  703. EFIAPI
  704. FmpDeviceCheckImage (
  705. IN CONST VOID *Image,
  706. IN UINTN ImageSize,
  707. OUT UINT32 *ImageUpdateable
  708. )
  709. {
  710. UINT32 LastAttemptStatus;
  711. return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdateable, &LastAttemptStatus);
  712. }
  713. /**
  714. Device firmware should trigger lock mechanism so that device fw can not be
  715. updated or tampered with. This lock mechanism is generally only cleared by a
  716. full system reset (not just sleep state/low power mode)
  717. @retval EFI_SUCCESS The device was successfully locked.
  718. @retval EFI_UNSUPPORTED The hardware device/firmware doesn't support locking
  719. **/
  720. EFI_STATUS
  721. EFIAPI
  722. FmpDeviceLock (
  723. VOID
  724. )
  725. {
  726. DEBUG ((DEBUG_INFO, "VLV2: FmpDeviceLock() for system FLASH\n"));
  727. // TODO: Add lock logic
  728. return EFI_UNSUPPORTED;
  729. }