]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
QuarkPlatformPkg/PlatformFlashAccessLib: Add instance for update.
[mirror_edk2.git] / QuarkPlatformPkg / Feature / Capsule / Library / PlatformFlashAccessLib / PlatformFlashAccessLibDxe.c
CommitLineData
63b9a685
JY
1/** @file\r
2 Platform Flash Access library.\r
3\r
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. 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
13**/\r
14\r
15#include <PiDxe.h>\r
16\r
17#include <Library/BaseLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/PlatformFlashAccessLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Protocol/Spi.h>\r
24\r
25//\r
26// SPI default opcode slots\r
27//\r
28#define SPI_OPCODE_JEDEC_ID_INDEX 0\r
29#define SPI_OPCODE_READ_ID_INDEX 1\r
30#define SPI_OPCODE_WRITE_S_INDEX 2\r
31#define SPI_OPCODE_WRITE_INDEX 3\r
32#define SPI_OPCODE_READ_INDEX 4\r
33#define SPI_OPCODE_ERASE_INDEX 5\r
34#define SPI_OPCODE_READ_S_INDEX 6\r
35#define SPI_OPCODE_CHIP_ERASE_INDEX 7\r
36\r
37#define SPI_ERASE_SECTOR_SIZE SIZE_4KB //This is the chipset requirement\r
38\r
39STATIC EFI_PHYSICAL_ADDRESS mInternalFdAddress;\r
40EFI_SPI_PROTOCOL *mSpiProtocol;\r
41\r
42/**\r
43 Writes specified number of bytes from the input buffer to the address\r
44\r
45 @param[in] WriteAddress The flash address to be written.\r
46 @param[in, out] NumBytes The number of bytes.\r
47 @param[in] Buffer The data buffer to be written.\r
48\r
49 @return The status of flash write.\r
50**/\r
51EFI_STATUS\r
52FlashFdWrite (\r
53 IN UINTN WriteAddress,\r
54 IN OUT UINTN *NumBytes,\r
55 IN UINT8 *Buffer\r
56 )\r
57{\r
58 EFI_STATUS Status;\r
59\r
60 Status = EFI_SUCCESS;\r
61\r
62 Status = mSpiProtocol->Execute (\r
63 mSpiProtocol,\r
64 SPI_OPCODE_WRITE_INDEX, // OpcodeIndex\r
65 0, // PrefixOpcodeIndex\r
66 TRUE, // DataCycle\r
67 TRUE, // Atomic\r
68 TRUE, // ShiftOut\r
69 WriteAddress, // Address\r
70 (UINT32) (*NumBytes), // Data Number\r
71 Buffer,\r
72 EnumSpiRegionBios\r
73 );\r
74 DEBUG((DEBUG_INFO, "FlashFdWrite - 0x%x - %r\n", (UINTN)WriteAddress, Status));\r
75\r
76 AsmWbinvd ();\r
77\r
78 return Status;\r
79}\r
80\r
81/**\r
82 Erase a certain block from address LbaWriteAddress\r
83\r
84 @param[in] WriteAddress The flash address to be erased.\r
85\r
86 @return The status of flash erase.\r
87**/\r
88EFI_STATUS\r
89FlashFdErase (\r
90 IN UINTN WriteAddress\r
91 )\r
92{\r
93 EFI_STATUS Status;\r
94\r
95 Status = mSpiProtocol->Execute (\r
96 mSpiProtocol,\r
97 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex\r
98 0, // PrefixOpcodeIndex\r
99 FALSE, // DataCycle\r
100 TRUE, // Atomic\r
101 FALSE, // ShiftOut\r
102 WriteAddress, // Address\r
103 0, // Data Number\r
104 NULL,\r
105 EnumSpiRegionBios // SPI_REGION_TYPE\r
106 );\r
107 DEBUG((DEBUG_INFO, "FlashFdErase - 0x%x - %r\n", (UINTN)WriteAddress, Status));\r
108\r
109 AsmWbinvd ();\r
110\r
111 return Status;\r
112}\r
113\r
114/**\r
115 Perform flash write opreation.\r
116\r
117 @param[in] FirmwareType The type of firmware.\r
118 @param[in] FlashAddress The address of flash device to be accessed.\r
119 @param[in] FlashAddressType The type of flash device address.\r
120 @param[in] Buffer The pointer to the data buffer.\r
121 @param[in] Length The length of data buffer in bytes.\r
122\r
123 @retval EFI_SUCCESS The operation returns successfully.\r
124 @retval EFI_WRITE_PROTECTED The flash device is read only.\r
125 @retval EFI_UNSUPPORTED The flash device access is unsupported.\r
126 @retval EFI_INVALID_PARAMETER The input parameter is not valid.\r
127**/\r
128EFI_STATUS\r
129EFIAPI\r
130PerformFlashWrite (\r
131 IN PLATFORM_FIRMWARE_TYPE FirmwareType,\r
132 IN EFI_PHYSICAL_ADDRESS FlashAddress,\r
133 IN FLASH_ADDRESS_TYPE FlashAddressType,\r
134 IN VOID *Buffer,\r
135 IN UINTN Length\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139 UINTN SectorNum;\r
140 UINTN Index;\r
141 UINTN NumBytes;\r
142\r
143 DEBUG((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));\r
144 if (FlashAddressType == FlashAddressTypeAbsoluteAddress) {\r
145 FlashAddress = FlashAddress - mInternalFdAddress;\r
146 }\r
147\r
148 //\r
149 // Erase & Write\r
150 //\r
151 SectorNum = Length / SPI_ERASE_SECTOR_SIZE;\r
152 for (Index = 0; Index < SectorNum; Index++){\r
153 if (CompareMem(\r
154 (UINT8 *)(UINTN)(FlashAddress + mInternalFdAddress) + Index * SPI_ERASE_SECTOR_SIZE,\r
155 (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE,\r
156 SPI_ERASE_SECTOR_SIZE) == 0) {\r
157 DEBUG((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));\r
158 continue;\r
159 }\r
160 DEBUG((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));\r
161\r
162 Status = FlashFdErase (\r
163 (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE\r
164 );\r
165 if (Status != EFI_SUCCESS){\r
166 break;\r
167 }\r
168 NumBytes = SPI_ERASE_SECTOR_SIZE;\r
169 Status = FlashFdWrite (\r
170 (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE,\r
171 &NumBytes,\r
172 (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE\r
173 );\r
174 if (Status != EFI_SUCCESS){\r
175 break;\r
176 }\r
177 }\r
178\r
179 return EFI_SUCCESS;\r
180}\r
181\r
182/**\r
183 Platform Flash Access Lib Constructor.\r
184\r
185 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
186 @param[in] SystemTable A pointer to the EFI System Table.\r
187\r
188 @retval EFI_SUCCESS Constructor returns successfully.\r
189**/\r
190EFI_STATUS\r
191EFIAPI\r
192PerformFlashAccessLibConstructor (\r
193 IN EFI_HANDLE ImageHandle,\r
194 IN EFI_SYSTEM_TABLE *SystemTable\r
195 )\r
196{\r
197 EFI_STATUS Status;\r
198\r
199 mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32(PcdFlashAreaBaseAddress);\r
200 DEBUG((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));\r
201\r
202 Status = gBS->LocateProtocol(&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);\r
203 ASSERT_EFI_ERROR(Status);\r
204\r
205 return EFI_SUCCESS;\r
206}\r