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