mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-26 23:41:50 +00:00
vbe: Handle loading from an unaligned offset
There is no guarantee that an FIT image starts on a block boundary. When it doesn't, the image starts part-way through the first block. Add logic to detect this and copy the image down into place. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
d337037e1a
commit
36d6c89950
1 changed files with 14 additions and 5 deletions
|
@ -192,32 +192,41 @@ int vbe_read_fit(struct udevice *blk, ulong area_offset, ulong area_size,
|
||||||
log_debug("load_addr %lx len %lx addr %lx aligned_size %lx\n",
|
log_debug("load_addr %lx len %lx addr %lx aligned_size %lx\n",
|
||||||
load_addr, len, addr, aligned_size);
|
load_addr, len, addr, aligned_size);
|
||||||
if (load_addr + len > addr + aligned_size) {
|
if (load_addr + len > addr + aligned_size) {
|
||||||
ulong base, full_size;
|
ulong base, full_size, offset, extra;
|
||||||
void *base_buf;
|
void *base_buf;
|
||||||
|
|
||||||
/* Find the start address to load from */
|
/* Find the start address to load from */
|
||||||
base = ALIGN_DOWN(load_addr, desc->blksz);
|
base = ALIGN_DOWN(load_addr, desc->blksz);
|
||||||
|
|
||||||
|
offset = area_offset + load_addr - addr;
|
||||||
|
blknum = offset / desc->blksz;
|
||||||
|
extra = offset % desc->blksz;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the total number of bytes to load, taking care of
|
* Get the total number of bytes to load, taking care of
|
||||||
* block alignment
|
* block alignment
|
||||||
*/
|
*/
|
||||||
full_size = load_addr + len - base;
|
full_size = len + extra;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the start block number, number of blocks and the address
|
* Get the start block number, number of blocks and the address
|
||||||
* to load to, then load the blocks
|
* to load to, then load the blocks
|
||||||
*/
|
*/
|
||||||
blknum = (area_offset + base - addr) / desc->blksz;
|
|
||||||
num_blks = DIV_ROUND_UP(full_size, desc->blksz);
|
num_blks = DIV_ROUND_UP(full_size, desc->blksz);
|
||||||
base_buf = map_sysmem(base, full_size);
|
base_buf = map_sysmem(base, full_size);
|
||||||
ret = blk_read(blk, blknum, num_blks, base_buf);
|
ret = blk_read(blk, blknum, num_blks, base_buf);
|
||||||
log_debug("read %lx %lx, %lx blocks to %lx / %p: ret=%d\n",
|
log_debug("read foffset %lx blknum %lx full_size %lx num_blks %lx to %lx / %p: ret=%d\n",
|
||||||
blknum, full_size, num_blks, base, base_buf, ret);
|
offset - 0x8000, blknum, full_size, num_blks, base, base_buf,
|
||||||
|
ret);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return log_msg_ret("rd", ret);
|
return log_msg_ret("rd", ret);
|
||||||
if (ret != num_blks)
|
if (ret != num_blks)
|
||||||
return log_msg_ret("rd", -EIO);
|
return log_msg_ret("rd", -EIO);
|
||||||
|
if (extra && !IS_ENABLED(CONFIG_SANDBOX)) {
|
||||||
|
log_debug("move %p %p %lx\n", base_buf,
|
||||||
|
base_buf + extra, len);
|
||||||
|
memmove(base_buf, base_buf + extra, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (load_addrp)
|
if (load_addrp)
|
||||||
*load_addrp = load_addr;
|
*load_addrp = load_addr;
|
||||||
|
|
Loading…
Add table
Reference in a new issue