--- /dev/null
+/*
+ * elf.h
+ */
+
+#ifndef _ELF_H
+#define _ELF_H
+
+#include <sys/elf32.h>
+#include <sys/elf64.h>
+
+#endif /* _ELF_H */
--- /dev/null
+/*
+ * sys/elf32.h
+ */
+
+#ifndef _SYS_ELF32_H
+#define _SYS_ELF32_H
+
+#include <sys/elfcommon.h>
+
+/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */
+typedef uint16_t Elf32_Half;
+typedef int16_t Elf32_SHalf;
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+
+typedef uint32_t Elf32_Off;
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Section;
+
+/* Dynamic header */
+
+typedef struct elf32_dyn {
+ Elf32_Sword d_tag;
+ union {
+ Elf32_Sword d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+/* Relocations */
+
+#define ELF32_R_SYM(x) ((x) >> 8)
+#define ELF32_R_TYPE(x) ((x) & 0xff)
+
+typedef struct elf32_rel {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct elf32_rela {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+/* Symbol */
+
+typedef struct elf32_sym {
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+/* Main file header */
+
+typedef struct elf32_hdr {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+/* Program header */
+
+typedef struct elf32_phdr {
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+/* Section header */
+
+typedef struct elf32_shdr {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+/* Note header */
+typedef struct elf32_note {
+ Elf32_Word n_namesz; /* Name size */
+ Elf32_Word n_descsz; /* Content size */
+ Elf32_Word n_type; /* Content type */
+} Elf32_Nhdr;
+
+#endif /* _SYS_ELF32_H */
--- /dev/null
+/*
+ * sys/elf64.h
+ */
+
+#ifndef _SYS_ELF64_H
+#define _SYS_ELF64_H
+
+#include <sys/elfcommon.h>
+
+/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */
+typedef uint16_t Elf64_Half;
+typedef int16_t Elf64_SHalf;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+typedef uint64_t Elf64_Off;
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Section;
+
+/* Dynamic header */
+
+typedef struct elf64_dyn {
+ Elf64_Sxword d_tag;
+ union {
+ Elf64_Xword d_val;
+ Elf64_Addr d_ptr;
+ } d_un;
+} Elf64_Dyn;
+
+/* Relocations */
+
+#define ELF64_R_SYM(x) ((x) >> 32)
+#define ELF64_R_TYPE(x) ((x) & 0xffffffff)
+
+typedef struct elf64_rel {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+} Elf64_Rel;
+
+typedef struct elf64_rela {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+ Elf64_Sxword r_addend;
+} Elf64_Rela;
+
+/* Symbol */
+
+typedef struct elf64_sym {
+ Elf64_Word st_name;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf64_Half st_shndx;
+ Elf64_Addr st_value;
+ Elf64_Xword st_size;
+} Elf64_Sym;
+
+/* Main file header */
+
+typedef struct elf64_hdr {
+ unsigned char e_ident[EI_NIDENT];
+ Elf64_Half e_type;
+ Elf64_Half e_machine;
+ Elf64_Word e_version;
+ Elf64_Addr e_entry;
+ Elf64_Off e_phoff;
+ Elf64_Off e_shoff;
+ Elf64_Word e_flags;
+ Elf64_Half e_ehsize;
+ Elf64_Half e_phentsize;
+ Elf64_Half e_phnum;
+ Elf64_Half e_shentsize;
+ Elf64_Half e_shnum;
+ Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+
+/* Program header */
+
+typedef struct elf64_phdr {
+ Elf64_Word p_type;
+ Elf64_Word p_flags;
+ Elf64_Off p_offset;
+ Elf64_Addr p_vaddr;
+ Elf64_Addr p_paddr;
+ Elf64_Xword p_filesz;
+ Elf64_Xword p_memsz;
+ Elf64_Xword p_align;
+} Elf64_Phdr;
+
+/* Section header */
+
+typedef struct elf64_shdr {
+ Elf64_Word sh_name;
+ Elf64_Word sh_type;
+ Elf64_Xword sh_flags;
+ Elf64_Addr sh_addr;
+ Elf64_Off sh_offset;
+ Elf64_Xword sh_size;
+ Elf64_Word sh_link;
+ Elf64_Word sh_info;
+ Elf64_Xword sh_addralign;
+ Elf64_Xword sh_entsize;
+} Elf64_Shdr;
+
+/* Note header */
+typedef struct elf64_note {
+ Elf64_Word n_namesz; /* Name size */
+ Elf64_Word n_descsz; /* Content size */
+ Elf64_Word n_type; /* Content type */
+} Elf64_Nhdr;
+
+#endif /* _SYS_ELF64_H */
--- /dev/null
+/*
+ * sys/elfcommon.h
+ */
+
+#ifndef _SYS_ELFCOMMON_H
+#define _SYS_ELFCOMMON_H
+
+#include <stdint.h>
+
+/* Segment types */
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_LOOS 0x60000000
+#define PT_HIOS 0x6fffffff
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */
+
+/* ELF file types */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+
+/* ELF machine types */
+#define EM_NONE 0
+#define EM_M32 1
+#define EM_SPARC 2
+#define EM_386 3
+#define EM_68K 4
+#define EM_88K 5
+#define EM_486 6 /* Not used in Linux at least */
+#define EM_860 7
+#define EM_MIPS 8 /* R3k, bigendian(?) */
+#define EM_MIPS_RS4_BE 10 /* R4k BE */
+#define EM_PARISC 15
+#define EM_SPARC32PLUS 18
+#define EM_PPC 20
+#define EM_PPC64 21
+#define EM_S390 22
+#define EM_SH 42
+#define EM_SPARCV9 43 /* v9 = SPARC64 */
+#define EM_H8_300H 47
+#define EM_H8S 48
+#define EM_IA_64 50 /* Itanic */
+#define EM_X86_64 62
+#define EM_CRIS 76
+#define EM_V850 87
+#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */
+#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */
+#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */
+
+/* Dynamic type values */
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
+
+/* Auxilliary table entries */
+#define AT_NULL 0 /* end of vector */
+#define AT_IGNORE 1 /* entry should be ignored */
+#define AT_EXECFD 2 /* file descriptor of program */
+#define AT_PHDR 3 /* program headers for program */
+#define AT_PHENT 4 /* size of program header entry */
+#define AT_PHNUM 5 /* number of program headers */
+#define AT_PAGESZ 6 /* system page size */
+#define AT_BASE 7 /* base address of interpreter */
+#define AT_FLAGS 8 /* flags */
+#define AT_ENTRY 9 /* entry point of program */
+#define AT_NOTELF 10 /* program is not ELF */
+#define AT_UID 11 /* real uid */
+#define AT_EUID 12 /* effective uid */
+#define AT_GID 13 /* real gid */
+#define AT_EGID 14 /* effective gid */
+#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
+#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+#define AT_CLKTCK 17 /* frequency at which times() increments */
+/* 18..22 = ? */
+#define AT_SECURE 23 /* secure mode boolean */
+
+/* Program header permission flags */
+#define PF_X 0x1
+#define PF_W 0x2
+#define PF_R 0x4
+
+/* Section header types */
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_NUM 12
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xffffffff
+
+/* Section header flags */
+#define SHF_WRITE 0x1
+#define SHF_ALLOC 0x2
+#define SHF_EXECINSTR 0x4
+#define SHF_MASKPROC 0xf0000000
+
+/* Special section numbers */
+#define SHN_UNDEF 0
+#define SHN_LORESERVE 0xff00
+#define SHN_LOPROC 0xff00
+#define SHN_HIPROC 0xff1f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_HIRESERVE 0xffff
+
+/* Lenght of magic at the start of a file */
+#define EI_NIDENT 16
+
+/* Magic number constants... */
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_OSABI 7
+#define EI_PAD 8
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define ELFCLASSNONE 0 /* EI_CLASS */
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define ELFDATANONE 0 /* e_ident[EI_DATA] */
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_NONE 0 /* e_version, EI_VERSION */
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+#define ELFOSABI_NONE 0
+#define ELFOSABI_LINUX 3
+
+#endif /* _SYS_ELFCOMMON_H */
--- /dev/null
+#ifndef _SYSLINUX_MOVEBITS_H
+#define _SYSLINUX_MOVEBITS_H
+
+#include <inttypes.h>
+#include <setjmp.h>
+
+typedef uint32_t addr_t;
+
+struct syslinux_movelist {
+ addr_t dst;
+ addr_t src;
+ addr_t len;
+ struct syslinux_movelist *next;
+};
+
+struct syslinux_pm_regs {
+ uint32_t eax, ecx, edx, ebx;
+ uint32_t esp, ebp, esi, edi;
+ uint32_t eip;
+};
+
+/*
+ * moves is computed from "frags" and "freemem". "space" lists
+ * free memory areas at our disposal, and is (src, cnt) only.
+ */
+
+int syslinux_compute_movelist(struct syslinux_movelist **,
+ struct syslinux_movelist *,
+ struct syslinux_movelist *);
+
+struct syslinux_movelist *syslinux_memory_map(void);
+void syslinux_free_movelist(struct syslinux_movelist *);
+int syslinux_add_movelist(struct syslinux_movelist **,
+ addr_t dst, addr_t src, addr_t len);
+int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist);
+int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist,
+ uint16_t bootflags,
+ uint32_t edx, uint32_t esi, uint16_t ds,
+ uint16_t cs, uint16_t ip);
+int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist,
+ uint16_t bootflags,
+ struct syslinux_pm_regs *regs);
+
+#endif /* _SYSLINUX_MOVEBITS_H */
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+int syslinux_add_movelist(struct syslinux_movelist **list,
+ addr_t dst, addr_t src, addr_t len)
+{
+ struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist));
+ if (!ml)
+ return -1;
+
+ ml->dst = dst;
+ ml->src = src;
+ ml->len = len;
+ ml->next = *list;
+
+ *list = ml;
+ return 0;
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * freelist.c
+ *
+ * Frees a syslinux_movelist
+ */
+
+#include <syslinux/movelist.h>
+
+void syslinux_free_movelist(struct syslinux_movelist *list)
+{
+ struct syslinux_movelist *m;
+
+ while (list) {
+ m = list;
+ list = list->next;
+ free(m);
+ }
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memmap.c
+ *
+ * Create initial memory map for "shuffle and boot" operation
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <string.h>
+
+#include <syslinux/movebits.h>
+
+static struct movelist *
+new_movelist(addr_t src, addr_t len)
+{
+ struct movelist *ml = malloc(sizeof(struct movelist));
+
+ if ( !ml )
+ return NULL;
+
+ ml->dst = (addr_t)0;
+ ml->src = src;
+ ml->len = len;
+ ml->next = NULL;
+
+ return ml;
+}
+
+struct e820_entry {
+ uint64_t start;
+ uint64_t len;
+ uint32_t type;
+};
+
+struct movelist *syslinux_memory_map(void)
+{
+ static com32sys_t ireg, zireg;
+ com32sys_t oreg;
+ struct movelist *ml = NULL;
+ struct movelist **mlp = &ml;
+ struct movelist *me;
+ struct e820_entry *e820buf = __com32.cs_bounce;
+ uint64_t start, len, maxlen;
+ int memfound = 0;
+
+ /* Use INT 12h to get DOS memory above 0x7c00 */
+ __intcall(0x12, &zireg, &oreg);
+ if (oreg.eax.w[0] > 31 && oreg.eax.w[0] <= 640) {
+ addr_t dosmem = (oreg.eax.w[0] << 10) - 0x7c00;
+ me = new_movelist(0, 0x7c00, dosmem);
+ if (!me)
+ goto bail;
+ *mlp = me;
+ mlp = &me->next;
+ }
+
+ /* First try INT 15h AX=E820h */
+ ireg.eax.l = 0xe820;
+ ireg.edx.l = 0x534d4150;
+ ireg.ebx.l = 0;
+ ireg.ecx.l = 20;
+ ireg.es = SEG(e820buf);
+ ireg.edi.w[0] = OFFS(e820buf);
+
+ do {
+ __intcall(0x15, &ireg, &oreg);
+
+ if ((oreg.eflags.l & EFLAGS_CF) ||
+ (oreg.eax.l != 0x534d4150) ||
+ (oreg.ecx.l < 20))
+ break;
+
+ if (e820buf.type == 1) {
+ start = e820buf.start;
+ len = e820buf.len;
+
+ if (start < 0x100000000ULL) {
+ /* Don't rely on E820 being valid for low memory. Doing so
+ could mean stuff like overwriting the PXE stack even when
+ using "keeppxe", etc. */
+ if (start < 0x100000ULL) {
+ if (len > 0x100000ULL-start)
+ len -= 0x100000ULL-start;
+ else
+ len = 0;
+ start = 0x100000ULL;
+ }
+
+ maxlen = 0x100000000ULL-start;
+ if (len > maxlen)
+ len = maxlen;
+
+ if (len) {
+ me = new_movelist(0, (addr_t)start, (addr_t)len);
+ if (!me)
+ goto bail;
+ *mlp = me;
+ mlp = &me->next;
+ memfound = 1;
+ }
+ }
+ }
+
+ ireg.ebx.l = oreg.ebx.l;
+ } while (oreg.ebx.l);
+
+ if (memfound)
+ return ml;
+
+ /* Next try INT 15h AX=E801h */
+ ireg.eax.w[0] = 0xe801;
+ __intcall(0x15, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) {
+ me = new_movelist(0, (addr_t)1 << 20, oreg.ecx.w[0] << 10);
+ if (!me)
+ goto bail;
+ *mlp = me;
+ mlp = &me->next;
+
+ if (oreg.edx.w[0]) {
+ me = new_movelist(0, (addr_t)16 << 20, oreg.edx.w[0] << 16);
+ if (!me)
+ goto bail;
+ *mlp = me;
+ mlp = &me->next;
+ }
+
+ return ml;
+ }
+
+ /* Finally try INT 15h AH=88h */
+ ireg.eax.w[0] = 0x8800;
+ if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) {
+ me = new_movelist(0, (addr_t)1 << 20, oreg.eax.w[0] << 10);
+ if (!me)
+ goto bail;
+ *mlp = me;
+ mlp = &me->next;
+ }
+
+ return ml;
+
+ bail:
+ while (ml) {
+ me = ml;
+ ml = ml->next;
+ free(ml);
+ }
+ return NULL;
+}
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * movebits.c
+ *
+ * Utility function to take a list of memory areas to shuffle and
+ * convert it to a set of shuffle operations.
+ */
+
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <inttypes.h>
#include <setjmp.h>
-#include "movebits.h"
+#include <syslinux/movebits.h>
#ifdef TEST
# define dprintf printf
#define min(x,y) ((x) < (y) ? (x) : (y))
#define max(x,y) ((x) > (y) ? (x) : (y))
-/*
- * Public utility function
- *
- * Creates a movelist consisting of only one element, and
- * if parent == NULL insert into the movelist chain immediately after
- * the parent element.
- */
-struct movelist *
-make_movelist(struct movelist *pptr, uintptr_t dst, uintptr_t src, uintptr_t len)
-{
- struct movelist *ml = malloc(sizeof(struct movelist));
-
- if ( !ml )
- return NULL;
-
- ml->dst = dst;
- ml->src = src;
- ml->len = len;
- ml->next = pptr ? pptr->next : NULL;
-
- if ( pptr )
- pptr->next = ml;
-
- return ml;
-}
-
-/*
- * Public utility function
- *
- * Convert a movelist into a linear array of struct move_descriptors
- */
-size_t
-linearize_movelist(struct move_descriptor **d, struct movelist *m)
-{
- size_t n;
- struct movelist *mm;
- struct move_descriptor *l;
-
- /* Count the length of the list */
- n = 0;
- for ( mm = m ; mm ; mm = mm->next )
- n++;
-
- *d = l = malloc(n * sizeof(struct move_descriptor));
- if ( !l )
- return (size_t)-1;
-
- while ( m ) {
- l->dst = m->dst;
- l->src = m->src;
- l->len = m->len;
- l++;
- mm = m;
- m = m->next;
- free(mm);
- }
-
- return n;
-}
-
-
static jmp_buf new_movelist_bail;
-static struct movelist *
-new_movelist(uintptr_t dst, uintptr_t src, uintptr_t len)
+static struct syslinux_movelist *
+new_movelist(addr_t dst, addr_t src, addr_t len)
{
- struct movelist *ml = malloc(sizeof(struct movelist));
+ struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist));
if ( !ml )
longjmp(new_movelist_bail, 1);
return ml;
}
-static struct movelist **
-split_movelist(uintptr_t start, uintptr_t len, struct movelist **parentptr)
+static struct syslinux_movelist **
+split_movelist(addr_t start, addr_t len, struct syslinux_movelist **parentptr)
{
- struct movelist *m, *ml = *parentptr;
+ struct syslinux_movelist *m, *ml = *parentptr;
assert(start >= ml->src);
assert(start < ml->src+ml->len);
/* Split off the beginning */
if ( start > ml->src ) {
- uintptr_t l = start - ml->src;
+ addr_t l = start - ml->src;
m = new_movelist(ml->dst+l, start, ml->len-l);
m->next = ml->next;
}
if ( ml->len > len ) {
- uintptr_t l = ml->len - len;
+ addr_t l = ml->len - len;
m = new_movelist(ml->dst+len, ml->src+len, l);
m->next = ml->next;
return parentptr;
}
-#if 0
static void
-delete_movelist(struct movelist **parentptr)
+delete_movelist(struct syslinux_movelist **parentptr)
{
- struct movelist *o = *parentptr;
+ struct syslinux_movelist *o = *parentptr;
*parentptr = o->next;
free(o);
}
-#endif
/*
* Scan the freelist looking for a particular chunk of memory
*/
-static struct movelist **
-is_free_zone(uintptr_t start, uintptr_t len, struct movelist **space)
+static struct syslinux_movelist **
+is_free_zone(addr_t start, addr_t len, struct syslinux_movelist **space)
{
- struct movelist *s;
+ struct syslinux_movelist *s;
while ( (s = *space) ) {
if ( s->src <= start && s->src+s->len >= start+len )
* Scan the freelist looking for the smallest chunk of memory which
* can fit X bytes
*/
-static struct movelist **
-free_area(uintptr_t len, struct movelist **space)
+static struct syslinux_movelist **
+free_area(addr_t len, struct syslinux_movelist **space)
{
- struct movelist **best = NULL;
- struct movelist *s;
+ struct syslinux_movelist **best = NULL;
+ struct syslinux_movelist *s;
while ( (s = *space) ) {
if ( s->len >= len ) {
/*
- * Scan the freelist looking for the largest chunk of memory, returns parent ptr
+ * Scan the freelist looking for the largest chunk of memory,
+ * returns parent ptr
*/
-static struct movelist **
-free_area_max(struct movelist **space)
+static struct syslinux_movelist **
+free_area_max(struct syslinux_movelist **space)
{
- struct movelist **best = NULL;
- struct movelist *s;
+ struct syslinux_movelist **best = NULL;
+ struct syslinux_movelist *s;
while ( (s = *space) ) {
if ( !best || s->len > (*best)->len )
* Remove a chunk from the freelist
*/
static void
-allocate_from(uintptr_t start, uintptr_t len, struct movelist **parentptr)
+allocate_from(addr_t start, addr_t len, struct syslinux_movelist **parentptr)
{
- struct movelist *c = *parentptr;
+ struct syslinux_movelist *c = *parentptr;
assert(c->src <= start);
assert(c->src+c->len >= start+len);
* covered by a free zone or not covered at all.
*/
static void
-tidy_freelist(struct movelist **frags, struct movelist **space)
+tidy_freelist(struct syslinux_movelist **frags,
+ struct syslinux_movelist **space)
{
- struct movelist **sep;
- struct movelist *f;
+ struct syslinux_movelist **sep;
+ struct syslinux_movelist *f;
while ( (f = *frags) ) {
if ( (sep = is_free_zone(f->src, f->len, space)) )
*/
int
-compute_movelist(struct movelist **moves, struct movelist *frags,
- struct movelist *space)
+syslinux_compute_movelist(struct syslinux_movelist **moves,
+ struct syslinux_movelist *frags,
+ struct syslinux_movelist *space)
{
- struct movelist *mv;
- struct movelist *f, **fp, **ep;
- struct movelist *o, **op;
- uintptr_t needbase, needlen, copysrc, copydst, copylen;
- uintptr_t freebase, freelen;
-
+ struct syslinux_movelist *mv;
+ struct syslinux_movelist *f, **fp, **ep;
+ struct syslinux_movelist *o, **op;
*moves = NULL;
+ addr_t needbase, needlen, copysrc, copydst, copylen;
+ addr_t freebase, freelen;
if ( setjmp(new_movelist_bail) )
return -1; /* malloc() failed */
if ( copylen < needlen ) {
/* Didn't get all we wanted, so we have to split the chunk */
+ addr_t l;
+
fp = split_movelist(f->src, copylen+(needbase-f->dst), fp);
f = *fp;
}
{
FILE *f;
unsigned long d, s, l;
- struct movelist *frags;
- struct movelist **fep = &frags;
- struct movelist *space;
- struct movelist **sep = &space;
- struct movelist *mv, *moves;
+ struct syslinux_movelist *frags;
+ struct syslinux_movelist **fep = &frags;
+ struct syslinux_movelist *space;
+ struct syslinux_movelist **sep = &space;
+ struct syslinux_movelist *mv, *moves;
f = fopen(argv[1], "r");
while ( fscanf(f, "%lx %lx %lx", &d, &s, &l) == 3 ) {
}
fclose(f);
- if ( compute_movelist(&moves, frags, space) ) {
+ if ( syslinux_compute_movelist(&moves, frags, space) ) {
printf("Failed to compute a move sequence\n");
return 1;
} else {
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * shuffle.c
+ *
+ * Common code for "shuffle and boot" operation; generates a shuffle list
+ * and puts it in the bounce buffer. Returns the number of shuffle
+ * descriptors.
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <com32.h>
+#include <syslinux/movebits.h>
+
+struct shuffle_descriptor {
+ uint32_t dst, src, len;
+};
+
+int syslinux_prepare_shuffle(struct syslinux_movelist *fraglist)
+{
+ struct syslinux_movelist *moves = NULL, *freelist = NULL, *mp;
+ int n;
+ struct shuffle_descriptor *dp;
+ int np, rv = -1;
+
+ freelist = syslinux_memory_map();
+ if (!freelist)
+ goto bail;
+
+ if (syslinux_compute_movelist(&moves, fraglist, freelist))
+ goto bail;
+
+ dp = __com32.cs_bounce;
+ np = 0;
+
+ for (mp = moves; mp; mp = mp->next) {
+ if (np >= 65536/12)
+ goto bail; /* Way too many descriptors... */
+
+ dp->dst = mp->dst;
+ dp->src = mp->src;
+ dp->len = mp->len;
+ np++;
+ }
+
+ rv = np;
+
+ bail:
+ if (freelist)
+ syslinux_free_movelist(freelist);
+ if (moves)
+ syslinux_free_movelist(moves);
+
+ return rv;
+}
+
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * shuffle_pm.c
+ *
+ * Shuffle and boot to protected mode code
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <com32.h>
+#include <string.h>
+#include <syslinux/movebits.h>
+
+int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist,
+ uint16_t bootflags,
+ struct syslinux_pm_regs *regs)
+{
+ int nd;
+ com32sys_t ireg;
+ char *regbuf;
+
+ nd = syslinux_prepare_shuffle(fraglist);
+ if (nd < 0)
+ return -1;
+
+ regbuf = (char *)__com32.cs_bounce + (12*nd);
+ memcpy(regbuf, regs, sizeof(*regs));
+
+ memset(&ireg, 0, sizeof ireg);
+
+ ireg.eax.w[0] = 0x001a;
+ ireg.edx.w[0] = bootflags;
+ ireg.es = SEG(__com32.cs_bounce);
+ ireg.edi.l = OFFS(__com32.cs_bounce);
+ ireg.ecx.l = nd;
+ ireg.ds = SEG(regbuf);
+ ireg.esi.l = OFFS(regbuf);
+ __intcall(0x22, &ireg, NULL);
+
+ return -1; /* Too many descriptors? */
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * shuffle_rm.c
+ *
+ * Shuffle and boot to real mode code
+ */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <com32.h>
+#include <string.h>
+#include <syslinux/movebits.h>
+
+int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist,
+ uint16_t bootflags,
+ uint32_t edx, uint32_t esi, uint16_t ds,
+ uint16_t cs, uint16_t ip)
+{
+ int nd;
+ com32sys_t ireg;
+
+ nd = syslinux_prepare_shuffle(fraglist);
+ if (nd < 0)
+ return -1;
+
+ memset(&ireg, 0, sizeof ireg);
+
+ ireg.eax.w[0] = 0x0012;
+ ireg.edx.w[0] = bootflags;
+ ireg.es = SEG(__com32.cs_bounce);
+ ireg.edi.l = OFFS(__com32.cs_bounce);
+ ireg.ecx.l = nd;
+ ireg.ebx.l = edx;
+ ireg.esi.l = esi;
+ ireg.ds = ds;
+ ireg.ebp.l = (cs << 16) + ip;
+ __intcall(0x22, &ireg, NULL);
+
+ return -1; /* Too many descriptors? */
+}
+++ /dev/null
-#ifndef LIBUTIL_MOVEBITS_H
-#define LIBUTIL_MOVEBITS_H
-
-#include <inttypes.h>
-#include <setjmp.h>
-
-struct movelist {
- uintptr_t dst;
- uintptr_t src;
- uintptr_t len;
- struct movelist *next;
-};
-
-struct move_descriptor {
- uint32_t dst;
- uint32_t src;
- uint32_t len;
-};
-
-/*
- * Creates a movelist consisting of only one element, and
- * if parent == NULL insert into the movelist chain immediately after
- * the parent element.
- */
-struct movelist *
-make_movelist(struct movelist *parent, uintptr_t dst,
- uintptr_t src, uintptr_t len);
-
-/*
- * Convert a movelist into a linear array of struct move_descriptors,
- * returning the number of descriptors and freeing the movelist.
- *
- * Returns (size_t)-1 on failure; if so the movelist is still valid.
- */
-size_t
-linearize_movelist(struct move_descriptor **d, struct movelist *m);
-
-/*
- * moves is computed from "frags" and "freemem". "space" lists
- * free memory areas at our disposal, and is (src, cnt) only.
- */
-
-int
-compute_movelist(struct movelist **moves, struct movelist *frags,
- struct movelist *space);
-
-#endif /* LIBUTIL_MOVEBITS_H */