1 /** @file
2 *
3 *  Copyright (c) 2017 Marvell International Ltd.
4 *
5 *  SPDX-License-Identifier: BSD-2-Clause-Patent
6 *
7 **/
8 
9 #include <PiDxe.h>
10 
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/DxeServicesLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/NorFlashInfoLib.h>
17 
18 STATIC CONST NOR_FLASH_INFO NorFlashIds[] = {
19   /* ATMEL */
20   {L"at45db011d",     {0x1f, 0x22, 0x00}, 3, 256, 64 * 1024,     4, NOR_FLASH_ERASE_4K},
21   {L"at45db021d",     {0x1f, 0x23, 0x00}, 3, 256, 64 * 1024,     8, NOR_FLASH_ERASE_4K},
22   {L"at45db041d",     {0x1f, 0x24, 0x00}, 3, 256, 64 * 1024,     8, NOR_FLASH_ERASE_4K},
23   {L"at45db081d",     {0x1f, 0x25, 0x00}, 3, 256, 64 * 1024,    16, NOR_FLASH_ERASE_4K},
24   {L"at45db161d",     {0x1f, 0x26, 0x00}, 3, 256, 64 * 1024,    32, NOR_FLASH_ERASE_4K},
25   {L"at45db321d",     {0x1f, 0x27, 0x00}, 3, 256, 64 * 1024,    64, NOR_FLASH_ERASE_4K},
26   {L"at45db641d",     {0x1f, 0x28, 0x00}, 3, 256, 64 * 1024,   128, NOR_FLASH_ERASE_4K},
27   {L"at25df321a",     {0x1f, 0x47, 0x01}, 3, 256, 64 * 1024,    64, NOR_FLASH_ERASE_4K},
28   {L"at25df321",      {0x1f, 0x47, 0x00}, 3, 256, 64 * 1024,    64, NOR_FLASH_ERASE_4K},
29   {L"at26df081a",     {0x1f, 0x45, 0x01}, 3, 256, 64 * 1024,    16, NOR_FLASH_ERASE_4K},
30   /* EON */
31   {L"en25q32b",       {0x1c, 0x30, 0x16}, 3, 256, 64 * 1024,    64, 0},
32   {L"en25q64",        {0x1c, 0x30, 0x17}, 3, 256, 64 * 1024,   128, NOR_FLASH_ERASE_4K},
33   {L"en25q128b",      {0x1c, 0x30, 0x18}, 3, 256, 64 * 1024,   256, 0},
34   {L"en25s64",        {0x1c, 0x38, 0x17}, 3, 256, 64 * 1024,   128, 0},
35   /* GIGADEVICE */
36   {L"gd25q64b",       {0xc8, 0x40, 0x17}, 3, 256, 64 * 1024,   128, NOR_FLASH_ERASE_4K},
37   {L"gd25lq32",       {0xc8, 0x60, 0x16}, 3, 256, 64 * 1024,    64, NOR_FLASH_ERASE_4K},
38   /* ISSI */
39   {L"is25lp032",      {0x9d, 0x60, 0x16}, 3, 256, 64 * 1024,    64, 0},
40   {L"is25lp064",      {0x9d, 0x60, 0x17}, 3, 256, 64 * 1024,   128, 0},
41   {L"is25lp128",      {0x9d, 0x60, 0x18}, 3, 256, 64 * 1024,   256, 0},
42   /* MACRONIX */
43   {L"mx25l2006e",     {0xc2, 0x20, 0x12}, 3, 256, 64 * 1024,     4, 0},
44   {L"mx25l4005",      {0xc2, 0x20, 0x13}, 3, 256, 64 * 1024,     8, 0},
45   {L"mx25l8005",      {0xc2, 0x20, 0x14}, 3, 256, 64 * 1024,    16, 0},
46   {L"mx25l1605d",     {0xc2, 0x20, 0x15}, 3, 256, 64 * 1024,    32, 0},
47   {L"mx25l3205d",     {0xc2, 0x20, 0x16}, 3, 256, 64 * 1024,    64, 0},
48   {L"mx25l6405d",     {0xc2, 0x20, 0x17}, 3, 256, 64 * 1024,   128, 0},
49   {L"mx25l12805",     {0xc2, 0x20, 0x18}, 3, 256, 64 * 1024,   256, 0},
50   {L"mx25l25635f",    {0xc2, 0x20, 0x19}, 3, 256, 64 * 1024,   512, 0},
51   {L"mx25l51235f",    {0xc2, 0x20, 0x1a}, 3, 256, 64 * 1024,  1024, 0},
52   {L"mx25l12855e",    {0xc2, 0x26, 0x18}, 3, 256, 64 * 1024,   256, 0},
53   {L"mx66u51235f",    {0xc2, 0x25, 0x3a}, 3, 256, 64 * 1024,  1024, 0},
54   {L"mx66u1g45g",     {0xc2, 0x25, 0x3b}, 3, 256, 64 * 1024,  2048, 0},
55   {L"mx66l1g45g",     {0xc2, 0x20, 0x1b}, 3, 256, 64 * 1024,  2048, 0},
56   /* SPANSION */
57   {L"s25fl008a",      {0x01, 0x02, 0x13}, 3, 256, 64 * 1024,    16, 0},
58   {L"s25fl016a",      {0x01, 0x02, 0x14}, 3, 256, 64 * 1024,    32, 0},
59   {L"s25fl032a",      {0x01, 0x02, 0x15}, 3, 256, 64 * 1024,    64, 0},
60   {L"s25fl064a",      {0x01, 0x02, 0x16}, 3, 256, 64 * 1024,   128, 0},
61   {L"s25fl116k",      {0x01, 0x40, 0x15}, 3, 256, 64 * 1024,   128, 0},
62   {L"s25fl164k",      {0x01, 0x40, 0x17, 0x01, 0x40}, 5, 256,  64 * 1024,   128, 0},
63   {L"s25fl128p_256k", {0x01, 0x20, 0x18, 0x03, 0x00}, 5, 256, 256 * 1024,    64, 0},
64   {L"s25fl128p_64k",  {0x01, 0x20, 0x18, 0x03, 0x01}, 5, 256,  64 * 1024,   256, 0},
65   {L"s25fl032p",      {0x01, 0x02, 0x15, 0x4d, 0x00}, 5, 256,  64 * 1024,    64, 0},
66   {L"s25fl064p",      {0x01, 0x02, 0x16, 0x4d, 0x00}, 5, 256,  64 * 1024,   128, 0},
67   {L"s25fl128s_256k", {0x01, 0x20, 0x18, 0x4d, 0x00}, 5, 256, 256 * 1024,    64, 0},
68   {L"s25fl128s_64k",  {0x01, 0x20, 0x18, 0x4d, 0x01}, 5, 256,  64 * 1024,   256, 0},
69   {L"s25fl256s_256k", {0x01, 0x02, 0x19, 0x4d, 0x00}, 5, 256, 256 * 1024,   128, 0},
70   {L"s25fl256s_64k",  {0x01, 0x02, 0x19, 0x4d, 0x01}, 5, 256,  64 * 1024,   512, 0},
71   {L"s25fl512s_256k", {0x01, 0x02, 0x20, 0x4d, 0x00}, 5, 256, 256 * 1024,   256, 0},
72   {L"s25fl512s_64k",  {0x01, 0x02, 0x20, 0x4d, 0x01}, 5, 256,  64 * 1024,  1024, 0},
73   {L"s25fl512s_512k", {0x01, 0x02, 0x20, 0x4f, 0x00}, 5, 256, 256 * 1024,   256, 0},
74   /* STMICRO */
75   {L"m25p10",         {0x20, 0x20, 0x11}, 3, 256, 32 * 1024,     4, 0},
76   {L"m25p20",         {0x20, 0x20, 0x12}, 3, 256, 64 * 1024,     4, 0},
77   {L"m25p40",         {0x20, 0x20, 0x13}, 3, 256, 64 * 1024,     8, 0},
78   {L"m25p80",         {0x20, 0x20, 0x14}, 3, 256, 64 * 1024,    16, 0},
79   {L"m25p16",         {0x20, 0x20, 0x15}, 3, 256, 64 * 1024,    32, 0},
80   {L"m25pE16",        {0x20, 0x80, 0x15, 0x10, 0x00}, 5, 256, 64 * 1024, 32, 0},
81   {L"m25pX16",        {0x20, 0x71, 0x15, 0x10, 0x00}, 5, 256, 64 * 1024, 32, 0},
82   {L"m25p32",         {0x20, 0x20, 0x16}, 3, 256,  64 * 1024,    64, 0},
83   {L"m25p64",         {0x20, 0x20, 0x17}, 3, 256,  64 * 1024,   128, 0},
84   {L"m25p128",        {0x20, 0x20, 0x18}, 3, 256, 256 * 1024,    64, 0},
85   {L"m25pX64",        {0x20, 0x71, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
86   {L"n25q016a",       {0x20, 0xbb, 0x15}, 3, 256,  64 * 1024,    32, NOR_FLASH_ERASE_4K},
87   {L"n25q32",         {0x20, 0xba, 0x16}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
88   {L"n25q32a",        {0x20, 0xbb, 0x16}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
89   {L"n25q64",         {0x20, 0xba, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
90   {L"n25q64a",        {0x20, 0xbb, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
91   {L"n25q128",        {0x20, 0xba, 0x18}, 3, 256,  64 * 1024,   256, 0},
92   {L"n25q128a",       {0x20, 0xbb, 0x18}, 3, 256,  64 * 1024,   256, 0},
93   {L"n25q256",        {0x20, 0xba, 0x19}, 3, 256,  64 * 1024,   512, NOR_FLASH_ERASE_4K},
94   {L"n25q256a",       {0x20, 0xbb, 0x19}, 3, 256,  64 * 1024,   512, NOR_FLASH_ERASE_4K},
95   {L"n25q512",        {0x20, 0xba, 0x20}, 3, 256,  64 * 1024,  1024, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
96   {L"n25q512a",       {0x20, 0xbb, 0x20}, 3, 256,  64 * 1024,  1024, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
97   {L"n25q1024",       {0x20, 0xba, 0x21}, 3, 256,  64 * 1024,  2048, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
98   {L"n25q1024a",      {0x20, 0xbb, 0x21}, 3, 256,  64 * 1024,  2048, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
99   {L"mt25qu02g",      {0x20, 0xbb, 0x22}, 3, 256,  64 * 1024,  4096, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
100   {L"mt25ql02g",      {0x20, 0xba, 0x22}, 3, 256,  64 * 1024,  4096, NOR_FLASH_WRITE_FSR | NOR_FLASH_ERASE_4K},
101   /* SST */
102   {L"sst25vf040b",    {0xbf, 0x25, 0x8d}, 3, 256,  64 * 1024,     8, NOR_FLASH_ERASE_4K},
103   {L"sst25vf080b",    {0xbf, 0x25, 0x8e}, 3, 256,  64 * 1024,    16, NOR_FLASH_ERASE_4K},
104   {L"sst25vf016b",    {0xbf, 0x25, 0x41}, 3, 256,  64 * 1024,    32, NOR_FLASH_ERASE_4K},
105   {L"sst25vf032b",    {0xbf, 0x25, 0x4a}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
106   {L"sst25vf064c",    {0xbf, 0x25, 0x4b}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
107   {L"sst25wf512",     {0xbf, 0x25, 0x01}, 3, 256,  64 * 1024,     1, NOR_FLASH_ERASE_4K},
108   {L"sst25wf010",     {0xbf, 0x25, 0x02}, 3, 256,  64 * 1024,     2, NOR_FLASH_ERASE_4K},
109   {L"sst25wf020",     {0xbf, 0x25, 0x03}, 3, 256,  64 * 1024,     4, NOR_FLASH_ERASE_4K},
110   {L"sst25wf040",     {0xbf, 0x25, 0x04}, 3, 256,  64 * 1024,     8, NOR_FLASH_ERASE_4K},
111   {L"sst25wf040b",    {0x62, 0x16, 0x13}, 3, 256,  64 * 1024,     8, NOR_FLASH_ERASE_4K},
112   {L"sst25wf080",     {0xbf, 0x25, 0x05}, 3, 256,  64 * 1024,    16, NOR_FLASH_ERASE_4K},
113   /* WINBOND */
114   {L"w25p80",         {0xef, 0x20, 0x14}, 3, 256,  64 * 1024,    16, 0},
115   {L"w25p16",         {0xef, 0x20, 0x15}, 3, 256,  64 * 1024,    32, 0},
116   {L"w25p32",         {0xef, 0x20, 0x16}, 3, 256,  64 * 1024,    64, 0},
117   {L"w25x40",         {0xef, 0x30, 0x13}, 3, 256,  64 * 1024,     8, NOR_FLASH_ERASE_4K},
118   {L"w25x16",         {0xef, 0x30, 0x15}, 3, 256,  64 * 1024,    32, NOR_FLASH_ERASE_4K},
119   {L"w25x32",         {0xef, 0x30, 0x16}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
120   {L"w25x64",         {0xef, 0x30, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
121   {L"w25q80bl",       {0xef, 0x40, 0x14}, 3, 256,  64 * 1024,    16, NOR_FLASH_ERASE_4K},
122   {L"w25q16cl",       {0xef, 0x40, 0x15}, 3, 256,  64 * 1024,    32, NOR_FLASH_ERASE_4K},
123   {L"w25q32bv",       {0xef, 0x40, 0x16}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
124   {L"w25q64cv",       {0xef, 0x40, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
125   {L"w25q128bv",      {0xef, 0x40, 0x18}, 3, 256,  64 * 1024,   256, NOR_FLASH_ERASE_4K},
126   {L"w25q256",        {0xef, 0x40, 0x19}, 3, 256,  64 * 1024,   512, NOR_FLASH_ERASE_4K},
127   {L"w25q80bw",       {0xef, 0x50, 0x14}, 3, 256,  64 * 1024,    16, NOR_FLASH_ERASE_4K},
128   {L"w25q16dw",       {0xef, 0x60, 0x15}, 3, 256,  64 * 1024,    32, NOR_FLASH_ERASE_4K},
129   {L"w25q32dw",       {0xef, 0x60, 0x16}, 3, 256,  64 * 1024,    64, NOR_FLASH_ERASE_4K},
130   {L"w25q64dw",       {0xef, 0x60, 0x17}, 3, 256,  64 * 1024,   128, NOR_FLASH_ERASE_4K},
131   {L"w25q128fw",      {0xef, 0x60, 0x18}, 3, 256,  64 * 1024,   256, NOR_FLASH_ERASE_4K},
132   {},  /* Empty entry to terminate the list */
133 };
134 
135 /**
136   Return an allocated copy pool of the NOR flash information structure.
137 
138   @param[in]       Id                 Pointer to an array with JEDEC ID obtained
139                                       from the NOR flash with READ_ID command
140                                       (0x9f)
141   @param[in out]   FlashInfo          Pointer to NOR flash information structure
142   @param[in]       AllocateForRuntime A flag specifying a type of a copy pool
143                                       allocation (TRUE for runtime, FALSE for
144                                       normal)
145 
146   @retval       EFI_SUCCESS           Operation completed successfully
147   @retval       EFI_NOT_FOUND         No matching entry in NOR ID table found
148   @retval       EFI_OUT_OF_RESOURCES  No pool memory available
149 
150 **/
151 EFI_STATUS
152 EFIAPI
NorFlashGetInfo(IN UINT8 * Id,IN OUT NOR_FLASH_INFO ** FlashInfo,IN BOOLEAN AllocateForRuntime)153 NorFlashGetInfo (
154   IN UINT8                *Id,
155   IN OUT NOR_FLASH_INFO  **FlashInfo,
156   IN BOOLEAN               AllocateForRuntime
157   )
158 {
159   CONST NOR_FLASH_INFO *TmpInfo;
160 
161   /*
162    * Iterate over NorFlashIds table, in order to find matching entry.
163    */
164   TmpInfo = NorFlashIds;
165   for (; TmpInfo->Name != NULL; TmpInfo++) {
166     if (CompareMem (TmpInfo->Id, Id, TmpInfo->IdLen) == 0) {
167       break;
168     }
169   }
170 
171   /*
172    * Matching entry was not found.
173    */
174   if (TmpInfo->Name == NULL) {
175     return EFI_NOT_FOUND;
176   }
177 
178   /*
179    * Allocate and copy NOR flash information structure.
180    */
181   if (AllocateForRuntime) {
182     *FlashInfo = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INFO), TmpInfo);
183   } else {
184     *FlashInfo = AllocateCopyPool (sizeof (NOR_FLASH_INFO), TmpInfo);
185   }
186   if (FlashInfo == NULL) {
187     return EFI_OUT_OF_RESOURCES;
188   }
189 
190   return EFI_SUCCESS;
191 }
192 
193 /**
194   Print NOR flash information basing on data stored in
195   the NOR_FLASH_INFO structure.
196 
197   @param[in]       FlashInfo          Pointer to NOR flash information structure
198 
199 **/
200 VOID
201 EFIAPI
NorFlashPrintInfo(IN NOR_FLASH_INFO * Info)202 NorFlashPrintInfo (
203   IN     NOR_FLASH_INFO  *Info
204   )
205 {
206   UINTN EraseSize;
207 
208   if (Info->Flags & NOR_FLASH_ERASE_4K) {
209     EraseSize = SIZE_4KB;
210   } else {
211     EraseSize = Info->SectorSize;
212   }
213 
214   DEBUG ((DEBUG_ERROR,
215     "Detected %s SPI NOR flash with page size %d B, erase size %d KB, total %d MB\n",
216     Info->Name,
217     Info->PageSize,
218     EraseSize / 1024,
219     (Info->SectorSize * Info->SectorCount) / 1024 / 1024));
220 }
221