Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 2 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 3 | #include <assert.h> |
| 4 | #include <arch/mmu.h> |
| 5 | #include <cbfs.h> |
Venkat Thogaru | 209efcc | 2022-09-26 17:46:45 +0530 | [diff] [blame] | 6 | #include <cbmem.h> |
| 7 | #include <commonlib/bsd/mem_chip_info.h> |
| 8 | #include <console/cbmem_console.h> |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 9 | #include <console/console.h> |
Venkat Thogaru | 209efcc | 2022-09-26 17:46:45 +0530 | [diff] [blame] | 10 | #include <fmap.h> |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 11 | #include <mrc_cache.h> |
Venkat Thogaru | 209efcc | 2022-09-26 17:46:45 +0530 | [diff] [blame] | 12 | #include <reset.h> |
| 13 | #include <security/vboot/misc.h> |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 14 | #include <soc/mmu.h> |
| 15 | #include <soc/mmu_common.h> |
| 16 | #include <soc/qclib_common.h> |
| 17 | #include <soc/symbols_common.h> |
Venkat Thogaru | 209efcc | 2022-09-26 17:46:45 +0530 | [diff] [blame] | 18 | #include <string.h> |
Ashwin Kumar | 16eb403 | 2019-10-29 13:20:06 +0530 | [diff] [blame] | 19 | #include <vb2_api.h> |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 20 | |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 21 | #define QCLIB_VERSION 0 |
| 22 | |
Kyösti Mälkki | fa3bc04 | 2022-03-31 07:40:10 +0300 | [diff] [blame] | 23 | /* store QcLib return data until CBMEM_CREATION_HOOK runs */ |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 24 | static struct mem_chip_info *mem_chip_info; |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 25 | |
| 26 | static void write_mem_chip_information(struct qclib_cb_if_table_entry *te) |
| 27 | { |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 28 | struct mem_chip_info *info = (void *)te->blob_address; |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 29 | if (te->size > sizeof(struct mem_chip_info) && |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 30 | te->size == mem_chip_info_size(info->num_entries)) { |
| 31 | /* Save mem_chip_info in global variable ahead of hook running */ |
| 32 | mem_chip_info = info; |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 33 | } |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | static void add_mem_chip_info(int unused) |
| 37 | { |
| 38 | void *mem_region_base = NULL; |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 39 | size_t size; |
| 40 | |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 41 | if (!mem_chip_info || !mem_chip_info->num_entries || |
| 42 | mem_chip_info->struct_version != MEM_CHIP_STRUCT_VERSION) { |
Yu-Ping Wu | fae1eb3 | 2023-08-21 16:02:57 +0800 | [diff] [blame] | 43 | printk(BIOS_ERR, "Did not receive valid mem_chip_info from QcLib!\n"); |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 44 | return; |
| 45 | } |
| 46 | |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 47 | size = mem_chip_info_size(mem_chip_info->num_entries); |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 48 | |
| 49 | /* Add cbmem table */ |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 50 | mem_region_base = cbmem_add(CBMEM_ID_MEM_CHIP_INFO, size); |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 51 | ASSERT(mem_region_base != NULL); |
| 52 | |
| 53 | /* Migrate the data into CBMEM */ |
Julius Werner | 3460aa3 | 2022-10-24 19:06:03 -0700 | [diff] [blame] | 54 | memcpy(mem_region_base, mem_chip_info, size); |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 55 | } |
| 56 | |
Kyösti Mälkki | fa3bc04 | 2022-03-31 07:40:10 +0300 | [diff] [blame] | 57 | CBMEM_CREATION_HOOK(add_mem_chip_info); |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 58 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 59 | struct qclib_cb_if_table qclib_cb_if_table = { |
| 60 | .magic = QCLIB_MAGIC_NUMBER, |
| 61 | .version = QCLIB_INTERFACE_VERSION, |
| 62 | .num_entries = 0, |
| 63 | .max_entries = QCLIB_MAX_NUMBER_OF_ENTRIES, |
| 64 | .global_attributes = 0, |
| 65 | .reserved = 0, |
| 66 | }; |
| 67 | |
Sudheer Kumar Amrabadi | 58f6031 | 2022-05-10 16:43:47 +0530 | [diff] [blame] | 68 | const char *qclib_file_default(enum qclib_cbfs_file file) |
| 69 | { |
| 70 | switch (file) { |
| 71 | case QCLIB_CBFS_PMICCFG: |
| 72 | return CONFIG_CBFS_PREFIX "/pmiccfg"; |
| 73 | case QCLIB_CBFS_QCSDI: |
| 74 | return CONFIG_CBFS_PREFIX "/qcsdi"; |
| 75 | case QCLIB_CBFS_QCLIB: |
| 76 | return CONFIG_CBFS_PREFIX "/qclib"; |
| 77 | case QCLIB_CBFS_DCB: |
| 78 | return CONFIG_CBFS_PREFIX "/dcb"; |
| 79 | default: |
| 80 | die("unknown QcLib file %d", file); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | const char *qclib_file(enum qclib_cbfs_file file) |
| 85 | __attribute__((weak, alias("qclib_file_default"))); |
| 86 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 87 | void qclib_add_if_table_entry(const char *name, void *base, |
| 88 | uint32_t size, uint32_t attrs) |
| 89 | { |
| 90 | struct qclib_cb_if_table_entry *te = |
| 91 | &qclib_cb_if_table.te[qclib_cb_if_table.num_entries++]; |
| 92 | assert(qclib_cb_if_table.num_entries <= qclib_cb_if_table.max_entries); |
Julius Werner | 096fd0a | 2019-06-10 13:18:59 -0700 | [diff] [blame] | 93 | strncpy(te->name, name, sizeof(te->name) - 1); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 94 | te->blob_address = (uintptr_t)base; |
| 95 | te->size = size; |
| 96 | te->blob_attributes = attrs; |
| 97 | } |
| 98 | |
| 99 | static void write_ddr_information(struct qclib_cb_if_table_entry *te) |
| 100 | { |
| 101 | uint64_t ddr_size; |
| 102 | |
| 103 | /* Save DDR info in SRAM region to share with ramstage */ |
| 104 | ddr_region->offset = te->blob_address; |
| 105 | ddr_size = te->size; |
| 106 | ddr_region->size = ddr_size * MiB; |
| 107 | |
| 108 | /* Use DDR info to configure MMU */ |
Nico Huber | f55b711 | 2024-01-11 18:50:50 +0100 | [diff] [blame] | 109 | qc_mmu_dram_config_post_dram_init( |
| 110 | (void *)(uintptr_t)region_offset(ddr_region), region_sz(ddr_region)); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | static void write_qclib_log_to_cbmemc(struct qclib_cb_if_table_entry *te) |
| 114 | { |
| 115 | int i; |
| 116 | char *ptr = (char *)te->blob_address; |
| 117 | |
Julius Werner | 37833fc | 2023-09-07 13:38:06 -0700 | [diff] [blame] | 118 | for (i = 0; i < te->size; i++) { |
| 119 | char c = *ptr++; |
| 120 | if (c != '\r') |
| 121 | __cbmemc_tx_byte(c); |
| 122 | } |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | static void write_table_entry(struct qclib_cb_if_table_entry *te) |
| 126 | { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 127 | if (!strncmp(QCLIB_TE_DDR_INFORMATION, te->name, |
| 128 | sizeof(te->name))) { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 129 | write_ddr_information(te); |
| 130 | |
| 131 | } else if (!strncmp(QCLIB_TE_DDR_TRAINING_DATA, te->name, |
| 132 | sizeof(te->name))) { |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 133 | assert(!mrc_cache_stash_data(MRC_TRAINING_DATA, QCLIB_VERSION, |
| 134 | (const void *)te->blob_address, te->size)); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 135 | |
| 136 | } else if (!strncmp(QCLIB_TE_LIMITS_CFG_DATA, te->name, |
| 137 | sizeof(te->name))) { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 138 | assert(fmap_overwrite_area(QCLIB_FR_LIMITS_CFG_DATA, |
| 139 | (const void *)te->blob_address, te->size)); |
| 140 | |
| 141 | } else if (!strncmp(QCLIB_TE_QCLIB_LOG_BUFFER, te->name, |
| 142 | sizeof(te->name))) { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 143 | write_qclib_log_to_cbmemc(te); |
| 144 | |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 145 | } else if (!strncmp(QCLIB_TE_MEM_CHIP_INFO, te->name, |
| 146 | sizeof(te->name))) { |
| 147 | write_mem_chip_information(te); |
| 148 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 149 | } else { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 150 | printk(BIOS_WARNING, "%s write not implemented\n", te->name); |
| 151 | printk(BIOS_WARNING, " blob_address[%llx]..size[%x]\n", |
| 152 | te->blob_address, te->size); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
| 156 | static void dump_te_table(void) |
| 157 | { |
| 158 | struct qclib_cb_if_table_entry *te; |
| 159 | int i; |
| 160 | |
| 161 | for (i = 0; i < qclib_cb_if_table.num_entries; i++) { |
| 162 | te = &qclib_cb_if_table.te[i]; |
| 163 | printk(BIOS_DEBUG, "[%s][%llx][%x][%x]\n", |
| 164 | te->name, te->blob_address, |
| 165 | te->size, te->blob_attributes); |
| 166 | } |
| 167 | } |
| 168 | |
Sudheer Kumar Amrabadi | 0225e80 | 2023-03-15 15:17:36 +0530 | [diff] [blame] | 169 | __weak int qclib_soc_override(struct qclib_cb_if_table *table) { return 0; } |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 170 | |
| 171 | void qclib_load_and_run(void) |
| 172 | { |
| 173 | int i; |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 174 | ssize_t data_size; |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 175 | struct mmu_context pre_qclib_mmu_context; |
| 176 | |
| 177 | /* zero ddr_information SRAM region, needs new data each boot */ |
| 178 | memset(ddr_region, 0, sizeof(struct region)); |
| 179 | |
| 180 | /* output area, QCLib copies console log buffer out */ |
Patrick Georgi | d939183 | 2019-05-15 21:33:42 +0200 | [diff] [blame] | 181 | if (CONFIG(CONSOLE_CBMEM)) |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 182 | qclib_add_if_table_entry(QCLIB_TE_QCLIB_LOG_BUFFER, |
| 183 | _qclib_serial_log, |
| 184 | REGION_SIZE(qclib_serial_log), 0); |
| 185 | |
| 186 | /* output area, QCLib fills in DDR details */ |
| 187 | qclib_add_if_table_entry(QCLIB_TE_DDR_INFORMATION, NULL, 0, 0); |
| 188 | |
Shelley Chen | 0263e0f | 2020-10-21 22:46:14 -0700 | [diff] [blame] | 189 | /* Attempt to load DDR Training Blob */ |
| 190 | data_size = mrc_cache_load_current(MRC_TRAINING_DATA, QCLIB_VERSION, |
| 191 | _ddr_training, REGION_SIZE(ddr_training)); |
| 192 | if (data_size < 0) { |
| 193 | printk(BIOS_ERR, "Unable to load previous training data.\n"); |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 194 | memset(_ddr_training, 0, REGION_SIZE(ddr_training)); |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 195 | } |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 196 | qclib_add_if_table_entry(QCLIB_TE_DDR_TRAINING_DATA, |
Shelley Chen | afaa3d0 | 2020-10-06 15:50:21 -0700 | [diff] [blame] | 197 | _ddr_training, REGION_SIZE(ddr_training), 0); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 198 | |
Ravi Kumar Bokka | 4f9cb42 | 2022-04-06 07:35:53 +0530 | [diff] [blame] | 199 | /* Address and size of this entry will be filled in by QcLib. */ |
| 200 | qclib_add_if_table_entry(QCLIB_TE_MEM_CHIP_INFO, NULL, 0, 0); |
Ravi Kumar Bokka | 4573ca4 | 2021-11-10 05:24:17 +0530 | [diff] [blame] | 201 | |
Ravi Kumar Bokka | 1faaa16 | 2021-03-31 08:05:24 +0530 | [diff] [blame] | 202 | /* Attempt to load PMICCFG Blob */ |
Sudheer Kumar Amrabadi | 58f6031 | 2022-05-10 16:43:47 +0530 | [diff] [blame] | 203 | data_size = cbfs_load(qclib_file(QCLIB_CBFS_PMICCFG), |
Ravi Kumar Bokka | 1faaa16 | 2021-03-31 08:05:24 +0530 | [diff] [blame] | 204 | _pmic, REGION_SIZE(pmic)); |
| 205 | if (!data_size) { |
| 206 | printk(BIOS_ERR, "[%s] /pmiccfg failed\n", __func__); |
| 207 | goto fail; |
| 208 | } |
| 209 | qclib_add_if_table_entry(QCLIB_TE_PMIC_SETTINGS, _pmic, data_size, 0); |
| 210 | |
| 211 | /* Attempt to load DCB Blob */ |
Sudheer Kumar Amrabadi | 58f6031 | 2022-05-10 16:43:47 +0530 | [diff] [blame] | 212 | data_size = cbfs_load(qclib_file(QCLIB_CBFS_DCB), |
Ravi Kumar Bokka | 1faaa16 | 2021-03-31 08:05:24 +0530 | [diff] [blame] | 213 | _dcb, REGION_SIZE(dcb)); |
| 214 | if (!data_size) { |
| 215 | printk(BIOS_ERR, "[%s] /dcb failed\n", __func__); |
| 216 | goto fail; |
| 217 | } |
| 218 | qclib_add_if_table_entry(QCLIB_TE_DCB_SETTINGS, _dcb, data_size, 0); |
| 219 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 220 | /* Enable QCLib serial output, based on Kconfig */ |
Patrick Georgi | d939183 | 2019-05-15 21:33:42 +0200 | [diff] [blame] | 221 | if (CONFIG(CONSOLE_SERIAL)) |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 222 | qclib_cb_if_table.global_attributes = |
| 223 | QCLIB_GA_ENABLE_UART_LOGGING; |
| 224 | |
Ashwin Kumar | 16eb403 | 2019-10-29 13:20:06 +0530 | [diff] [blame] | 225 | if (CONFIG(QC_SDI_ENABLE) && (!CONFIG(VBOOT) || |
| 226 | !vboot_is_gbb_flag_set(VB2_GBB_FLAG_RUNNING_FAFT))) { |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 227 | struct prog qcsdi = |
Ashwin Kumar | 16eb403 | 2019-10-29 13:20:06 +0530 | [diff] [blame] | 228 | PROG_INIT(PROG_REFCODE, |
Sudheer Kumar Amrabadi | 58f6031 | 2022-05-10 16:43:47 +0530 | [diff] [blame] | 229 | qclib_file(QCLIB_CBFS_QCSDI)); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 230 | |
| 231 | /* Attempt to load QCSDI elf */ |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 232 | if (cbfs_prog_stage_load(&qcsdi)) |
| 233 | goto fail; |
| 234 | |
Ashwin Kumar | 16eb403 | 2019-10-29 13:20:06 +0530 | [diff] [blame] | 235 | qclib_add_if_table_entry(QCLIB_TE_QCSDI, |
| 236 | prog_entry(&qcsdi), prog_size(&qcsdi), 0); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 237 | printk(BIOS_INFO, "qcsdi.entry[%p]\n", qcsdi.entry); |
| 238 | } |
| 239 | |
Sudheer Kumar Amrabadi | 0225e80 | 2023-03-15 15:17:36 +0530 | [diff] [blame] | 240 | /* hook for SoC specific binary blob loads */ |
| 241 | if (qclib_soc_override(&qclib_cb_if_table)) { |
| 242 | printk(BIOS_ERR, "qclib_soc_override failed\n"); |
| 243 | goto fail; |
| 244 | } |
| 245 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 246 | dump_te_table(); |
| 247 | |
| 248 | /* Attempt to load QCLib elf */ |
| 249 | struct prog qclib = |
Sudheer Kumar Amrabadi | 58f6031 | 2022-05-10 16:43:47 +0530 | [diff] [blame] | 250 | PROG_INIT(PROG_REFCODE, qclib_file(QCLIB_CBFS_QCLIB)); |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 251 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 252 | if (cbfs_prog_stage_load(&qclib)) |
| 253 | goto fail; |
| 254 | |
| 255 | prog_set_entry(&qclib, prog_entry(&qclib), &qclib_cb_if_table); |
| 256 | |
| 257 | printk(BIOS_DEBUG, "\n\n\nQCLib is about to Initialize DDR\n"); |
Sudheer Kumar Amrabadi | 0225e80 | 2023-03-15 15:17:36 +0530 | [diff] [blame] | 258 | printk(BIOS_DEBUG, "Global Attributes[%#x]..Table Entries Count[%d]\n", |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 259 | qclib_cb_if_table.global_attributes, |
| 260 | qclib_cb_if_table.num_entries); |
| 261 | printk(BIOS_DEBUG, "Jumping to QCLib code at %p(%p)\n", |
| 262 | prog_entry(&qclib), prog_entry_arg(&qclib)); |
| 263 | |
| 264 | /* back-up mmu context before disabling mmu and executing qclib */ |
| 265 | mmu_save_context(&pre_qclib_mmu_context); |
| 266 | /* disable mmu before jumping to qclib. mmu_disable also |
| 267 | flushes and invalidates caches before disabling mmu. */ |
| 268 | mmu_disable(); |
| 269 | |
| 270 | prog_run(&qclib); |
| 271 | |
| 272 | /* Before returning, QCLib flushes cache and disables mmu. |
| 273 | Explicitly disable mmu (flush, invalidate and disable mmu) |
| 274 | before re-enabling mmu with backed-up mmu context */ |
| 275 | mmu_disable(); |
| 276 | mmu_restore_context(&pre_qclib_mmu_context); |
| 277 | mmu_enable(); |
| 278 | |
Venkat Thogaru | fec9abc | 2022-09-07 17:17:39 +0530 | [diff] [blame] | 279 | if (qclib_cb_if_table.global_attributes & QCLIB_GA_FORCE_COLD_REBOOT) { |
| 280 | printk(BIOS_NOTICE, "QcLib requested cold reboot\n"); |
| 281 | board_reset(); |
| 282 | } |
| 283 | |
T Michael Turney | 7a3e46d | 2019-03-21 14:21:26 -0700 | [diff] [blame] | 284 | /* step through I/F table, handling return values */ |
| 285 | for (i = 0; i < qclib_cb_if_table.num_entries; i++) |
| 286 | if (qclib_cb_if_table.te[i].blob_attributes & |
| 287 | QCLIB_BA_SAVE_TO_STORAGE) |
| 288 | write_table_entry(&qclib_cb_if_table.te[i]); |
| 289 | |
| 290 | /* confirm that we received valid ddr information from QCLib */ |
| 291 | assert((uintptr_t)_dram == region_offset(ddr_region) && |
| 292 | region_sz(ddr_region) >= (u8 *)cbmem_top() - _dram); |
| 293 | |
| 294 | printk(BIOS_DEBUG, "QCLib completed\n\n\n"); |
| 295 | |
| 296 | return; |
| 297 | |
| 298 | fail: |
| 299 | die("Couldn't run QCLib.\n"); |
| 300 | } |