Wrapper infrastructure for "shuffle and boot"
authorH. Peter Anvin <hpa@zytor.com>
Mon, 12 Mar 2007 20:17:35 +0000 (13:17 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 12 Mar 2007 20:17:35 +0000 (13:17 -0700)
Initial checkin of a wrapper infrastructure for the "shuffle and boot"
interface, both real and protected mode.  This code automatically will
figure out the necessary sequence of moves, taking into account swaps
and overlaps as necessary.

13 files changed:
com32/include/elf.h [new file with mode: 0644]
com32/include/sys/elf32.h [new file with mode: 0644]
com32/include/sys/elf64.h [new file with mode: 0644]
com32/include/sys/elfcommon.h [new file with mode: 0644]
com32/include/syslinux/movebits.h [new file with mode: 0644]
com32/lib/syslinux/addlist.c [new file with mode: 0644]
com32/lib/syslinux/freelist.c [new file with mode: 0644]
com32/lib/syslinux/memmap.c [new file with mode: 0644]
com32/lib/syslinux/movebits.c [moved from com32/libutil/movebits.c with 67% similarity]
com32/lib/syslinux/shuffle.c [new file with mode: 0644]
com32/lib/syslinux/shuffle_pm.c [new file with mode: 0644]
com32/lib/syslinux/shuffle_rm.c [new file with mode: 0644]
com32/libutil/include/movebits.h [deleted file]

diff --git a/com32/include/elf.h b/com32/include/elf.h
new file mode 100644 (file)
index 0000000..c543a81
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * elf.h
+ */
+
+#ifndef _ELF_H
+#define _ELF_H
+
+#include <sys/elf32.h>
+#include <sys/elf64.h>
+
+#endif                         /* _ELF_H */
diff --git a/com32/include/sys/elf32.h b/com32/include/sys/elf32.h
new file mode 100644 (file)
index 0000000..e4df8ce
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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 */
diff --git a/com32/include/sys/elf64.h b/com32/include/sys/elf64.h
new file mode 100644 (file)
index 0000000..0b486ac
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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 */
diff --git a/com32/include/sys/elfcommon.h b/com32/include/sys/elfcommon.h
new file mode 100644 (file)
index 0000000..0d81db5
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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 */
diff --git a/com32/include/syslinux/movebits.h b/com32/include/syslinux/movebits.h
new file mode 100644 (file)
index 0000000..95adf6e
--- /dev/null
@@ -0,0 +1,44 @@
+#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 */
diff --git a/com32/lib/syslinux/addlist.c b/com32/lib/syslinux/addlist.c
new file mode 100644 (file)
index 0000000..d544de9
--- /dev/null
@@ -0,0 +1,42 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   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;
+}
diff --git a/com32/lib/syslinux/freelist.c b/com32/lib/syslinux/freelist.c
new file mode 100644 (file)
index 0000000..4b7d1f9
--- /dev/null
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   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);
+  }
+}
diff --git a/com32/lib/syslinux/memmap.c b/com32/lib/syslinux/memmap.c
new file mode 100644 (file)
index 0000000..05b2edd
--- /dev/null
@@ -0,0 +1,182 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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;
+}
similarity index 67%
rename from com32/libutil/movebits.c
rename to com32/lib/syslinux/movebits.c
index 00bdad7..4689508 100644 (file)
@@ -1,3 +1,37 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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>
@@ -5,7 +39,7 @@
 #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);
@@ -95,17 +68,17 @@ new_movelist(uintptr_t dst, uintptr_t src, uintptr_t len)
   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;
@@ -117,7 +90,7 @@ split_movelist(uintptr_t start, uintptr_t len, struct movelist **parentptr)
   }
 
   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;
@@ -128,23 +101,21 @@ split_movelist(uintptr_t start, uintptr_t len, struct movelist **parentptr)
   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 )
@@ -159,11 +130,11 @@ is_free_zone(uintptr_t start, uintptr_t len, struct movelist **space)
  * 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 ) {
@@ -178,13 +149,14 @@ free_area(uintptr_t len, struct movelist **space)
 
 
 /*
- * 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 )
@@ -199,9 +171,9 @@ free_area_max(struct movelist **space)
  * 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);
@@ -222,10 +194,11 @@ allocate_from(uintptr_t start, uintptr_t len, struct movelist **parentptr)
  * 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)) )
@@ -240,16 +213,16 @@ tidy_freelist(struct movelist **frags, struct movelist **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 */
@@ -360,6 +333,8 @@ compute_movelist(struct movelist **moves, struct movelist *frags,
 
     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;
     }
@@ -398,11 +373,11 @@ int main(int argc, char *argv[])
 {
   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 ) {
@@ -418,7 +393,7 @@ int main(int argc, char *argv[])
   }
   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 {
diff --git a/com32/lib/syslinux/shuffle.c b/com32/lib/syslinux/shuffle.c
new file mode 100644 (file)
index 0000000..ad6e7d0
--- /dev/null
@@ -0,0 +1,82 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   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;
+}
+
diff --git a/com32/lib/syslinux/shuffle_pm.c b/com32/lib/syslinux/shuffle_pm.c
new file mode 100644 (file)
index 0000000..45235e0
--- /dev/null
@@ -0,0 +1,67 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   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? */
+}
diff --git a/com32/lib/syslinux/shuffle_rm.c b/com32/lib/syslinux/shuffle_rm.c
new file mode 100644 (file)
index 0000000..a72d87e
--- /dev/null
@@ -0,0 +1,66 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   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? */
+}
diff --git a/com32/libutil/include/movebits.h b/com32/libutil/include/movebits.h
deleted file mode 100644 (file)
index de6ee1f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#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 */