diff options
| author | H. Peter Anvin <hpa@zytor.com> | 2007-03-15 17:17:29 -0700 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2007-03-15 17:17:29 -0700 |
| commit | 5c55d7059b5078df7faad8b260cfc59abd1ab332 (patch) | |
| tree | 96649d0df42c99a05bdd8deea400fc9eacb06a5a /com32/lib/syslinux/load_linux.c | |
| parent | c5e9d7a496936b9ea553be6fef4dff74596bbf11 (diff) | |
| download | syslinux-5c55d7059b5078df7faad8b260cfc59abd1ab332.tar.gz | |
initramfs chain handling: add support for forcing the alignment.
cpio has annoying alignment constraints; make it possible to enforce
them without adding padding to the end of last member (which breaks things
which relies on gzip and need to know the final length.)
Diffstat (limited to 'com32/lib/syslinux/load_linux.c')
| -rw-r--r-- | com32/lib/syslinux/load_linux.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c index 620ad081..b8d5a732 100644 --- a/com32/lib/syslinux/load_linux.c +++ b/com32/lib/syslinux/load_linux.c @@ -93,8 +93,10 @@ static addr_t initramfs_size(struct initramfs *initramfs) if (!initramfs) return 0; - for (ip = initramfs->next; ip->len; ip = ip->next) + for (ip = initramfs->next; ip->len; ip = ip->next) { + size = (size+ip->align-1) & ~(ip->align-1); /* Alignment */ size += ip->len; + } return size; } @@ -106,18 +108,30 @@ static int map_initramfs(struct syslinux_movelist **fraglist, addr_t addr) { struct initramfs *ip; + addr_t next_addr, len, pad; for (ip = initramfs->next; ip->len; ip = ip->next) { + len = ip->len; + next_addr = addr+len; + + /* If this isn't the last entry, extend the zero-pad region + to enforce the alignment of the next chunk. */ + if (ip->next->len) { + pad = -next_addr & (ip->next->align-1); + len += pad; + next_addr += pad; + } + if (ip->data_len) { - if (syslinux_add_movelist(fraglist, addr, (addr_t)ip->data, ip->len)) + if (syslinux_add_movelist(fraglist, addr, (addr_t)ip->data, len)) return -1; } - if (ip->len > ip->data_len) { + if (len > ip->data_len) { if (syslinux_add_memmap(mmap, addr+ip->data_len, - ip->len-ip->data_len, SMT_ZERO)) + len-ip->data_len, SMT_ZERO)) return -1; } - addr += ip->len; + addr = next_addr; } return 0; @@ -253,13 +267,14 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, if (irf_size) { addr_t best_addr = 0; struct syslinux_memmap *ml; + const addr_t align_mask = INITRAMFS_MAX_ALIGN-1; if (irf_size) { for (ml = amap; ml->type != SMT_END; ml = ml->next) { - addr_t adj_start = (ml->start+0xfff) & ~0xfff; /* Page-aligned */ + addr_t adj_start = (ml->start+align_mask) & ~align_mask; if (ml->type == SMT_FREE && ml->next->start - adj_start >= irf_size) - best_addr = (ml->next->start - irf_size) & ~0xfff; + best_addr = (ml->next->start - irf_size) & ~align_mask; } if (!best_addr) |
