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