blob: 6cc09fbcc4a5086385ff83d123bea2f5b5f094ff [file] [log] [blame]
Lee Leahy3dad4892015-05-05 11:14:02 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
Lee Leahyb5ad8272015-04-20 15:29:16 -07005 * Copyright (C) 2015 Intel Corp.
Lee Leahy3dad4892015-05-05 11:14:02 -07006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
Patrick Georgib890a122015-03-26 15:17:45 +010018 * Foundation, Inc.
Lee Leahy3dad4892015-05-05 11:14:02 -070019 */
20
Lee Leahyb5ad8272015-04-20 15:29:16 -070021#include <arch/early_variables.h>
22#include <arch/hlt.h>
23#include <bootstate.h>
24#include <cbmem.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070025#include <console/console.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070026#include "fsp_util.h"
Lee Leahyb5ad8272015-04-20 15:29:16 -070027#include <ip_checksum.h>
28#include <lib.h> // hexdump
29#include <string.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070030
Lee Leahyb5ad8272015-04-20 15:29:16 -070031/*
32 * Reads a 64-bit value from memory that may be unaligned.
Lee Leahy3dad4892015-05-05 11:14:02 -070033 *
Lee Leahyb5ad8272015-04-20 15:29:16 -070034 * This function returns the 64-bit value pointed to by buffer. The
35 * function guarantees that the read operation does not produce an
36 * alignment fault.
37 *
38 * If buffer is NULL, then ASSERT().
39 *
40 * buffer: Pointer to a 64-bit value that may be unaligned.
41 *
42 * Returns the 64-bit value read from buffer.
43 *
Lee Leahy3dad4892015-05-05 11:14:02 -070044 */
Lee Leahyb5ad8272015-04-20 15:29:16 -070045static
46uint64_t
47read_unaligned_64(
48 const uint64_t *buffer
49 )
Lee Leahy3dad4892015-05-05 11:14:02 -070050{
Lee Leahyb5ad8272015-04-20 15:29:16 -070051 ASSERT(buffer != NULL);
52
53 return *buffer;
Lee Leahy3dad4892015-05-05 11:14:02 -070054}
55
Lee Leahyb5ad8272015-04-20 15:29:16 -070056/*
57 * Compares two GUIDs.
58 *
59 * This function compares guid1 to guid2. If the GUIDs are identical then
60 * TRUE is returned. If there are any bit differences in the two GUIDs,
61 * then FALSE is returned.
62 *
63 * If guid1 is NULL, then ASSERT().
64 * If guid2 is NULL, then ASSERT().
65 *
66 * guid1: A pointer to a 128 bit GUID.
67 * guid2: A pointer to a 128 bit GUID.
68 *
69 * Returns non-zero if guid1 and guid2 are identical, otherwise returns 0.
70 *
71 */
72static
73long
74compare_guid(
75 const EFI_GUID * guid1,
76 const EFI_GUID * guid2
77 )
Lee Leahy3dad4892015-05-05 11:14:02 -070078{
Lee Leahyb5ad8272015-04-20 15:29:16 -070079 uint64_t low_part_of_guid1;
80 uint64_t low_part_of_guid2;
81 uint64_t high_part_of_guid1;
82 uint64_t high_part_of_guid2;
Lee Leahy3dad4892015-05-05 11:14:02 -070083
Lee Leahyb5ad8272015-04-20 15:29:16 -070084 low_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1);
85 low_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2);
86 high_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1 + 1);
87 high_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2 + 1);
88
89 return ((low_part_of_guid1 == low_part_of_guid2)
90 && (high_part_of_guid1 == high_part_of_guid2));
91}
92
93/* Returns the pointer to the HOB list. */
94VOID *
95EFIAPI
96get_hob_list(
97 VOID
98 )
99{
100 void *hob_list;
101
102 hob_list = fsp_get_hob_list();
103 if (hob_list == NULL)
104 die("Call fsp_set_runtime() before this call!\n");
105 return hob_list;
106}
107
108/* Returns the next instance of a HOB type from the starting HOB. */
109VOID *
110EFIAPI
111get_next_hob(
112 UINT16 type,
113 CONST VOID *hob_start
114 )
115{
116 EFI_PEI_HOB_POINTERS hob;
117
118 ASSERT(hob_start != NULL);
119
120 hob.Raw = (UINT8 *)hob_start;
121
122 /* Parse the HOB list until end of list or matching type is found. */
123 while (!END_OF_HOB_LIST(hob.Raw)) {
124 if (hob.Header->HobType == type)
125 return hob.Raw;
126 if (GET_HOB_LENGTH(hob.Raw) < sizeof(*hob.Header))
127 break;
128 hob.Raw = GET_NEXT_HOB(hob.Raw);
129 }
130 return NULL;
131}
132
133/* Returns the first instance of a HOB type among the whole HOB list. */
134VOID *
135EFIAPI
136get_first_hob(
137 UINT16 type
138 )
139{
140 VOID *hob_list;
141
142 hob_list = get_hob_list();
143 return get_next_hob(type, hob_list);
144}
145
146/* Returns the next instance of the matched GUID HOB from the starting HOB. */
147VOID *
148EFIAPI
149get_next_guid_hob(
150 CONST EFI_GUID * guid,
151 CONST VOID *hob_start
152 )
153{
154 EFI_PEI_HOB_POINTERS hob;
155
156 hob.Raw = (UINT8 *)hob_start;
157 while ((hob.Raw = get_next_hob(EFI_HOB_TYPE_GUID_EXTENSION, hob.Raw))
158 != NULL) {
159 if (compare_guid(guid, &hob.Guid->Name))
160 break;
161 hob.Raw = GET_NEXT_HOB(hob.Raw);
162 }
163 return hob.Raw;
164}
165
166/*
167 * Returns the first instance of the matched GUID HOB among the whole HOB list.
168 */
169VOID *
170EFIAPI
171get_first_guid_hob(
172 CONST EFI_GUID * guid
173 )
174{
175 return get_next_guid_hob(guid, get_hob_list());
176}
177
178/*
179 * Returns the next instance of the matching resource HOB from the starting HOB.
180 */
181void *get_next_resource_hob(const EFI_GUID *guid, const void *hob_start)
182{
183 EFI_PEI_HOB_POINTERS hob;
184
185 hob.Raw = (UINT8 *)hob_start;
186 while ((hob.Raw = get_next_hob(EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
187 hob.Raw)) != NULL) {
188 if (compare_guid(guid, &hob.ResourceDescriptor->Owner))
189 break;
190 hob.Raw = GET_NEXT_HOB(hob.Raw);
191 }
192 return hob.Raw;
193}
194
195/*
196 * Returns the first instance of the matching resource HOB among the whole HOB
197 * list.
198 */
199void *get_first_resource_hob(const EFI_GUID *guid)
200{
201 return get_next_resource_hob(guid, get_hob_list());
202}
203
204static void print_hob_mem_attributes(void *hob_ptr)
205{
206 EFI_HOB_MEMORY_ALLOCATION *hob_memory_ptr =
207 (EFI_HOB_MEMORY_ALLOCATION *)hob_ptr;
208 EFI_MEMORY_TYPE hob_mem_type =
209 hob_memory_ptr->AllocDescriptor.MemoryType;
210 u64 hob_mem_addr = hob_memory_ptr->AllocDescriptor.MemoryBaseAddress;
211 u64 hob_mem_length = hob_memory_ptr->AllocDescriptor.MemoryLength;
212 const char *hob_mem_type_names[15];
213
214 hob_mem_type_names[0] = "EfiReservedMemoryType";
215 hob_mem_type_names[1] = "EfiLoaderCode";
216 hob_mem_type_names[2] = "EfiLoaderData";
217 hob_mem_type_names[3] = "EfiBootServicesCode";
218 hob_mem_type_names[4] = "EfiBootServicesData";
219 hob_mem_type_names[5] = "EfiRuntimeServicesCode";
220 hob_mem_type_names[6] = "EfiRuntimeServicesData";
221 hob_mem_type_names[7] = "EfiConventionalMemory";
222 hob_mem_type_names[8] = "EfiUnusableMemory";
223 hob_mem_type_names[9] = "EfiACPIReclaimMemory";
224 hob_mem_type_names[10] = "EfiACPIMemoryNVS";
225 hob_mem_type_names[11] = "EfiMemoryMappedIO";
226 hob_mem_type_names[12] = "EfiMemoryMappedIOPortSpace";
227 hob_mem_type_names[13] = "EfiPalCode";
228 hob_mem_type_names[14] = "EfiMaxMemoryType";
Lee Leahy3dad4892015-05-05 11:14:02 -0700229
230 printk(BIOS_SPEW, " Memory type %s (0x%x)\n",
Lee Leahyb5ad8272015-04-20 15:29:16 -0700231 hob_mem_type_names[(u32)hob_mem_type],
232 (u32)hob_mem_type);
Lee Leahy3dad4892015-05-05 11:14:02 -0700233 printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
Lee Leahyb5ad8272015-04-20 15:29:16 -0700234 (unsigned long)hob_mem_addr,
235 (unsigned long)hob_mem_length);
Lee Leahy3dad4892015-05-05 11:14:02 -0700236}
237
Lee Leahyb5ad8272015-04-20 15:29:16 -0700238static void print_hob_resource_attributes(void *hob_ptr)
Lee Leahy3dad4892015-05-05 11:14:02 -0700239{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700240 EFI_HOB_RESOURCE_DESCRIPTOR *hob_resource_ptr =
241 (EFI_HOB_RESOURCE_DESCRIPTOR *)hob_ptr;
242 u32 hob_res_type = hob_resource_ptr->ResourceType;
243 u32 hob_res_attr = hob_resource_ptr->ResourceAttribute;
244 u64 hob_res_addr = hob_resource_ptr->PhysicalStart;
245 u64 hob_res_length = hob_resource_ptr->ResourceLength;
246 const char *hob_res_type_str = NULL;
Lee Leahy3dad4892015-05-05 11:14:02 -0700247
Lee Leahyb5ad8272015-04-20 15:29:16 -0700248 /* HOB Resource Types */
249 switch (hob_res_type) {
Lee Leahy3dad4892015-05-05 11:14:02 -0700250 case EFI_RESOURCE_SYSTEM_MEMORY:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700251 hob_res_type_str = "EFI_RESOURCE_SYSTEM_MEMORY";
252 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700253 case EFI_RESOURCE_MEMORY_MAPPED_IO:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700254 hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO";
255 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700256 case EFI_RESOURCE_IO:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700257 hob_res_type_str = "EFI_RESOURCE_IO";
258 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700259 case EFI_RESOURCE_FIRMWARE_DEVICE:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700260 hob_res_type_str = "EFI_RESOURCE_FIRMWARE_DEVICE";
261 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700262 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700263 hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT";
264 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700265 case EFI_RESOURCE_MEMORY_RESERVED:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700266 hob_res_type_str = "EFI_RESOURCE_MEMORY_RESERVED";
267 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700268 case EFI_RESOURCE_IO_RESERVED:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700269 hob_res_type_str = "EFI_RESOURCE_IO_RESERVED";
270 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700271 case EFI_RESOURCE_MAX_MEMORY_TYPE:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700272 hob_res_type_str = "EFI_RESOURCE_MAX_MEMORY_TYPE";
273 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700274 default:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700275 hob_res_type_str = "EFI_RESOURCE_UNKNOWN";
276 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700277 }
278
279 printk(BIOS_SPEW, " Resource %s (0x%0x) has attributes 0x%0x\n",
Lee Leahyb5ad8272015-04-20 15:29:16 -0700280 hob_res_type_str, hob_res_type, hob_res_attr);
Lee Leahy3dad4892015-05-05 11:14:02 -0700281 printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
Lee Leahyb5ad8272015-04-20 15:29:16 -0700282 (unsigned long)hob_res_addr,
283 (unsigned long)hob_res_length);
Lee Leahy3dad4892015-05-05 11:14:02 -0700284}
285
Lee Leahyb5ad8272015-04-20 15:29:16 -0700286static const char *get_hob_type_string(void *hob_ptr)
Lee Leahy3dad4892015-05-05 11:14:02 -0700287{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700288 EFI_PEI_HOB_POINTERS hob;
289 const char *hob_type_string = NULL;
290 const EFI_GUID fsp_reserved_guid =
291 FSP_RESERVED_MEMORY_RESOURCE_HOB_GUID;
292 const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
293 const EFI_GUID bootldr_tmp_mem_guid =
294 FSP_BOOTLOADER_TEMP_MEMORY_HOB_GUID;
295 const EFI_GUID bootldr_tolum_guid = FSP_BOOTLOADER_TOLUM_HOB_GUID;
296 const EFI_GUID graphics_info_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
Lee Leahy4a8c19c2015-06-16 14:33:30 -0700297 const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
Lee Leahy3dad4892015-05-05 11:14:02 -0700298
Lee Leahyb5ad8272015-04-20 15:29:16 -0700299 hob.Header = (EFI_HOB_GENERIC_HEADER *)hob_ptr;
300 switch (hob.Header->HobType) {
Lee Leahy3dad4892015-05-05 11:14:02 -0700301 case EFI_HOB_TYPE_HANDOFF:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700302 hob_type_string = "EFI_HOB_TYPE_HANDOFF";
303 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700304 case EFI_HOB_TYPE_MEMORY_ALLOCATION:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700305 hob_type_string = "EFI_HOB_TYPE_MEMORY_ALLOCATION";
306 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700307 case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700308 hob_type_string = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR";
Lee Leahy4a8c19c2015-06-16 14:33:30 -0700309 if (compare_guid(&fsp_reserved_guid, &hob.Guid->Name))
310 hob_type_string = "FSP_RESERVED_MEMORY_RESOURCE_HOB";
311 else if (compare_guid(&bootldr_tolum_guid, &hob.Guid->Name))
312 hob_type_string = "FSP_BOOTLOADER_TOLUM_HOB_GUID";
Lee Leahyb5ad8272015-04-20 15:29:16 -0700313 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700314 case EFI_HOB_TYPE_GUID_EXTENSION:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700315 hob_type_string = "EFI_HOB_TYPE_GUID_EXTENSION";
316 if (compare_guid(&bootldr_tmp_mem_guid, &hob.Guid->Name))
317 hob_type_string = "FSP_BOOTLOADER_TEMP_MEMORY_HOB";
Lee Leahyb5ad8272015-04-20 15:29:16 -0700318 else if (compare_guid(&mrc_guid, &hob.Guid->Name))
319 hob_type_string = "FSP_NON_VOLATILE_STORAGE_HOB";
Lee Leahyb5ad8272015-04-20 15:29:16 -0700320 else if (compare_guid(&graphics_info_guid, &hob.Guid->Name))
321 hob_type_string = "EFI_PEI_GRAPHICS_INFO_HOB_GUID";
Lee Leahy4a8c19c2015-06-16 14:33:30 -0700322 else if (compare_guid(&memory_info_hob_guid, &hob.Guid->Name))
323 hob_type_string = "FSP_SMBIOS_MEMORY_INFO_GUID";
Lee Leahyb5ad8272015-04-20 15:29:16 -0700324 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700325 case EFI_HOB_TYPE_MEMORY_POOL:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700326 hob_type_string = "EFI_HOB_TYPE_MEMORY_POOL";
327 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700328 case EFI_HOB_TYPE_UNUSED:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700329 hob_type_string = "EFI_HOB_TYPE_UNUSED";
330 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700331 case EFI_HOB_TYPE_END_OF_HOB_LIST:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700332 hob_type_string = "EFI_HOB_TYPE_END_OF_HOB_LIST";
333 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700334 default:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700335 hob_type_string = "EFI_HOB_TYPE_UNRECOGNIZED";
336 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700337 }
338
Lee Leahyb5ad8272015-04-20 15:29:16 -0700339 return hob_type_string;
Lee Leahy3dad4892015-05-05 11:14:02 -0700340}
341
Lee Leahyb5ad8272015-04-20 15:29:16 -0700342/*
343 * Print out a structure of all the HOBs
Lee Leahy3dad4892015-05-05 11:14:02 -0700344 * that match a certain type:
345 * Print all types (0x0000)
Lee Leahyb5ad8272015-04-20 15:29:16 -0700346 * EFI_HOB_TYPE_HANDOFF (0x0001)
Lee Leahy3dad4892015-05-05 11:14:02 -0700347 * EFI_HOB_TYPE_MEMORY_ALLOCATION (0x0002)
348 * EFI_HOB_TYPE_RESOURCE_DESCRIPTOR (0x0003)
349 * EFI_HOB_TYPE_GUID_EXTENSION (0x0004)
350 * EFI_HOB_TYPE_MEMORY_POOL (0x0007)
351 * EFI_HOB_TYPE_UNUSED (0xFFFE)
352 * EFI_HOB_TYPE_END_OF_HOB_LIST (0xFFFF)
353 */
Lee Leahyb5ad8272015-04-20 15:29:16 -0700354void print_hob_type_structure(u16 hob_type, void *hob_list_ptr)
Lee Leahy3dad4892015-05-05 11:14:02 -0700355{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700356 u32 *current_hob;
357 u32 *next_hob = 0;
358 u8 last_hob = 0;
359 u32 current_type;
360 const char *current_type_str;
Lee Leahy3dad4892015-05-05 11:14:02 -0700361
Lee Leahyb5ad8272015-04-20 15:29:16 -0700362 current_hob = hob_list_ptr;
Lee Leahy3dad4892015-05-05 11:14:02 -0700363
Lee Leahyb5ad8272015-04-20 15:29:16 -0700364 /*
365 * Print out HOBs of our desired type until
Lee Leahy3dad4892015-05-05 11:14:02 -0700366 * the end of the HOB list
367 */
368 printk(BIOS_DEBUG, "\n=== FSP HOB Data Structure ===\n");
Lee Leahyb5ad8272015-04-20 15:29:16 -0700369 printk(BIOS_DEBUG, "0x%p: hob_list_ptr\n", hob_list_ptr);
Lee Leahy3dad4892015-05-05 11:14:02 -0700370 do {
Lee Leahyb5ad8272015-04-20 15:29:16 -0700371 EFI_HOB_GENERIC_HEADER *current_header_ptr =
372 (EFI_HOB_GENERIC_HEADER *)current_hob;
Lee Leahy3dad4892015-05-05 11:14:02 -0700373
Lee Leahyb5ad8272015-04-20 15:29:16 -0700374 /* Get the type of this HOB */
375 current_type = current_header_ptr->HobType;
376 current_type_str = get_hob_type_string(current_hob);
377
378 if (current_type == hob_type || hob_type == 0x0000) {
Lee Leahy3dad4892015-05-05 11:14:02 -0700379 printk(BIOS_DEBUG, "HOB 0x%0x is an %s (type 0x%0x)\n",
Lee Leahyb5ad8272015-04-20 15:29:16 -0700380 (u32)current_hob, current_type_str,
381 current_type);
382 switch (current_type) {
Lee Leahy3dad4892015-05-05 11:14:02 -0700383 case EFI_HOB_TYPE_MEMORY_ALLOCATION:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700384 print_hob_mem_attributes(current_hob);
385 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700386 case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
Lee Leahyb5ad8272015-04-20 15:29:16 -0700387 print_hob_resource_attributes(current_hob);
388 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700389 }
390 }
391
Lee Leahyb5ad8272015-04-20 15:29:16 -0700392 /* Check for end of HOB list */
393 last_hob = END_OF_HOB_LIST(current_hob);
394 if (!last_hob) {
395 /* Get next HOB pointer */
396 next_hob = GET_NEXT_HOB(current_hob);
397
398 /* Start on next HOB */
399 current_hob = next_hob;
Lee Leahy3dad4892015-05-05 11:14:02 -0700400 }
Lee Leahyb5ad8272015-04-20 15:29:16 -0700401 } while (!last_hob);
Lee Leahy3dad4892015-05-05 11:14:02 -0700402 printk(BIOS_DEBUG, "=== End of FSP HOB Data Structure ===\n\n");
403}
404
Lee Leahyb5ad8272015-04-20 15:29:16 -0700405#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
406/*
407 * Save the FSP memory HOB (mrc data) to the MRC area in CBMEM
Lee Leahy3dad4892015-05-05 11:14:02 -0700408 */
Lee Leahyb5ad8272015-04-20 15:29:16 -0700409int save_mrc_data(void *hob_start)
Lee Leahy3dad4892015-05-05 11:14:02 -0700410{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700411 u32 *mrc_hob;
412 u32 *mrc_hob_data;
413 u32 mrc_hob_size;
414 struct mrc_data_container *mrc_data;
415 int output_len;
416 const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
Lee Leahy3dad4892015-05-05 11:14:02 -0700417
Lee Leahyb5ad8272015-04-20 15:29:16 -0700418 mrc_hob = get_next_guid_hob(&mrc_guid, hob_start);
419 if (mrc_hob == NULL) {
420 printk(BIOS_DEBUG,
421 "Memory Configure Data Hob is not present\n");
Lee Leahy3dad4892015-05-05 11:14:02 -0700422 return 0;
Lee Leahyb5ad8272015-04-20 15:29:16 -0700423 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700424
Lee Leahyb5ad8272015-04-20 15:29:16 -0700425 mrc_hob_data = GET_GUID_HOB_DATA(mrc_hob);
426 mrc_hob_size = (u32) GET_HOB_LENGTH(mrc_hob);
427
428 printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n",
429 (void *)mrc_hob_data, mrc_hob_size);
430
431 output_len = ALIGN(mrc_hob_size, 16);
432
433 /* Save the MRC S3/fast boot/ADR restore data to cbmem */
434 mrc_data = cbmem_add(CBMEM_ID_MRCDATA,
435 output_len + sizeof(struct mrc_data_container));
436
437 /* Just return if there was a problem with getting CBMEM */
438 if (mrc_data == NULL) {
439 printk(BIOS_WARNING,
440 "CBMEM was not available to save the fast boot cache data.\n");
441 return 0;
442 }
443
444 printk(BIOS_DEBUG,
445 "Copy FSP MRC DATA to HOB (source addr %p, dest addr %p, %u bytes)\n",
446 (void *)mrc_hob_data, mrc_data, output_len);
447
448 mrc_data->mrc_signature = MRC_DATA_SIGNATURE;
449 mrc_data->mrc_data_size = output_len;
450 mrc_data->reserved = 0;
451 memcpy(mrc_data->mrc_data, (const void *)mrc_hob_data, mrc_hob_size);
452
453 /* Zero the unused space in aligned buffer. */
454 if (output_len > mrc_hob_size)
455 memset((mrc_data->mrc_data + mrc_hob_size), 0,
456 output_len - mrc_hob_size);
457
458 mrc_data->mrc_checksum = compute_ip_checksum(mrc_data->mrc_data,
459 mrc_data->mrc_data_size);
460
461#if IS_ENABLED(CONFIG_DISPLAY_FAST_BOOT_DATA)
462 printk(BIOS_SPEW, "Fast boot data (includes align and checksum):\n");
463 hexdump32(BIOS_SPEW, (void *)mrc_data->mrc_data, output_len);
464#endif
Lee Leahy3dad4892015-05-05 11:14:02 -0700465 return 1;
466}
Lee Leahyb5ad8272015-04-20 15:29:16 -0700467
468void __attribute__ ((weak)) update_mrc_cache(void *unused)
469{
470 printk(BIOS_ERR, "Add routine %s to save the MRC data.\n", __func__);
471}
472#endif /* CONFIG_ENABLE_MRC_CACHE */
473
474#if ENV_RAMSTAGE
475
476static void find_fsp_hob_update_mrc(void *unused)
477{
478 void *hob_list_ptr;
479
480 /* 0x0000: Print all types */
481 hob_list_ptr = get_hob_list();
482#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
483 print_hob_type_structure(0x000, hob_list_ptr);
484#endif
485
486 #if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
487 if (save_mrc_data(hob_list_ptr))
488 update_mrc_cache(NULL);
489 else
490 printk(BIOS_DEBUG, "Not updating MRC data in flash.\n");
491 #endif
492}
493
494/* Update the MRC/fast boot cache as part of the late table writing stage */
495BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
496 find_fsp_hob_update_mrc, NULL);
497
498#endif /* ENV_RAMSTAGE */