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 Convert a packed value from cbuint64 to a UINT64 value.
31 @param val The pointer to packed data.
33 @return the UNIT64 value after convertion.
38 IN
struct cbuint64 val
41 return LShiftU64 (val
.hi
, 32) | val
.lo
;
46 Returns the sum of all elements in a buffer of 16-bit values. During
47 calculation, the carry bits are also been added.
49 @param Buffer The pointer to the buffer to carry out the sum operation.
50 @param Length The size, in bytes, of Buffer.
52 @return Sum The sum of Buffer with carry bits included during additions.
66 TmpPtr
= (UINT8
*)Buffer
;
67 for(Idx
= 0; Idx
< Length
; Idx
++) {
68 TmpValue
= TmpPtr
[Idx
];
77 Sum
= (Sum
+ (Sum
>> 16)) & 0xFFFF;
81 return (UINT16
)((~Sum
) & 0xFFFF);
86 Find coreboot record with given Tag from the memory Start in 4096
89 @param Start The start memory to be searched in
90 @param Tag The tag id to be found
92 @retval NULL The Tag is not found.
93 @retval Others The poiter to the record found.
102 struct cb_header
*Header
;
103 struct cb_record
*Record
;
110 TmpPtr
= (UINT8
*)Start
;
111 for (Idx
= 0; Idx
< 4096; Idx
+= 16, TmpPtr
+= 16) {
112 Header
= (struct cb_header
*)TmpPtr
;
113 if (Header
->signature
== CB_HEADER_SIGNATURE
) {
122 if ((Header
== NULL
) || (Header
->table_bytes
== 0)) {
127 // Check the checksum of the coreboot table header
129 CheckSum
= CbCheckSum16 ((UINT16
*)Header
, sizeof (*Header
));
131 DEBUG ((EFI_D_ERROR
, "Invalid coreboot table header checksum\n"));
135 CheckSum
= CbCheckSum16 ((UINT16
*)(TmpPtr
+ sizeof (*Header
)), Header
->table_bytes
);
136 if (CheckSum
!= Header
->table_checksum
) {
137 DEBUG ((EFI_D_ERROR
, "Incorrect checksum of all the coreboot table entries\n"));
142 TmpPtr
+= Header
->header_bytes
;
143 for (Idx
= 0; Idx
< Header
->table_entries
; Idx
++) {
144 Record
= (struct cb_record
*)TmpPtr
;
145 if (Record
->tag
== CB_TAG_FORWARD
) {
146 TmpPtr
= (VOID
*)(UINTN
)((struct cb_forward
*)(UINTN
)Record
)->forward
;
147 if (Tag
== CB_TAG_FORWARD
) {
150 return FindCbTag (TmpPtr
, Tag
);
153 if (Record
->tag
== Tag
) {
157 TmpPtr
+= Record
->size
;
165 Find the given table with TableId from the given coreboot memory Root.
167 @param Root The coreboot memory table to be searched in
168 @param TableId Table id to be found
169 @param pMemTable To save the base address of the memory table found
170 @param pMemTableSize To save the size of memory table found
172 @retval RETURN_SUCCESS Successfully find out the memory table.
173 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
174 @retval RETURN_NOT_FOUND Failed to find the memory table.
179 IN
struct cbmem_root
*Root
,
181 OUT VOID
**pMemTable
,
182 OUT UINT32
*pMemTableSize
187 struct cbmem_entry
*Entries
;
189 if ((Root
== NULL
) || (pMemTable
== NULL
)) {
190 return RETURN_INVALID_PARAMETER
;
193 // Check if the entry is CBMEM or IMD
194 // and handle them separately
196 Entries
= Root
->entries
;
197 if (Entries
[0].magic
== CBMEM_ENTRY_MAGIC
) {
200 Entries
= (struct cbmem_entry
*)((struct imd_root
*)Root
)->entries
;
201 if (Entries
[0].magic
== IMD_ENTRY_MAGIC
) {
204 return RETURN_NOT_FOUND
;
208 for (Idx
= 0; Idx
< Root
->num_entries
; Idx
++) {
209 if (Entries
[Idx
].id
== TableId
) {
211 *pMemTable
= (VOID
*) ((UINTN
)Entries
[Idx
].start
+ (UINTN
)Root
);
213 *pMemTable
= (VOID
*) (UINTN
)Entries
[Idx
].start
;
215 if (pMemTableSize
!= NULL
) {
216 *pMemTableSize
= Entries
[Idx
].size
;
219 DEBUG ((EFI_D_INFO
, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n",
220 TableId
, *pMemTable
, Entries
[Idx
].size
));
221 return RETURN_SUCCESS
;
225 return RETURN_NOT_FOUND
;
230 Acquire the memory information from the coreboot table in memory.
232 @param pLowMemorySize Pointer to the variable of low memory size
233 @param pHighMemorySize Pointer to the variable of high memory size
235 @retval RETURN_SUCCESS Successfully find out the memory information.
236 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
237 @retval RETURN_NOT_FOUND Failed to find the memory information.
242 OUT UINT64
*pLowMemorySize
,
243 OUT UINT64
*pHighMemorySize
246 struct cb_memory
*rec
;
247 struct cb_memory_range
*Range
;
252 if ((pLowMemorySize
== NULL
) || (pHighMemorySize
== NULL
)) {
253 return RETURN_INVALID_PARAMETER
;
257 // Get the coreboot memory table
259 rec
= (struct cb_memory
*)FindCbTag (0, CB_TAG_MEMORY
);
261 rec
= (struct cb_memory
*)FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_MEMORY
);
265 return RETURN_NOT_FOUND
;
269 *pHighMemorySize
= 0;
271 for (Index
= 0; Index
< MEM_RANGE_COUNT(rec
); Index
++) {
272 Range
= MEM_RANGE_PTR(rec
, Index
);
273 Start
= cb_unpack64(Range
->start
);
274 Size
= cb_unpack64(Range
->size
);
275 DEBUG ((EFI_D_INFO
, "%d. %016lx - %016lx [%02x]\n",
276 Index
, Start
, Start
+ Size
- 1, Range
->type
));
278 if (Range
->type
!= CB_MEM_RAM
) {
282 if (Start
+ Size
< 0x100000000ULL
) {
283 *pLowMemorySize
= Start
+ Size
;
285 *pHighMemorySize
= Start
+ Size
- 0x100000000ULL
;
289 DEBUG ((EFI_D_INFO
, "Low memory 0x%lx, High Memory 0x%lx\n", *pLowMemorySize
, *pHighMemorySize
));
291 return RETURN_SUCCESS
;
296 Acquire the coreboot memory table with the given table id
298 @param TableId Table id to be searched
299 @param pMemTable Pointer to the base address of the memory table
300 @param pMemTableSize Pointer to the size of the memory table
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.
310 OUT VOID
**pMemTable
,
311 OUT UINT32
*pMemTableSize
314 struct cb_memory
*rec
;
315 struct cb_memory_range
*Range
;
320 if (pMemTable
== NULL
) {
321 return RETURN_INVALID_PARAMETER
;
326 // Get the coreboot memory table
328 rec
= (struct cb_memory
*)FindCbTag (0, CB_TAG_MEMORY
);
330 rec
= (struct cb_memory
*)FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_MEMORY
);
334 return RETURN_NOT_FOUND
;
337 for (Index
= 0; Index
< MEM_RANGE_COUNT(rec
); Index
++) {
338 Range
= MEM_RANGE_PTR(rec
, Index
);
339 Start
= cb_unpack64(Range
->start
);
340 Size
= cb_unpack64(Range
->size
);
342 if ((Range
->type
== CB_MEM_TABLE
) && (Start
> 0x1000)) {
343 if (FindCbMemTable ((struct cbmem_root
*)(UINTN
)(Start
+ Size
- DYN_CBMEM_ALIGN_SIZE
), TableId
, pMemTable
, pMemTableSize
) == RETURN_SUCCESS
)
344 return RETURN_SUCCESS
;
348 return RETURN_NOT_FOUND
;
353 Acquire the acpi table from coreboot
355 @param pMemTable Pointer to the base address of the memory table
356 @param pMemTableSize Pointer to the size of the memory table
358 @retval RETURN_SUCCESS Successfully find out the memory table.
359 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
360 @retval RETURN_NOT_FOUND Failed to find the memory table.
365 OUT VOID
**pMemTable
,
366 OUT UINT32
*pMemTableSize
369 return CbParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), pMemTable
, pMemTableSize
);
373 Acquire the smbios table from coreboot
375 @param pMemTable Pointer to the base address of the memory table
376 @param pMemTableSize Pointer to the size of the memory table
378 @retval RETURN_SUCCESS Successfully find out the memory table.
379 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
380 @retval RETURN_NOT_FOUND Failed to find the memory table.
385 OUT VOID
**pMemTable
,
386 OUT UINT32
*pMemTableSize
389 return CbParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), pMemTable
, pMemTableSize
);
393 Find the required fadt information
395 @param pPmCtrlReg Pointer to the address of power management control register
396 @param pPmTimerReg Pointer to the address of power management timer register
397 @param pResetReg Pointer to the address of system reset register
398 @param pResetValue Pointer to the value to be writen to the system reset register
399 @param pPmEvtReg Pointer to the address of power management event register
400 @param pPmGpeEnReg Pointer to the address of power management GPE enable register
402 @retval RETURN_SUCCESS Successfully find out all the required fadt information.
403 @retval RETURN_NOT_FOUND Failed to find the fadt table.
408 OUT UINTN
*pPmCtrlReg
,
409 OUT UINTN
*pPmTimerReg
,
410 OUT UINTN
*pResetReg
,
411 OUT UINTN
*pResetValue
,
412 OUT UINTN
*pPmEvtReg
,
413 OUT UINTN
*pPmGpeEnReg
416 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*Rsdp
;
417 EFI_ACPI_DESCRIPTION_HEADER
*Rsdt
;
420 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*Fadt
;
421 EFI_ACPI_DESCRIPTION_HEADER
*Xsdt
;
425 RETURN_STATUS Status
;
428 Status
= RETURN_SUCCESS
;
430 Status
= CbParseAcpiTable ((VOID
**)&Rsdp
, NULL
);
431 if (RETURN_ERROR(Status
)) {
436 return RETURN_NOT_FOUND
;
439 DEBUG ((EFI_D_INFO
, "Find Rsdp at %p\n", Rsdp
));
440 DEBUG ((EFI_D_INFO
, "Find Rsdt 0x%x, Xsdt 0x%lx\n", Rsdp
->RsdtAddress
, Rsdp
->XsdtAddress
));
445 Rsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->RsdtAddress
);
447 Entry32
= (UINT32
*)(Rsdt
+ 1);
448 Entry32Num
= (Rsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 2;
449 for (Idx
= 0; Idx
< Entry32Num
; Idx
++) {
450 if (*(UINT32
*)(UINTN
)(Entry32
[Idx
]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
451 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)(UINTN
)(Entry32
[Idx
]);
452 if (pPmCtrlReg
!= NULL
) {
453 *pPmCtrlReg
= Fadt
->Pm1aCntBlk
;
455 DEBUG ((EFI_D_INFO
, "PmCtrl Reg 0x%x\n", Fadt
->Pm1aCntBlk
));
457 if (pPmTimerReg
!= NULL
) {
458 *pPmTimerReg
= Fadt
->PmTmrBlk
;
460 DEBUG ((EFI_D_INFO
, "PmTimer Reg 0x%x\n", Fadt
->PmTmrBlk
));
462 if (pResetReg
!= NULL
) {
463 *pResetReg
= (UINTN
)Fadt
->ResetReg
.Address
;
465 DEBUG ((EFI_D_INFO
, "Reset Reg 0x%lx\n", Fadt
->ResetReg
.Address
));
467 if (pResetValue
!= NULL
) {
468 *pResetValue
= Fadt
->ResetValue
;
470 DEBUG ((EFI_D_INFO
, "Reset Value 0x%x\n", Fadt
->ResetValue
));
472 if (pPmEvtReg
!= NULL
) {
473 *pPmEvtReg
= Fadt
->Pm1aEvtBlk
;
474 DEBUG ((EFI_D_INFO
, "PmEvt Reg 0x%x\n", Fadt
->Pm1aEvtBlk
));
477 if (pPmGpeEnReg
!= NULL
) {
478 *pPmGpeEnReg
= Fadt
->Gpe0Blk
+ Fadt
->Gpe0BlkLen
/ 2;
479 DEBUG ((EFI_D_INFO
, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg
));
483 // Verify values for proper operation
485 ASSERT(Fadt
->Pm1aCntBlk
!= 0);
486 ASSERT(Fadt
->PmTmrBlk
!= 0);
487 ASSERT(Fadt
->ResetReg
.Address
!= 0);
488 ASSERT(Fadt
->Pm1aEvtBlk
!= 0);
489 ASSERT(Fadt
->Gpe0Blk
!= 0);
491 return RETURN_SUCCESS
;
497 // Search Xsdt Second
499 Xsdt
= (EFI_ACPI_DESCRIPTION_HEADER
*)(UINTN
)(Rsdp
->XsdtAddress
);
501 Entry64
= (UINT64
*)(Xsdt
+ 1);
502 Entry64Num
= (Xsdt
->Length
- sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) >> 3;
503 for (Idx
= 0; Idx
< Entry64Num
; Idx
++) {
504 if (*(UINT32
*)(UINTN
)(Entry64
[Idx
]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
) {
505 Fadt
= (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
*)(UINTN
)(Entry64
[Idx
]);
507 *pPmCtrlReg
= Fadt
->Pm1aCntBlk
;
508 DEBUG ((EFI_D_ERROR
, "PmCtrl Reg 0x%x\n", Fadt
->Pm1aCntBlk
));
511 *pPmTimerReg
= Fadt
->PmTmrBlk
;
512 DEBUG ((EFI_D_ERROR
, "PmTimer Reg 0x%x\n", Fadt
->PmTmrBlk
));
515 *pResetReg
= (UINTN
)Fadt
->ResetReg
.Address
;
516 DEBUG ((EFI_D_ERROR
, "Reset Reg 0x%lx\n", Fadt
->ResetReg
.Address
));
519 *pResetValue
= Fadt
->ResetValue
;
520 DEBUG ((EFI_D_ERROR
, "Reset Value 0x%x\n", Fadt
->ResetValue
));
522 if (pPmEvtReg
!= NULL
) {
523 *pPmEvtReg
= Fadt
->Pm1aEvtBlk
;
524 DEBUG ((EFI_D_INFO
, "PmEvt Reg 0x%x\n", Fadt
->Pm1aEvtBlk
));
527 if (pPmGpeEnReg
!= NULL
) {
528 *pPmGpeEnReg
= Fadt
->Gpe0Blk
+ Fadt
->Gpe0BlkLen
/ 2;
529 DEBUG ((EFI_D_INFO
, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg
));
531 return RETURN_SUCCESS
;
536 return RETURN_NOT_FOUND
;
540 Find the serial port information
542 @param pRegBase Pointer to the base address of serial port registers
543 @param pRegAccessType Pointer to the access type of serial port registers
544 @param pRegWidth Pointer to the register width in bytes
545 @param pBaudrate Pointer to the serial port baudrate
546 @param pInputHertz Pointer to the input clock frequency
547 @param pUartPciAddr Pointer to the UART PCI bus, dev and func address
549 @retval RETURN_SUCCESS Successfully find the serial port information.
550 @retval RETURN_NOT_FOUND Failed to find the serial port information .
555 OUT UINT32
*pRegBase
,
556 OUT UINT32
*pRegAccessType
,
557 OUT UINT32
*pRegWidth
,
558 OUT UINT32
*pBaudrate
,
559 OUT UINT32
*pInputHertz
,
560 OUT UINT32
*pUartPciAddr
563 struct cb_serial
*CbSerial
;
565 CbSerial
= FindCbTag (0, CB_TAG_SERIAL
);
566 if (CbSerial
== NULL
) {
567 CbSerial
= FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_SERIAL
);
570 if (CbSerial
== NULL
) {
571 return RETURN_NOT_FOUND
;
574 if (pRegBase
!= NULL
) {
575 *pRegBase
= CbSerial
->baseaddr
;
578 if (pRegWidth
!= NULL
) {
579 *pRegWidth
= CbSerial
->regwidth
;
582 if (pRegAccessType
!= NULL
) {
583 *pRegAccessType
= CbSerial
->type
;
586 if (pBaudrate
!= NULL
) {
587 *pBaudrate
= CbSerial
->baud
;
590 if (pInputHertz
!= NULL
) {
591 *pInputHertz
= CbSerial
->input_hertz
;
594 if (pUartPciAddr
!= NULL
) {
595 *pUartPciAddr
= CbSerial
->uart_pci_addr
;
598 return RETURN_SUCCESS
;
602 Search for the coreboot table header
604 @param Level Level of the search depth
605 @param HeaderPtr Pointer to the pointer of coreboot table header
607 @retval RETURN_SUCCESS Successfully find the coreboot table header .
608 @retval RETURN_NOT_FOUND Failed to find the coreboot table header .
620 if (HeaderPtr
== NULL
) {
621 return RETURN_NOT_FOUND
;
625 for (Index
= 0; Index
< Level
; Index
++) {
626 TempPtr
= FindCbTag (TempPtr
, CB_TAG_FORWARD
);
627 if (TempPtr
== NULL
) {
632 if ((Index
>= Level
) && (TempPtr
!= NULL
)) {
633 *HeaderPtr
= TempPtr
;
634 return RETURN_SUCCESS
;
637 return RETURN_NOT_FOUND
;
641 Find the video frame buffer information
643 @param pFbInfo Pointer to the FRAME_BUFFER_INFO structure
645 @retval RETURN_SUCCESS Successfully find the video frame buffer information.
646 @retval RETURN_NOT_FOUND Failed to find the video frame buffer information .
651 OUT FRAME_BUFFER_INFO
*pFbInfo
654 struct cb_framebuffer
*CbFbRec
;
656 if (pFbInfo
== NULL
) {
657 return RETURN_INVALID_PARAMETER
;
660 CbFbRec
= FindCbTag (0, CB_TAG_FRAMEBUFFER
);
661 if (CbFbRec
== NULL
) {
662 CbFbRec
= FindCbTag ((VOID
*)(UINTN
)PcdGet32 (PcdCbHeaderPointer
), CB_TAG_FRAMEBUFFER
);
665 if (CbFbRec
== NULL
) {
666 return RETURN_NOT_FOUND
;
669 DEBUG ((EFI_D_INFO
, "Found coreboot video frame buffer information\n"));
670 DEBUG ((EFI_D_INFO
, "physical_address: 0x%lx\n", CbFbRec
->physical_address
));
671 DEBUG ((EFI_D_INFO
, "x_resolution: 0x%x\n", CbFbRec
->x_resolution
));
672 DEBUG ((EFI_D_INFO
, "y_resolution: 0x%x\n", CbFbRec
->y_resolution
));
673 DEBUG ((EFI_D_INFO
, "bits_per_pixel: 0x%x\n", CbFbRec
->bits_per_pixel
));
674 DEBUG ((EFI_D_INFO
, "bytes_per_line: 0x%x\n", CbFbRec
->bytes_per_line
));
676 DEBUG ((EFI_D_INFO
, "red_mask_size: 0x%x\n", CbFbRec
->red_mask_size
));
677 DEBUG ((EFI_D_INFO
, "red_mask_pos: 0x%x\n", CbFbRec
->red_mask_pos
));
678 DEBUG ((EFI_D_INFO
, "green_mask_size: 0x%x\n", CbFbRec
->green_mask_size
));
679 DEBUG ((EFI_D_INFO
, "green_mask_pos: 0x%x\n", CbFbRec
->green_mask_pos
));
680 DEBUG ((EFI_D_INFO
, "blue_mask_size: 0x%x\n", CbFbRec
->blue_mask_size
));
681 DEBUG ((EFI_D_INFO
, "blue_mask_pos: 0x%x\n", CbFbRec
->blue_mask_pos
));
682 DEBUG ((EFI_D_INFO
, "reserved_mask_size: 0x%x\n", CbFbRec
->reserved_mask_size
));
683 DEBUG ((EFI_D_INFO
, "reserved_mask_pos: 0x%x\n", CbFbRec
->reserved_mask_pos
));
685 pFbInfo
->LinearFrameBuffer
= CbFbRec
->physical_address
;
686 pFbInfo
->HorizontalResolution
= CbFbRec
->x_resolution
;
687 pFbInfo
->VerticalResolution
= CbFbRec
->y_resolution
;
688 pFbInfo
->BitsPerPixel
= CbFbRec
->bits_per_pixel
;
689 pFbInfo
->BytesPerScanLine
= (UINT16
)CbFbRec
->bytes_per_line
;
690 pFbInfo
->Red
.Mask
= (1 << CbFbRec
->red_mask_size
) - 1;
691 pFbInfo
->Red
.Position
= CbFbRec
->red_mask_pos
;
692 pFbInfo
->Green
.Mask
= (1 << CbFbRec
->green_mask_size
) - 1;
693 pFbInfo
->Green
.Position
= CbFbRec
->green_mask_pos
;
694 pFbInfo
->Blue
.Mask
= (1 << CbFbRec
->blue_mask_size
) - 1;
695 pFbInfo
->Blue
.Position
= CbFbRec
->blue_mask_pos
;
696 pFbInfo
->Reserved
.Mask
= (1 << CbFbRec
->reserved_mask_size
) - 1;
697 pFbInfo
->Reserved
.Position
= CbFbRec
->reserved_mask_pos
;
699 return RETURN_SUCCESS
;