]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c
ArmPkg/CompilerIntrinsicsLib: Add uread, uwrite GCC assembly sources
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Dxe / MemorySubClass / MemorySubClass.c
1 /** @file
2 This is the driver that locates the MemoryConfigurationData Variable, if it
3 exists, and reports the data to the DataHub.
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "MemorySubClass.h"
12
13 extern UINT8 MemorySubClassStrings[];
14
15 EFI_GUID gEfiMemorySubClassDriverGuid = EFI_MEMORY_SUBCLASS_DRIVER_GUID;
16
17 EFI_STATUS
18 MemorySubClassEntryPoint (
19 IN EFI_HANDLE ImageHandle,
20 IN EFI_SYSTEM_TABLE *SystemTable
21 )
22 /*++
23
24 Routine Description:
25 This is the standard EFI driver point that detects whether there is a
26 MemoryConfigurationData Variable and, if so, reports memory configuration info
27 to the DataHub.
28
29 Arguments:
30 ImageHandle - Handle for the image of this driver
31 SystemTable - Pointer to the EFI System Table
32
33 Returns:
34 EFI_SUCCESS if the data is successfully reported
35 EFI_NOT_FOUND if the HOB list could not be located.
36
37 --*/
38 {
39 // UINT8 Index;
40 UINTN DataSize;
41 UINT8 Dimm;
42 UINTN StringBufferSize;
43 UINT8 NumSlots;
44 UINTN DevLocStrLen;
45 UINTN BankLocStrLen;
46 UINTN ManuStrLen;
47 UINTN SerialNumStrLen;
48 UINTN AssertTagStrLen;
49 UINTN PartNumStrLen;
50 UINTN MemoryDeviceSize;
51 CHAR8* OptionalStrStart;
52 UINT16 ArrayInstance;
53 UINT64 DimmMemorySize;
54 UINT64 TotalMemorySize;
55 UINT32 Data;
56 UINT32 MemoryCapacity;
57 BOOLEAN MemoryDeviceSizeUnitMega;
58 EFI_STATUS Status;
59 EFI_STRING StringBuffer;
60 EFI_STRING DevLocStr;
61 EFI_STRING BankLocStr;
62 EFI_STRING ManuStr;
63 EFI_STRING SerialNumStr;
64 EFI_STRING AssertTagStr;
65 EFI_STRING PartNumStr;
66 EFI_HII_HANDLE HiiHandle;
67 EFI_SMBIOS_HANDLE MemArraySmbiosHandle;
68 EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
69 EFI_SMBIOS_HANDLE MemDevSmbiosHandle;
70 EFI_SMBIOS_HANDLE MemDevMappedAddrSmbiosHandle;
71 EFI_SMBIOS_HANDLE MemModuleInfoSmbiosHandle;
72 SMBIOS_TABLE_TYPE6 *Type6Record;
73 SMBIOS_TABLE_TYPE16 *Type16Record;
74 SMBIOS_TABLE_TYPE17 *Type17Record;
75 SMBIOS_TABLE_TYPE19 *Type19Record;
76 SMBIOS_TABLE_TYPE20 *Type20Record;
77 EFI_SMBIOS_PROTOCOL *Smbios;
78 EFI_MEMORY_ARRAY_LINK_DATA ArrayLink;
79 EFI_MEMORY_ARRAY_LOCATION_DATA ArrayLocationData;
80 EFI_MEMORY_DEVICE_START_ADDRESS_DATA DeviceStartAddress;
81
82
83 DataSize = 0;
84 Dimm = 0;
85
86
87 //
88 // Allocate Buffers
89 //
90 StringBufferSize = (sizeof (CHAR16)) * 100;
91 StringBuffer = AllocateZeroPool (StringBufferSize);
92 ASSERT (StringBuffer != NULL);
93
94 //
95 // Locate dependent protocols
96 //
97 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
98 ASSERT_EFI_ERROR (Status);
99
100
101 //
102 // Add our default strings to the HII database. They will be modified later.
103 //
104 HiiHandle = HiiAddPackages (
105 &gEfiMemorySubClassDriverGuid,
106 NULL,
107 MemorySubClassStrings,
108 NULL
109 );
110 ASSERT (HiiHandle != NULL);
111
112 //
113 // Create physical array and associated data for all mainboard memory
114 // This will translate into a Type 16 SMBIOS Record
115 //
116 ArrayInstance = 1;
117
118 McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (0x3, 0x8);
119 TotalMemorySize = McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
120
121 ArrayLocationData.MemoryArrayLocation = EfiMemoryArrayLocationSystemBoard;
122 ArrayLocationData.MemoryArrayUse = EfiMemoryArrayUseSystemMemory;
123
124 ArrayLocationData.MemoryErrorCorrection = EfiMemoryErrorCorrectionNone;
125
126 Data = 0x40000000;//(UINT32) RShiftU64(MemConfigData->RowInfo.MaxMemory, 10);
127
128 ArrayLocationData.MaximumMemoryCapacity.Exponent = (UINT16) LowBitSet32 (Data);
129 ArrayLocationData.MaximumMemoryCapacity.Value = (UINT16) (Data >> ArrayLocationData.MaximumMemoryCapacity.Exponent);
130
131 NumSlots = 2;// (UINT8)(MemConfigData->RowInfo.MaxRows >> 1);
132 ArrayLocationData.NumberMemoryDevices = (UINT16)(NumSlots);
133
134 //
135 // Report top level physical array to Type 16 SMBIOS Record
136 //
137 Type16Record = AllocatePool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);
138 ZeroMem(Type16Record, sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);
139
140 Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY;
141 Type16Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE16);
142 Type16Record->Hdr.Handle = 0;
143
144 Type16Record->Location = (UINT8)ArrayLocationData.MemoryArrayLocation;
145
146 Type16Record->Use = (UINT8)ArrayLocationData.MemoryArrayUse;
147
148 Type16Record->MemoryErrorCorrection = (UINT8)ArrayLocationData.MemoryErrorCorrection;
149
150 MemoryCapacity = (UINT32) ArrayLocationData.MaximumMemoryCapacity.Value * (1 << ((UINT32) ArrayLocationData.MaximumMemoryCapacity.Exponent - 10));
151 Type16Record->MaximumCapacity = MemoryCapacity;
152
153 Type16Record->MemoryErrorInformationHandle = 0xfffe;
154
155 Type16Record->NumberOfMemoryDevices = ArrayLocationData.NumberMemoryDevices;
156 //
157 // Don't change it. This handle will be referenced by type 17 records
158 //
159 MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
160 Status = Smbios->Add (Smbios, NULL, &MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type16Record);
161 FreePool(Type16Record);
162 ASSERT_EFI_ERROR (Status);
163
164 // Do associated data for each DIMM
165 //RowConfArray = &MemConfigData->RowConfArray;
166
167 //
168 // Get total memory size for the construction of smbios record type 19
169 //
170 //TotalMemorySize = 0;// MSG_BUS_READ(0x0208);
171
172 //
173 // Generate Memory Array Mapped Address info
174 //
175 Type19Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE19));
176 ZeroMem(Type19Record, sizeof(SMBIOS_TABLE_TYPE19));
177 Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
178 Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
179 Type19Record->Hdr.Handle = 0;
180 Type19Record->StartingAddress = 0;
181 Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1;
182 Type19Record->MemoryArrayHandle = MemArraySmbiosHandle;
183 Type19Record->PartitionWidth = (UINT8)(NumSlots);
184
185 //
186 // Generate Memory Array Mapped Address info (TYPE 19)
187 //
188 MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
189 Status = Smbios->Add (Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type19Record);
190 FreePool(Type19Record);
191 ASSERT_EFI_ERROR (Status);
192
193
194 // Use SPD data to generate Device Type info
195 ZeroMem (&ArrayLink, sizeof (EFI_MEMORY_ARRAY_LINK_DATA));
196 ArrayLink.MemoryDeviceLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);
197 ArrayLink.MemoryBankLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);
198 ArrayLink.MemoryAssetTag = STRING_TOKEN(STR_MEMORY_SUBCLASS_UNKNOWN);
199 ArrayLink.MemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
200 ArrayLink.MemoryArrayLink.Instance = ArrayInstance;
201 ArrayLink.MemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
202 ArrayLink.MemorySubArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
203 ArrayLink.MemorySubArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
204 ArrayLink.MemoryFormFactor = EfiMemoryFormFactorChip;
205 ArrayLink.MemoryType = EfiMemoryTypeDdr2;
206
207
208 StrCpy (StringBuffer, L"NO DIMM,MEMROY DOWN");
209 ArrayLink.MemoryManufacturer = HiiSetString (
210 HiiHandle,
211 0,
212 StringBuffer,
213 NULL
214 );
215 ArrayLink.MemorySerialNumber = HiiSetString (
216 HiiHandle,
217 0,
218 StringBuffer,
219 NULL
220 );
221
222 ArrayLink.MemoryPartNumber = HiiSetString (
223 HiiHandle,
224 0,
225 StringBuffer,
226 NULL
227 );
228
229 //
230 // Hardcode value. Need to revise for different configuration.
231 //
232 ArrayLink.MemoryTotalWidth = 64;
233 ArrayLink.MemoryDataWidth = 64;
234
235 DimmMemorySize = TotalMemorySize;// MSG_BUS_READ(0x0208);
236
237 ArrayLink.MemoryDeviceSize.Exponent = (UINT16) LowBitSet64 (DimmMemorySize);
238 ArrayLink.MemoryDeviceSize.Value = (UINT16) RShiftU64(DimmMemorySize, ArrayLink.MemoryDeviceSize.Exponent);
239 ArrayLink.MemoryTypeDetail.Synchronous = 1;
240 Data = 800;
241 ArrayLink.MemorySpeed = *((EFI_EXP_BASE10_DATA *) &Data);
242
243
244
245 DevLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryDeviceLocator, NULL);
246 DevLocStrLen = StrLen(DevLocStr);
247 ASSERT(DevLocStrLen <= SMBIOS_STRING_MAX_LENGTH);
248
249 BankLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryBankLocator, NULL);
250 BankLocStrLen = StrLen(BankLocStr);
251 ASSERT(BankLocStrLen <= SMBIOS_STRING_MAX_LENGTH);
252
253 ManuStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryManufacturer, NULL);
254 ManuStrLen = StrLen(ManuStr);
255 ASSERT(ManuStrLen <= SMBIOS_STRING_MAX_LENGTH);
256
257 SerialNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemorySerialNumber, NULL);
258 SerialNumStrLen = StrLen(SerialNumStr);
259 ASSERT(SerialNumStrLen <= SMBIOS_STRING_MAX_LENGTH);
260
261 AssertTagStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryAssetTag, NULL);
262 AssertTagStrLen = StrLen(AssertTagStr);
263 ASSERT(AssertTagStrLen <= SMBIOS_STRING_MAX_LENGTH);
264
265 PartNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryPartNumber, NULL);
266 PartNumStrLen = StrLen(PartNumStr);
267 ASSERT(PartNumStrLen <= SMBIOS_STRING_MAX_LENGTH);
268
269 //
270 // Report DIMM level memory module information to smbios (Type 6)
271 //
272 DataSize = sizeof(SMBIOS_TABLE_TYPE6) + DevLocStrLen + 1 + 1;
273 Type6Record = AllocatePool(DataSize);
274 ZeroMem(Type6Record, DataSize);
275 Type6Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_MODULE_INFORMATON;
276 Type6Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE6);
277 Type6Record->Hdr.Handle = 0;
278 Type6Record->SocketDesignation = 1;
279 if (ArrayLink.MemorySpeed.Value == 0) {
280 Type6Record->CurrentSpeed = 0;
281 } else {
282 //
283 // Memory speed is in ns unit
284 //
285 Type6Record->CurrentSpeed = (UINT8)(1000 / (ArrayLink.MemorySpeed.Value));
286 }
287 //
288 // Device Size
289 //
290 MemoryDeviceSize = (UINTN)(ArrayLink.MemoryDeviceSize.Value) * (UINTN)(1 << ArrayLink.MemoryDeviceSize.Exponent);
291 if (MemoryDeviceSize == 0) {
292 *(UINT8*)&(Type6Record->InstalledSize) = 0x7F;
293 *(UINT8*)&(Type6Record->EnabledSize) = 0x7F;
294 } else {
295 MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize, 21);
296 while (MemoryDeviceSize != 0) {
297 (*(UINT8*)&(Type6Record->InstalledSize))++;
298 (*(UINT8*)&(Type6Record->EnabledSize))++;
299 MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize,1);
300 }
301 }
302
303 if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorDimm ||
304 ArrayLink.MemoryFormFactor == EfiMemoryFormFactorFbDimm) {
305 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<8;
306 }
307 if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorSimm) {
308 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<7;
309 }
310 if (ArrayLink.MemoryType == EfiMemoryTypeSdram) {
311 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<10;
312 }
313 if (ArrayLink.MemoryTypeDetail.Edo == 1) {
314 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<4;
315 }
316 if (ArrayLink.MemoryTypeDetail.FastPaged == 1) {
317 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<3;
318 }
319 OptionalStrStart = (CHAR8 *)(Type6Record + 1);
320 UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);
321 MemModuleInfoSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
322 Status = Smbios->Add (Smbios, NULL, &MemModuleInfoSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type6Record);
323 FreePool(Type6Record);
324 ASSERT_EFI_ERROR (Status);
325 //
326 // Report DIMM level Device Type to smbios (Type 17)
327 //
328 DataSize = sizeof (SMBIOS_TABLE_TYPE17) + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + PartNumStrLen + 1 + 1;
329 Type17Record = AllocatePool(DataSize);
330 ZeroMem(Type17Record, DataSize);
331 Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
332 Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);
333 Type17Record->Hdr.Handle = 0;
334
335 Type17Record->MemoryArrayHandle = MemArraySmbiosHandle;
336 Type17Record->MemoryErrorInformationHandle = 0xfffe;
337 Type17Record->TotalWidth = ArrayLink.MemoryTotalWidth;
338 Type17Record->DataWidth = ArrayLink.MemoryDataWidth;
339 //
340 // Device Size
341 //
342 MemoryDeviceSize = ((UINTN) ArrayLink.MemoryDeviceSize.Value) << (ArrayLink.MemoryDeviceSize.Exponent - 10);
343 MemoryDeviceSizeUnitMega = FALSE;
344 //
345 // kilo as unit
346 //
347 if (MemoryDeviceSize > 0xffff) {
348 MemoryDeviceSize = MemoryDeviceSize >> 10;
349 //
350 // Mega as unit
351 //
352 MemoryDeviceSizeUnitMega = TRUE;
353 }
354
355 MemoryDeviceSize = MemoryDeviceSize & 0x7fff;
356 if (MemoryDeviceSize != 0 && MemoryDeviceSizeUnitMega == FALSE) {
357 MemoryDeviceSize |= 0x8000;
358 }
359 Type17Record->Size = (UINT16)MemoryDeviceSize;
360
361 Type17Record->FormFactor = (UINT8)ArrayLink.MemoryFormFactor;
362 Type17Record->DeviceLocator = 1;
363 Type17Record->BankLocator = 2;
364 Type17Record->MemoryType = (UINT8)ArrayLink.MemoryType;
365 CopyMem (
366 (UINT8 *) &Type17Record->TypeDetail,
367 &ArrayLink.MemoryTypeDetail,
368 2
369 );
370
371 Type17Record->Speed = ArrayLink.MemorySpeed.Value;
372 Type17Record->Manufacturer = 3;
373 Type17Record->SerialNumber = 4;
374 Type17Record->AssetTag = 5;
375 Type17Record->PartNumber = 6;
376 //
377 // temporary solution for save device label information.
378 //
379 Type17Record->Attributes = (UINT8)(Dimm + 1);
380
381 OptionalStrStart = (CHAR8 *)(Type17Record + 1);
382 UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);
383 UnicodeStrToAsciiStr(BankLocStr, OptionalStrStart + DevLocStrLen + 1);
384 UnicodeStrToAsciiStr(ManuStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1);
385 UnicodeStrToAsciiStr(SerialNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1);
386 UnicodeStrToAsciiStr(AssertTagStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1);
387 UnicodeStrToAsciiStr(PartNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1);
388 MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
389 Status = Smbios->Add (Smbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record);
390 FreePool(Type17Record);
391 ASSERT_EFI_ERROR (Status);
392
393 //
394 // Generate Memory Device Mapped Address info
395 //
396 ZeroMem(&DeviceStartAddress, sizeof(EFI_MEMORY_DEVICE_START_ADDRESS_DATA));
397 DeviceStartAddress.MemoryDeviceStartAddress = 0;
398 DeviceStartAddress.MemoryDeviceEndAddress = DeviceStartAddress.MemoryDeviceStartAddress + DimmMemorySize-1;
399 DeviceStartAddress.PhysicalMemoryDeviceLink.ProducerName = gEfiMemorySubClassDriverGuid;
400 DeviceStartAddress.PhysicalMemoryDeviceLink.Instance = ArrayInstance;
401 DeviceStartAddress.PhysicalMemoryDeviceLink.SubInstance = (UINT16)(Dimm + 1);
402 DeviceStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;
403 DeviceStartAddress.PhysicalMemoryArrayLink.Instance = ArrayInstance;
404 DeviceStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
405
406 //
407 // Single channel mode
408 //
409 DeviceStartAddress.MemoryDevicePartitionRowPosition = 0x01;
410 DeviceStartAddress.MemoryDeviceInterleavePosition = 0x00;
411 DeviceStartAddress.MemoryDeviceInterleaveDataDepth = 0x00;
412
413 //
414 // Generate Memory Device Mapped Address info (TYPE 20)
415 //
416 Type20Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE20));
417 ZeroMem(Type20Record, sizeof (SMBIOS_TABLE_TYPE20));
418 Type20Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS;
419 Type20Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE20);
420 Type20Record->Hdr.Handle = 0;
421
422 Type20Record->StartingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceStartAddress, 10);
423 Type20Record->EndingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceEndAddress, 10);
424 Type20Record->MemoryDeviceHandle = MemDevSmbiosHandle;
425 Type20Record->MemoryArrayMappedAddressHandle = MemArrayMappedAddrSmbiosHandle;
426 Type20Record->PartitionRowPosition = DeviceStartAddress.MemoryDevicePartitionRowPosition;
427 Type20Record->InterleavePosition = DeviceStartAddress.MemoryDeviceInterleavePosition;
428 Type20Record->InterleavedDataDepth = DeviceStartAddress.MemoryDeviceInterleaveDataDepth;
429 MemDevMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
430 Status = Smbios->Add (Smbios, NULL, &MemDevMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type20Record);
431 FreePool(Type20Record);
432 ASSERT_EFI_ERROR (Status);
433
434 return Status;
435 }