int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist, struct syslinux_memmap *memmap, uint16_t bootflags, struct syslinux_pm_regs *regs) { int nd; com32sys_t ireg; char *regbuf; uint8_t handoff_code[9*5], *p; const uint32_t *rp; int i, rv; struct syslinux_memmap *tmap; addr_t regstub, stublen, safe; tmap = syslinux_target_memmap(fraglist, memmap); if (!tmap) return -1; regstub = 0x800; /* Locate anywhere above this point */ stublen = sizeof handoff_code; rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 1); syslinux_free_memmap(tmap); if (rv) return -1; /* Build register-setting stub */ p = handoff_code; rp = (const uint32_t *)regs; for (i = 0; i < 8; i++) { *p = 0xb8 + i; /* MOV gpr,imm32 */ *(uint32_t *)(p+1) = *rp++; p += 5; } *p = 0xe9; /* JMP */ *(uint32_t *)(p+1) = regs->eip - regstub - sizeof handoff_code; /* Add register-setting stub to shuffle list */ if (syslinux_add_movelist(&fraglist, regstub, (addr_t)handoff_code, sizeof handoff_code)) return -1; return syslinux_do_shuffle(fraglist, memmap, regstub, 1, bootflags); }
/* * Note: although there is no such thing in the spec, at least Xen makes * assumptions as to where in the memory space Grub would have loaded * certain things. To support that, if "high" is set, then allocate this * at an address strictly above any previous allocations. * * As a precaution, this also pads the data with zero up to the next * alignment datum. */ addr_t map_data(const void *data, size_t len, size_t align, int flags) { addr_t start = (flags & MAP_HIGH) ? mboot_high_water_mark : 0x2000; addr_t pad = (flags & MAP_NOPAD) ? 0 : -len & (align - 1); addr_t xlen = len + pad; if (syslinux_memmap_find(amap, SMT_FREE, &start, &xlen, align) || syslinux_add_memmap(&amap, start, len + pad, SMT_ALLOC) || syslinux_add_movelist(&ml, start, (addr_t) data, len) || (pad && syslinux_add_memmap(&mmap, start + len, pad, SMT_ZERO))) { printf("Cannot map %zu bytes\n", len + pad); return 0; } dprintf("Mapping 0x%08x bytes (%#x pad) at 0x%08x\n", len, pad, start); if (start + len + pad > mboot_high_water_mark) mboot_high_water_mark = start + len + pad; return start; }