TianoCore EDK2 master
Loading...
Searching...
No Matches
FdtNorFlashQemuLib.c
Go to the documentation of this file.
1
10#include <Library/BaseLib.h>
11#include <Library/DebugLib.h>
14
15#include <Protocol/FdtClient.h>
16#include <stdbool.h>
17
18#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
19#define MAX_FLASH_BANKS 4
20
21STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
22
25 VOID
26 )
27{
28 return EFI_SUCCESS;
29}
30
33 OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
34 OUT UINT32 *Count
35 )
36{
37 FDT_CLIENT_PROTOCOL *FdtClient;
38 INT32 Node;
39 EFI_STATUS Status;
40 EFI_STATUS FindNodeStatus;
41 CONST UINT32 *Reg;
42 UINT32 PropSize;
43 UINT32 Num;
44 UINT64 Base;
45 UINT64 Size;
46 BOOLEAN Found;
47
48 Status = gBS->LocateProtocol (
49 &gFdtClientProtocolGuid,
50 NULL,
51 (VOID **)&FdtClient
52 );
53 ASSERT_EFI_ERROR (Status);
54
55 Num = 0;
56 Found = FALSE;
57 for (FindNodeStatus = FdtClient->FindCompatibleNode (
58 FdtClient,
59 "cfi-flash",
60 &Node
61 );
62 !EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS;
63 FindNodeStatus = FdtClient->FindNextCompatibleNode (
64 FdtClient,
65 "cfi-flash",
66 Node,
67 &Node
68 ))
69 {
70 Status = FdtClient->GetNodeProperty (
71 FdtClient,
72 Node,
73 "reg",
74 (CONST VOID **)&Reg,
75 &PropSize
76 );
77 if (EFI_ERROR (Status)) {
78 DEBUG ((
79 DEBUG_ERROR,
80 "%a: GetNodeProperty () failed (Status == %r)\n",
81 __func__,
82 Status
83 ));
84 continue;
85 }
86
87 ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
88
89 while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) {
90 Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
91 Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
92 Reg += 4;
93
94 PropSize -= 4 * sizeof (UINT32);
95
96 //
97 // Disregard any flash devices that overlap with the primary FV.
98 // The firmware is not updatable from inside the guest anyway.
99 //
100 if ((PcdGet32 (PcdOvmfFdBaseAddress) + PcdGet32 (PcdOvmfFirmwareFdSize) > Base) &&
101 ((Base + Size) > PcdGet32 (PcdOvmfFdBaseAddress)))
102 {
103 continue;
104 }
105
106 mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
107 mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
108 mNorFlashDevices[Num].Size = (UINTN)Size;
109 mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
110 Num++;
111 if (!Found) {
112 //
113 // By default, the second available flash is stored as a non-volatile variable.
114 //
115 Status = PcdSet32S (PcdFlashNvStorageVariableBase, Base);
116 ASSERT_EFI_ERROR (Status);
117
118 //
119 // The Base is the value of PcdFlashNvStorageVariableBase,
120 // PcdFlashNvStorageFtwWorkingBase can be got by
121 // PcdFlashNvStorageVariableBase + PcdFlashNvStorageVariableSize
122 //
123 Base += PcdGet32 (PcdFlashNvStorageVariableSize);
124 Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, Base);
125 ASSERT_EFI_ERROR (Status);
126
127 //
128 // Now, the Base is the value of PcdFlashNvStorageFtwWorkingBase,
129 // PcdFlashNvStorageFtwSpareBase can be got by
130 // PcdFlashNvStorageFtwWorkingBase + PcdFlashNvStorageFtwWorkingSize.
131 //
132 Base += PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
133 Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, Base);
134 ASSERT_EFI_ERROR (Status);
135 Found = TRUE;
136 }
137 }
138
139 //
140 // UEFI takes ownership of the NOR flash, and exposes its functionality
141 // through the UEFI Runtime Services GetVariable, SetVariable, etc. This
142 // means we need to disable it in the device tree to prevent the OS from
143 // attaching its device driver as well.
144 // Note that this also hides other flash banks, but the only other flash
145 // bank we expect to encounter is the one that carries the UEFI executable
146 // code, which is not intended to be guest updatable, and is usually backed
147 // in a readonly manner by QEMU anyway.
148 //
149 Status = FdtClient->SetNodeProperty (
150 FdtClient,
151 Node,
152 "status",
153 "disabled",
154 sizeof ("disabled")
155 );
156 if (EFI_ERROR (Status)) {
157 DEBUG ((DEBUG_WARN, "Failed to set NOR flash status to 'disabled'\n"));
158 }
159 }
160
161 *NorFlashDescriptions = mNorFlashDevices;
162 *Count = Num;
163
164 return EFI_SUCCESS;
165}
UINT64 UINTN
UINT64 EFIAPI ReadUnaligned64(IN CONST UINT64 *Buffer)
Definition: Unaligned.c:204
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
EFI_STATUS VirtNorFlashPlatformInitialization(VOID)
EFI_STATUS VirtNorFlashPlatformGetDevices(OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions, OUT UINT32 *Count)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdSet32S(TokenName, Value)
Definition: PcdLib.h:497
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS