]> git.proxmox.com Git - mirror_edk2.git/blob - CorebootModulePkg/Library/CbParseLib/CbParseLib.c
CorebootModulePkg/CbParseLib: Remove tab and spaces
[mirror_edk2.git] / CorebootModulePkg / Library / CbParseLib / CbParseLib.c
1 /** @file
2 This library will parse the coreboot table in memory and extract those required
3 information.
4
5 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <Uefi/UefiBaseType.h>
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/CbParseLib.h>
22
23 #include <IndustryStandard/Acpi.h>
24
25 #include "Coreboot.h"
26
27 /* Helpful inlines */
28
29 static UINT64 cb_unpack64(struct cbuint64 val)
30 {
31 return LShiftU64 (val.hi, 32) | val.lo;
32 }
33
34 UINT16
35 CbCheckSum16 (
36 IN UINT16 *Buffer,
37 IN UINTN Length
38 )
39 {
40 UINT32 Sum, TmpValue;
41 UINTN Idx;
42 UINT8 *TmpPtr;
43
44 Sum = 0;
45 TmpPtr = (UINT8 *)Buffer;
46 for(Idx = 0; Idx < Length; Idx++) {
47 TmpValue = TmpPtr[Idx];
48 if (Idx % 2 == 1) {
49 TmpValue <<= 8;
50 }
51
52 Sum += TmpValue;
53
54 // Wrap
55 if (Sum >= 0x10000) {
56 Sum = (Sum + (Sum >> 16)) & 0xFFFF;
57 }
58 }
59
60 return (UINT16)((~Sum) & 0xFFFF);
61 }
62
63 VOID *
64 FindCbTag (
65 IN VOID *Start,
66 IN UINT32 Tag
67 )
68 {
69 struct cb_header *Header;
70 struct cb_record *Record;
71 UINT8 *TmpPtr;
72 UINT8 *TagPtr;
73 UINTN Idx;
74 UINT16 CheckSum;
75
76 Header = NULL;
77 TmpPtr = (UINT8 *)Start;
78 for (Idx = 0; Idx < 4096; Idx += 16, TmpPtr += 16) {
79 Header = (struct cb_header *)TmpPtr;
80 if (Header->signature == CB_HEADER_SIGNATURE) {
81 break;
82 }
83 }
84
85 if (Idx >= 4096)
86 return NULL;
87
88 if (Header == NULL || !Header->table_bytes)
89 return NULL;
90
91 //
92 // Check the checksum of the coreboot table header
93 //
94 CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header));
95 if (CheckSum != 0) {
96 DEBUG ((EFI_D_ERROR, "Invalid coreboot table header checksum\n"));
97 return NULL;
98 }
99
100 CheckSum = CbCheckSum16 ((UINT16 *)(TmpPtr + sizeof (*Header)), Header->table_bytes);
101 if (CheckSum != Header->table_checksum) {
102 DEBUG ((EFI_D_ERROR, "Incorrect checksum of all the coreboot table entries\n"));
103 return NULL;
104 }
105
106 TagPtr = NULL;
107 TmpPtr += Header->header_bytes;
108 for (Idx = 0; Idx < Header->table_entries; Idx++) {
109 Record = (struct cb_record *)TmpPtr;
110 if (Record->tag == CB_TAG_FORWARD) {
111 TmpPtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward;
112 if (Tag == CB_TAG_FORWARD)
113 return TmpPtr;
114 else
115 return FindCbTag (TmpPtr, Tag);
116 }
117 if (Record->tag == Tag) {
118 TagPtr = TmpPtr;
119 break;
120 }
121 TmpPtr += Record->size;
122 }
123
124 return TagPtr;
125 }
126
127 RETURN_STATUS
128 FindCbMemTable (
129 IN struct cbmem_root *Root,
130 IN UINT32 TableId,
131 OUT VOID **pMemTable,
132 OUT UINT32 *pMemTableSize
133 )
134 {
135 UINTN Idx;
136 BOOLEAN IsImdEntry;
137 struct cbmem_entry *Entries;
138
139 if ((Root == NULL) || (pMemTable == NULL)) {
140 return RETURN_INVALID_PARAMETER;
141 }
142 //
143 // Check if the entry is CBMEM or IMD
144 // and handle them separately
145 //
146 Entries = Root->entries;
147 if (Entries[0].magic == CBMEM_ENTRY_MAGIC) {
148 IsImdEntry = FALSE;
149 } else {
150 Entries = (struct cbmem_entry *)((struct imd_root *)Root)->entries;
151 if (Entries[0].magic == IMD_ENTRY_MAGIC) {
152 IsImdEntry = TRUE;
153 } else {
154 return RETURN_NOT_FOUND;
155 }
156 }
157
158 for (Idx = 0; Idx < Root->num_entries; Idx++) {
159 if (Entries[Idx].id == TableId) {
160 if (IsImdEntry) {
161 *pMemTable = (VOID *) ((UINTN)Entries[Idx].start + (UINTN)Root);
162 } else {
163 *pMemTable = (VOID *) (UINTN)Entries[Idx].start;
164 }
165 if (pMemTableSize != NULL) {
166 *pMemTableSize = Entries[Idx].size;
167 }
168
169 DEBUG ((EFI_D_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n", TableId, *pMemTable, *pMemTableSize));
170 return RETURN_SUCCESS;
171 }
172 }
173
174 return RETURN_NOT_FOUND;
175 }
176
177
178 /**
179 Acquire the memory information from the coreboot table in memory.
180
181 @param pLowMemorySize Pointer to the variable of low memory size
182 @param pHighMemorySize Pointer to the variable of high memory size
183
184 @retval RETURN_SUCCESS Successfully find out the memory information.
185 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
186 @retval RETURN_NOT_FOUND Failed to find the memory information.
187
188 **/
189 RETURN_STATUS
190 CbParseMemoryInfo (
191 IN UINT64* pLowMemorySize,
192 IN UINT64* pHighMemorySize
193 )
194 {
195 struct cb_memory* rec;
196 struct cb_memory_range* Range;
197 UINT64 Start;
198 UINT64 Size;
199 UINTN Index;
200
201 if ((!pLowMemorySize) || (!pHighMemorySize))
202 return RETURN_INVALID_PARAMETER;
203
204 //
205 // Get the coreboot memory table
206 //
207 rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY);
208 if (!rec)
209 rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY);
210
211 if (!rec)
212 return RETURN_NOT_FOUND;
213
214 *pLowMemorySize = 0;
215 *pHighMemorySize = 0;
216
217 for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
218 Range = MEM_RANGE_PTR(rec, Index);
219 Start = cb_unpack64(Range->start);
220 Size = cb_unpack64(Range->size);
221 DEBUG ((EFI_D_ERROR, "%d. %016lx - %016lx [%02x]\n",
222 Index, Start, Start + Size - 1, Range->type));
223
224 if (Range->type != CB_MEM_RAM) {
225 continue;
226 }
227
228 if (Start + Size < 0x100000000ULL) {
229 *pLowMemorySize = Start + Size;
230 } else {
231 *pHighMemorySize = Start + Size - 0x100000000ULL;
232 }
233 }
234
235 DEBUG ((EFI_D_ERROR, "Low memory 0x%lx, High Memory 0x%lx\n", *pLowMemorySize, *pHighMemorySize));
236
237 return RETURN_SUCCESS;
238 }
239
240
241 /**
242 Acquire the coreboot memory table with the given table id
243
244 @param TableId Table id to be searched
245 @param pMemTable Pointer to the base address of the memory table
246 @param pMemTableSize Pointer to the size of the memory table
247
248 @retval RETURN_SUCCESS Successfully find out the memory table.
249 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
250 @retval RETURN_NOT_FOUND Failed to find the memory table.
251
252 **/
253 RETURN_STATUS
254 CbParseCbMemTable (
255 IN UINT32 TableId,
256 IN VOID** pMemTable,
257 IN UINT32* pMemTableSize
258 )
259 {
260 struct cb_memory* rec;
261 struct cb_memory_range* Range;
262 UINT64 Start;
263 UINT64 Size;
264 UINTN Index;
265
266 if (!pMemTable)
267 return RETURN_INVALID_PARAMETER;
268
269 *pMemTable = NULL;
270
271 //
272 // Get the coreboot memory table
273 //
274 rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY);
275 if (!rec)
276 rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY);
277
278 if (!rec)
279 return RETURN_NOT_FOUND;
280
281 for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
282 Range = MEM_RANGE_PTR(rec, Index);
283 Start = cb_unpack64(Range->start);
284 Size = cb_unpack64(Range->size);
285
286 if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) {
287 if (FindCbMemTable ((struct cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE), TableId, pMemTable, pMemTableSize) == RETURN_SUCCESS)
288 return RETURN_SUCCESS;
289 }
290 }
291
292 return RETURN_NOT_FOUND;
293 }
294
295
296 /**
297 Acquire the acpi table from coreboot
298
299 @param pMemTable Pointer to the base address of the memory table
300 @param pMemTableSize Pointer to the size of the memory table
301
302 @retval RETURN_SUCCESS Successfully find out the memory table.
303 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
304 @retval RETURN_NOT_FOUND Failed to find the memory table.
305
306 **/
307 RETURN_STATUS
308 CbParseAcpiTable (
309 IN VOID* pMemTable,
310 IN UINT32* pMemTableSize
311 )
312 {
313 return CbParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), (VOID **)pMemTable, pMemTableSize);
314 }
315
316 /**
317 Acquire the smbios table from coreboot
318
319 @param pMemTable Pointer to the base address of the memory table
320 @param pMemTableSize Pointer to the size of the memory table
321
322 @retval RETURN_SUCCESS Successfully find out the memory table.
323 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
324 @retval RETURN_NOT_FOUND Failed to find the memory table.
325
326 **/
327 RETURN_STATUS
328 CbParseSmbiosTable (
329 IN VOID** pMemTable,
330 IN UINT32* pMemTableSize
331 )
332 {
333 return CbParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), pMemTable, pMemTableSize);
334 }
335
336 /**
337 Find the required fadt information
338
339 @param pPmCtrlReg Pointer to the address of power management control register
340 @param pPmTimerReg Pointer to the address of power management timer register
341 @param pResetReg Pointer to the address of system reset register
342 @param pResetValue Pointer to the value to be writen to the system reset register
343
344 @retval RETURN_SUCCESS Successfully find out all the required fadt information.
345 @retval RETURN_NOT_FOUND Failed to find the fadt table.
346
347 **/
348 RETURN_STATUS
349 CbParseFadtInfo (
350 IN UINTN* pPmCtrlReg,
351 IN UINTN* pPmTimerReg,
352 IN UINTN* pResetReg,
353 IN UINTN* pResetValue
354 )
355 {
356 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER* Rsdp;
357 EFI_ACPI_DESCRIPTION_HEADER* Rsdt;
358 UINT32* Entry32;
359 UINTN Entry32Num;
360 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE* Fadt;
361 EFI_ACPI_DESCRIPTION_HEADER* Xsdt;
362 UINT64* Entry64;
363 UINTN Entry64Num;
364 UINTN Idx;
365 RETURN_STATUS Status;
366
367 Rsdp = NULL;
368 Status = RETURN_SUCCESS;
369
370 Status = CbParseAcpiTable (&Rsdp, NULL);
371 if (RETURN_ERROR(Status))
372 return Status;
373
374 if (!Rsdp)
375 return RETURN_NOT_FOUND;
376
377 DEBUG ((EFI_D_ERROR, "Find Rsdp at %p\n", Rsdp));
378 DEBUG ((EFI_D_ERROR, "Find Rsdt 0x%x, Xsdt 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));
379
380 //
381 // Search Rsdt First
382 //
383 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);
384 if (Rsdt != NULL) {
385 Entry32 = (UINT32 *)(Rsdt + 1);
386 Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
387 for (Idx = 0; Idx < Entry32Num; Idx++) {
388 if (*(UINT32 *)(UINTN)(Entry32[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
389 Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry32[Idx]);
390 if (pPmCtrlReg)
391 *pPmCtrlReg = Fadt->Pm1aCntBlk;
392 DEBUG ((EFI_D_ERROR, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk));
393
394 if (pPmTimerReg)
395 *pPmTimerReg = Fadt->PmTmrBlk;
396 DEBUG ((EFI_D_ERROR, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk));
397
398 if (pResetReg)
399 *pResetReg = (UINTN)Fadt->ResetReg.Address;
400 DEBUG ((EFI_D_ERROR, "Reset Reg 0x%lx\n", Fadt->ResetReg.Address));
401
402 if (pResetValue)
403 *pResetValue = Fadt->ResetValue;
404 DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue));
405
406 return RETURN_SUCCESS;
407 }
408 }
409 }
410
411 //
412 // Search Xsdt Second
413 //
414 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
415 if (Xsdt != NULL) {
416 Entry64 = (UINT64 *)(Xsdt + 1);
417 Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3;
418 for (Idx = 0; Idx < Entry64Num; Idx++) {
419 if (*(UINT32 *)(UINTN)(Entry64[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
420 Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry64[Idx]);
421 if (pPmCtrlReg)
422 *pPmCtrlReg = Fadt->Pm1aCntBlk;
423 DEBUG ((EFI_D_ERROR, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk));
424
425 if (pPmTimerReg)
426 *pPmTimerReg = Fadt->PmTmrBlk;
427 DEBUG ((EFI_D_ERROR, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk));
428
429 if (pResetReg)
430 *pResetReg = (UINTN)Fadt->ResetReg.Address;
431 DEBUG ((EFI_D_ERROR, "Reset Reg 0x%lx\n", Fadt->ResetReg.Address));
432
433 if (pResetValue)
434 *pResetValue = Fadt->ResetValue;
435 DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue));
436
437 return RETURN_SUCCESS;
438 }
439 }
440 }
441
442 return RETURN_NOT_FOUND;
443 }
444
445 /**
446 Find the serial port information
447
448 @param pRegBase Pointer to the base address of serial port registers
449 @param pRegAccessType Pointer to the access type of serial port registers
450 @param pBaudrate Pointer to the serial port baudrate
451
452 @retval RETURN_SUCCESS Successfully find the serial port information.
453 @retval RETURN_NOT_FOUND Failed to find the serial port information .
454
455 **/
456 RETURN_STATUS
457 CbParseSerialInfo (
458 IN UINT32* pRegBase,
459 IN UINT32* pRegAccessType,
460 IN UINT32* pBaudrate
461 )
462 {
463 struct cb_serial* CbSerial;
464
465 CbSerial = FindCbTag (0, CB_TAG_SERIAL);
466 if (!CbSerial)
467 CbSerial = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_SERIAL);
468
469 if (!CbSerial)
470 return RETURN_NOT_FOUND;
471
472 if (pRegBase)
473 *pRegBase = CbSerial->baseaddr;
474
475 if (pRegAccessType)
476 *pRegAccessType = CbSerial->type;
477
478 if (pBaudrate)
479 *pBaudrate = CbSerial->baud;
480
481 return RETURN_SUCCESS;
482 }
483
484 /**
485 Search for the coreboot table header
486
487 @param Level Level of the search depth
488 @param HeaderPtr Pointer to the pointer of coreboot table header
489
490 @retval RETURN_SUCCESS Successfully find the coreboot table header .
491 @retval RETURN_NOT_FOUND Failed to find the coreboot table header .
492
493 **/
494 RETURN_STATUS
495 CbParseGetCbHeader (
496 IN UINTN Level,
497 IN VOID** HeaderPtr
498 )
499 {
500 UINTN Index;
501 VOID* TempPtr;
502
503 if (!HeaderPtr)
504 return RETURN_NOT_FOUND;
505
506 TempPtr = NULL;
507 for (Index = 0; Index < Level; Index++) {
508 TempPtr = FindCbTag (TempPtr, CB_TAG_FORWARD);
509 if (!TempPtr)
510 break;
511 }
512
513 if ((Index >= Level) && (TempPtr != NULL)) {
514 *HeaderPtr = TempPtr;
515 return RETURN_SUCCESS;
516 }
517
518 return RETURN_NOT_FOUND;
519 }
520
521 /**
522 Find the video frame buffer information
523
524 @param pFbInfo Pointer to the FRAME_BUFFER_INFO structure
525
526 @retval RETURN_SUCCESS Successfully find the video frame buffer information.
527 @retval RETURN_NOT_FOUND Failed to find the video frame buffer information .
528
529 **/
530 RETURN_STATUS
531 CbParseFbInfo (
532 IN FRAME_BUFFER_INFO* pFbInfo
533 )
534 {
535 struct cb_framebuffer* CbFbRec;
536
537 if (!pFbInfo)
538 return RETURN_INVALID_PARAMETER;
539
540 CbFbRec = FindCbTag (0, CB_TAG_FRAMEBUFFER);
541 if (!CbFbRec)
542 CbFbRec = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_FRAMEBUFFER);
543
544 if (!CbFbRec)
545 return RETURN_NOT_FOUND;
546
547 DEBUG ((EFI_D_ERROR, "Found coreboot video frame buffer information\n"));
548 DEBUG ((EFI_D_ERROR, "physical_address: 0x%lx\n", CbFbRec->physical_address));
549 DEBUG ((EFI_D_ERROR, "x_resolution: 0x%x\n", CbFbRec->x_resolution));
550 DEBUG ((EFI_D_ERROR, "y_resolution: 0x%x\n", CbFbRec->y_resolution));
551 DEBUG ((EFI_D_ERROR, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel));
552 DEBUG ((EFI_D_ERROR, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line));
553
554 DEBUG ((EFI_D_ERROR, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size));
555 DEBUG ((EFI_D_ERROR, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos));
556 DEBUG ((EFI_D_ERROR, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size));
557 DEBUG ((EFI_D_ERROR, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos));
558 DEBUG ((EFI_D_ERROR, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size));
559 DEBUG ((EFI_D_ERROR, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos));
560 DEBUG ((EFI_D_ERROR, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size));
561 DEBUG ((EFI_D_ERROR, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos));
562
563 pFbInfo->LinearFrameBuffer = CbFbRec->physical_address;
564 pFbInfo->HorizontalResolution = CbFbRec->x_resolution;
565 pFbInfo->VerticalResolution = CbFbRec->y_resolution;
566 pFbInfo->BitsPerPixel = CbFbRec->bits_per_pixel;
567 pFbInfo->BytesPerScanLine = (UINT16)CbFbRec->bytes_per_line;
568 pFbInfo->Red.Mask = (1 << CbFbRec->red_mask_size) - 1;
569 pFbInfo->Red.Position = CbFbRec->red_mask_pos;
570 pFbInfo->Green.Mask = (1 << CbFbRec->green_mask_size) - 1;
571 pFbInfo->Green.Position = CbFbRec->green_mask_pos;
572 pFbInfo->Blue.Mask = (1 << CbFbRec->blue_mask_size) - 1;
573 pFbInfo->Blue.Position = CbFbRec->blue_mask_pos;
574 pFbInfo->Reserved.Mask = (1 << CbFbRec->reserved_mask_size) - 1;
575 pFbInfo->Reserved.Position = CbFbRec->reserved_mask_pos;
576
577 return RETURN_SUCCESS;
578 }
579