1 /** @file
2 Wrap EFI_SPI_PROTOCOL to provide some library level interfaces
3 for module use.
4
5 Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 **/
9
10 #include <Library/SpiFlashCommonLib.h>
11 #include <Library/IoLib.h>
12 #include <Library/PciLib.h>
13 #include <Protocol/Spi.h>
14
15
16 EFI_SPI_PROTOCOL *mSpiProtocol;
17
18 //
19 // FlashAreaBaseAddress and Size for boottime and runtime usage.
20 //
21 UINTN mFlashAreaBaseAddress = 0;
22 UINTN mFlashAreaSize = 0;
23
24 /**
25 Enable block protection on the Serial Flash device.
26
27 @retval EFI_SUCCESS Opertion is successful.
28 @retval EFI_DEVICE_ERROR If there is any device errors.
29
30 **/
31 EFI_STATUS
32 EFIAPI
SpiFlashLock(VOID)33 SpiFlashLock (
34 VOID
35 )
36 {
37 return EFI_SUCCESS;
38 }
39
40 /**
41 Read NumBytes bytes of data from the address specified by
42 PAddress into Buffer.
43
44 @param[in] Address The starting physical address of the read.
45 @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
46 of bytes actually read.
47 @param[out] Buffer The destination data buffer for the read.
48
49 @retval EFI_SUCCESS Opertion is successful.
50 @retval EFI_DEVICE_ERROR If there is any device errors.
51
52 **/
53 EFI_STATUS
54 EFIAPI
SpiFlashRead(IN UINTN Address,IN OUT UINT32 * NumBytes,OUT UINT8 * Buffer)55 SpiFlashRead (
56 IN UINTN Address,
57 IN OUT UINT32 *NumBytes,
58 OUT UINT8 *Buffer
59 )
60 {
61 ASSERT ((NumBytes != NULL) && (Buffer != NULL));
62 if ((NumBytes == NULL) || (Buffer == NULL)) {
63 return EFI_INVALID_PARAMETER;
64 }
65
66 //
67 // This function is implemented specifically for those platforms
68 // at which the SPI device is memory mapped for read. So this
69 // function just do a memory copy for Spi Flash Read.
70 //
71 CopyMem (Buffer, (VOID *) Address, *NumBytes);
72
73 return EFI_SUCCESS;
74 }
75
76 /**
77 Write NumBytes bytes of data from Buffer to the address specified by
78 PAddresss.
79
80 @param[in] Address The starting physical address of the write.
81 @param[in,out] NumBytes On input, the number of bytes to write. On output,
82 the actual number of bytes written.
83 @param[in] Buffer The source data buffer for the write.
84
85 @retval EFI_SUCCESS Opertion is successful.
86 @retval EFI_DEVICE_ERROR If there is any device errors.
87
88 **/
89 EFI_STATUS
90 EFIAPI
SpiFlashWrite(IN UINTN Address,IN OUT UINT32 * NumBytes,IN UINT8 * Buffer)91 SpiFlashWrite (
92 IN UINTN Address,
93 IN OUT UINT32 *NumBytes,
94 IN UINT8 *Buffer
95 )
96 {
97 EFI_STATUS Status;
98 UINTN Offset;
99 UINT32 Length;
100 UINT32 RemainingBytes;
101
102 ASSERT ((NumBytes != NULL) && (Buffer != NULL));
103 if ((NumBytes == NULL) || (Buffer == NULL)) {
104 return EFI_INVALID_PARAMETER;
105 }
106
107 ASSERT (Address >= mFlashAreaBaseAddress);
108
109 Offset = Address - mFlashAreaBaseAddress;
110
111 ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
112
113 Status = EFI_SUCCESS;
114 RemainingBytes = *NumBytes;
115
116
117 while (RemainingBytes > 0) {
118 if (RemainingBytes > SECTOR_SIZE_4KB) {
119 Length = SECTOR_SIZE_4KB;
120 } else {
121 Length = RemainingBytes;
122 }
123 Status = mSpiProtocol->FlashWrite (
124 mSpiProtocol,
125 FlashRegionBios,
126 (UINT32) Offset,
127 Length,
128 Buffer
129 );
130 if (EFI_ERROR (Status)) {
131 break;
132 }
133 RemainingBytes -= Length;
134 Offset += Length;
135 Buffer += Length;
136 }
137
138 //
139 // Actual number of bytes written
140 //
141 *NumBytes -= RemainingBytes;
142
143 return Status;
144 }
145
146 /**
147 Erase the block starting at Address.
148
149 @param[in] Address The starting physical address of the block to be erased.
150 This library assume that caller garantee that the PAddress
151 is at the starting address of this block.
152 @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
153 On output, the actual number of bytes erased.
154
155 @retval EFI_SUCCESS. Opertion is successful.
156 @retval EFI_DEVICE_ERROR If there is any device errors.
157
158 **/
159 EFI_STATUS
160 EFIAPI
SpiFlashBlockErase(IN UINTN Address,IN UINTN * NumBytes)161 SpiFlashBlockErase (
162 IN UINTN Address,
163 IN UINTN *NumBytes
164 )
165 {
166 EFI_STATUS Status;
167 UINTN Offset;
168 UINTN RemainingBytes;
169
170 ASSERT (NumBytes != NULL);
171 if (NumBytes == NULL) {
172 return EFI_INVALID_PARAMETER;
173 }
174
175 ASSERT (Address >= mFlashAreaBaseAddress);
176
177 Offset = Address - mFlashAreaBaseAddress;
178
179 ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0);
180 ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
181
182 Status = EFI_SUCCESS;
183 RemainingBytes = *NumBytes;
184
185
186 Status = mSpiProtocol->FlashErase (
187 mSpiProtocol,
188 FlashRegionBios,
189 (UINT32) Offset,
190 (UINT32) RemainingBytes
191 );
192 return Status;
193 }
194
195