2 An instance of the NorFlashPlatformLib for Kvmtool platform.
4 Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/UefiBootServicesTableLib.h>
13 #include <Library/VirtNorFlashPlatformLib.h>
14 #include <Protocol/FdtClient.h>
16 /** Macro defining the NOR block size configured in Kvmtool.
18 #define KVMTOOL_NOR_BLOCK_SIZE SIZE_64KB
20 /** Macro defining the maximum number of Flash devices.
22 #define MAX_FLASH_DEVICES 4
24 /** Macro defining the cfi-flash label describing the UEFI variable store.
26 #define LABEL_UEFI_VAR_STORE "System-firmware"
28 STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices
[MAX_FLASH_DEVICES
];
29 STATIC UINTN mNorFlashDeviceCount
= 0;
30 STATIC INT32 mUefiVarStoreNode
= MAX_INT32
;
31 STATIC FDT_CLIENT_PROTOCOL
*mFdtClient
;
33 /** This function performs platform specific actions to initialise
34 the NOR flash, if required.
36 @retval EFI_SUCCESS Success.
39 VirtNorFlashPlatformInitialization (
45 DEBUG ((DEBUG_INFO
, "NorFlashPlatformInitialization\n"));
47 if ((mNorFlashDeviceCount
> 0) && (mUefiVarStoreNode
!= MAX_INT32
)) {
49 // UEFI takes ownership of the cfi-flash hardware, and exposes its
50 // functionality through the UEFI Runtime Variable Service. This means we
51 // need to disable it in the device tree to prevent the OS from attaching
52 // its device driver as well.
53 // Note: This library is loaded twice. First by FaultTolerantWriteDxe to
54 // setup the PcdFlashNvStorageFtw* and later by NorFlashDxe to provide the
55 // NorFlashPlatformLib interfaces. If the node is disabled when the library
56 // is first loaded, then during the subsequent loading of the library the
57 // call to FindNextCompatibleNode() from the library constructor skips the
58 // FDT node used for UEFI storage variable. Due to this we cannot setup the
59 // NOR flash device description i.e. mNorFlashDevices[].
60 // Since NorFlashPlatformInitialization() is called only by NorFlashDxe,
61 // we know it is safe to disable the node here.
63 Status
= mFdtClient
->SetNodeProperty (
70 if (EFI_ERROR (Status
)) {
71 DEBUG ((DEBUG_WARN
, "Failed to set cfi-flash status to 'disabled'\n"));
74 Status
= EFI_NOT_FOUND
;
75 DEBUG ((DEBUG_ERROR
, "Flash device for UEFI variable storage not found\n"));
81 /** Initialise Non volatile Flash storage variables.
83 @param [in] FlashDevice Pointer to the NOR Flash device.
85 @retval EFI_SUCCESS Success.
86 @retval EFI_INVALID_PARAMETER A parameter is invalid.
87 @retval EFI_OUT_OF_RESOURCES Insufficient flash storage space.
92 IN VIRT_NOR_FLASH_DESCRIPTION
*FlashDevice
96 UINTN FlashNvStorageVariableBase
;
97 UINTN FlashNvStorageFtwWorkingBase
;
98 UINTN FlashNvStorageFtwSpareBase
;
99 UINTN FlashNvStorageVariableSize
;
100 UINTN FlashNvStorageFtwWorkingSize
;
101 UINTN FlashNvStorageFtwSpareSize
;
103 FlashNvStorageVariableSize
= PcdGet32 (PcdFlashNvStorageVariableSize
);
104 FlashNvStorageFtwWorkingSize
= PcdGet32 (PcdFlashNvStorageFtwWorkingSize
);
105 FlashNvStorageFtwSpareSize
= PcdGet32 (PcdFlashNvStorageFtwSpareSize
);
107 if ((FlashNvStorageVariableSize
== 0) ||
108 (FlashNvStorageFtwWorkingSize
== 0) ||
109 (FlashNvStorageFtwSpareSize
== 0))
111 DEBUG ((DEBUG_ERROR
, "FlashNvStorage size not defined\n"));
112 return EFI_INVALID_PARAMETER
;
115 // Setup the variable store
116 FlashRegion
= FlashDevice
->DeviceBaseAddress
;
118 FlashNvStorageVariableBase
= FlashRegion
;
119 FlashRegion
+= PcdGet32 (PcdFlashNvStorageVariableSize
);
121 FlashNvStorageFtwWorkingBase
= FlashRegion
;
122 FlashRegion
+= PcdGet32 (PcdFlashNvStorageFtwWorkingSize
);
124 FlashNvStorageFtwSpareBase
= FlashRegion
;
125 FlashRegion
+= PcdGet32 (PcdFlashNvStorageFtwSpareSize
);
127 if (FlashRegion
> (FlashDevice
->DeviceBaseAddress
+ FlashDevice
->Size
)) {
128 DEBUG ((DEBUG_ERROR
, "Insufficient flash storage size\n"));
129 return EFI_OUT_OF_RESOURCES
;
133 PcdFlashNvStorageVariableBase
,
134 FlashNvStorageVariableBase
138 PcdFlashNvStorageFtwWorkingBase
,
139 FlashNvStorageFtwWorkingBase
143 PcdFlashNvStorageFtwSpareBase
,
144 FlashNvStorageFtwSpareBase
149 "PcdFlashNvStorageVariableBase = 0x%x\n",
150 FlashNvStorageVariableBase
154 "PcdFlashNvStorageVariableSize = 0x%x\n",
155 FlashNvStorageVariableSize
159 "PcdFlashNvStorageFtwWorkingBase = 0x%x\n",
160 FlashNvStorageFtwWorkingBase
164 "PcdFlashNvStorageFtwWorkingSize = 0x%x\n",
165 FlashNvStorageFtwWorkingSize
169 "PcdFlashNvStorageFtwSpareBase = 0x%x\n",
170 FlashNvStorageFtwSpareBase
174 "PcdFlashNvStorageFtwSpareSize = 0x%x\n",
175 FlashNvStorageFtwSpareSize
181 /** Return the Flash devices on the platform.
183 @param [out] NorFlashDescriptions Pointer to the Flash device description.
184 @param [out] Count Number of Flash devices.
186 @retval EFI_SUCCESS Success.
187 @retval EFI_NOT_FOUND Flash device not found.
190 VirtNorFlashPlatformGetDevices (
191 OUT VIRT_NOR_FLASH_DESCRIPTION
**NorFlashDescriptions
,
195 if (mNorFlashDeviceCount
> 0) {
196 *NorFlashDescriptions
= mNorFlashDevices
;
197 *Count
= mNorFlashDeviceCount
;
201 return EFI_NOT_FOUND
;
204 /** Entrypoint for NorFlashPlatformLib.
206 @param [in] ImageHandle The handle to the image.
207 @param [in] SystemTable Pointer to the System Table.
209 @retval EFI_SUCCESS Success.
210 @retval EFI_INVALID_PARAMETER A parameter is invalid.
211 @retval EFI_NOT_FOUND Flash device not found.
215 NorFlashPlatformLibConstructor (
216 IN EFI_HANDLE ImageHandle
,
217 IN EFI_SYSTEM_TABLE
*SystemTable
222 EFI_STATUS FindNodeStatus
;
227 UINTN UefiVarStoreIndex
;
231 if (mNorFlashDeviceCount
!= 0) {
235 Status
= gBS
->LocateProtocol (
236 &gFdtClientProtocolGuid
,
240 ASSERT_EFI_ERROR (Status
);
242 UefiVarStoreIndex
= MAX_UINTN
;
243 for (FindNodeStatus
= mFdtClient
->FindCompatibleNode (
248 !EFI_ERROR (FindNodeStatus
) &&
249 (mNorFlashDeviceCount
< MAX_FLASH_DEVICES
);
250 FindNodeStatus
= mFdtClient
->FindNextCompatibleNode (
257 Status
= mFdtClient
->GetNodeProperty (
261 (CONST VOID
**)&Label
,
264 if (EFI_ERROR (Status
)) {
267 "%a: GetNodeProperty ('label') failed (Status == %r)\n",
271 } else if (AsciiStrCmp (Label
, LABEL_UEFI_VAR_STORE
) == 0) {
272 UefiVarStoreIndex
= mNorFlashDeviceCount
;
273 mUefiVarStoreNode
= Node
;
276 Status
= mFdtClient
->GetNodeProperty (
283 if (EFI_ERROR (Status
)) {
286 "%a: GetNodeProperty () failed (Status == %r)\n",
293 ASSERT ((PropSize
% (4 * sizeof (UINT32
))) == 0);
295 while ((PropSize
>= (4 * sizeof (UINT32
))) &&
296 (mNorFlashDeviceCount
< MAX_FLASH_DEVICES
))
298 Base
= SwapBytes64 (ReadUnaligned64 ((VOID
*)&Reg
[0]));
299 Size
= SwapBytes64 (ReadUnaligned64 ((VOID
*)&Reg
[2]));
302 PropSize
-= 4 * sizeof (UINT32
);
305 // Disregard any flash devices that overlap with the primary FV.
306 // The firmware is not updatable from inside the guest anyway.
308 if ((PcdGet64 (PcdFvBaseAddress
) + PcdGet32 (PcdFvSize
) > Base
) &&
309 ((Base
+ Size
) > PcdGet64 (PcdFvBaseAddress
)))
316 "NOR%d : Base = 0x%lx, Size = 0x%lx\n",
317 mNorFlashDeviceCount
,
322 mNorFlashDevices
[mNorFlashDeviceCount
].DeviceBaseAddress
= (UINTN
)Base
;
323 mNorFlashDevices
[mNorFlashDeviceCount
].RegionBaseAddress
= (UINTN
)Base
;
324 mNorFlashDevices
[mNorFlashDeviceCount
].Size
= (UINTN
)Size
;
325 mNorFlashDevices
[mNorFlashDeviceCount
].BlockSize
= KVMTOOL_NOR_BLOCK_SIZE
;
326 mNorFlashDeviceCount
++;
330 // Setup the variable store in the last device
331 if (mNorFlashDeviceCount
> 0) {
332 if (UefiVarStoreIndex
== MAX_UINTN
) {
333 // We did not find a label matching the UEFI Variable store. Default to
334 // using the last cfi-flash device as the variable store.
335 UefiVarStoreIndex
= mNorFlashDeviceCount
- 1;
336 mUefiVarStoreNode
= Node
;
339 if (mNorFlashDevices
[UefiVarStoreIndex
].DeviceBaseAddress
!= 0) {
340 return SetupVariableStore (&mNorFlashDevices
[UefiVarStoreIndex
]);
344 return EFI_NOT_FOUND
;