1 /** @file
2 
3   Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
4 
5   This program and the accompanying materials are licensed and made available under
6   the terms and conditions of the BSD License that accompanies this distribution.
7   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 **/
16 
17 #include <PiDxe.h>
18 
19 #include <Library/FlashDeviceLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiRuntimeServicesTableLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/UefiRuntimeLib.h>
26 #include <Protocol/SmmBase2.h>
27 #include <Guid/EventGroup.h>
28 #include "SpiChipDefinitions.h"
29 
30 extern UINTN FlashDeviceBase;
31 
32 extern EFI_SPI_PROTOCOL *mSpiProtocol;
33 
34 VOID
35 EFIAPI
LibFvbFlashDeviceVirtualAddressChangeNotifyEvent(IN EFI_EVENT Event,IN VOID * Context)36 LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
37   IN EFI_EVENT        Event,
38   IN VOID             *Context
39   )
40 {
41   gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
42   gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
43 }
44 
45 
46 /**
47   The library constructuor.
48 
49   The function does the necessary initialization work for this library
50   instance. Please put all initialization works in it.
51 
52   @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
53   @param[in]  SystemTable       A pointer to the EFI system table.
54 
55   @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
56                                 It will ASSERT on error for debug version.
57   @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
58 
59 **/
60 EFI_STATUS
61 EFIAPI
LibFvbFlashDeviceSupportInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)62 LibFvbFlashDeviceSupportInit (
63   IN EFI_HANDLE         ImageHandle,
64   IN EFI_SYSTEM_TABLE   *SystemTable
65   )
66 {
67   EFI_STATUS Status;
68   EFI_EVENT  Event;
69   UINT8                         SfId[3];
70   UINT8                         FlashIndex;
71   UINT8                         SpiReadError;
72   UINT8                         SpiNotMatchError;
73   EFI_SMM_BASE2_PROTOCOL       *SmmBase;
74   BOOLEAN                       InSmm;
75 
76   SpiReadError     = 0x00;
77   SpiNotMatchError = 0x00;
78 
79   InSmm = FALSE;
80   Status = gBS->LocateProtocol (
81                   &gEfiSmmBase2ProtocolGuid,
82                   NULL,
83                   (void **)&SmmBase
84                   );
85   if (!EFI_ERROR(Status)) {
86     Status = SmmBase->InSmm(SmmBase, &InSmm);
87     if (EFI_ERROR(Status)) {
88       InSmm = FALSE;
89     }
90   }
91 
92   if (!InSmm) {
93     Status = gBS->LocateProtocol (
94                   &gEfiSpiProtocolGuid,
95                   NULL,
96                   (VOID **)&mSpiProtocol
97                   );
98     ASSERT_EFI_ERROR (Status);
99 
100     Status = gBS->CreateEventEx (
101                   EVT_NOTIFY_SIGNAL,
102                   TPL_NOTIFY,
103                   LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
104                   NULL,
105                   &gEfiEventVirtualAddressChangeGuid,
106                   &Event
107                   );
108     ASSERT_EFI_ERROR (Status);
109 
110   } else {
111     Status = gBS->LocateProtocol (
112                     &gEfiSmmSpiProtocolGuid,
113                     NULL,
114                     (VOID **)&mSpiProtocol
115                     );
116     ASSERT_EFI_ERROR (Status);
117   }
118 
119 
120   for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
121     Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
122     if (!EFI_ERROR (Status)) {
123       //
124       // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
125       //
126       Status = mSpiProtocol->Execute (
127                                mSpiProtocol,
128                                SPI_READ_ID,
129                                SPI_WREN,
130                                TRUE,
131                                FALSE,
132                                FALSE,
133                                0,
134                                3,
135                                SfId,
136                                EnumSpiRegionAll
137                                );
138       if (!EFI_ERROR (Status)) {
139         if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
140             (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
141             (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
142             //
143             // Found a matching SPI device, FlashIndex now contains flash device.
144             //
145             DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
146             DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
147 
148             if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
149               DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
150               CpuDeadLoop ();
151             }
152             break;
153         } else {
154           SpiNotMatchError++;
155         }
156       } else {
157         SpiReadError++;
158       }
159     }
160   }
161 
162   DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
163 
164   if (FlashIndex < EnumSpiFlashMax)  {
165     return EFI_SUCCESS;
166   } else {
167   if (SpiReadError != 0) {
168       DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
169    }
170     else {
171       if (SpiNotMatchError != 0) {
172         DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
173         DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
174       }
175     }
176     return EFI_UNSUPPORTED;
177   }
178 }
179 
180