]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c
Vlv2TbltDevicePkg: Display logo on BOOT_ON_FLASH_UPDATE
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / FlashDeviceLib / FlashDeviceLib.c
CommitLineData
3cbfba02
DW
1/** @file\r
2\r
7a0a32f1
JY
3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
4\r
5 This program and the accompanying materials are licensed and made available under\r
6 the terms and conditions of the BSD License that accompanies this distribution.\r
7 The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
3cbfba02
DW
13\r
14\r
15**/\r
16\r
17#include <PiDxe.h>\r
18\r
19#include <Library/FlashDeviceLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/BaseLib.h>\r
3cbfba02 22#include <Library/BaseMemoryLib.h>\r
3cbfba02 23#include <Guid/EventGroup.h>\r
7a0a32f1 24#include <Library/SpiFlash.H>\r
3cbfba02 25\r
7a0a32f1
JY
26#define FLASH_SIZE 0x400000\r
27\r
28#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1)\r
3cbfba02
DW
29UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS;\r
30\r
31EFI_SPI_PROTOCOL *mSpiProtocol = NULL;\r
32\r
33EFI_STATUS\r
34SpiFlashErase (\r
35 UINT8 *BaseAddress,\r
36 UINTN NumBytes\r
37 )\r
38{\r
39 EFI_STATUS Status = EFI_SUCCESS;\r
40 UINT32 SectorSize;\r
41 UINT32 SpiAddress;\r
42\r
43 SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase;\r
44 SectorSize = SECTOR_SIZE_4KB;\r
45 while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) {\r
46 Status = mSpiProtocol->Execute (\r
47 mSpiProtocol,\r
48 SPI_SERASE,\r
49 SPI_WREN,\r
50 FALSE,\r
51 TRUE,\r
52 FALSE,\r
53 (UINT32) SpiAddress,\r
54 0,\r
55 NULL,\r
56 EnumSpiRegionBios\r
57 );\r
58 if (EFI_ERROR (Status)) {\r
59 break;\r
60 }\r
61 SpiAddress += SectorSize;\r
62 NumBytes -= SectorSize;\r
63 }\r
64\r
65 return Status;\r
66}\r
67\r
68\r
69EFI_STATUS\r
70SpiFlashBlockErase (\r
71 UINT8 *BaseAddress,\r
72 UINTN NumBytes\r
73 )\r
74{\r
75 EFI_STATUS Status = EFI_SUCCESS;\r
76 UINT32 SectorSize;\r
77 UINT32 SpiAddress;\r
78\r
79 SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase;\r
80 SectorSize = SECTOR_SIZE_64KB;\r
81 while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) {\r
82 Status = mSpiProtocol->Execute (\r
83 mSpiProtocol,\r
84 SPI_BERASE,\r
85 SPI_WREN,\r
86 FALSE,\r
87 TRUE,\r
88 FALSE,\r
89 (UINT32) SpiAddress,\r
90 0,\r
91 NULL,\r
92 EnumSpiRegionBios\r
93 );\r
94 if (EFI_ERROR (Status)) {\r
95 break;\r
96 }\r
97 SpiAddress += SectorSize;\r
98 NumBytes -= SectorSize;\r
99 }\r
100\r
101 return Status;\r
102}\r
103\r
104\r
105static\r
106EFI_STATUS\r
107SpiFlashWrite (\r
108 UINT8 *DstBufferPtr,\r
109 UINT8 *Byte,\r
110 IN UINTN Length\r
111 )\r
112{\r
113 EFI_STATUS Status;\r
114 UINT32 NumBytes = (UINT32)Length;\r
115 UINT8* pBuf8 = Byte;\r
116 UINT32 SpiAddress;\r
117\r
118 SpiAddress = (UINT32)(UINTN)(DstBufferPtr) - (UINT32)FlashDeviceBase;\r
119 Status = mSpiProtocol->Execute (\r
120 mSpiProtocol,\r
121 SPI_PROG,\r
122 SPI_WREN,\r
123 TRUE,\r
124 TRUE,\r
125 TRUE,\r
126 (UINT32)SpiAddress,\r
127 NumBytes,\r
128 pBuf8,\r
129 EnumSpiRegionBios\r
130 );\r
131 return Status;\r
132}\r
133\r
134/**\r
135 Read the Serial Flash Status Registers.\r
136\r
137 @param SpiStatus Pointer to a caller-allocated UINT8. On successful return, it contains the\r
138 status data read from the Serial Flash Status Register.\r
139\r
140\r
141 @retval EFI_SUCCESS Operation success, status is returned in SpiStatus.\r
142 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and the operation failed.\r
143\r
144**/\r
145EFI_STATUS\r
146ReadStatusRegister (\r
147 UINT8 *SpiStatus\r
148 )\r
149{\r
150 EFI_STATUS Status;\r
151\r
152 Status = mSpiProtocol->Execute (\r
153 mSpiProtocol,\r
154 SPI_RDSR,\r
155 SPI_WREN,\r
156 TRUE,\r
157 FALSE,\r
158 FALSE,\r
159 0,\r
160 1,\r
161 SpiStatus,\r
162 EnumSpiRegionBios\r
163 );\r
164 return Status;\r
165}\r
166\r
167EFI_STATUS\r
168SpiFlashLock (\r
169 IN UINT8 *BaseAddress,\r
170 IN UINTN NumBytes,\r
171 IN BOOLEAN Lock\r
172 )\r
173{\r
174 EFI_STATUS Status;\r
175 UINT8 SpiData;\r
176 UINT8 SpiStatus;\r
177\r
178 if (Lock) {\r
179 SpiData = SF_SR_WPE;\r
180 } else {\r
181 SpiData = 0;\r
182 }\r
183\r
184 //\r
185 // Always disable block protection to workaround tool issue.\r
186 // Feature may be re-enabled in a future bios.\r
187 //\r
188 SpiData = 0;\r
189 Status = mSpiProtocol->Execute (\r
190 mSpiProtocol,\r
191 SPI_WRSR,\r
192 SPI_EWSR,\r
193 TRUE,\r
194 TRUE,\r
195 TRUE,\r
196 0,\r
197 1,\r
198 &SpiData,\r
199 EnumSpiRegionBios\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
202 return Status;\r
203 }\r
204\r
205 Status = ReadStatusRegister (&SpiStatus);\r
206 if (EFI_ERROR (Status)) {\r
207 return Status;\r
208 }\r
209\r
210 if ((SpiStatus & SpiData) != SpiData) {\r
211 Status = EFI_DEVICE_ERROR;\r
212 }\r
213\r
214 return Status;\r
215}\r
216\r
217\r
218/**\r
219 Read NumBytes bytes of data from the address specified by\r
220 PAddress into Buffer.\r
221\r
222 @param[in] PAddress The starting physical address of the read.\r
223 @param[in,out] NumBytes On input, the number of bytes to read. On output, the number\r
224 of bytes actually read.\r
225 @param[out] Buffer The destination data buffer for the read.\r
226\r
227 @retval EFI_SUCCESS. Opertion is successful.\r
228 @retval EFI_DEVICE_ERROR If there is any device errors.\r
229\r
230**/\r
231EFI_STATUS\r
232EFIAPI\r
233LibFvbFlashDeviceRead (\r
234 IN UINTN PAddress,\r
235 IN OUT UINTN *NumBytes,\r
236 OUT UINT8 *Buffer\r
237 )\r
238{\r
239 CopyMem(Buffer, (VOID*)PAddress, *NumBytes);\r
240 return EFI_SUCCESS;\r
241}\r
242\r
243\r
244/**\r
245 Write NumBytes bytes of data from Buffer to the address specified by\r
246 PAddresss.\r
247\r
248 @param[in] PAddress The starting physical address of the write.\r
249 @param[in,out] NumBytes On input, the number of bytes to write. On output,\r
250 the actual number of bytes written.\r
251 @param[in] Buffer The source data buffer for the write.\r
252\r
253 @retval EFI_SUCCESS. Opertion is successful.\r
254 @retval EFI_DEVICE_ERROR If there is any device errors.\r
255\r
256**/\r
257EFI_STATUS\r
258EFIAPI\r
259LibFvbFlashDeviceWrite (\r
260 IN UINTN PAddress,\r
261 IN OUT UINTN *NumBytes,\r
262 IN UINT8 *Buffer\r
263 )\r
264{\r
265EFI_STATUS Status;\r
266 Status = SpiFlashWrite((UINT8 *)PAddress, Buffer, *NumBytes);\r
267 return Status;\r
268}\r
269\r
270\r
271/**\r
272 Erase the block staring at PAddress.\r
273\r
274 @param[in] PAddress The starting physical address of the block to be erased.\r
275 This library assume that caller garantee that the PAddress\r
276 is at the starting address of this block.\r
277 @param[in] LbaLength The length of the logical block to be erased.\r
278\r
279 @retval EFI_SUCCESS. Opertion is successful.\r
280 @retval EFI_DEVICE_ERROR If there is any device errors.\r
281\r
282**/\r
283EFI_STATUS\r
284EFIAPI\r
285LibFvbFlashDeviceBlockErase (\r
286 IN UINTN PAddress,\r
287 IN UINTN LbaLength\r
288 )\r
289{\r
290 EFI_STATUS Status;\r
291 Status = SpiFlashBlockErase((UINT8 *)PAddress, LbaLength);\r
292\r
293 return Status;\r
294}\r
295\r
296\r
297/**\r
298 Lock or unlock the block staring at PAddress.\r
299\r
300 @param[in] PAddress The starting physical address of region to be (un)locked.\r
301 @param[in] LbaLength The length of the logical block to be erased.\r
302 @param[in] Lock TRUE to lock. FALSE to unlock.\r
303\r
304 @retval EFI_SUCCESS. Opertion is successful.\r
305 @retval EFI_DEVICE_ERROR If there is any device errors.\r
306\r
307**/\r
308EFI_STATUS\r
309EFIAPI\r
310LibFvbFlashDeviceBlockLock (\r
311 IN UINTN PAddress,\r
312 IN UINTN LbaLength,\r
313 IN BOOLEAN Lock\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317\r
318 Status = SpiFlashLock((UINT8*)PAddress, LbaLength, Lock);\r
319 return Status;\r
320}\r
321\r