1 /** @file
2   This module provide Hand-Off Block manupulation.
3 
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PeiMain.h"
16 
17 /**
18 
19   Gets the pointer to the HOB List.
20 
21   @param PeiServices                   An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
22   @param HobList                       Pointer to the HOB List.
23 
24   @retval EFI_SUCCESS                  Get the pointer of HOB List
25   @retval EFI_NOT_AVAILABLE_YET        the HOB List is not yet published
26   @retval EFI_INVALID_PARAMETER        HobList is NULL (in debug mode)
27 
28 **/
29 EFI_STATUS
30 EFIAPI
PeiGetHobList(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT VOID ** HobList)31 PeiGetHobList (
32   IN CONST EFI_PEI_SERVICES  **PeiServices,
33   IN OUT VOID          **HobList
34   )
35 {
36   PEI_CORE_INSTANCE *PrivateData;
37 
38   //
39   // Only check this parameter in debug mode
40   //
41 
42   DEBUG_CODE_BEGIN ();
43     if (HobList == NULL) {
44       return EFI_INVALID_PARAMETER;
45     }
46   DEBUG_CODE_END ();
47 
48   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
49 
50   *HobList    = PrivateData->HobList.Raw;
51 
52   return EFI_SUCCESS;
53 }
54 
55 
56 /**
57   Add a new HOB to the HOB List.
58 
59   @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
60   @param Type             Type of the new HOB.
61   @param Length           Length of the new HOB to allocate.
62   @param Hob              Pointer to the new HOB.
63 
64   @return  EFI_SUCCESS           Success to create hob.
65   @retval  EFI_INVALID_PARAMETER if Hob is NULL
66   @retval  EFI_NOT_AVAILABLE_YET if HobList is still not available.
67   @retval  EFI_OUT_OF_RESOURCES  if there is no more memory to grow the Hoblist.
68 
69 **/
70 EFI_STATUS
71 EFIAPI
PeiCreateHob(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINT16 Type,IN UINT16 Length,IN OUT VOID ** Hob)72 PeiCreateHob (
73   IN CONST EFI_PEI_SERVICES  **PeiServices,
74   IN UINT16            Type,
75   IN UINT16            Length,
76   IN OUT VOID          **Hob
77   )
78 {
79   EFI_STATUS                           Status;
80   EFI_HOB_HANDOFF_INFO_TABLE           *HandOffHob;
81   EFI_HOB_GENERIC_HEADER               *HobEnd;
82   EFI_PHYSICAL_ADDRESS                 FreeMemory;
83 
84 
85   Status = PeiGetHobList (PeiServices, Hob);
86   if (EFI_ERROR(Status)) {
87     return Status;
88   }
89 
90   HandOffHob = *Hob;
91 
92   //
93   // Check Length to avoid data overflow.
94   //
95   if (0x10000 - Length <= 0x7) {
96     return EFI_INVALID_PARAMETER;
97   }
98   Length     = (UINT16)((Length + 0x7) & (~0x7));
99 
100   FreeMemory = HandOffHob->EfiFreeMemoryTop -
101                HandOffHob->EfiFreeMemoryBottom;
102 
103   if (FreeMemory < Length) {
104     DEBUG ((EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));
105     DEBUG ((EFI_D_ERROR, "  FreeMemoryTop    - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
106     DEBUG ((EFI_D_ERROR, "  FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
107     return EFI_OUT_OF_RESOURCES;
108   }
109 
110   *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
111   ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType   = Type;
112   ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
113   ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved  = 0;
114 
115   HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
116   HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
117 
118   HobEnd->HobType   = EFI_HOB_TYPE_END_OF_HOB_LIST;
119   HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
120   HobEnd->Reserved  = 0;
121   HobEnd++;
122   HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
123 
124   return EFI_SUCCESS;
125 }
126 
127 /**
128 
129   Builds a Handoff Information Table HOB
130 
131   @param BootMode        - Current Bootmode
132   @param MemoryBegin     - Start Memory Address.
133   @param MemoryLength    - Length of Memory.
134 
135   @return EFI_SUCCESS Always success to initialize HOB.
136 
137 **/
138 EFI_STATUS
PeiCoreBuildHobHandoffInfoTable(IN EFI_BOOT_MODE BootMode,IN EFI_PHYSICAL_ADDRESS MemoryBegin,IN UINT64 MemoryLength)139 PeiCoreBuildHobHandoffInfoTable (
140   IN EFI_BOOT_MODE         BootMode,
141   IN EFI_PHYSICAL_ADDRESS  MemoryBegin,
142   IN UINT64                MemoryLength
143   )
144 {
145   EFI_HOB_HANDOFF_INFO_TABLE   *Hob;
146   EFI_HOB_GENERIC_HEADER       *HobEnd;
147 
148   Hob                      = (VOID *)(UINTN)MemoryBegin;
149   HobEnd                   = (EFI_HOB_GENERIC_HEADER*) (Hob+1);
150   Hob->Header.HobType      = EFI_HOB_TYPE_HANDOFF;
151   Hob->Header.HobLength    = (UINT16) sizeof (EFI_HOB_HANDOFF_INFO_TABLE);
152   Hob->Header.Reserved     = 0;
153 
154   HobEnd->HobType          = EFI_HOB_TYPE_END_OF_HOB_LIST;
155   HobEnd->HobLength        = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
156   HobEnd->Reserved         = 0;
157 
158   Hob->Version             = EFI_HOB_HANDOFF_TABLE_VERSION;
159   Hob->BootMode            = BootMode;
160 
161   Hob->EfiMemoryTop        = MemoryBegin + MemoryLength;
162   Hob->EfiMemoryBottom     = MemoryBegin;
163   Hob->EfiFreeMemoryTop    = MemoryBegin + MemoryLength;
164   Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd + 1);
165   Hob->EfiEndOfHobList     = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
166 
167   return EFI_SUCCESS;
168 }
169