2 This library will parse the coreboot table in memory and extract those required
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
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.
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>
23 #include <IndustryStandard/Acpi.h>
29 static UINT64
cb_unpack64(struct cbuint64 val
)
31 return LShiftU64 (val
.hi
, 32) | val
.lo
;
45 TmpPtr
= (UINT8
*)Buffer
;
46 for(Idx
= 0; Idx
< Length
; Idx
++) {
47 TmpValue
= TmpPtr
[Idx
];
56 Sum
= (Sum
+ (Sum
>> 16)) & 0xFFFF;
60 return (UINT16
)((~Sum
) & 0xFFFF);
69 struct cb_header
*Header
;
70 struct cb_record
*Record
;
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
) {
88 if (Header
== NULL
|| !Header
->table_bytes
)
92 // Check the checksum of the coreboot table header
94 CheckSum
= CbCheckSum16 ((UINT16
*)Header
, sizeof (*Header
));
96 DEBUG ((EFI_D_ERROR
, "Invalid coreboot table header checksum\n"));
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"));
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
)
115 return FindCbTag (TmpPtr
, Tag
);
117 if (Record
->tag
== Tag
) {
121 TmpPtr
+= Record
->size
;
129 IN
struct cbmem_root
*Root
,
131 OUT VOID
**pMemTable
,
132 OUT UINT32
*pMemTableSize
137 struct cbmem_entry
*Entries
;
139 if ((Root
== NULL
) || (pMemTable
== NULL
)) {
140 return RETURN_INVALID_PARAMETER
;
144 // Check if the entry is CBMEM or IMD
145 // and handle them separately
147 Entries
= Root
->entries
;
148 if (Entries
[0].magic
== CBMEM_ENTRY_MAGIC
) {
151 Entries
= (struct cbmem_entry
*)((struct imd_root
*)Root
)->entries
;
152 if (Entries
[0].magic
== IMD_ENTRY_MAGIC
) {
155 return RETURN_NOT_FOUND
;
159 for (Idx
= 0; Idx
< Root
->num_entries
; Idx
++) {
160 if (Entries
[Idx
].id
== TableId
) {
162 *pMemTable
= (VOID
*) ((UINTN
)Entries
[Idx
].start
+ (UINTN
)Root
);
164 *pMemTable
= (VOID
*) (UINTN
)Entries
[Idx
].start
;
166 if (pMemTableSize
!= NULL
) {
167 *pMemTableSize
= Entries
[Idx
].size
;
170 DEBUG ((EFI_D_INFO
, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n", TableId
, *pMemTable
, *pMemTableSize
));
171 return RETURN_SUCCESS
;
175 return RETURN_NOT_FOUND
;
180 Acquire the memory information from the coreboot table in memory.
182 @param pLowMemorySize Pointer to the variable of low memory size
183 @param pHighMemorySize Pointer to the variable of high memory size
185 @retval RETURN_SUCCESS Successfully find out the memory information.
186 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
187 @retval RETURN_NOT_FOUND Failed to find the memory information.
192 IN UINT64
* pLowMemorySize
,
193 IN UINT64
* pHighMemorySize
196 struct cb_memory
* rec
;
197 struct cb_memory_range
* Range
;
202 if ((!pLowMemorySize
) || (!pHighMemorySize
))
203 return RETURN_INVALID_PARAMETER
;
206 // Get the coreboot memory table
208 rec
= (struct cb_memory
*)FindCbTag (0, CB_TAG_MEMORY
);
210 rec
= (struct cb_memory
*)FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_MEMORY
);
213 return RETURN_NOT_FOUND
;
216 *pHighMemorySize
= 0;
218 for (Index
= 0; Index
< MEM_RANGE_COUNT(rec
); Index
++) {
219 Range
= MEM_RANGE_PTR(rec
, Index
);
220 Start
= cb_unpack64(Range
->start
);
221 Size
= cb_unpack64(Range
->size
);
222 DEBUG ((EFI_D_ERROR
, "%d. %016lx - %016lx [%02x]\n",
223 Index
, Start
, Start
+ Size
- 1, Range
->type
));
225 if (Range
->type
!= CB_MEM_RAM
) {
229 if (Start
+ Size
< 0x100000000ULL
) {
230 *pLowMemorySize
= Start
+ Size
;
232 *pHighMemorySize
= Start
+ Size
- 0x100000000ULL
;
236 DEBUG ((EFI_D_ERROR
, "Low memory 0x%lx, High Memory 0x%lx\n", *pLowMemorySize
, *pHighMemorySize
));
238 return RETURN_SUCCESS
;
243 Acquire the coreboot memory table with the given table id
245 @param TableId Table id to be searched
246 @param pMemTable Pointer to the base address of the memory table
247 @param pMemTableSize Pointer to the size of the memory table
249 @retval RETURN_SUCCESS Successfully find out the memory table.
250 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
251 @retval RETURN_NOT_FOUND Failed to find the memory table.
258 IN UINT32
* pMemTableSize
261 struct cb_memory
* rec
;
262 struct cb_memory_range
* Range
;
268 return RETURN_INVALID_PARAMETER
;
273 // Get the coreboot memory table
275 rec
= (struct cb_memory
*)FindCbTag (0, CB_TAG_MEMORY
);
277 rec
= (struct cb_memory
*)FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_MEMORY
);
280 return RETURN_NOT_FOUND
;
282 for (Index
= 0; Index
< MEM_RANGE_COUNT(rec
); Index
++) {
283 Range
= MEM_RANGE_PTR(rec
, Index
);
284 Start
= cb_unpack64(Range
->start
);
285 Size
= cb_unpack64(Range
->size
);
287 if ((Range
->type
== CB_MEM_TABLE
) && (Start
> 0x1000)) {
288 if (FindCbMemTable ((struct cbmem_root
*)(UINTN
)(Start
+ Size
- DYN_CBMEM_ALIGN_SIZE
), TableId
, pMemTable
, pMemTableSize
) == RETURN_SUCCESS
)
289 return RETURN_SUCCESS
;
293 return RETURN_NOT_FOUND
;
298 Acquire the acpi table from coreboot
300 @param pMemTable Pointer to the base address of the memory table
301 @param pMemTableSize Pointer to the size of the memory table
303 @retval RETURN_SUCCESS Successfully find out the memory table.
304 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
305 @retval RETURN_NOT_FOUND Failed to find the memory table.
311 IN UINT32
* pMemTableSize
314 return CbParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), (VOID
**)pMemTable
, pMemTableSize
);
318 Acquire the smbios table from coreboot
320 @param pMemTable Pointer to the base address of the memory table
321 @param pMemTableSize Pointer to the size of the memory table
323 @retval RETURN_SUCCESS Successfully find out the memory table.
324 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
325 @retval RETURN_NOT_FOUND Failed to find the memory table.
331 IN UINT32
* pMemTableSize
334 return CbParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), pMemTable
, pMemTableSize
);
338 Find the required fadt information
340 @param pPmCtrlReg Pointer to the address of power management control register
341 @param pPmTimerReg Pointer to the address of power management timer register
342 @param pResetReg Pointer to the address of system reset register
343 @param pResetValue Pointer to the value to be writen to the system reset register
345 @retval RETURN_SUCCESS Successfully find out all the required fadt information.
346 @retval RETURN_NOT_FOUND Failed to find the fadt table.
351 IN UINTN
* pPmCtrlReg
,
352 IN UINTN
* pPmTimerReg
,
354 IN UINTN
* pResetValue
357 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
* Rsdp
;
358 EFI_ACPI_DESCRIPTION_HEADER
* Rsdt
;
361 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
* Fadt
;
362 EFI_ACPI_DESCRIPTION_HEADER
* Xsdt
;
366 RETURN_STATUS Status
;
369 Status
= RETURN_SUCCESS
;
371 Status
= CbParseAcpiTable (&Rsdp
, NULL
);
372 if (RETURN_ERROR(Status
))
376 return RETURN_NOT_FOUND
;
378 DEBUG ((EFI_D_ERROR
, "Find Rsdp at %p\n", Rsdp
));
379 DEBUG ((EFI_D_ERROR
, "Find Rsdt 0x%x, Xsdt 0x%lx\n", Rsdp
->RsdtAddress
, Rsdp
->XsdtAddress
));
384 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->RsdtAddress
);
386 Entry32
= (UINT32
*)(Rsdt
+ 1);
387 Entry32Num
= (Rsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 2;
388 for (Idx
= 0; Idx
< Entry32Num
; Idx
++) {
389 if (*(UINT32
*)(UINTN
)(Entry32
[Idx
]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
390 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)(UINTN
)(Entry32
[Idx
]);
392 *pPmCtrlReg
= Fadt
->Pm1aCntBlk
;
393 DEBUG ((EFI_D_ERROR
, "PmCtrl Reg 0x%x\n", Fadt
->Pm1aCntBlk
));
396 *pPmTimerReg
= Fadt
->PmTmrBlk
;
397 DEBUG ((EFI_D_ERROR
, "PmTimer Reg 0x%x\n", Fadt
->PmTmrBlk
));
400 *pResetReg
= (UINTN
)Fadt
->ResetReg
.Address
;
401 DEBUG ((EFI_D_ERROR
, "Reset Reg 0x%lx\n", Fadt
->ResetReg
.Address
));
404 *pResetValue
= Fadt
->ResetValue
;
405 DEBUG ((EFI_D_ERROR
, "Reset Value 0x%x\n", Fadt
->ResetValue
));
407 return RETURN_SUCCESS
;
413 // Search Xsdt Second
415 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->XsdtAddress
);
417 Entry64
= (UINT64
*)(Xsdt
+ 1);
418 Entry64Num
= (Xsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 3;
419 for (Idx
= 0; Idx
< Entry64Num
; Idx
++) {
420 if (*(UINT32
*)(UINTN
)(Entry64
[Idx
]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
421 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)(UINTN
)(Entry64
[Idx
]);
423 *pPmCtrlReg
= Fadt
->Pm1aCntBlk
;
424 DEBUG ((EFI_D_ERROR
, "PmCtrl Reg 0x%x\n", Fadt
->Pm1aCntBlk
));
427 *pPmTimerReg
= Fadt
->PmTmrBlk
;
428 DEBUG ((EFI_D_ERROR
, "PmTimer Reg 0x%x\n", Fadt
->PmTmrBlk
));
431 *pResetReg
= (UINTN
)Fadt
->ResetReg
.Address
;
432 DEBUG ((EFI_D_ERROR
, "Reset Reg 0x%lx\n", Fadt
->ResetReg
.Address
));
435 *pResetValue
= Fadt
->ResetValue
;
436 DEBUG ((EFI_D_ERROR
, "Reset Value 0x%x\n", Fadt
->ResetValue
));
438 return RETURN_SUCCESS
;
443 return RETURN_NOT_FOUND
;
447 Find the serial port information
449 @param pRegBase Pointer to the base address of serial port registers
450 @param pRegAccessType Pointer to the access type of serial port registers
451 @param pBaudrate Pointer to the serial port baudrate
453 @retval RETURN_SUCCESS Successfully find the serial port information.
454 @retval RETURN_NOT_FOUND Failed to find the serial port information .
460 IN UINT32
* pRegAccessType
,
464 struct cb_serial
* CbSerial
;
466 CbSerial
= FindCbTag (0, CB_TAG_SERIAL
);
468 CbSerial
= FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_SERIAL
);
471 return RETURN_NOT_FOUND
;
474 *pRegBase
= CbSerial
->baseaddr
;
477 *pRegAccessType
= CbSerial
->type
;
480 *pBaudrate
= CbSerial
->baud
;
482 return RETURN_SUCCESS
;
486 Search for the coreboot table header
488 @param Level Level of the search depth
489 @param HeaderPtr Pointer to the pointer of coreboot table header
491 @retval RETURN_SUCCESS Successfully find the coreboot table header .
492 @retval RETURN_NOT_FOUND Failed to find the coreboot table header .
505 return RETURN_NOT_FOUND
;
508 for (Index
= 0; Index
< Level
; Index
++) {
509 TempPtr
= FindCbTag (TempPtr
, CB_TAG_FORWARD
);
514 if ((Index
>= Level
) && (TempPtr
!= NULL
)) {
515 *HeaderPtr
= TempPtr
;
516 return RETURN_SUCCESS
;
519 return RETURN_NOT_FOUND
;
523 Find the video frame buffer information
525 @param pFbInfo Pointer to the FRAME_BUFFER_INFO structure
527 @retval RETURN_SUCCESS Successfully find the video frame buffer information.
528 @retval RETURN_NOT_FOUND Failed to find the video frame buffer information .
533 IN FRAME_BUFFER_INFO
* pFbInfo
536 struct cb_framebuffer
* CbFbRec
;
539 return RETURN_INVALID_PARAMETER
;
541 CbFbRec
= FindCbTag (0, CB_TAG_FRAMEBUFFER
);
543 CbFbRec
= FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_FRAMEBUFFER
);
546 return RETURN_NOT_FOUND
;
548 DEBUG ((EFI_D_ERROR
, "Found coreboot video frame buffer information\n"));
549 DEBUG ((EFI_D_ERROR
, "physical_address: 0x%lx\n", CbFbRec
->physical_address
));
550 DEBUG ((EFI_D_ERROR
, "x_resolution: 0x%x\n", CbFbRec
->x_resolution
));
551 DEBUG ((EFI_D_ERROR
, "y_resolution: 0x%x\n", CbFbRec
->y_resolution
));
552 DEBUG ((EFI_D_ERROR
, "bits_per_pixel: 0x%x\n", CbFbRec
->bits_per_pixel
));
553 DEBUG ((EFI_D_ERROR
, "bytes_per_line: 0x%x\n", CbFbRec
->bytes_per_line
));
555 DEBUG ((EFI_D_ERROR
, "red_mask_size: 0x%x\n", CbFbRec
->red_mask_size
));
556 DEBUG ((EFI_D_ERROR
, "red_mask_pos: 0x%x\n", CbFbRec
->red_mask_pos
));
557 DEBUG ((EFI_D_ERROR
, "green_mask_size: 0x%x\n", CbFbRec
->green_mask_size
));
558 DEBUG ((EFI_D_ERROR
, "green_mask_pos: 0x%x\n", CbFbRec
->green_mask_pos
));
559 DEBUG ((EFI_D_ERROR
, "blue_mask_size: 0x%x\n", CbFbRec
->blue_mask_size
));
560 DEBUG ((EFI_D_ERROR
, "blue_mask_pos: 0x%x\n", CbFbRec
->blue_mask_pos
));
561 DEBUG ((EFI_D_ERROR
, "reserved_mask_size: 0x%x\n", CbFbRec
->reserved_mask_size
));
562 DEBUG ((EFI_D_ERROR
, "reserved_mask_pos: 0x%x\n", CbFbRec
->reserved_mask_pos
));
564 pFbInfo
->LinearFrameBuffer
= CbFbRec
->physical_address
;
565 pFbInfo
->HorizontalResolution
= CbFbRec
->x_resolution
;
566 pFbInfo
->VerticalResolution
= CbFbRec
->y_resolution
;
567 pFbInfo
->BitsPerPixel
= CbFbRec
->bits_per_pixel
;
568 pFbInfo
->BytesPerScanLine
= (UINT16
)CbFbRec
->bytes_per_line
;
569 pFbInfo
->Red
.Mask
= (1 << CbFbRec
->red_mask_size
) - 1;
570 pFbInfo
->Red
.Position
= CbFbRec
->red_mask_pos
;
571 pFbInfo
->Green
.Mask
= (1 << CbFbRec
->green_mask_size
) - 1;
572 pFbInfo
->Green
.Position
= CbFbRec
->green_mask_pos
;
573 pFbInfo
->Blue
.Mask
= (1 << CbFbRec
->blue_mask_size
) - 1;
574 pFbInfo
->Blue
.Position
= CbFbRec
->blue_mask_pos
;
575 pFbInfo
->Reserved
.Mask
= (1 << CbFbRec
->reserved_mask_size
) - 1;
576 pFbInfo
->Reserved
.Position
= CbFbRec
->reserved_mask_pos
;
578 return RETURN_SUCCESS
;