diff options
Diffstat (limited to 'com32/lib')
-rw-r--r-- | com32/lib/MCONFIG | 80 | ||||
-rw-r--r-- | com32/lib/Makefile | 15 | ||||
-rw-r--r-- | com32/lib/bufprintf.c | 41 | ||||
-rw-r--r-- | com32/lib/chrreplace.c | 11 | ||||
-rw-r--r-- | com32/lib/com32.ld | 33 | ||||
-rw-r--r-- | com32/lib/dhcppack.c | 166 | ||||
-rw-r--r-- | com32/lib/dhcpunpack.c | 116 | ||||
-rw-r--r-- | com32/lib/dprintf.c | 2 | ||||
-rw-r--r-- | com32/lib/inet.c | 39 | ||||
-rw-r--r-- | com32/lib/pci/scan.c | 24 | ||||
-rw-r--r-- | com32/lib/strreplace.c | 58 | ||||
-rw-r--r-- | com32/lib/syslinux/disk.c | 534 | ||||
-rw-r--r-- | com32/lib/syslinux/dump_mmap.c | 12 | ||||
-rw-r--r-- | com32/lib/syslinux/dump_movelist.c | 9 | ||||
-rw-r--r-- | com32/lib/syslinux/load_linux.c | 72 | ||||
-rw-r--r-- | com32/lib/syslinux/movebits.c | 42 | ||||
-rw-r--r-- | com32/lib/syslinux/setup_data.c | 47 | ||||
-rw-r--r-- | com32/lib/syslinux/shuffle.c | 18 | ||||
-rw-r--r-- | com32/lib/syslinux/zonelist.c | 24 | ||||
-rw-r--r-- | com32/lib/vdprintf.c | 4 |
20 files changed, 1126 insertions, 221 deletions
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG deleted file mode 100644 index 44278bd1..00000000 --- a/com32/lib/MCONFIG +++ /dev/null @@ -1,80 +0,0 @@ -# -*- makefile -*- - -include $(topdir)/MCONFIG - -GCCOPT := $(call gcc_ok,-std=gnu99,) -GCCOPT += $(call gcc_ok,-m32,) -GCCOPT += $(call gcc_ok,-fno-stack-protector,) -GCCOPT += $(call gcc_ok,-fwrapv,) -GCCOPT += $(call gcc_ok,-freg-struct-return,) -GCCOPT += $(call gcc_ok,-fPIE,-fPIC) -GCCOPT += $(call gcc_ok,-fno-exceptions,) -GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) -GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) -GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) -GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) -GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) -GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0) -GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,) - -INCLUDE = -I. -STRIP = strip --strip-all -R .comment -R .note - -# zlib and libpng configuration flags -LIBFLAGS = -DDYNAMIC_CRC_TABLE -DPNG_NO_CONSOLE_IO \ - -DPNG_NO_WRITE_SUPPORTED \ - -DPNG_NO_MNG_FEATURES \ - -DPNG_NO_READ_tIME -DPNG_NO_WRITE_tIME - -# We need some features in libpng which apparently aren't available in the -# fixed-point versions. It's OK, because we have to have a non-graphical -# fallback anyway, just use that on old machines... -# LIBFLAGS += -DPNG_NO_FLOATING_POINT_SUPPORTED - -REQFLAGS = $(GCCOPT) -g -mregparm=3 -DREGPARM=3 -D__COM32__ \ - -nostdinc -iwithprefix include -I. -I./sys -I../include -OPTFLAGS = -Os -march=i386 -falign-functions=0 -falign-jumps=0 \ - -falign-labels=0 -ffast-math -fomit-frame-pointer -WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline - -CFLAGS = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS) -LDFLAGS = -m elf32_i386 - -.SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss - -% : %.c # Cancel default rule - -% : %.S - -.c.o: - $(CC) $(MAKEDEPS) $(CFLAGS) -c -o $@ $< - -.c.i: - $(CC) $(MAKEDEPS) $(CFLAGS) -E -o $@ $< - -.c.s: - $(CC) $(MAKEDEPS) $(CFLAGS) -S -o $@ $< - -.S.o: - $(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< - -.S.s: - $(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $< - -.S.lo: - $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $< - -.S.ls: - $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $< - -.s.o: - $(CC) $(MAKEDEPS) $(CFLAGS) -x assembler -c -o $@ $< - -.ls.lo: - $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -x assembler -c -o $@ $< - -.c.lo: - $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -c -o $@ $< - -.c.ls: - $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -S -o $@ $< diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 48a166dd..5ab1fac4 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -4,8 +4,9 @@ # Include configuration rules NOGPL := 1 -topdir = ../.. -include MCONFIG +topdir = ../../ +MAKEDIR = $(topdir)/mk +include $(MAKEDIR)/lib.mk LIBOBJS = \ abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \ @@ -28,6 +29,10 @@ LIBOBJS = \ asprintf.o vasprintf.o strlcpy.o strlcat.o \ vsscanf.o zalloc.o \ skipspace.o \ + chrreplace.o \ + bufprintf.o \ + inet.o dhcppack.o dhcpunpack.o \ + strreplace.o \ \ lmalloc.o lstrdup.o \ \ @@ -122,7 +127,11 @@ LIBOBJS = \ syslinux/setadv.o \ \ syslinux/video/fontquery.o syslinux/video/forcetext.o \ - syslinux/video/reportmode.o + syslinux/video/reportmode.o \ + \ + syslinux/disk.o \ + \ + syslinux/setup_data.o # These are the objects which are also imported into the core LIBCOREOBJS = \ diff --git a/com32/lib/bufprintf.c b/com32/lib/bufprintf.c new file mode 100644 index 00000000..939bcec3 --- /dev/null +++ b/com32/lib/bufprintf.c @@ -0,0 +1,41 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <bufprintf.h> + +int vbufprintf(struct print_buf *buf, const char *format, va_list ap) +{ + va_list ap2; + int rv; + + va_copy(ap2, ap); + rv = vsnprintf(NULL, 0, format, ap); + + /* >= to make sure we have space for terminating null */ + if (rv + buf->len >= buf->size) { + size_t newsize = rv + buf->len + BUFPAD; + char *newbuf; + + newbuf = realloc(buf->buf, newsize); + if (!newbuf) + return -1; + + buf->buf = newbuf; + buf->size = newsize; + } + + rv = vsnprintf(buf->buf + buf->len, buf->size - buf->len, format, ap2); + buf->len += rv; + return rv; +} + +int bufprintf(struct print_buf *buf, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vbufprintf(buf, format, ap); + va_end(ap); + return rv; +} diff --git a/com32/lib/chrreplace.c b/com32/lib/chrreplace.c new file mode 100644 index 00000000..65786f94 --- /dev/null +++ b/com32/lib/chrreplace.c @@ -0,0 +1,11 @@ +#include <ctype.h> + +/* Replace char 'old' by char 'new' in source */ +void chrreplace(char *source, char old, char new) +{ + while (*source) { + source++; + if (source[0] == old) source[0]=new; + } +} + diff --git a/com32/lib/com32.ld b/com32/lib/com32.ld index 37ee46cf..008e4ceb 100644 --- a/com32/lib/com32.ld +++ b/com32/lib/com32.ld @@ -36,36 +36,23 @@ SECTIONS .rodata1 : { *(.rodata1) } __rodata_end = .; - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ + /* + * The difference betwee .ctors/.dtors and .init_array/.fini_array + * is the ordering, but we don't use prioritization for libcom32, so + * just lump them all together and hope that's okay. + */ . = ALIGN(4); - .preinit_array : { - PROVIDE (__preinit_array_start = .); - *(.preinit_array) - PROVIDE (__preinit_array_end = .); - } - .init_array : { - PROVIDE (__init_array_start = .); - *(.init_array) - PROVIDE (__init_array_end = .); - } - .fini_array : { - PROVIDE (__fini_array_start = .); - *(.fini_array) - PROVIDE (__fini_array_end = .); - } .ctors : { PROVIDE (__ctors_start = .); - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) + KEEP (*(SORT(.preinit_array*))) + KEEP (*(SORT(.init_array*))) + KEEP (*(SORT(.ctors*))) PROVIDE (__ctors_end = .); } .dtors : { PROVIDE (__dtors_start = .); - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) + KEEP (*(SORT(.fini_array*))) + KEEP (*(SORT(.dtors*))) PROVIDE (__dtors_end = .); } diff --git a/com32/lib/dhcppack.c b/com32/lib/dhcppack.c new file mode 100644 index 00000000..a08583c4 --- /dev/null +++ b/com32/lib/dhcppack.c @@ -0,0 +1,166 @@ +#include <stdlib.h> +#include <errno.h> +#include <string.h> +// #include <arpa/inet.h> +#include <netinet/in.h> + +// #include "dhcp.h" +#include <dhcp.h> + +/* + * Pack DHCP options into an option field, without overload support. + * On return, len contains the number of active bytes, and the full + * field is zero-padded. + * + * Options which are successfully placed have their length zeroed out. + */ +static int dhcp_pack_field_zero(void *field, size_t *len, + struct dhcp_option opt[256]) +{ + int i; + size_t xlen, plen; + const uint8_t *p; + uint8_t *q = field; + size_t spc = *len; + int err = 0; + + if (!*len) + return ENOSPC; + + for (i = 1; i < 255; i++) { + if (opt[i].len < 0) + continue; + + /* We need to handle the 0 case as well as > 255 */ + if (opt[i].len <= 255) + xlen = opt[i].len + 2; + else + xlen = opt[i].len + 2*((opt[i].len+254)/255); + + p = opt[i].data; + + if (xlen >= spc) { + /* This option doesn't fit... */ + err++; + continue; + } + + xlen = opt[i].len; + do { + *q++ = i; + *q++ = plen = xlen > 255 ? 255 : xlen; + if (plen) + memcpy(q, p, plen); + q += plen; + p += plen; + spc -= plen+2; + xlen -= plen; + } while (xlen); + + opt[i].len = -1; + } + + *q++ = 255; /* End marker */ + memset(q, 0, spc); /* Zero-pad the rest of the field */ + + *len = xlen = q - (uint8_t *)field; + return err; +} + +/* + * Pack DHCP options into an option field, without overload support. + * On return, len contains the number of active bytes, and the full + * field is zero-padded. + * + * Use this to encode encapsulated option fields. + */ +int dhcp_pack_field(void *field, size_t *len, + struct dhcp_option opt[256]) +{ + struct dhcp_option ox[256]; + + memcpy(ox, opt, sizeof ox); + return dhcp_pack_field_zero(field, len, ox); +} + +/* + * Pack DHCP options into a packet. + * Apply overloading if (and only if) the "file" or "sname" option + * doesn't fit in the respective dedicated fields. + */ +int dhcp_pack_packet(void *packet, size_t *len, + const struct dhcp_option opt[256]) +{ + struct dhcp_packet *pkt = packet; + size_t spc = *len; + uint8_t overload; + struct dhcp_option ox[256]; + uint8_t *q; + int err; + + if (spc < sizeof(struct dhcp_packet)) + return ENOSPC; /* Buffer impossibly small */ + + pkt->magic = htonl(DHCP_VENDOR_MAGIC); + + memcpy(ox, opt, sizeof ox); + + /* Figure out if we should do overloading or not */ + overload = 0; + + if (opt[67].len > 128) + overload |= 1; + else + ox[67].len = -1; + + if (opt[66].len > 64) + overload |= 2; + else + ox[66].len = -1; + + /* Kill any passed-in overload option */ + ox[52].len = -1; + + q = pkt->options; + spc -= 240; + + /* Force option 53 (DHCP packet type) first */ + if (ox[53].len == 1) { + *q++ = 53; + *q++ = 1; + *q++ = *(uint8_t *)ox[53].data; + spc -= 3; + ox[53].len = -1; + } + + /* Follow with the overload option, if applicable */ + if (overload) { + *q++ = 52; + *q++ = 1; + *q++ = overload; + spc -= 3; + } + + err = dhcp_pack_field_zero(q, &spc, ox); + *len = spc + (q-(uint8_t *)packet); + + if (overload & 1) { + spc = 128; + err = dhcp_pack_field_zero(pkt->file, &spc, ox); + } else { + memset(pkt->file, 0, 128); + if (opt[67].len > 0) + memcpy(pkt->file, opt[67].data, opt[67].len); + } + + if (overload & 2) { + spc = 64; + err = dhcp_pack_field_zero(pkt->sname, &spc, ox); + } else { + memset(pkt->sname, 0, 64); + if (opt[66].len > 0) + memcpy(pkt->sname, opt[66].data, opt[66].len); + } + + return err; +} diff --git a/com32/lib/dhcpunpack.c b/com32/lib/dhcpunpack.c new file mode 100644 index 00000000..248173a8 --- /dev/null +++ b/com32/lib/dhcpunpack.c @@ -0,0 +1,116 @@ +#define _GNU_SOURCE /* For strnlen() */ +#include <stdlib.h> +#include <errno.h> +#include <string.h> +// #include <arpa/inet.h> +#include <netinet/in.h> + +// #include "dhcp.h" +#include <dhcp.h> + +/* + * Unpack DHCP options from a field. Assumes opt is pre-initalized + * (to all zero in the common case.) + */ +int dhcp_unpack_field(const void *field, size_t len, + struct dhcp_option opt[256]) +{ + const uint8_t *p = field; + int err = 0; + + while (len > 1) { + uint8_t op; + size_t xlen; + + op = *p++; len--; + if (op == 0) + continue; + else if (op == 255) + break; + + xlen = *p++; len--; + if (xlen > len) + break; + if (opt[op].len < 0) + opt[op].len = 0; + if (xlen) { + opt[op].data = realloc(opt[op].data, + opt[op].len + xlen + 1); + if (!opt[op].data) { + err = ENOMEM; + continue; + } + memcpy((char *)opt[op].data + opt[op].len, p, xlen); + opt[op].len += xlen; + /* Null-terminate as a courtesy to users */ + *((char *)opt[op].data + opt[op].len) = 0; + p += xlen; + len -= xlen; + } + } + + return err; +} + +/* + * Unpack a DHCP packet, with overload support. Do not use this + * to unpack an encapsulated option set. + */ +int dhcp_unpack_packet(const void *packet, size_t len, + struct dhcp_option opt[256]) +{ + const struct dhcp_packet *pkt = packet; + int err; + uint8_t overload; + int i; + + if (len < 240 || pkt->magic != htonl(DHCP_VENDOR_MAGIC)) + return EINVAL; /* Bogus packet */ + + for (i = 0; i < 256; i++) { + opt[i].len = -1; /* Option not present */ + opt[i].data = NULL; + } + + err = dhcp_unpack_field(pkt->options, len-240, opt); + + overload = 0; + if (opt[52].len == 1) { + overload = *(uint8_t *)opt[52].data; + free(opt[52].data); + opt[52].len = -1; + opt[52].data = NULL; + } + + if (overload & 1) { + err |= dhcp_unpack_field(pkt->file, 128, opt); + } else { + opt[67].len = strnlen((const char *)pkt->file, 128); + if (opt[67].len) { + opt[67].data = malloc(opt[67].len + 1); + if (opt[67].data) { + memcpy(opt[67].data, pkt->file, opt[67].len); + *((char *)opt[67].data + opt[67].len) = 0; + } else { + err |= ENOMEM; + } + } + } + + if (overload & 2) { + err |= dhcp_unpack_field(pkt->sname, 64, opt); + } else { + opt[66].len = strnlen((const char *)pkt->sname, 64); + if (opt[66].len) { + opt[66].data = malloc(opt[66].len + 1); + if (opt[66].data) { + memcpy(opt[66].data, pkt->file, opt[66].len); + *((char *)opt[66].data + opt[66].len) = 0; + } else { + err |= ENOMEM; + } + } + } + + return err; +} diff --git a/com32/lib/dprintf.c b/com32/lib/dprintf.c index 900c0a47..aad11746 100644 --- a/com32/lib/dprintf.c +++ b/com32/lib/dprintf.c @@ -9,6 +9,7 @@ #define DEBUG 1 #include <dprintf.h> +#ifndef dprintf void dprintf(const char *format, ...) { va_list ap; @@ -17,3 +18,4 @@ void dprintf(const char *format, ...) vdprintf(format, ap); va_end(ap); } +#endif diff --git a/com32/lib/inet.c b/com32/lib/inet.c new file mode 100644 index 00000000..133645ed --- /dev/null +++ b/com32/lib/inet.c @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2011 Erwan Velu - 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. + * + * ----------------------------------------------------------------------- + */ + +#include <stdio.h> +#include <netinet/in.h> + +char *inet_ntoa(struct in_addr addr) +{ + static char buf[16]; + const uint8_t *bytes = (const uint8_t *)&addr.s_addr; + + sprintf(buf, "%u.%u.%u.%u", bytes[0], bytes[1], bytes[2], bytes[3]); + return buf; +} diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index c8334b11..fe00fc25 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -41,12 +41,7 @@ #include <stdbool.h> #include <ctype.h> #include <syslinux/zio.h> - -#ifdef DEBUG -# define dprintf printf -#else -# define dprintf(...) ((void)0) -#endif +#include <dprintf.h> #define MAX_LINE 512 @@ -66,15 +61,6 @@ static int hex_to_int(char *hexa) return strtoul(hexa, NULL, 16); } -/* Replace char 'old' by char 'new' in source */ -void chr_replace(char *source, char old, char new) -{ - while (*source) { - source++; - if (source[0] == old) source[0]=new; - } -} - /* Try to match any pci device to the appropriate kernel module */ /* it uses the modules.pcimap from the boot device */ int get_module_name_from_pcimap(struct pci_domain *domain, @@ -135,7 +121,7 @@ int get_module_name_from_pcimap(struct pci_domain *domain, * in the module name whereas modules.alias is only using '_'. * To avoid kernel modules duplication, let's rename all '-' in '_' * to match what modules.alias provides */ - case 0:chr_replace(result,'-','_');strcpy(module_name,result); break; + case 0:chrreplace(result,'-','_');strcpy(module_name,result); break; case 1:strcpy(vendor_id,result); break; case 2:strcpy(product_id,result); break; case 3:strcpy(sub_vendor_id,result); break; @@ -593,14 +579,14 @@ void free_pci_domain(struct pci_domain *domain) free(func->dev_info); free(func); } - free(slot); } + free(slot); } - free(bus); } + free(bus); } - free(domain); } + free(domain); } } diff --git a/com32/lib/strreplace.c b/com32/lib/strreplace.c new file mode 100644 index 00000000..d59efe0e --- /dev/null +++ b/com32/lib/strreplace.c @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2011 Erwan Velu - 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. + * + * ----------------------------------------------------------------------- + */ + +#include <string.h> +#include <stdlib.h> + +char *strreplace(const char *string, const char *string_to_replace, + const char *string_to_insert) +{ + char *token = NULL; + char *out = NULL; + + size_t slen, srlen, silen; + + token = strstr(string, string_to_replace); + if (!token) + return strdup(string); + + slen = strlen(string); + srlen = strlen(string_to_replace); + silen = strlen(string_to_insert); + + out = malloc(slen - srlen + silen + 1); + if (!out) + return NULL; + + memcpy(out, string, token - string); + memcpy(out + (token - string), string_to_insert, silen); + memcpy(out + (token - string) + silen, token + srlen, + slen - srlen - (token - string) + 1); + + return out; +} diff --git a/com32/lib/syslinux/disk.c b/com32/lib/syslinux/disk.c new file mode 100644 index 00000000..d6409af6 --- /dev/null +++ b/com32/lib/syslinux/disk.c @@ -0,0 +1,534 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Copyright (C) 2010 Shao Miller + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/** + * @file disk.c + * + * Deal with disks and partitions + */ + +#include <dprintf.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslinux/disk.h> + +/** + * Call int 13h, but with retry on failure. Especially floppies need this. + * + * @v inreg CPU register settings upon INT call + * @v outreg CPU register settings returned by INT call + * @ret (int) 0 upon success, -1 upon failure + */ +int disk_int13_retry(const com32sys_t * inreg, com32sys_t * outreg) +{ + int retry = 6; /* Number of retries */ + com32sys_t tmpregs; + + if (!outreg) + outreg = &tmpregs; + + while (retry--) { + __intcall(0x13, inreg, outreg); + if (!(outreg->eflags.l & EFLAGS_CF)) + return 0; /* CF=0, OK */ + } + + return -1; /* Error */ +} + +/** + * Query disk parameters and EBIOS availability for a particular disk. + * + * @v disk The INT 0x13 disk drive number to process + * @v diskinfo The structure to save the queried params to + * @ret (int) 0 upon success, -1 upon failure + */ +int disk_get_params(int disk, struct disk_info *const diskinfo) +{ + static com32sys_t inreg, outreg; + struct disk_ebios_eparam *eparam = __com32.cs_bounce; + + memset(diskinfo, 0, sizeof *diskinfo); + diskinfo->disk = disk; + diskinfo->bps = SECTOR; + + /* Get EBIOS support */ + memset(&inreg, 0, sizeof inreg); + inreg.eax.b[1] = 0x41; + inreg.ebx.w[0] = 0x55aa; + inreg.edx.b[0] = disk; + inreg.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &inreg, &outreg); + + if (!(outreg.eflags.l & EFLAGS_CF) && + outreg.ebx.w[0] == 0xaa55 && (outreg.ecx.b[0] & 1)) { + diskinfo->ebios = 1; + } + + /* Get extended disk parameters if ebios == 1 */ + if (diskinfo->ebios) { + memset(&inreg, 0, sizeof inreg); + inreg.eax.b[1] = 0x48; + inreg.edx.b[0] = disk; + inreg.esi.w[0] = OFFS(eparam); + inreg.ds = SEG(eparam); + + memset(eparam, 0, sizeof *eparam); + eparam->len = sizeof *eparam; + + __intcall(0x13, &inreg, &outreg); + + if (!(outreg.eflags.l & EFLAGS_CF)) { + diskinfo->lbacnt = eparam->lbacnt; + if (eparam->bps) + diskinfo->bps = eparam->bps; + /* + * don't think about using geometry data returned by + * 48h, as it can differ from 08h a lot ... + */ + } + } + /* + * Get disk parameters the old way - really only useful for hard + * disks, but if we have a partitioned floppy it's actually our best + * chance... + */ + memset(&inreg, 0, sizeof inreg); + inreg.eax.b[1] = 0x08; + inreg.edx.b[0] = disk; + + __intcall(0x13, &inreg, &outreg); + + if (outreg.eflags.l & EFLAGS_CF) + return diskinfo->ebios ? 0 : -1; + + diskinfo->spt = 0x3f & outreg.ecx.b[0]; + diskinfo->head = 1 + outreg.edx.b[1]; + diskinfo->cyl = 1 + (outreg.ecx.b[1] | ((outreg.ecx.b[0] & 0xc0u) << 2)); + + if (diskinfo->spt) + diskinfo->cbios = 1; /* Valid geometry */ + else { + diskinfo->head = 1; + diskinfo->spt = 1; + diskinfo->cyl = 1; + } + + if (!diskinfo->lbacnt) + diskinfo->lbacnt = diskinfo->cyl * diskinfo->head * diskinfo->spt; + + return 0; +} + +/** + * Get disk block(s) and return a malloc'd buffer. + * + * @v diskinfo The disk drive to read from + * @v lba The logical block address to begin reading at + * @v count The number of sectors to read + * @ret data An allocated buffer with the read data + * + * Uses the disk number and information from diskinfo. Read count sectors + * from drive, starting at lba. Return a new buffer, or NULL upon failure. + */ +void *disk_read_sectors(const struct disk_info *const diskinfo, uint64_t lba, + uint8_t count) +{ + com32sys_t inreg; + struct disk_ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + diskinfo->bps; + void *data; + uint32_t maxcnt; + + maxcnt = (__com32.cs_bounce_size - diskinfo->bps) / diskinfo->bps; + if (!count || count > maxcnt || lba + count > diskinfo->lbacnt) + return NULL; + + memset(&inreg, 0, sizeof inreg); + + if (diskinfo->ebios) { + dapa->len = sizeof(*dapa); + dapa->count = count; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = diskinfo->disk; + inreg.eax.b[1] = 0x42; /* Extended read */ + } else { + unsigned int c, h, s, t; + /* + * if we passed lba + count check and we get here, that means that + * lbacnt was calculated from chs geometry (or faked from 1/1/1), thus + * 32bits are perfectly enough and lbacnt corresponds to cylinder + * boundary + */ + s = lba % diskinfo->spt; + t = lba / diskinfo->spt; + h = t % diskinfo->head; + c = t / diskinfo->head; + + inreg.eax.b[0] = count; + inreg.eax.b[1] = 0x02; /* Read */ + inreg.ecx.b[1] = c; + inreg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1); + inreg.edx.b[1] = h; + inreg.edx.b[0] = diskinfo->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + if (disk_int13_retry(&inreg, NULL)) + return NULL; + + data = malloc(count * diskinfo->bps); + if (data) + memcpy(data, buf, count * diskinfo->bps); + return data; +} + +/** + * Write disk block(s). + * + * @v diskinfo The disk drive to write to + * @v lba The logical block address to begin writing at + * @v data The data to write + * @v count The number of sectors to write + * @ret (int) 0 upon success, -1 upon failure + * + * Uses the disk number and information from diskinfo. + * Write sector(s) to a disk drive, starting at lba. + */ +int disk_write_sectors(const struct disk_info *const diskinfo, uint64_t lba, + const void *data, uint8_t count) +{ + com32sys_t inreg; + struct disk_ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + diskinfo->bps; + uint32_t maxcnt; + + maxcnt = (__com32.cs_bounce_size - diskinfo->bps) / diskinfo->bps; + if (!count || count > maxcnt || lba + count > diskinfo->lbacnt) + return -1; + + memcpy(buf, data, count * diskinfo->bps); + memset(&inreg, 0, sizeof inreg); + + if (diskinfo->ebios) { + dapa->len = sizeof(*dapa); + dapa->count = count; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = diskinfo->disk; + inreg.eax.b[1] = 0x43; /* Extended write */ + } else { + unsigned int c, h, s, t; + /* + * if we passed lba + count check and we get here, that means that + * lbacnt was calculated from chs geometry (or faked from 1/1/1), thus + * 32bits are perfectly enough and lbacnt corresponds to cylinder + * boundary + */ + s = lba % diskinfo->spt; + t = lba / diskinfo->spt; + h = t % diskinfo->head; + c = t / diskinfo->head; + + inreg.eax.b[0] = count; + inreg.eax.b[1] = 0x03; /* Write */ + inreg.ecx.b[1] = c; + inreg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1); + inreg.edx.b[1] = h; + inreg.edx.b[0] = diskinfo->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + if (disk_int13_retry(&inreg, NULL)) + return -1; + + return 0; /* ok */ +} + +/** + * Write disk blocks and verify they were written. + * + * @v diskinfo The disk drive to write to + * @v lba The logical block address to begin writing at + * @v buf The data to write + * @v count The number of sectors to write + * @ret rv 0 upon success, -1 upon failure + * + * Uses the disk number and information from diskinfo. + * Writes sectors to a disk drive starting at lba, then reads them back + * to verify they were written correctly. + */ +int disk_write_verify_sectors(const struct disk_info *const diskinfo, + uint64_t lba, const void *buf, uint8_t count) +{ + char *rb; + int rv; + + rv = disk_write_sectors(diskinfo, lba, buf, count); + if (rv) + return rv; /* Write failure */ + rb = disk_read_sectors(diskinfo, lba, count); + if (!rb) + return -1; /* Readback failure */ + rv = memcmp(buf, rb, count * diskinfo->bps); + free(rb); + return rv ? -1 : 0; +} + +/** + * Dump info about a DOS partition entry + * + * @v part The 16-byte partition entry to examine + */ +void disk_dos_part_dump(const struct disk_dos_part_entry *const part) +{ + (void)part; + dprintf("Partition status _____ : 0x%.2x\n" + "Partition CHS start\n" + " Cylinder ___________ : 0x%.4x (%u)\n" + " Head _______________ : 0x%.2x (%u)\n" + " Sector _____________ : 0x%.2x (%u)\n" + "Partition type _______ : 0x%.2x\n" + "Partition CHS end\n" + " Cylinder ___________ : 0x%.4x (%u)\n" + " Head _______________ : 0x%.2x (%u)\n" + " Sector _____________ : 0x%.2x (%u)\n" + "Partition LBA start __ : 0x%.8x (%u)\n" + "Partition LBA count __ : 0x%.8x (%u)\n" + "-------------------------------\n", + part->active_flag, + chs_cylinder(part->start), + chs_cylinder(part->start), + chs_head(part->start), + chs_head(part->start), + chs_sector(part->start), + chs_sector(part->start), + part->ostype, + chs_cylinder(part->end), + chs_cylinder(part->end), + chs_head(part->end), + chs_head(part->end), + chs_sector(part->end), + chs_sector(part->end), + part->start_lba, part->start_lba, part->length, part->length); +} + +/* Trivial error message output */ +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +/** + * This walk-map effectively reverses the little-endian + * portions of a GPT disk/partition GUID for a string representation. + * There might be a better header for this... + */ +static const char guid_le_walk_map[] = { + 3, -1, -1, -1, 0, + 5, -1, 0, + 3, -1, 0, + 2, 1, 0, + 1, 1, 1, 1, 1, 1 +}; + +/** + * Fill a buffer with a textual GUID representation. + * + * @v buf Points to a minimum array of 37 chars + * @v id The GUID to represent as text + * + * The buffer must be >= char[37] and will be populated + * with an ASCII NUL C string terminator. + * Example: 11111111-2222-3333-4444-444444444444 + * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB + */ +void guid_to_str(char *buf, const struct guid *const id) +{ + unsigned int i = 0; + const char *walker = (const char *)id; + + while (i < sizeof(guid_le_walk_map)) { + walker += guid_le_walk_map[i]; + if (!guid_le_walk_map[i]) + *buf = '-'; + else { + *buf = ((*walker & 0xF0) >> 4) + '0'; + if (*buf > '9') + *buf += 'A' - '9' - 1; + buf++; + *buf = (*walker & 0x0F) + '0'; + if (*buf > '9') + *buf += 'A' - '9' - 1; + } + buf++; + i++; + } + *buf = 0; +} + +/** + * Create a GUID structure from a textual GUID representation. + * + * @v buf Points to a GUID string to parse + * @v id Points to a GUID to be populated + * @ret (int) Returns 0 upon success, -1 upon failure + * + * The input buffer must be >= 32 hexadecimal chars and be + * terminated with an ASCII NUL. Returns non-zero on failure. + * Example: 11111111-2222-3333-4444-444444444444 + * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB + */ +int str_to_guid(const char *buf, struct guid *const id) +{ + char guid_seq[sizeof(struct guid) * 2]; + unsigned int i = 0; + char *walker = (char *)id; + + while (*buf && i < sizeof(guid_seq)) { + switch (*buf) { + /* Skip these three characters */ + case '{': + case '}': + case '-': + break; + default: + /* Copy something useful to the temp. sequence */ + if ((*buf >= '0') && (*buf <= '9')) + guid_seq[i] = *buf - '0'; + else if ((*buf >= 'A') && (*buf <= 'F')) + guid_seq[i] = *buf - 'A' + 10; + else if ((*buf >= 'a') && (*buf <= 'f')) + guid_seq[i] = *buf - 'a' + 10; + else { + /* Or not */ + error("Illegal character in GUID!\n"); + return -1; + } + i++; + } + buf++; + } + /* Check for insufficient valid characters */ + if (i < sizeof(guid_seq)) { + error("Too few GUID characters!\n"); + return -1; + } + buf = guid_seq; + i = 0; + while (i < sizeof(guid_le_walk_map)) { + if (!guid_le_walk_map[i]) + i++; + walker += guid_le_walk_map[i]; + *walker = *buf << 4; + buf++; + *walker |= *buf; + buf++; + i++; + } + return 0; +} + +/** + * Display GPT partition details. + * + * @v gpt_part The GPT partition entry to display + */ +void disk_gpt_part_dump(const struct disk_gpt_part_entry *const gpt_part) +{ + unsigned int i; + char guid_text[37]; + + dprintf("----------------------------------\n" + "GPT part. LBA first __ : 0x%.16llx\n" + "GPT part. LBA last ___ : 0x%.16llx\n" + "GPT part. attribs ____ : 0x%.16llx\n" + "GPT part. name _______ : '", + gpt_part->lba_first, gpt_part->lba_last, gpt_part->attribs); + for (i = 0; i < sizeof(gpt_part->name); i++) { + if (gpt_part->name[i]) + dprintf("%c", gpt_part->name[i]); + } + dprintf("'"); + guid_to_str(guid_text, &gpt_part->type); + dprintf("GPT part. type GUID __ : {%s}\n", guid_text); + guid_to_str(guid_text, &gpt_part->uid); + dprintf("GPT part. unique ID __ : {%s}\n", guid_text); +} + +/** + * Display GPT header details. + * + * @v gpt The GPT header to display + */ +void disk_gpt_header_dump(const struct disk_gpt_header *const gpt) +{ + char guid_text[37]; + + printf("GPT sig ______________ : '%8.8s'\n" + "GPT major revision ___ : 0x%.4x\n" + "GPT minor revision ___ : 0x%.4x\n" + "GPT header size ______ : 0x%.8x\n" + "GPT header checksum __ : 0x%.8x\n" + "GPT reserved _________ : '%4.4s'\n" + "GPT LBA current ______ : 0x%.16llx\n" + "GPT LBA alternative __ : 0x%.16llx\n" + "GPT LBA first usable _ : 0x%.16llx\n" + "GPT LBA last usable __ : 0x%.16llx\n" + "GPT LBA part. table __ : 0x%.16llx\n" + "GPT partition count __ : 0x%.8x\n" + "GPT partition size ___ : 0x%.8x\n" + "GPT part. table chksum : 0x%.8x\n", + gpt->sig, + gpt->rev.fields.major, + gpt->rev.fields.minor, + gpt->hdr_size, + gpt->chksum, + gpt->reserved1, + gpt->lba_cur, + gpt->lba_alt, + gpt->lba_first_usable, + gpt->lba_last_usable, + gpt->lba_table, gpt->part_count, gpt->part_size, gpt->table_chksum); + guid_to_str(guid_text, &gpt->disk_guid); + printf("GPT disk GUID ________ : {%s}\n", guid_text); +} diff --git a/com32/lib/syslinux/dump_mmap.c b/com32/lib/syslinux/dump_mmap.c index 3f1e340b..85638cd9 100644 --- a/com32/lib/syslinux/dump_mmap.c +++ b/com32/lib/syslinux/dump_mmap.c @@ -28,20 +28,22 @@ /* * dump_mmap.c * - * Writes a syslinux_memmap out to a specified file. This is - * intended for debugging. + * Writes a syslinux_memmap out to a dprintf. */ #include <stdio.h> +#include <dprintf.h> #include <syslinux/movebits.h> -void syslinux_dump_memmap(FILE * file, struct syslinux_memmap *memmap) +#ifdef DEBUG +void syslinux_dump_memmap(struct syslinux_memmap *memmap) { - fprintf(file, "%10s %10s %10s\n" + dprintf("%10s %10s %10s\n" "--------------------------------\n", "Start", "Length", "Type"); while (memmap->next) { - fprintf(file, "0x%08x 0x%08x %10d\n", memmap->start, + dprintf("0x%08x 0x%08x %10d\n", memmap->start, memmap->next->start - memmap->start, memmap->type); memmap = memmap->next; } } +#endif diff --git a/com32/lib/syslinux/dump_movelist.c b/com32/lib/syslinux/dump_movelist.c index 282d0068..4042ce96 100644 --- a/com32/lib/syslinux/dump_movelist.c +++ b/com32/lib/syslinux/dump_movelist.c @@ -33,14 +33,17 @@ */ #include <stdio.h> +#include <dprintf.h> #include <syslinux/movebits.h> -void syslinux_dump_movelist(FILE * file, struct syslinux_movelist *ml) +#ifdef DEBUG +void syslinux_dump_movelist(struct syslinux_movelist *ml) { - fprintf(file, "%10s %10s %10s\n" + dprintf("%10s %10s %10s\n" "--------------------------------\n", "Dest", "Src", "Length"); while (ml) { - fprintf(file, "0x%08x 0x%08x 0x%08x\n", ml->dst, ml->src, ml->len); + dprintf("0x%08x 0x%08x 0x%08x\n", ml->dst, ml->src, ml->len); ml = ml->next; } } +#endif diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c index c1ce875c..856141f8 100644 --- a/com32/lib/syslinux/load_linux.c +++ b/com32/lib/syslinux/load_linux.c @@ -38,21 +38,13 @@ #include <inttypes.h> #include <string.h> #include <minmax.h> +#include <errno.h> #include <suffix_number.h> #include <syslinux/align.h> #include <syslinux/linux.h> #include <syslinux/bootrm.h> #include <syslinux/movebits.h> - -#ifndef DEBUG -# define DEBUG 0 -#endif -#if DEBUG -# include <stdio.h> -# define dprintf printf -#else -# define dprintf(f, ...) ((void)0) -#endif +#include <dprintf.h> struct linux_header { uint8_t boot_sector_1[0x0020]; @@ -189,13 +181,16 @@ static int map_initramfs(struct syslinux_movelist **fraglist, } int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, char *cmdline) + struct initramfs *initramfs, + struct setup_data *setup_data, + char *cmdline) { struct linux_header hdr, *whdr; size_t real_mode_size, prot_mode_size; addr_t real_mode_base, prot_mode_base; addr_t irf_size; size_t cmdline_size, cmdline_offset; + struct setup_data *sdp; struct syslinux_rm_regs regs; struct syslinux_movelist *fraglist = NULL; struct syslinux_memmap *mmap = NULL; @@ -318,10 +313,8 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, if (!mmap || !amap) goto bail; -#if DEBUG dprintf("Initial memory map:\n"); - syslinux_dump_memmap(stdout, mmap); -#endif + syslinux_dump_memmap(mmap); /* If the user has specified a memory limit, mark that as unavailable. Question: should we mark this off-limit in the mmap as well (meaning @@ -460,6 +453,49 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, } } + if (setup_data) { + uint64_t *prev_ptr = &whdr->setup_data; + + for (sdp = setup_data->next; sdp != setup_data; sdp = sdp->next) { + struct syslinux_memmap *ml; + const addr_t align_mask = 15; /* Header is 16 bytes */ + addr_t best_addr = 0; + size_t size = sdp->hdr.len + sizeof(sdp->hdr); + + if (!sdp->data || !sdp->hdr.len) + continue; + + if (hdr.version < 0x0209) { + /* Setup data not supported */ + errno = ENXIO; /* Kind of arbitrary... */ + goto bail; + } + + for (ml = amap; ml->type != SMT_END; ml = ml->next) { + addr_t adj_start = (ml->start + align_mask) & ~align_mask; + addr_t adj_end = ml->next->start & ~align_mask; + + if (ml->type == SMT_FREE && adj_end - adj_start >= size) + best_addr = (adj_end - size) & ~align_mask; + } + + if (!best_addr) + goto bail; + + *prev_ptr = best_addr; + prev_ptr = &sdp->hdr.next; + + if (syslinux_add_memmap(&amap, best_addr, size, SMT_ALLOC)) + goto bail; + if (syslinux_add_movelist(&fraglist, best_addr, + (addr_t)&sdp->hdr, sizeof sdp->hdr)) + goto bail; + if (syslinux_add_movelist(&fraglist, best_addr + sizeof sdp->hdr, + (addr_t)sdp->data, sdp->hdr.len)) + goto bail; + } + } + /* Set up the registers on entry */ memset(®s, 0, sizeof regs); regs.es = regs.ds = regs.ss = regs.fs = regs.gs = real_mode_base >> 4; @@ -468,16 +504,14 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, /* Linux is OK with sp = 0 = 64K, but perhaps other things aren't... */ regs.esp.w[0] = min(cmdline_offset, (size_t) 0xfff0); -#if DEBUG dprintf("Final memory map:\n"); - syslinux_dump_memmap(stdout, mmap); + syslinux_dump_memmap(mmap); dprintf("Final available map:\n"); - syslinux_dump_memmap(stdout, amap); + syslinux_dump_memmap(amap); dprintf("Initial movelist:\n"); - syslinux_dump_movelist(stdout, fraglist); -#endif + syslinux_dump_movelist(fraglist); syslinux_shuffle_boot_rm(fraglist, mmap, 0, ®s); diff --git a/com32/lib/syslinux/movebits.c b/com32/lib/syslinux/movebits.c index bd5ce0e8..7a05f3c1 100644 --- a/com32/lib/syslinux/movebits.c +++ b/com32/lib/syslinux/movebits.c @@ -48,21 +48,7 @@ #include <stdbool.h> #include <syslinux/movebits.h> - -#ifndef DEBUG -# ifdef TEST -# define DEBUG 1 -# else -# define DEBUG 0 -# endif -#endif - -#if DEBUG -# include <stdio.h> -# define dprintf printf -#else -# define dprintf(...) ((void)0) -#endif +#include <dprintf.h> static jmp_buf new_movelist_bail; @@ -242,10 +228,8 @@ static void shuffle_dealias(struct syslinux_movelist **fraglist, addr_t ps, pe, xs, xe, delta; bool advance; -#if DEBUG dprintf("Before alias resolution:\n"); - syslinux_dump_movelist(stdout, *fraglist); -#endif + syslinux_dump_movelist(*fraglist); *postcopy = NULL; @@ -316,12 +300,10 @@ restart: ; } -#if DEBUG dprintf("After alias resolution:\n"); - syslinux_dump_movelist(stdout, *fraglist); + syslinux_dump_movelist(*fraglist); dprintf("Post-shuffle copies:\n"); - syslinux_dump_movelist(stdout, *postcopy); -#endif + syslinux_dump_movelist(*postcopy); } /* @@ -449,12 +431,10 @@ nomem: /* As long as there are unprocessed fragments in the chain... */ while ((fp = &frags, f = *fp)) { -#if DEBUG dprintf("Current free list:\n"); - syslinux_dump_memmap(stdout, mmap); + syslinux_dump_memmap(mmap); dprintf("Current frag list:\n"); - syslinux_dump_movelist(stdout, frags); -#endif + syslinux_dump_movelist(frags); /* Scan for fragments which can be discarded without action. */ if (f->src == f->dst) { @@ -692,16 +672,16 @@ int main(int argc, char *argv[]) *fep = NULL; - printf("Input move list:\n"); - syslinux_dump_movelist(stdout, frags); - printf("Input free list:\n"); - syslinux_dump_memmap(stdout, memmap); + dprintf("Input move list:\n"); + syslinux_dump_movelist(frags); + dprintf("Input free list:\n"); + syslinux_dump_memmap(memmap); if (syslinux_compute_movelist(&moves, frags, memmap)) { printf("Failed to compute a move sequence\n"); return 1; } else { - printf("Final move list:\n"); + dprintf("Final move list:\n"); syslinux_dump_movelist(stdout, moves); return 0; } diff --git a/com32/lib/syslinux/setup_data.c b/com32/lib/syslinux/setup_data.c new file mode 100644 index 00000000..a36c5b61 --- /dev/null +++ b/com32/lib/syslinux/setup_data.c @@ -0,0 +1,47 @@ +#include <stdlib.h> +#include <syslinux/linux.h> +#include <syslinux/loadfile.h> + +struct setup_data *setup_data_init(void) +{ + struct setup_data *setup_data; + + setup_data = zalloc(sizeof(*setup_data)); + if (!setup_data) + return NULL; + + setup_data->prev = setup_data->next = setup_data; + return setup_data; +} + +int setup_data_add(struct setup_data *head, uint32_t type, + const void *data, size_t data_len) +{ + struct setup_data *setup_data; + + setup_data = zalloc(sizeof(*setup_data)); + if (!setup_data) + return -1; + + setup_data->data = data; + setup_data->hdr.len = data_len; + setup_data->hdr.type = type; + setup_data->prev = head->prev; + setup_data->next = head; + head->prev->next = setup_data; + head->prev = setup_data; + + return 0; +} + +int setup_data_load(struct setup_data *head, uint32_t type, + const char *filename) +{ + void *data; + size_t len; + + if (loadfile(filename, &data, &len)) + return -1; + + return setup_data_add(head, type, data, len); +} diff --git a/com32/lib/syslinux/shuffle.c b/com32/lib/syslinux/shuffle.c index 54a7e651..e9ee6aad 100644 --- a/com32/lib/syslinux/shuffle.c +++ b/com32/lib/syslinux/shuffle.c @@ -39,26 +39,10 @@ #include <inttypes.h> #include <com32.h> #include <minmax.h> +#include <dprintf.h> #include <syslinux/movebits.h> #include <klibc/compiler.h> -#ifndef DEBUG -# define DEBUG 0 -#endif - -#define dprintf(f, ...) ((void)0) -#define dprintf2(f, ...) ((void)0) - -#if DEBUG -# include <stdio.h> -# undef dprintf -# define dprintf printf -# if DEBUG > 1 -# undef dprintf2 -# define dprintf2 printf -# endif -#endif - struct shuffle_descriptor { uint32_t dst, src, len; }; diff --git a/com32/lib/syslinux/zonelist.c b/com32/lib/syslinux/zonelist.c index b548211f..7034c4be 100644 --- a/com32/lib/syslinux/zonelist.c +++ b/com32/lib/syslinux/zonelist.c @@ -39,21 +39,7 @@ #include <stdlib.h> #include <syslinux/align.h> #include <syslinux/movebits.h> - -#ifndef DEBUG -# ifdef TEST -# define DEBUG 1 -# else -# define DEBUG 0 -# endif -#endif - -#if DEBUG -# include <stdio.h> -# define dprintf printf -#else -# define dprintf(...) ((void)0) -#endif +#include <dprintf.h> /* * Create an empty syslinux_memmap list. @@ -96,10 +82,8 @@ int syslinux_add_memmap(struct syslinux_memmap **list, struct syslinux_memmap *range; enum syslinux_memmap_types oldtype; -#if DEBUG dprintf("Input memmap:\n"); - syslinux_dump_memmap(stdout, *list); -#endif + syslinux_dump_memmap(*list); /* Remove this to make len == 0 mean all of memory */ if (len == 0) @@ -164,10 +148,8 @@ int syslinux_add_memmap(struct syslinux_memmap **list, } } -#if DEBUG dprintf("After adding (%#x,%#x,%d):\n", start, len, type); - syslinux_dump_memmap(stdout, *list); -#endif + syslinux_dump_memmap(*list); return 0; } diff --git a/com32/lib/vdprintf.c b/com32/lib/vdprintf.c index d74f2782..c1f90a63 100644 --- a/com32/lib/vdprintf.c +++ b/com32/lib/vdprintf.c @@ -14,6 +14,8 @@ #define DEBUG 1 #include <dprintf.h> +#ifndef vdprintf + #define BUFFER_SIZE 4096 enum serial_port_regs { @@ -114,3 +116,5 @@ void vdprintf(const char *format, va_list ap) while (rv--) debug_putc(*p++); } + +#endif /* vdprintf */ |