]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/Library/CbParseLib/CbParseLib.c
UefiPayloadPkg: Add PCI root bridge info hob support for SBL
[mirror_edk2.git] / UefiPayloadPkg / 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 - 2021, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Uefi/UefiBaseType.h>
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/IoLib.h>
16 #include <Library/BlParseLib.h>
17 #include <IndustryStandard/Acpi.h>
18 #include <Coreboot.h>
19
20
21 /**
22 Convert a packed value from cbuint64 to a UINT64 value.
23
24 @param val The pointer to packed data.
25
26 @return the UNIT64 value after conversion.
27
28 **/
29 UINT64
30 cb_unpack64 (
31 IN struct cbuint64 val
32 )
33 {
34 return LShiftU64 (val.hi, 32) | val.lo;
35 }
36
37
38 /**
39 Returns the sum of all elements in a buffer of 16-bit values. During
40 calculation, the carry bits are also been added.
41
42 @param Buffer The pointer to the buffer to carry out the sum operation.
43 @param Length The size, in bytes, of Buffer.
44
45 @return Sum The sum of Buffer with carry bits included during additions.
46
47 **/
48 UINT16
49 CbCheckSum16 (
50 IN UINT16 *Buffer,
51 IN UINTN Length
52 )
53 {
54 UINT32 Sum;
55 UINT32 TmpValue;
56 UINTN Idx;
57 UINT8 *TmpPtr;
58
59 Sum = 0;
60 TmpPtr = (UINT8 *)Buffer;
61 for(Idx = 0; Idx < Length; Idx++) {
62 TmpValue = TmpPtr[Idx];
63 if (Idx % 2 == 1) {
64 TmpValue <<= 8;
65 }
66
67 Sum += TmpValue;
68
69 // Wrap
70 if (Sum >= 0x10000) {
71 Sum = (Sum + (Sum >> 16)) & 0xFFFF;
72 }
73 }
74
75 return (UINT16)((~Sum) & 0xFFFF);
76 }
77
78
79 /**
80 Check the coreboot table if it is valid.
81
82 @param Header Pointer to coreboot table
83
84 @retval TRUE The coreboot table is valid.
85 @retval Others The coreboot table is not valid.
86
87 **/
88 BOOLEAN
89 IsValidCbTable (
90 IN struct cb_header *Header
91 )
92 {
93 UINT16 CheckSum;
94
95 if ((Header == NULL) || (Header->table_bytes == 0)) {
96 return FALSE;
97 }
98
99 if (Header->signature != CB_HEADER_SIGNATURE) {
100 return FALSE;
101 }
102
103 //
104 // Check the checksum of the coreboot table header
105 //
106 CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header));
107 if (CheckSum != 0) {
108 DEBUG ((DEBUG_ERROR, "Invalid coreboot table header checksum\n"));
109 return FALSE;
110 }
111
112 CheckSum = CbCheckSum16 ((UINT16 *)((UINT8 *)Header + sizeof (*Header)), Header->table_bytes);
113 if (CheckSum != Header->table_checksum) {
114 DEBUG ((DEBUG_ERROR, "Incorrect checksum of all the coreboot table entries\n"));
115 return FALSE;
116 }
117
118 return TRUE;
119 }
120
121
122 /**
123 This function retrieves the parameter base address from boot loader.
124
125 This function will get bootloader specific parameter address for UEFI payload.
126 e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot.
127
128 @retval NULL Failed to find the GUID HOB.
129 @retval others GUIDed HOB data pointer.
130
131 **/
132 VOID *
133 EFIAPI
134 GetParameterBase (
135 VOID
136 )
137 {
138 struct cb_header *Header;
139 struct cb_record *Record;
140 UINT8 *TmpPtr;
141 UINT8 *CbTablePtr;
142 UINTN Idx;
143 EFI_STATUS Status;
144
145 //
146 // coreboot could pass coreboot table to UEFI payload
147 //
148 Header = (struct cb_header *)(UINTN)GET_BOOTLOADER_PARAMETER ();
149 if (IsValidCbTable (Header)) {
150 return Header;
151 }
152
153 //
154 // Find simplified coreboot table in memory range 0 ~ 4KB.
155 // Some GCC version does not allow directly access to NULL pointer,
156 // so start the search from 0x10 instead.
157 //
158 for (Idx = 16; Idx < 4096; Idx += 16) {
159 Header = (struct cb_header *)Idx;
160 if (Header->signature == CB_HEADER_SIGNATURE) {
161 break;
162 }
163 }
164
165 if (Idx >= 4096) {
166 return NULL;
167 }
168
169 //
170 // Check the coreboot header
171 //
172 if (!IsValidCbTable (Header)) {
173 return NULL;
174 }
175
176 //
177 // Find full coreboot table in high memory
178 //
179 CbTablePtr = NULL;
180 TmpPtr = (UINT8 *)Header + Header->header_bytes;
181 for (Idx = 0; Idx < Header->table_entries; Idx++) {
182 Record = (struct cb_record *)TmpPtr;
183 if (Record->tag == CB_TAG_FORWARD) {
184 CbTablePtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward;
185 break;
186 }
187 TmpPtr += Record->size;
188 }
189
190 //
191 // Check the coreboot header in high memory
192 //
193 if (!IsValidCbTable ((struct cb_header *)CbTablePtr)) {
194 return NULL;
195 }
196
197 PcdSet64S (PcdBootloaderParameter, (UINTN)CbTablePtr);
198 ASSERT_EFI_STATUS (Status);
199
200 return CbTablePtr;
201 }
202
203
204 /**
205 Find coreboot record with given Tag.
206
207 @param Tag The tag id to be found
208
209 @retval NULL The Tag is not found.
210 @retval Others The pointer to the record found.
211
212 **/
213 VOID *
214 FindCbTag (
215 IN UINT32 Tag
216 )
217 {
218 struct cb_header *Header;
219 struct cb_record *Record;
220 UINT8 *TmpPtr;
221 UINT8 *TagPtr;
222 UINTN Idx;
223
224 Header = (struct cb_header *) GetParameterBase ();
225
226 TagPtr = NULL;
227 TmpPtr = (UINT8 *)Header + Header->header_bytes;
228 for (Idx = 0; Idx < Header->table_entries; Idx++) {
229 Record = (struct cb_record *)TmpPtr;
230 if (Record->tag == Tag) {
231 TagPtr = TmpPtr;
232 break;
233 }
234 TmpPtr += Record->size;
235 }
236
237 return TagPtr;
238 }
239
240
241 /**
242 Find the given table with TableId from the given coreboot memory Root.
243
244 @param Root The coreboot memory table to be searched in
245 @param TableId Table id to be found
246 @param MemTable To save the base address of the memory table found
247 @param MemTableSize To save the size of memory table found
248
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.
252
253 **/
254 RETURN_STATUS
255 FindCbMemTable (
256 IN struct cbmem_root *Root,
257 IN UINT32 TableId,
258 OUT VOID **MemTable,
259 OUT UINT32 *MemTableSize
260 )
261 {
262 UINTN Idx;
263 BOOLEAN IsImdEntry;
264 struct cbmem_entry *Entries;
265
266 if ((Root == NULL) || (MemTable == NULL)) {
267 return RETURN_INVALID_PARAMETER;
268 }
269 //
270 // Check if the entry is CBMEM or IMD
271 // and handle them separately
272 //
273 Entries = Root->entries;
274 if (Entries[0].magic == CBMEM_ENTRY_MAGIC) {
275 IsImdEntry = FALSE;
276 } else {
277 Entries = (struct cbmem_entry *)((struct imd_root *)Root)->entries;
278 if (Entries[0].magic == IMD_ENTRY_MAGIC) {
279 IsImdEntry = TRUE;
280 } else {
281 return RETURN_NOT_FOUND;
282 }
283 }
284
285 for (Idx = 0; Idx < Root->num_entries; Idx++) {
286 if (Entries[Idx].id == TableId) {
287 if (IsImdEntry) {
288 *MemTable = (VOID *) ((UINTN)Entries[Idx].start + (UINTN)Root);
289 } else {
290 *MemTable = (VOID *) (UINTN)Entries[Idx].start;
291 }
292 if (MemTableSize != NULL) {
293 *MemTableSize = Entries[Idx].size;
294 }
295
296 DEBUG ((DEBUG_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n",
297 TableId, *MemTable, Entries[Idx].size));
298 return RETURN_SUCCESS;
299 }
300 }
301
302 return RETURN_NOT_FOUND;
303 }
304
305 /**
306 Acquire the coreboot memory table with the given table id
307
308 @param TableId Table id to be searched
309 @param MemTable Pointer to the base address of the memory table
310 @param MemTableSize Pointer to the size of the memory table
311
312 @retval RETURN_SUCCESS Successfully find out the memory table.
313 @retval RETURN_INVALID_PARAMETER Invalid input parameters.
314 @retval RETURN_NOT_FOUND Failed to find the memory table.
315
316 **/
317 RETURN_STATUS
318 ParseCbMemTable (
319 IN UINT32 TableId,
320 OUT VOID **MemTable,
321 OUT UINT32 *MemTableSize
322 )
323 {
324 EFI_STATUS Status;
325 struct cb_memory *rec;
326 struct cb_memory_range *Range;
327 UINT64 Start;
328 UINT64 Size;
329 UINTN Index;
330 struct cbmem_root *CbMemRoot;
331
332 if (MemTable == NULL) {
333 return RETURN_INVALID_PARAMETER;
334 }
335
336 *MemTable = NULL;
337 Status = RETURN_NOT_FOUND;
338
339 //
340 // Get the coreboot memory table
341 //
342 rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY);
343 if (rec == NULL) {
344 return Status;
345 }
346
347 for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
348 Range = MEM_RANGE_PTR(rec, Index);
349 Start = cb_unpack64(Range->start);
350 Size = cb_unpack64(Range->size);
351
352 if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) {
353 CbMemRoot = (struct cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE);
354 Status = FindCbMemTable (CbMemRoot, TableId, MemTable, MemTableSize);
355 if (!EFI_ERROR (Status)) {
356 break;
357 }
358 }
359 }
360
361 return Status;
362 }
363
364
365
366 /**
367 Acquire the memory information from the coreboot table in memory.
368
369 @param MemInfoCallback The callback routine
370 @param Params Pointer to the callback routine parameter
371
372 @retval RETURN_SUCCESS Successfully find out the memory information.
373 @retval RETURN_NOT_FOUND Failed to find the memory information.
374
375 **/
376 RETURN_STATUS
377 EFIAPI
378 ParseMemoryInfo (
379 IN BL_MEM_INFO_CALLBACK MemInfoCallback,
380 IN VOID *Params
381 )
382 {
383 struct cb_memory *rec;
384 struct cb_memory_range *Range;
385 UINTN Index;
386 MEMROY_MAP_ENTRY MemoryMap;
387
388 //
389 // Get the coreboot memory table
390 //
391 rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY);
392 if (rec == NULL) {
393 return RETURN_NOT_FOUND;
394 }
395
396 for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
397 Range = MEM_RANGE_PTR(rec, Index);
398 MemoryMap.Base = cb_unpack64(Range->start);
399 MemoryMap.Size = cb_unpack64(Range->size);
400 MemoryMap.Type = (UINT8)Range->type;
401 MemoryMap.Flag = 0;
402 DEBUG ((DEBUG_INFO, "%d. %016lx - %016lx [%02x]\n",
403 Index, MemoryMap.Base, MemoryMap.Base + MemoryMap.Size - 1, MemoryMap.Type));
404
405 MemInfoCallback (&MemoryMap, Params);
406 }
407
408 return RETURN_SUCCESS;
409 }
410
411
412 /**
413 Acquire acpi table and smbios table from coreboot
414
415 @param SystemTableInfo Pointer to the system table info
416
417 @retval RETURN_SUCCESS Successfully find out the tables.
418 @retval RETURN_NOT_FOUND Failed to find the tables.
419
420 **/
421 RETURN_STATUS
422 EFIAPI
423 ParseSystemTable (
424 OUT SYSTEM_TABLE_INFO *SystemTableInfo
425 )
426 {
427 EFI_STATUS Status;
428 VOID *MemTable;
429 UINT32 MemTableSize;
430
431 Status = ParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), &MemTable, &MemTableSize);
432 if (EFI_ERROR (Status)) {
433 return EFI_NOT_FOUND;
434 }
435 SystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)MemTable;
436 SystemTableInfo->SmbiosTableSize = MemTableSize;
437
438 Status = ParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), &MemTable, &MemTableSize);
439 if (EFI_ERROR (Status)) {
440 return EFI_NOT_FOUND;
441 }
442 SystemTableInfo->AcpiTableBase = (UINT64) (UINTN)MemTable;
443 SystemTableInfo->AcpiTableSize = MemTableSize;
444
445 return Status;
446 }
447
448
449 /**
450 Find the serial port information
451
452 @param SERIAL_PORT_INFO Pointer to serial port info structure
453
454 @retval RETURN_SUCCESS Successfully find the serial port information.
455 @retval RETURN_NOT_FOUND Failed to find the serial port information .
456
457 **/
458 RETURN_STATUS
459 EFIAPI
460 ParseSerialInfo (
461 OUT SERIAL_PORT_INFO *SerialPortInfo
462 )
463 {
464 struct cb_serial *CbSerial;
465
466 CbSerial = FindCbTag (CB_TAG_SERIAL);
467 if (CbSerial == NULL) {
468 return RETURN_NOT_FOUND;
469 }
470
471 SerialPortInfo->BaseAddr = CbSerial->baseaddr;
472 SerialPortInfo->RegWidth = CbSerial->regwidth;
473 SerialPortInfo->Type = CbSerial->type;
474 SerialPortInfo->Baud = CbSerial->baud;
475 SerialPortInfo->InputHertz = CbSerial->input_hertz;
476 SerialPortInfo->UartPciAddr = CbSerial->uart_pci_addr;
477
478 return RETURN_SUCCESS;
479 }
480
481 /**
482 Find the video frame buffer information
483
484 @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure
485
486 @retval RETURN_SUCCESS Successfully find the video frame buffer information.
487 @retval RETURN_NOT_FOUND Failed to find the video frame buffer information .
488
489 **/
490 RETURN_STATUS
491 EFIAPI
492 ParseGfxInfo (
493 OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo
494 )
495 {
496 struct cb_framebuffer *CbFbRec;
497 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GfxMode;
498
499 if (GfxInfo == NULL) {
500 return RETURN_INVALID_PARAMETER;
501 }
502
503 CbFbRec = FindCbTag (CB_TAG_FRAMEBUFFER);
504 if (CbFbRec == NULL) {
505 return RETURN_NOT_FOUND;
506 }
507
508 DEBUG ((DEBUG_INFO, "Found coreboot video frame buffer information\n"));
509 DEBUG ((DEBUG_INFO, "physical_address: 0x%lx\n", CbFbRec->physical_address));
510 DEBUG ((DEBUG_INFO, "x_resolution: 0x%x\n", CbFbRec->x_resolution));
511 DEBUG ((DEBUG_INFO, "y_resolution: 0x%x\n", CbFbRec->y_resolution));
512 DEBUG ((DEBUG_INFO, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel));
513 DEBUG ((DEBUG_INFO, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line));
514
515 DEBUG ((DEBUG_INFO, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size));
516 DEBUG ((DEBUG_INFO, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos));
517 DEBUG ((DEBUG_INFO, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size));
518 DEBUG ((DEBUG_INFO, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos));
519 DEBUG ((DEBUG_INFO, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size));
520 DEBUG ((DEBUG_INFO, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos));
521 DEBUG ((DEBUG_INFO, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size));
522 DEBUG ((DEBUG_INFO, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos));
523
524 GfxMode = &GfxInfo->GraphicsMode;
525 GfxMode->Version = 0;
526 GfxMode->HorizontalResolution = CbFbRec->x_resolution;
527 GfxMode->VerticalResolution = CbFbRec->y_resolution;
528 GfxMode->PixelsPerScanLine = (CbFbRec->bytes_per_line << 3) / CbFbRec->bits_per_pixel;
529 if ((CbFbRec->red_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->blue_mask_pos == 16)) {
530 GfxMode->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
531 } else if ((CbFbRec->blue_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->red_mask_pos == 16)) {
532 GfxMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
533 }
534 GfxMode->PixelInformation.RedMask = ((1 << CbFbRec->red_mask_size) - 1) << CbFbRec->red_mask_pos;
535 GfxMode->PixelInformation.GreenMask = ((1 << CbFbRec->green_mask_size) - 1) << CbFbRec->green_mask_pos;
536 GfxMode->PixelInformation.BlueMask = ((1 << CbFbRec->blue_mask_size) - 1) << CbFbRec->blue_mask_pos;
537 GfxMode->PixelInformation.ReservedMask = ((1 << CbFbRec->reserved_mask_size) - 1) << CbFbRec->reserved_mask_pos;
538
539 GfxInfo->FrameBufferBase = CbFbRec->physical_address;
540 GfxInfo->FrameBufferSize = CbFbRec->bytes_per_line * CbFbRec->y_resolution;
541
542 return RETURN_SUCCESS;
543 }
544
545 /**
546 Find the video frame buffer device information
547
548 @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure
549
550 @retval RETURN_SUCCESS Successfully find the video frame buffer information.
551 @retval RETURN_NOT_FOUND Failed to find the video frame buffer information.
552
553 **/
554 RETURN_STATUS
555 EFIAPI
556 ParseGfxDeviceInfo (
557 OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo
558 )
559 {
560 return RETURN_NOT_FOUND;
561 }
562
563 /**
564 Parse and handle the misc info provided by bootloader
565
566 @retval RETURN_SUCCESS The misc information was parsed successfully.
567 @retval RETURN_NOT_FOUND Could not find required misc info.
568 @retval RETURN_OUT_OF_RESOURCES Insufficant memory space.
569
570 **/
571 RETURN_STATUS
572 EFIAPI
573 ParseMiscInfo (
574 VOID
575 )
576 {
577 return RETURN_SUCCESS;
578 }