1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 Module Name:
24 
25 
26   BoardId.c
27 
28 Abstract:
29 
30   Initialization for the board ID.
31 
32   This code should be common across a chipset family of products.
33 
34 
35 
36 --*/
37 
38 #include "PchRegs.h"
39 #include "PlatformDxe.h"
40 #include <Guid/IdccData.h>
41 #include <Guid/EfiVpdData.h>
42 #include <Protocol/DataHub.h>
43 
44 
45 extern EFI_GUID mPlatformDriverGuid;
46 
47 //
48 // Global module data
49 //
50 UINT32 mBoardId;
51 UINT8  mBoardIdIndex;
52 EFI_BOARD_FEATURES mBoardFeatures;
53 UINT16 mSubsystemDeviceId;
54 UINT16 mSubsystemAudioDeviceId;
InitializeBoardId()55 CHAR8  BoardAaNumber[7];
56 BOOLEAN mFoundAANum;
57 
58 /**
59 
60   Write the boardid variable if it does not already exist.
61 
62 **/
63 VOID
64 InitializeBoardId (
65   )
66 {
67 
68   UINT32                        BoardIdBufferSize;
69   EFI_IDCC_BOARD_FORM_FACTOR    IdccBoardFormFactor;
70   EFI_DATA_HUB_PROTOCOL         *DataHub;
71   EFI_STATUS                    Status;
72   DMI_DATA                      DmiDataVariable;
73   UINTN                         Size;
74 #if defined(DUPLICATE_AA_NO_BASE_ADDR)
75   CHAR8                         DuplicateAaNoAscii[sizeof(DmiDataVariable.BaseBoardVersion)];
76   UINTN                         iter;
77 #endif
78 #if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0
79   UINT8                         Data8;
80 #endif
81 
82   //
83   // Update data from the updatable DMI data area
84   //
85   Size = sizeof (DMI_DATA);
86   SetMem(&DmiDataVariable, Size, 0xFF);
87   Status = gRT->GetVariable (
88                   DMI_DATA_NAME,
89                   &gDmiDataGuid,
90                   NULL,
91                   &Size,
92                   &DmiDataVariable
93                   );
94 
95 #if defined(DUPLICATE_AA_NO_BASE_ADDR)
96   //
97   // Get AA# from flash descriptor region
98   //
99   EfiSetMem(DuplicateAaNoAscii, sizeof(DuplicateAaNoAscii), 0xFF);
100   FlashRead((UINT8 *)(UINTN)DUPLICATE_AA_NO_BASE_ADDR,
101             (UINT8 *)DuplicateAaNoAscii,
102             sizeof(DuplicateAaNoAscii));
103 
104   //
105   // Validate AA# read from VPD
106   //
107   for (iter = 0; iter < sizeof(DuplicateAaNoAscii); iter++) {
108      if ((DuplicateAaNoAscii[iter] != 0xFF) &&
109          (DuplicateAaNoAscii[iter] != DmiDataVariable.BaseBoardVersion[iter])) {
110        DmiDataVariable.BaseBoardVersion[iter] = DuplicateAaNoAscii[iter];
111      }
112   }
113 
114   Status = EFI_SUCCESS;
115 #endif
116 
117   mFoundAANum = FALSE;
118 
119   //
120   // No variable...no copy
121   //
122   if (EFI_ERROR (Status)) {
123     mBoardIdIndex = 0; // If we can't find the BoardId in the table, use the first entry
124   } else {
125   	//
126     // This is the correct method of checking for AA#.
127     //
128     CopyMem(&BoardAaNumber, ((((UINT8*)&DmiDataVariable.BaseBoardVersion)+2)), 6);
129     BoardAaNumber[6] = 0;
130     for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) {
131       if (AsciiStrnCmp(mBoardIdDecodeTable[mBoardIdIndex].AaNumber, BoardAaNumber, 6) == 0) {
132         mFoundAANum = TRUE;
133         break;
134       }
135     }
136 
137     if(!mFoundAANum) {
138     	//
139       // Add check for AA#'s that is programmed without the AA as leading chars.
140       //
141       CopyMem(&BoardAaNumber, (((UINT8*)&DmiDataVariable.BaseBoardVersion)), 6);
142       BoardAaNumber[6] = 0;
143       for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) {
144         if (AsciiStrnCmp(mBoardIdDecodeTable[mBoardIdIndex].AaNumber, BoardAaNumber, 6) == 0) {
145           mFoundAANum = TRUE;
146           break;
147         }
148       }
149     }
150   }
151 
152 #if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0
153   //
154   // If we can't find the BoardAA# in the table, find BoardId
155   //
156   if (mFoundAANum != TRUE) {
157     //
158     // BoardID BIT    Location
159     //  0             GPIO33  (ICH)
160     //  1             GPIO34  (ICH)
161     //
162     Data8 = IoRead8(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2);
163 
164     //
165     // BoardId[0]
166     //
167     mBoardId = (UINT32)((Data8 >> 1) & BIT0);
168     //
169     // BoardId[1]
170     //
171     mBoardId |= (UINT32)((Data8 >> 1) & BIT1);
172 
173     for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) {
174       if (mBoardIdDecodeTable[mBoardIdIndex].BoardId == mBoardId) {
175         break;
176       }
177     }
178 #endif
179     if (mBoardIdIndex == mBoardIdDecodeTableSize) {
180       mBoardIdIndex = 0; // If we can't find the BoardId in the table, use the first entry
181     }
182 #if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0
183   }
184 #endif
185 
186   mBoardFeatures = mBoardIdDecodeTable[mBoardIdIndex].Features;
187   mSubsystemDeviceId = mBoardIdDecodeTable[mBoardIdIndex].SubsystemDeviceId;
188   mSubsystemAudioDeviceId = mBoardIdDecodeTable[mBoardIdIndex].AudioSubsystemDeviceId;
189 
190   //
191   // Set the BoardFeatures variable
192   //
193   BoardIdBufferSize = sizeof (mBoardFeatures);
194   gRT->SetVariable (
195          BOARD_FEATURES_NAME,
196          &gEfiBoardFeaturesGuid,
197          EFI_VARIABLE_NON_VOLATILE |
198          EFI_VARIABLE_BOOTSERVICE_ACCESS |
199          EFI_VARIABLE_RUNTIME_ACCESS,
200          BoardIdBufferSize,
201          &mBoardFeatures
202          );
203 
204   //
205   // Get the Data Hub protocol
206   //
207   Status = gBS->LocateProtocol (
208                   &gEfiDataHubProtocolGuid,
209                   NULL,
210                   (VOID **) &DataHub
211                   );
212   if (!(EFI_ERROR(Status))) {
213     //
214     // Fill out data
215     //
216     IdccBoardFormFactor.IdccHeader.Type = EFI_IDCC_BOARD_FORM_FACTOR_TYPE;
217     IdccBoardFormFactor.IdccHeader.RecordLength = sizeof(EFI_IDCC_BOARD_FORM_FACTOR);
218     if ((mBoardFeatures & B_BOARD_FEATURES_FORM_FACTOR_ATX) || (mBoardFeatures & B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX)) {
219         IdccBoardFormFactor.BoardFormFactor = ATX_FORM_FACTOR; // ATX
220     } else {
221         IdccBoardFormFactor.BoardFormFactor = BTX_FORM_FACTOR; // BTX
222     }
223 
224     //
225     // Publish the Board Form Factor value for IDCC
226     //
227     Status = DataHub->LogData (
228                         DataHub,
229                         &gIdccDataHubGuid,
230                         &mPlatformDriverGuid,
231                         EFI_DATA_RECORD_CLASS_DATA,
232                         &IdccBoardFormFactor,
233                         sizeof(EFI_IDCC_BOARD_FORM_FACTOR)
234                         );
235   }
236 }
237 
238