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