Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | // SPDX-License-Identifier: GPL-2.0 /* * Copyright 2019 Google LLC */ #include <binman.h> #include <binman_sym.h> #include <bootstage.h> #include <cbfs.h> #include <dm.h> #include <event.h> #include <init.h> #include <log.h> #include <spi.h> #include <spl.h> #include <spi_flash.h> #include <asm/intel_pinctrl.h> #include <dm/uclass-internal.h> #include <asm/fsp2/fsp_internal.h> int fsp_setup_pinctrl(void) { struct udevice *dev; ofnode node; int ret; /* Make sure pads are set up early in U-Boot */ if (!ll_boot_init() || xpl_phase() != PHASE_BOARD_F) return 0; /* Probe all pinctrl devices to set up the pads */ ret = uclass_first_device_err(UCLASS_PINCTRL, &dev); if (ret) return log_msg_ret("no fsp pinctrl", ret); node = ofnode_path("fsp"); if (!ofnode_valid(node)) return log_msg_ret("no fsp params", -EINVAL); ret = pinctrl_config_pads_for_node(dev, node); if (ret) return log_msg_ret("pad config", ret); return ret; } EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, fsp_setup_pinctrl); #if !defined(CONFIG_TPL_BUILD) binman_sym_declare(ulong, intel_fsp_m, image_pos); binman_sym_declare(ulong, intel_fsp_m, size); /** * get_cbfs_fsp() - Obtain the FSP by looking up in CBFS * * This looks up an FSP in a CBFS. It is used mostly for testing, when booting * U-Boot from a hybrid image containing coreboot as the first-stage bootloader. * * The typical use for this feature is when building a Chrome OS image which * includes coreboot in it. By adding U-Boot into the 'COREBOOT' CBFS as well, * it is possible to make coreboot chain-load U-Boot. Thus the initial stages of * the SoC init can be done by coreboot and the later stages by U-Boot. This is * a convenient way to start the porting work. The jump to U-Boot can then be * moved progressively earlier and earlier, until U-Boot takes over all the init * and you have a native port. * * This function looks up a CBFS at a known location and reads the FSP-M from it * so that U-Boot can init the memory. * * This function is not used in the normal boot but is kept here for future * development. * * @type; Type to look up (only FSP_M supported at present) * @map_base: Base memory address for mapped SPI * @entry: Returns an entry containing the position of the FSP image */ static int get_cbfs_fsp(enum fsp_type_t type, ulong map_base, struct binman_entry *entry) { /* * Use a hard-coded position of CBFS in the ROM for now. It would be * possible to read the position using the FMAP in the ROM, but since * this code is only used for development, it doesn't seem worth it. * Use the 'cbfstool <image> layout' command to get these values, e.g.: * 'COREBOOT' (CBFS, size 1814528, offset 2117632). */ ulong cbfs_base = 0x205000; struct cbfs_priv *cbfs; int ret; ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true, &cbfs); if (ret) return ret; if (!ret) { const struct cbfs_cachenode *node; node = cbfs_find_file(cbfs, "fspm.bin"); if (!node) return log_msg_ret("fspm node", -ENOENT); entry->image_pos = (ulong)node->data; entry->size = node->data_length; } return 0; } int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, bool use_spi_flash, struct udevice **devp, struct fsp_header **hdrp, ulong *rom_offsetp) { struct udevice *dev; ulong rom_offset = 0; uint map_size; ulong map_base; uint offset; int ret; /* * Find the devices but don't probe them, since we don't want to * auto-config PCI before silicon init runs */ ret = uclass_find_first_device(UCLASS_NORTHBRIDGE, &dev); if (ret) return log_msg_ret("Cannot get northbridge", ret); if (!use_spi_flash) { struct udevice *sf; /* Just use the SPI driver to get the memory map */ ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf); if (ret) return log_msg_ret("Cannot get SPI flash", ret); ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset); if (ret) return log_msg_ret("Could not get flash mmap", ret); } if (xpl_phase() >= PHASE_BOARD_F) { if (type != FSP_S) return -EPROTONOSUPPORT; ret = binman_entry_find("intel-fsp-s", entry); if (ret) return log_msg_ret("binman entry", ret); if (!use_spi_flash) rom_offset = map_base; } else { ret = -ENOENT; if (false) /* * Support using a hybrid image build by coreboot. See * the function comments for details */ ret = get_cbfs_fsp(type, map_base, entry); if (ret) { ulong mask = CONFIG_ROM_SIZE - 1; if (type != FSP_M) return -EPROTONOSUPPORT; entry->image_pos = binman_sym(ulong, intel_fsp_m, image_pos); entry->size = binman_sym(ulong, intel_fsp_m, size); if (entry->image_pos != BINMAN_SYM_MISSING) { ret = 0; if (use_spi_flash) entry->image_pos &= mask; else entry->image_pos += (map_base & mask); } else { ret = -ENOENT; } } } if (ret) return log_msg_ret("Cannot find FSP", ret); entry->image_pos += rom_offset; /* * Account for the time taken to read memory-mapped SPI flash since in * this case we don't use the SPI driver and BOOTSTAGE_ID_ACCUM_SPI. */ if (!use_spi_flash) bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi"); ret = fsp_get_header(entry->image_pos, entry->size, use_spi_flash, hdrp); if (!use_spi_flash) bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI); if (ret) return log_msg_ret("fsp_get_header", ret); *devp = dev; if (rom_offsetp) *rom_offsetp = rom_offset; return 0; } #endif |