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/NorFlashPlatformLib.h>
13 #include <Library/UefiBootServicesTableLib.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 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 NorFlashPlatformInitialization (
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 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)) {
110 DEBUG ((DEBUG_ERROR
, "FlashNvStorage size not defined\n"));
111 return EFI_INVALID_PARAMETER
;
114 // Setup the variable store
115 FlashRegion
= FlashDevice
->DeviceBaseAddress
;
117 FlashNvStorageVariableBase
= FlashRegion
;
118 FlashRegion
+= PcdGet32 (PcdFlashNvStorageVariableSize
);
120 FlashNvStorageFtwWorkingBase
= FlashRegion
;
121 FlashRegion
+= PcdGet32 (PcdFlashNvStorageFtwWorkingSize
);
123 FlashNvStorageFtwSpareBase
= FlashRegion
;
124 FlashRegion
+= PcdGet32 (PcdFlashNvStorageFtwSpareSize
);
126 if (FlashRegion
> (FlashDevice
->DeviceBaseAddress
+ FlashDevice
->Size
)) {
127 DEBUG ((DEBUG_ERROR
, "Insufficient flash storage size\n"));
128 return EFI_OUT_OF_RESOURCES
;
132 PcdFlashNvStorageVariableBase
,
133 FlashNvStorageVariableBase
137 PcdFlashNvStorageFtwWorkingBase
,
138 FlashNvStorageFtwWorkingBase
142 PcdFlashNvStorageFtwSpareBase
,
143 FlashNvStorageFtwSpareBase
148 "PcdFlashNvStorageVariableBase = 0x%x\n",
149 FlashNvStorageVariableBase
153 "PcdFlashNvStorageVariableSize = 0x%x\n",
154 FlashNvStorageVariableSize
158 "PcdFlashNvStorageFtwWorkingBase = 0x%x\n",
159 FlashNvStorageFtwWorkingBase
163 "PcdFlashNvStorageFtwWorkingSize = 0x%x\n",
164 FlashNvStorageFtwWorkingSize
168 "PcdFlashNvStorageFtwSpareBase = 0x%x\n",
169 FlashNvStorageFtwSpareBase
173 "PcdFlashNvStorageFtwSpareSize = 0x%x\n",
174 FlashNvStorageFtwSpareSize
180 /** Return the Flash devices on the platform.
182 @param [out] NorFlashDescriptions Pointer to the Flash device description.
183 @param [out] Count Number of Flash devices.
185 @retval EFI_SUCCESS Success.
186 @retval EFI_NOT_FOUND Flash device not found.
189 NorFlashPlatformGetDevices (
190 OUT NOR_FLASH_DESCRIPTION
**NorFlashDescriptions
,
194 if (mNorFlashDeviceCount
> 0) {
195 *NorFlashDescriptions
= mNorFlashDevices
;
196 *Count
= mNorFlashDeviceCount
;
199 return EFI_NOT_FOUND
;
202 /** Entrypoint for NorFlashPlatformLib.
204 @param [in] ImageHandle The handle to the image.
205 @param [in] SystemTable Pointer to the System Table.
207 @retval EFI_SUCCESS Success.
208 @retval EFI_INVALID_PARAMETER A parameter is invalid.
209 @retval EFI_NOT_FOUND Flash device not found.
213 NorFlashPlatformLibConstructor (
214 IN EFI_HANDLE ImageHandle
,
215 IN EFI_SYSTEM_TABLE
* SystemTable
220 EFI_STATUS FindNodeStatus
;
225 UINTN UefiVarStoreIndex
;
229 if (mNorFlashDeviceCount
!= 0) {
233 Status
= gBS
->LocateProtocol (
234 &gFdtClientProtocolGuid
,
238 ASSERT_EFI_ERROR (Status
);
240 UefiVarStoreIndex
= MAX_UINTN
;
241 for (FindNodeStatus
= mFdtClient
->FindCompatibleNode (
246 !EFI_ERROR (FindNodeStatus
) &&
247 (mNorFlashDeviceCount
< MAX_FLASH_DEVICES
);
248 FindNodeStatus
= mFdtClient
->FindNextCompatibleNode (
254 Status
= mFdtClient
->GetNodeProperty (
258 (CONST VOID
**)&Label
,
261 if (EFI_ERROR (Status
)) {
264 "%a: GetNodeProperty ('label') failed (Status == %r)\n",
268 } else if (AsciiStrCmp (Label
, LABEL_UEFI_VAR_STORE
) == 0) {
269 UefiVarStoreIndex
= mNorFlashDeviceCount
;
270 mUefiVarStoreNode
= Node
;
273 Status
= mFdtClient
->GetNodeProperty (
280 if (EFI_ERROR (Status
)) {
281 DEBUG ((DEBUG_ERROR
, "%a: GetNodeProperty () failed (Status == %r)\n",
282 __FUNCTION__
, Status
));
286 ASSERT ((PropSize
% (4 * sizeof (UINT32
))) == 0);
288 while ((PropSize
>= (4 * sizeof (UINT32
))) &&
289 (mNorFlashDeviceCount
< MAX_FLASH_DEVICES
)) {
290 Base
= SwapBytes64 (ReadUnaligned64 ((VOID
*)&Reg
[0]));
291 Size
= SwapBytes64 (ReadUnaligned64 ((VOID
*)&Reg
[2]));
294 PropSize
-= 4 * sizeof (UINT32
);
297 // Disregard any flash devices that overlap with the primary FV.
298 // The firmware is not updatable from inside the guest anyway.
300 if ((PcdGet64 (PcdFvBaseAddress
) + PcdGet32 (PcdFvSize
) > Base
) &&
301 (Base
+ Size
) > PcdGet64 (PcdFvBaseAddress
)) {
307 "NOR%d : Base = 0x%lx, Size = 0x%lx\n",
308 mNorFlashDeviceCount
,
313 mNorFlashDevices
[mNorFlashDeviceCount
].DeviceBaseAddress
= (UINTN
)Base
;
314 mNorFlashDevices
[mNorFlashDeviceCount
].RegionBaseAddress
= (UINTN
)Base
;
315 mNorFlashDevices
[mNorFlashDeviceCount
].Size
= (UINTN
)Size
;
316 mNorFlashDevices
[mNorFlashDeviceCount
].BlockSize
= KVMTOOL_NOR_BLOCK_SIZE
;
317 mNorFlashDeviceCount
++;
321 // Setup the variable store in the last device
322 if (mNorFlashDeviceCount
> 0) {
323 if (UefiVarStoreIndex
== MAX_UINTN
) {
324 // We did not find a label matching the UEFI Variable store. Default to
325 // using the last cfi-flash device as the variable store.
326 UefiVarStoreIndex
= mNorFlashDeviceCount
- 1;
327 mUefiVarStoreNode
= Node
;
329 if (mNorFlashDevices
[UefiVarStoreIndex
].DeviceBaseAddress
!= 0) {
330 return SetupVariableStore (&mNorFlashDevices
[UefiVarStoreIndex
]);
334 return EFI_NOT_FOUND
;