MCPcopy Create free account
hub / github.com/coreboot/coreboot / rmodule_cbfs_allocator

Function rmodule_cbfs_allocator

src/lib/rmodule.c:194–247  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

192}
193
194static void *rmodule_cbfs_allocator(void *rsl_arg, size_t unused,
195 const union cbfs_mdata *mdata)
196{
197 struct rmod_stage_load *rsl = rsl_arg;
198
199 assert(IS_POWER_OF_2(region_alignment) &&
200 region_alignment >= sizeof(struct rmodule_header));
201
202 /* The CBFS core just passes us the decompressed size of the file, but
203 we need to know the memlen of the binary image. We need to find and
204 parse the stage header explicitly. */
205 const struct cbfs_file_attr_stageheader *sattr = cbfs_find_attr(mdata,
206 CBFS_FILE_ATTR_TAG_STAGEHEADER, sizeof(*sattr));
207 if (!sattr) {
208 printk(BIOS_ERR, "rmodule '%s' has no stage header!\n",
209 rsl->prog->name);
210 return NULL;
211 }
212
213 const size_t memlen = be32toh(sattr->memlen);
214
215 /* Place the rmodule according to alignment. The rmodule files
216 * themselves are packed as a header and a payload, however the rmodule
217 * itself is linked along with the header. The header starts at address
218 * 0. Immediately following the header in the file is the program,
219 * however its starting address is determined by the rmodule linker
220 * script. In short, sizeof(struct rmodule_header) can be less than
221 * or equal to the linked address of the program. Therefore we want
222 * to place the rmodule so that the program falls on the aligned
223 * address with the header just before it. Therefore, we need at least
224 * a page to account for the size of the header. */
225 size_t region_size = ALIGN_UP(memlen + region_alignment, 4096);
226 /* The program starts immediately after the header. However,
227 * it needs to be aligned to a 4KiB boundary. Therefore, adjust the
228 * program location so that the program lands on a page boundary. The
229 * layout looks like the following:
230 *
231 * +--------------------------------+ region_alignment + region_size
232 * | >= 0 bytes from alignment |
233 * +--------------------------------+ program end (4KiB aligned)
234 * | program size |
235 * +--------------------------------+ program_begin (4KiB aligned)
236 * | sizeof(struct rmodule_header) |
237 * +--------------------------------+ rmodule header start
238 * | >= 0 bytes from alignment |
239 * +--------------------------------+ region_alignment
240 */
241
242 uint8_t *stage_region = cbmem_add(rsl->cbmem_id, region_size);
243 if (stage_region == NULL)
244 return NULL;
245
246 return stage_region + region_alignment - sizeof(struct rmodule_header);
247}
248
249int rmodule_stage_load(struct rmod_stage_load *rsl)
250{

Callers

nothing calls this directly

Calls 3

cbmem_addFunction · 0.70
cbfs_find_attrFunction · 0.50
printkFunction · 0.50

Tested by

no test coverage detected