• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   This library will parse the coreboot table in memory and extract those required
3   information.
4 
5   Copyright (c) 2014 - 2016, 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 
28 /**
29   Convert a packed value from cbuint64 to a UINT64 value.
30 
31   @param  val      The pointer to packed data.
32 
33   @return          the UNIT64 value after convertion.
34 
35 **/
36 UINT64
cb_unpack64(IN struct cbuint64 val)37 cb_unpack64 (
38   IN struct cbuint64 val
39   )
40 {
41   return LShiftU64 (val.hi, 32) | val.lo;
42 }
43 
44 
45 /**
46   Returns the sum of all elements in a buffer of 16-bit values.  During
47   calculation, the carry bits are also been added.
48 
49   @param  Buffer      The pointer to the buffer to carry out the sum operation.
50   @param  Length      The size, in bytes, of Buffer.
51 
52   @return Sum         The sum of Buffer with carry bits included during additions.
53 
54 **/
55 UINT16
CbCheckSum16(IN UINT16 * Buffer,IN UINTN Length)56 CbCheckSum16 (
57   IN UINT16   *Buffer,
58   IN UINTN    Length
59   )
60 {
61   UINT32 Sum, TmpValue;
62   UINTN  Idx;
63   UINT8  *TmpPtr;
64 
65   Sum = 0;
66   TmpPtr = (UINT8 *)Buffer;
67   for(Idx = 0; Idx < Length; Idx++) {
68     TmpValue  = TmpPtr[Idx];
69     if (Idx % 2 == 1) {
70       TmpValue <<= 8;
71     }
72 
73     Sum += TmpValue;
74 
75     // Wrap
76     if (Sum >= 0x10000) {
77       Sum = (Sum + (Sum >> 16)) & 0xFFFF;
78     }
79   }
80 
81   return (UINT16)((~Sum) & 0xFFFF);
82 }
83 
84 
85 /**
86   Find coreboot record with given Tag from the memory Start in 4096
87   bytes range.
88 
89   @param  Start              The start memory to be searched in
90   @param  Tag                The tag id to be found
91 
92   @retval NULL              The Tag is not found.
93   @retval Others            The poiter to the record found.
94 
95 **/
96 VOID *
97 EFIAPI
FindCbTag(IN VOID * Start,IN UINT32 Tag)98 FindCbTag (
99   IN  VOID     *Start,
100   IN  UINT32   Tag
101   )
102 {
103   struct cb_header   *Header;
104   struct cb_record   *Record;
105   UINT8              *TmpPtr;
106   UINT8              *TagPtr;
107   UINTN              Idx;
108   UINT16             CheckSum;
109 
110   Header = NULL;
111   TmpPtr = (UINT8 *)Start;
112   for (Idx = 0; Idx < 4096; Idx += 16, TmpPtr += 16) {
113     Header = (struct cb_header *)TmpPtr;
114     if (Header->signature == CB_HEADER_SIGNATURE) {
115       break;
116     }
117   }
118 
119   if (Idx >= 4096) {
120     return NULL;
121   }
122 
123   if ((Header == NULL) || (Header->table_bytes == 0)) {
124     return NULL;
125   }
126 
127   //
128   // Check the checksum of the coreboot table header
129   //
130   CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header));
131   if (CheckSum != 0) {
132     DEBUG ((EFI_D_ERROR, "Invalid coreboot table header checksum\n"));
133     return NULL;
134   }
135 
136   CheckSum = CbCheckSum16 ((UINT16 *)(TmpPtr + sizeof (*Header)), Header->table_bytes);
137   if (CheckSum != Header->table_checksum) {
138     DEBUG ((EFI_D_ERROR, "Incorrect checksum of all the coreboot table entries\n"));
139     return NULL;
140   }
141 
142   TagPtr = NULL;
143   TmpPtr += Header->header_bytes;
144   for (Idx = 0; Idx < Header->table_entries; Idx++) {
145     Record = (struct cb_record *)TmpPtr;
146     if (Record->tag == CB_TAG_FORWARD) {
147       TmpPtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward;
148       if (Tag == CB_TAG_FORWARD) {
149         return TmpPtr;
150       } else {
151         return FindCbTag (TmpPtr, Tag);
152       }
153     }
154     if (Record->tag == Tag) {
155       TagPtr = TmpPtr;
156       break;
157     }
158     TmpPtr += Record->size;
159   }
160 
161   return TagPtr;
162 }
163 
164 
165 /**
166   Find the given table with TableId from the given coreboot memory Root.
167 
168   @param  Root               The coreboot memory table to be searched in
169   @param  TableId            Table id to be found
170   @param  pMemTable          To save the base address of the memory table found
171   @param  pMemTableSize      To save the size of memory table found
172 
173   @retval RETURN_SUCCESS            Successfully find out the memory table.
174   @retval RETURN_INVALID_PARAMETER  Invalid input parameters.
175   @retval RETURN_NOT_FOUND          Failed to find the memory table.
176 
177 **/
178 RETURN_STATUS
179 EFIAPI
FindCbMemTable(IN struct cbmem_root * Root,IN UINT32 TableId,OUT VOID ** pMemTable,OUT UINT32 * pMemTableSize)180 FindCbMemTable (
181   IN  struct cbmem_root  *Root,
182   IN  UINT32             TableId,
183   OUT VOID               **pMemTable,
184   OUT UINT32             *pMemTableSize
185   )
186 {
187   UINTN                Idx;
188   BOOLEAN              IsImdEntry;
189   struct cbmem_entry  *Entries;
190 
191   if ((Root == NULL) || (pMemTable == NULL)) {
192     return RETURN_INVALID_PARAMETER;
193   }
194   //
195   // Check if the entry is CBMEM or IMD
196   // and handle them separately
197   //
198   Entries = Root->entries;
199   if (Entries[0].magic == CBMEM_ENTRY_MAGIC) {
200     IsImdEntry = FALSE;
201   } else {
202     Entries = (struct cbmem_entry *)((struct imd_root *)Root)->entries;
203     if (Entries[0].magic == IMD_ENTRY_MAGIC) {
204       IsImdEntry = TRUE;
205     } else {
206       return RETURN_NOT_FOUND;
207     }
208   }
209 
210   for (Idx = 0; Idx < Root->num_entries; Idx++) {
211     if (Entries[Idx].id == TableId) {
212       if (IsImdEntry) {
213         *pMemTable = (VOID *) ((UINTN)Entries[Idx].start + (UINTN)Root);
214       } else {
215         *pMemTable = (VOID *) (UINTN)Entries[Idx].start;
216       }
217       if (pMemTableSize != NULL) {
218         *pMemTableSize = Entries[Idx].size;
219       }
220 
221       DEBUG ((EFI_D_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n",
222         TableId, *pMemTable, Entries[Idx].size));
223       return RETURN_SUCCESS;
224     }
225   }
226 
227   return RETURN_NOT_FOUND;
228 }
229 
230 
231 /**
232   Acquire the memory information from the coreboot table in memory.
233 
234   @param  MemInfoCallback     The callback routine
235   @param  pParam              Pointer to the callback routine parameter
236 
237   @retval RETURN_SUCCESS     Successfully find out the memory information.
238   @retval RETURN_NOT_FOUND   Failed to find the memory information.
239 
240 **/
241 RETURN_STATUS
242 EFIAPI
CbParseMemoryInfo(IN CB_MEM_INFO_CALLBACK MemInfoCallback,IN VOID * pParam)243 CbParseMemoryInfo (
244   IN  CB_MEM_INFO_CALLBACK  MemInfoCallback,
245   IN  VOID                  *pParam
246   )
247 {
248   struct cb_memory         *rec;
249   struct cb_memory_range   *Range;
250   UINT64                   Start;
251   UINT64                   Size;
252   UINTN                    Index;
253 
254   //
255   // Get the coreboot memory table
256   //
257   rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY);
258   if (rec == NULL) {
259     rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY);
260   }
261 
262   if (rec == NULL) {
263     return RETURN_NOT_FOUND;
264   }
265 
266   for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
267     Range = MEM_RANGE_PTR(rec, Index);
268     Start = cb_unpack64(Range->start);
269     Size = cb_unpack64(Range->size);
270     DEBUG ((EFI_D_INFO, "%d. %016lx - %016lx [%02x]\n",
271             Index, Start, Start + Size - 1, Range->type));
272 
273     MemInfoCallback (Start, Size, Range->type, pParam);
274   }
275 
276   return RETURN_SUCCESS;
277 }
278 
279 
280 /**
281   Acquire the coreboot memory table with the given table id
282 
283   @param  TableId            Table id to be searched
284   @param  pMemTable          Pointer to the base address of the memory table
285   @param  pMemTableSize      Pointer to the size of the memory table
286 
287   @retval RETURN_SUCCESS     Successfully find out the memory table.
288   @retval RETURN_INVALID_PARAMETER  Invalid input parameters.
289   @retval RETURN_NOT_FOUND   Failed to find the memory table.
290 
291 **/
292 RETURN_STATUS
293 EFIAPI
CbParseCbMemTable(IN UINT32 TableId,OUT VOID ** pMemTable,OUT UINT32 * pMemTableSize)294 CbParseCbMemTable (
295   IN  UINT32     TableId,
296   OUT VOID       **pMemTable,
297   OUT UINT32     *pMemTableSize
298   )
299 {
300   struct cb_memory         *rec;
301   struct cb_memory_range   *Range;
302   UINT64                   Start;
303   UINT64                   Size;
304   UINTN                    Index;
305 
306   if (pMemTable == NULL) {
307     return RETURN_INVALID_PARAMETER;
308   }
309   *pMemTable = NULL;
310 
311   //
312   // Get the coreboot memory table
313   //
314   rec = (struct cb_memory *)FindCbTag (0, CB_TAG_MEMORY);
315   if (rec == NULL) {
316     rec = (struct cb_memory *)FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_MEMORY);
317   }
318 
319   if (rec == NULL) {
320     return RETURN_NOT_FOUND;
321   }
322 
323   for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) {
324     Range = MEM_RANGE_PTR(rec, Index);
325     Start = cb_unpack64(Range->start);
326     Size = cb_unpack64(Range->size);
327 
328     if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) {
329       if (FindCbMemTable ((struct  cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE), TableId, pMemTable, pMemTableSize) == RETURN_SUCCESS)
330         return RETURN_SUCCESS;
331     }
332   }
333 
334   return RETURN_NOT_FOUND;
335 }
336 
337 
338 /**
339   Acquire the acpi table from coreboot
340 
341   @param  pMemTable          Pointer to the base address of the memory table
342   @param  pMemTableSize      Pointer to the size of the memory table
343 
344   @retval RETURN_SUCCESS     Successfully find out the memory table.
345   @retval RETURN_INVALID_PARAMETER  Invalid input parameters.
346   @retval RETURN_NOT_FOUND   Failed to find the memory table.
347 
348 **/
349 RETURN_STATUS
350 EFIAPI
CbParseAcpiTable(OUT VOID ** pMemTable,OUT UINT32 * pMemTableSize)351 CbParseAcpiTable (
352   OUT VOID       **pMemTable,
353   OUT UINT32     *pMemTableSize
354   )
355 {
356   return CbParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), pMemTable, pMemTableSize);
357 }
358 
359 /**
360   Acquire the smbios table from coreboot
361 
362   @param  pMemTable          Pointer to the base address of the memory table
363   @param  pMemTableSize      Pointer to the size of the memory table
364 
365   @retval RETURN_SUCCESS     Successfully find out the memory table.
366   @retval RETURN_INVALID_PARAMETER  Invalid input parameters.
367   @retval RETURN_NOT_FOUND   Failed to find the memory table.
368 
369 **/
370 RETURN_STATUS
371 EFIAPI
CbParseSmbiosTable(OUT VOID ** pMemTable,OUT UINT32 * pMemTableSize)372 CbParseSmbiosTable (
373   OUT VOID       **pMemTable,
374   OUT UINT32     *pMemTableSize
375   )
376 {
377   return CbParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), pMemTable, pMemTableSize);
378 }
379 
380 /**
381   Find the required fadt information
382 
383   @param  pPmCtrlReg         Pointer to the address of power management control register
384   @param  pPmTimerReg        Pointer to the address of power management timer register
385   @param  pResetReg          Pointer to the address of system reset register
386   @param  pResetValue        Pointer to the value to be writen to the system reset register
387   @param  pPmEvtReg          Pointer to the address of power management event register
388   @param  pPmGpeEnReg        Pointer to the address of power management GPE enable register
389 
390   @retval RETURN_SUCCESS     Successfully find out all the required fadt information.
391   @retval RETURN_NOT_FOUND   Failed to find the fadt table.
392 
393 **/
394 RETURN_STATUS
395 EFIAPI
CbParseFadtInfo(OUT UINTN * pPmCtrlReg,OUT UINTN * pPmTimerReg,OUT UINTN * pResetReg,OUT UINTN * pResetValue,OUT UINTN * pPmEvtReg,OUT UINTN * pPmGpeEnReg)396 CbParseFadtInfo (
397   OUT UINTN      *pPmCtrlReg,
398   OUT UINTN      *pPmTimerReg,
399   OUT UINTN      *pResetReg,
400   OUT UINTN      *pResetValue,
401   OUT UINTN      *pPmEvtReg,
402   OUT UINTN      *pPmGpeEnReg
403   )
404 {
405   EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
406   EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
407   UINT32                                        *Entry32;
408   UINTN                                         Entry32Num;
409   EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;
410   EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;
411   UINT64                                        *Entry64;
412   UINTN                                         Entry64Num;
413   UINTN                                         Idx;
414   RETURN_STATUS                                 Status;
415 
416   Rsdp = NULL;
417   Status = RETURN_SUCCESS;
418 
419   Status = CbParseAcpiTable ((VOID **)&Rsdp, NULL);
420   if (RETURN_ERROR(Status)) {
421     return Status;
422   }
423 
424   if (Rsdp == NULL) {
425     return RETURN_NOT_FOUND;
426   }
427 
428   DEBUG ((EFI_D_INFO, "Find Rsdp at %p\n", Rsdp));
429   DEBUG ((EFI_D_INFO, "Find Rsdt 0x%x, Xsdt 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));
430 
431   //
432   // Search Rsdt First
433   //
434   Rsdt     = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);
435   if (Rsdt != NULL) {
436     Entry32  = (UINT32 *)(Rsdt + 1);
437     Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
438     for (Idx = 0; Idx < Entry32Num; Idx++) {
439       if (*(UINT32 *)(UINTN)(Entry32[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
440         Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry32[Idx]);
441         if (pPmCtrlReg != NULL) {
442           *pPmCtrlReg = Fadt->Pm1aCntBlk;
443         }
444         DEBUG ((EFI_D_INFO, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk));
445 
446         if (pPmTimerReg != NULL) {
447           *pPmTimerReg = Fadt->PmTmrBlk;
448         }
449         DEBUG ((EFI_D_INFO, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk));
450 
451         if (pResetReg != NULL) {
452           *pResetReg = (UINTN)Fadt->ResetReg.Address;
453         }
454         DEBUG ((EFI_D_INFO, "Reset Reg 0x%lx\n", Fadt->ResetReg.Address));
455 
456         if (pResetValue != NULL) {
457           *pResetValue = Fadt->ResetValue;
458         }
459         DEBUG ((EFI_D_INFO, "Reset Value 0x%x\n", Fadt->ResetValue));
460 
461         if (pPmEvtReg != NULL) {
462           *pPmEvtReg = Fadt->Pm1aEvtBlk;
463           DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk));
464         }
465 
466         if (pPmGpeEnReg != NULL) {
467           *pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
468           DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg));
469         }
470 
471         //
472         // Verify values for proper operation
473         //
474         ASSERT(Fadt->Pm1aCntBlk != 0);
475         ASSERT(Fadt->PmTmrBlk != 0);
476         ASSERT(Fadt->ResetReg.Address != 0);
477         ASSERT(Fadt->Pm1aEvtBlk != 0);
478         ASSERT(Fadt->Gpe0Blk != 0);
479 
480         return RETURN_SUCCESS;
481       }
482     }
483   }
484 
485   //
486   // Search Xsdt Second
487   //
488   Xsdt     = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
489   if (Xsdt != NULL) {
490     Entry64  = (UINT64 *)(Xsdt + 1);
491     Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3;
492     for (Idx = 0; Idx < Entry64Num; Idx++) {
493       if (*(UINT32 *)(UINTN)(Entry64[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
494         Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry64[Idx]);
495         if (pPmCtrlReg)
496           *pPmCtrlReg = Fadt->Pm1aCntBlk;
497         DEBUG ((EFI_D_ERROR, "PmCtrl Reg 0x%x\n", Fadt->Pm1aCntBlk));
498 
499         if (pPmTimerReg)
500           *pPmTimerReg = Fadt->PmTmrBlk;
501         DEBUG ((EFI_D_ERROR, "PmTimer Reg 0x%x\n", Fadt->PmTmrBlk));
502 
503         if (pResetReg)
504           *pResetReg = (UINTN)Fadt->ResetReg.Address;
505         DEBUG ((EFI_D_ERROR, "Reset Reg 0x%lx\n", Fadt->ResetReg.Address));
506 
507         if (pResetValue)
508           *pResetValue = Fadt->ResetValue;
509         DEBUG ((EFI_D_ERROR, "Reset Value 0x%x\n", Fadt->ResetValue));
510 
511         if (pPmEvtReg != NULL) {
512           *pPmEvtReg = Fadt->Pm1aEvtBlk;
513            DEBUG ((EFI_D_INFO, "PmEvt Reg 0x%x\n", Fadt->Pm1aEvtBlk));
514         }
515 
516         if (pPmGpeEnReg != NULL) {
517           *pPmGpeEnReg = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
518           DEBUG ((EFI_D_INFO, "PmGpeEn Reg 0x%x\n", *pPmGpeEnReg));
519         }
520         return RETURN_SUCCESS;
521       }
522     }
523   }
524 
525   return RETURN_NOT_FOUND;
526 }
527 
528 /**
529   Find the serial port information
530 
531   @param  pRegBase           Pointer to the base address of serial port registers
532   @param  pRegAccessType     Pointer to the access type of serial port registers
533   @param  pRegWidth          Pointer to the register width in bytes
534   @param  pBaudrate          Pointer to the serial port baudrate
535   @param  pInputHertz        Pointer to the input clock frequency
536   @param  pUartPciAddr       Pointer to the UART PCI bus, dev and func address
537 
538   @retval RETURN_SUCCESS     Successfully find the serial port information.
539   @retval RETURN_NOT_FOUND   Failed to find the serial port information .
540 
541 **/
542 RETURN_STATUS
543 EFIAPI
CbParseSerialInfo(OUT UINT32 * pRegBase,OUT UINT32 * pRegAccessType,OUT UINT32 * pRegWidth,OUT UINT32 * pBaudrate,OUT UINT32 * pInputHertz,OUT UINT32 * pUartPciAddr)544 CbParseSerialInfo (
545   OUT UINT32      *pRegBase,
546   OUT UINT32      *pRegAccessType,
547   OUT UINT32      *pRegWidth,
548   OUT UINT32      *pBaudrate,
549   OUT UINT32      *pInputHertz,
550   OUT UINT32      *pUartPciAddr
551   )
552 {
553   struct cb_serial    *CbSerial;
554 
555   CbSerial = FindCbTag (0, CB_TAG_SERIAL);
556   if (CbSerial == NULL) {
557     CbSerial = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_SERIAL);
558   }
559 
560   if (CbSerial == NULL) {
561     return RETURN_NOT_FOUND;
562   }
563 
564   if (pRegBase != NULL) {
565     *pRegBase = CbSerial->baseaddr;
566   }
567 
568   if (pRegWidth != NULL) {
569     *pRegWidth = CbSerial->regwidth;
570   }
571 
572   if (pRegAccessType != NULL) {
573     *pRegAccessType = CbSerial->type;
574   }
575 
576   if (pBaudrate != NULL) {
577     *pBaudrate = CbSerial->baud;
578   }
579 
580   if (pInputHertz != NULL) {
581     *pInputHertz = CbSerial->input_hertz;
582   }
583 
584   if (pUartPciAddr != NULL) {
585     *pUartPciAddr = CbSerial->uart_pci_addr;
586   }
587 
588   return RETURN_SUCCESS;
589 }
590 
591 /**
592   Search for the coreboot table header
593 
594   @param  Level              Level of the search depth
595   @param  HeaderPtr          Pointer to the pointer of coreboot table header
596 
597   @retval RETURN_SUCCESS     Successfully find the coreboot table header .
598   @retval RETURN_NOT_FOUND   Failed to find the coreboot table header .
599 
600 **/
601 RETURN_STATUS
602 EFIAPI
CbParseGetCbHeader(IN UINTN Level,OUT VOID ** HeaderPtr)603 CbParseGetCbHeader (
604   IN  UINTN  Level,
605   OUT VOID   **HeaderPtr
606   )
607 {
608   UINTN Index;
609   VOID  *TempPtr;
610 
611   if (HeaderPtr == NULL) {
612     return RETURN_NOT_FOUND;
613   }
614 
615   TempPtr = NULL;
616   for (Index = 0; Index < Level; Index++) {
617     TempPtr = FindCbTag (TempPtr, CB_TAG_FORWARD);
618     if (TempPtr == NULL) {
619       break;
620     }
621   }
622 
623   if ((Index >= Level) && (TempPtr != NULL)) {
624     *HeaderPtr = TempPtr;
625     return RETURN_SUCCESS;
626   }
627 
628   return RETURN_NOT_FOUND;
629 }
630 
631 /**
632   Find the video frame buffer information
633 
634   @param  pFbInfo            Pointer to the FRAME_BUFFER_INFO structure
635 
636   @retval RETURN_SUCCESS     Successfully find the video frame buffer information.
637   @retval RETURN_NOT_FOUND   Failed to find the video frame buffer information .
638 
639 **/
640 RETURN_STATUS
641 EFIAPI
CbParseFbInfo(OUT FRAME_BUFFER_INFO * pFbInfo)642 CbParseFbInfo (
643   OUT FRAME_BUFFER_INFO       *pFbInfo
644   )
645 {
646   struct cb_framebuffer       *CbFbRec;
647 
648   if (pFbInfo == NULL) {
649     return RETURN_INVALID_PARAMETER;
650   }
651 
652   CbFbRec = FindCbTag (0, CB_TAG_FRAMEBUFFER);
653   if (CbFbRec == NULL) {
654     CbFbRec = FindCbTag ((VOID *)(UINTN)PcdGet32 (PcdCbHeaderPointer), CB_TAG_FRAMEBUFFER);
655   }
656 
657   if (CbFbRec == NULL) {
658     return RETURN_NOT_FOUND;
659   }
660 
661   DEBUG ((EFI_D_INFO, "Found coreboot video frame buffer information\n"));
662   DEBUG ((EFI_D_INFO, "physical_address: 0x%lx\n", CbFbRec->physical_address));
663   DEBUG ((EFI_D_INFO, "x_resolution: 0x%x\n", CbFbRec->x_resolution));
664   DEBUG ((EFI_D_INFO, "y_resolution: 0x%x\n", CbFbRec->y_resolution));
665   DEBUG ((EFI_D_INFO, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel));
666   DEBUG ((EFI_D_INFO, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line));
667 
668   DEBUG ((EFI_D_INFO, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size));
669   DEBUG ((EFI_D_INFO, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos));
670   DEBUG ((EFI_D_INFO, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size));
671   DEBUG ((EFI_D_INFO, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos));
672   DEBUG ((EFI_D_INFO, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size));
673   DEBUG ((EFI_D_INFO, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos));
674   DEBUG ((EFI_D_INFO, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size));
675   DEBUG ((EFI_D_INFO, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos));
676 
677   pFbInfo->LinearFrameBuffer    = CbFbRec->physical_address;
678   pFbInfo->HorizontalResolution = CbFbRec->x_resolution;
679   pFbInfo->VerticalResolution   = CbFbRec->y_resolution;
680   pFbInfo->BitsPerPixel         = CbFbRec->bits_per_pixel;
681   pFbInfo->BytesPerScanLine     = (UINT16)CbFbRec->bytes_per_line;
682   pFbInfo->Red.Mask             = (1 << CbFbRec->red_mask_size) - 1;
683   pFbInfo->Red.Position         = CbFbRec->red_mask_pos;
684   pFbInfo->Green.Mask           = (1 << CbFbRec->green_mask_size) - 1;
685   pFbInfo->Green.Position       = CbFbRec->green_mask_pos;
686   pFbInfo->Blue.Mask            = (1 << CbFbRec->blue_mask_size) - 1;
687   pFbInfo->Blue.Position        = CbFbRec->blue_mask_pos;
688   pFbInfo->Reserved.Mask        = (1 << CbFbRec->reserved_mask_size) - 1;
689   pFbInfo->Reserved.Position    = CbFbRec->reserved_mask_pos;
690 
691   return RETURN_SUCCESS;
692 }
693 
694