topdir = ..
include $(topdir)/MCONFIG.embedded
-LDFLAGS = -T com16.ld
+CFLAGS += -D__MSDOS__
+
+LDFLAGS = -T dosexe.ld
OPTFLAGS = -g
INCLUDES = -include code16.h -nostdinc -iwithprefix include \
-I. -I.. -I../libfat -I ../libinstaller
../libinstaller/ldlinux_bin.c \
../libinstaller/mbr_bin.c \
$(wildcard ../libfat/*.c)
-OBJS = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
+OBJS = header.o crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
LIBOBJS = conio.o memcpy.o memset.o skipatou.o atou.o malloc.o free.o \
argv.o printf.o __divdi3.o __udivmoddi4.o
installer:
-syslinux.elf: $(OBJS) libcom.a
- $(LD) $(LDFLAGS) -o $@ $^
+syslinux.elf: $(OBJS) dosexe.ld libcom.a
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) libcom.a
libcom.a: $(LIBOBJS)
-rm -f $@
#define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1)))
-extern char _end[]; /* Symbol created by linker */
-void *__mem_end = &_end; /* Global variable for use by malloc() */
+extern char __heap_start[];
+void *__mem_end = &__heap_start; /* Global variable for use by malloc() */
int __parse_argv(char ***argv, const char *str)
{
+++ /dev/null
-/*
- * Linker script for COM16 binaries
- */
-
-/* Script for -z combreloc: combine and sort reloc sections */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386",
- "elf32-i386")
-OUTPUT_ARCH(i386)
-EXTERN(_start)
-ENTRY(_start)
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0x100;
- PROVIDE (__executable_start = .);
-
- .init :
- {
- KEEP (*(.init))
- } =0x90909090
- .text :
- {
- *(.text .stub .text.* .gnu.linkonce.t.*)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- } =0x90909090
- .fini :
- {
- KEEP (*(.fini))
- } =0x90909090
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
-
- /* 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. */
- . = ALIGN(4);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
- PROVIDE (__ctors_start = .);
- .ctors :
- {
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- }
- PROVIDE (__ctors_end = .);
- PROVIDE (__dtors_start = .);
- .dtors :
- {
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- }
- PROVIDE (__dtors_end = .);
-
- /* Adjust the address for the data segment. Avoid mixing code and
- data within same 128-byte chunk. */
- . = ALIGN(128);
-
- .data :
- {
- *(.data .data.* .gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- }
- .data1 : { *(.data1) }
- _edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- .bss :
- {
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- *(COMMON)
- /* Align here to ensure that the .bss section occupies space up to
- _end. Align after .bss to ensure correct alignment even if the
- .bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
- }
- . = ALIGN(32 / 8);
- _end = .;
- PROVIDE (end = .);
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
- /DISCARD/ : { *(.note.GNU-stack) }
-}
# error "This file assumes -mregparm=3 -DREGPARM=3"
#endif
- .section ".init","ax"
+ .section ".text","ax"
.globl _start
.type _start,@function
_start:
# Align the stack and make sure the high half is zero
andl $0xfff8,%esp
+ # DS, ES points to the PSP at this point
+ pushw %es # Save PSP pointer
+ movw %cs,%ax
+ movw %ax,%ds
+ movw %ax,%es
+
# Clear the .bss
cld
xorl %eax,%eax
movw $__bss_start,%di
- movw $_end+3,%cx
+ movw $__bss_end+3,%cx
subw %di,%cx
shrw $2,%cx
rep ; stosl
+ # Copy the command line into our own segment
+ popw %fs # FS -> PSP
+ movw $_cmdline,%di
+ movzbw %fs:0x80,%cx
+ movw $0x81,%si
+ fs ; rep ; movsb
+ # Already zero-terminated since we're writing into clean bss
+
# Compute argc and argv (assumes REGPARM)
- xorl %edx,%edx
- movzbw 0x80,%bx
- movb %dl,0x81(%bx) # Zero-terminate string
- movb $0x81,%dl
+ movl $_cmdline,%edx
pushl %eax # Make space for argv
movl %esp,%eax
calll __parse_argv
1: hlt
jmp 1b
.size exit,.-exit
+
+ .section ".bss","aw"
+ .balign 4
+_cmdline:
+ .space 128
+ .size _cmdline,.-_cmdline
--- /dev/null
+/*
+ * Linker script for an MS-DOS EXE binary; this hard-codes a simple
+ * MZ header without relocations.
+ *
+ * For documentation on the MS-DOS MZ EXE format, see:
+ * http://www.delorie.com/djgpp/doc/exe/
+ */
+
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0;
+ /* EXE header, from header.S */
+ .header : {
+ *(.header)
+ } =0
+
+ . = ALIGN(16);
+ __header_size = .;
+ __payload_lma = .;
+
+ . = 0;
+ .payload : AT (__payload_lma) {
+ __payload_start = .;
+ ldlinux_bin.o(.data)
+ __payload_end = .;
+ }
+ __payload_len = __payload_end - __payload_start;
+ __payload_dwords = __payload_len >> 2;
+
+ . = ALIGN(16);
+ __text_lma = __payload_lma + .;
+ __payload_sseg = (__payload_lma - __text_lma) >> 4;
+ _exe_text_seg = (__text_lma - __header_size) >> 4;
+
+ . = 0;
+ .text : AT (__text_lma) {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.gnu.warning)
+ } =0x90909090
+ _etext = .;
+
+ . = ALIGN(16);
+ __rodata_vma = .;
+ .rodata : AT (__rodata_vma + __text_lma) {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ }
+
+ /* Adjust the address for the data segment. Avoid mixing code and
+ data within same 128-byte chunk. */
+ . = ALIGN(128);
+ __data_vma = .;
+ .data : AT (__data_vma + __text_lma) {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .;
+
+ _exe_edata_low = ((_edata + __text_lma) & 511);
+ _exe_edata_blocks = ((_edata + __text_lma) + 511) >> 9;
+
+ .bss (NOLOAD) : {
+ __bss_start = .;
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ __bss_end = .;
+ }
+
+ . = ALIGN(16);
+ .heap (NOLOAD) : {
+ __heap_start = .;
+ *(.heap)
+ __heap_end = .;
+ }
+
+ . = ALIGN(16);
+ .stack (NOLOAD) : {
+ __stack_start = .;
+ *(.stack)
+ __stack_end = .;
+ }
+ . = ALIGN(16);
+ _end = .;
+
+ _exe_bss_paras = (_end - __bss_start) >> 4;
+
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
--- /dev/null
+STACK_SIZE = 8192
+HEAP_SIZE = 16384
+
+ .section ".header","a"
+ .balign 512
+__header_start:
+ .short 0x5a4d
+ .short _exe_edata_low
+ .short _exe_edata_blocks
+ .short 0 /* Relocation count */
+ .short (__header_end - __header_start) >> 4
+ .short _exe_bss_paras
+ .short _exe_bss_paras
+ .short _exe_text_seg /* SP */
+ .short __stack_end
+ .short 0 /* Checksum */
+ .short _start
+ .short _exe_text_seg /* CS */
+ .short __reloc
+ .short 0 /* Overlay number */
+ .short 0 /* Unknown/pad? */
+ .short 0 /* Unknown/pad? */
+__reloc:
+ .balign 512
+__header_end:
+
+ .section ".heap","aw"
+ .space HEAP_SIZE
+
+ .section ".stack","aw"
+ .space STACK_SIZE
*/
#include <stdlib.h>
+#include <string.h>
#include "malloc.h"
struct free_arena_header __malloc_head =
&__malloc_head
};
-/* This is extern so it can be overridden by the user application */
-const size_t __stack_size = 4096;
-
-static inline size_t sp(void)
-{
- uint32_t sp;
- asm volatile("movl %%esp,%0" : "=rm" (sp));
- return sp;
-}
-
-extern void *__mem_end;
+extern void *__mem_end; /* In argv.c */
void __init_memory_arena(void)
{
+ extern char __heap_end[];
struct free_arena_header *fp;
- size_t start, total_space;
- start = (size_t)ARENA_ALIGN_UP(__mem_end);
- total_space = sp() - start;
-
- fp = (struct free_arena_header *)start;
+ fp = (struct free_arena_header *)__mem_end;
fp->a.type = ARENA_TYPE_FREE;
- fp->a.size = total_space - __stack_size;
+ fp->a.size = __heap_end - (char *)__mem_end;
/* Insert into chains */
fp->a.next = fp->a.prev = &__malloc_head;
/* Nothing found... need to request a block from the kernel */
return NULL; /* No kernel to get stuff from */
}
+
+void *calloc(size_t nmemb, size_t size)
+{
+ void *p;
+ size *= nmemb;
+ p = malloc(size);
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
return 0;
}
+extern const char __payload_sseg[];
+static uint16_t ldlinux_seg;
+
+ssize_t write_ldlinux(int fd)
+{
+ uint32_t offset = 0;
+ uint16_t rv;
+ uint8_t err;
+
+ while (offset < syslinux_ldlinux_len) {
+ uint32_t chunk = syslinux_ldlinux_len - offset;
+ if (chunk > 32768)
+ chunk = 32768;
+ asm volatile("pushw %%ds ; "
+ "movw %6,%%ds ; "
+ "int $0x21 ; "
+ "popw %%ds ; "
+ "setc %0"
+ : "=bcdm" (err), "=a" (rv)
+ : "a" (0x4000), "b" (fd), "c" (chunk), "d" (offset & 15),
+ "SD" ((uint16_t)(ldlinux_seg + (offset >> 4))));
+ if ( err || rv == 0 )
+ die("file write error");
+ offset += rv;
+ }
+
+ return offset;
+}
+
ssize_t write_file(int fd, const void *buf, size_t count)
{
uint16_t rv;
dprintf("write_file(%d,%p,%u)\n", fd, buf, count);
while ( count ) {
- rv = 0x4000;
asm volatile("int $0x21 ; setc %0"
- : "=abcdm" (err), "+a" (rv)
- : "b" (fd), "c" (count), "d" (buf));
+ : "=bcdm" (err), "=a" (rv)
+ : "a" (0x4000), "b" (fd), "c" (count), "d" (buf));
if ( err || rv == 0 )
die("file write error");
char **argp, *opt;
int force = 0; /* -f (force) option */
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
+ int ldlinux_sectors;
int32_t ldlinux_cluster;
int nsectors;
const char *device = NULL, *bootsecfile = NULL;
const char *subdir = NULL;
int stupid = 0;
int raid_mode = 0;
+ int patch_sectors;
+
+ ldlinux_seg = (size_t)__payload_sseg + data_segment();
dprintf("argv = %p\n", argv);
for ( i = 0 ; i <= argc ; i++ )
set_attributes(ldlinux_name, 0);
fd = creat(ldlinux_name, 0x07); /* SYSTEM HIDDEN READONLY */
- write_file(fd, syslinux_ldlinux, syslinux_ldlinux_len);
+ write_ldlinux(fd);
close(fd);
/*
* this is supposed to be a simple, privileged version
* of the installer.
*/
+ ldlinux_sectors = (syslinux_ldlinux_len+SECTOR_SIZE-1) >> SECTOR_BITS;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
lock_device(2);
fs = libfat_open(libfat_xpread, dev_fd);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while ( s && nsectors < 65 ) {
+ while ( s && nsectors < ldlinux_sectors ) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + 511) >> 9;
/*
- * Write the now-patched first sector of ldlinux.sys
+ * Overwrite the now-patched ldlinux.sys
*/
lock_device(3);
- write_device(dev_fd, syslinux_ldlinux, 1, sectors[0]);
+ for (i = 0; i < patch_sectors; i++) {
+ uint16_t si, di, cx;
+ si = 0;
+ di = (size_t)sectbuf;
+ cx = 512 >> 2;
+ asm volatile("movw %3,%%fs ; fs ; rep ; movsl"
+ : "+S" (si), "+D" (di), "+c" (cx)
+ : "abd" ((uint16_t)(ldlinux_seg + (i << (9-4)))));
+ write_device(dev_fd, sectbuf, 1, sectors[i]);
+ }
/*
* Muck with the MBR, if desired, while we hold the lock
return -1;
/* Number of sectors per block */
- blksize >>= SECTOR_SHIFT;
+ blksize >>= SECTOR_BITS;
nblk = 0;
while ( nsectors ) {
geo->heads = opt.heads ?: 64;
geo->sectors = opt.sectors ?: 32;
- geo->cylinders = totalbytes/(geo->heads*geo->sectors << SECTOR_SHIFT);
+ geo->cylinders = totalbytes/(geo->heads*geo->sectors << SECTOR_BITS);
geo->start = 0;
if ( !opt.sectors && !opt.heads )
bs = (struct boot_sector *)boot_block;
- totalsectors = totalbytes >> SECTOR_SHIFT;
+ totalsectors = totalbytes >> SECTOR_BITS;
if ( totalsectors >= 65536 ) {
set_16(&bs->bsSectors, 0);
} else {
/* Construct the boot file */
dprintf("directory inode = %lu\n", (unsigned long) dirst.st_ino);
- nsect = (boot_image_len+SECTOR_SIZE-1) >> SECTOR_SHIFT;
+ nsect = (boot_image_len+SECTOR_SIZE-1) >> SECTOR_BITS;
nsect += 2; /* Two sectors for the ADV */
sectp = alloca(sizeof(uint32_t)*nsect);
if ( sectmap(fd, sectp, nsect) ) {
}
}
-printf "\n};\n\nunsigned int %s_len = %u;\n", $table_name, $total_len;
+printf "\n};\n\nconst unsigned int %s_len = %u;\n", $table_name, $total_len;
@st = stat STDIN;
-printf "\nint %s_mtime = %d;\n", $table_name, $st[9];
+printf "\nconst int %s_mtime = %d;\n", $table_name, $st[9];
exit 0;
#include "advconst.h"
/* The standard boot sector and ldlinux image */
-extern unsigned char syslinux_bootsect[];
-extern unsigned int syslinux_bootsect_len;
-extern int syslinux_bootsect_mtime;
+extern unsigned char syslinux_bootsect[];
+extern const unsigned int syslinux_bootsect_len;
+extern const int syslinux_bootsect_mtime;
-extern unsigned char syslinux_ldlinux[];
-extern unsigned int syslinux_ldlinux_len;
-extern int syslinux_ldlinux_mtime;
+extern unsigned char syslinux_ldlinux[];
+extern const unsigned int syslinux_ldlinux_len;
+extern const int syslinux_ldlinux_mtime;
-extern unsigned char syslinux_mbr[];
-extern unsigned int syslinux_mbr_len;
-extern int syslinux_mbr_mtime;
+extern unsigned char syslinux_mbr[];
+extern const unsigned int syslinux_mbr_len;
+extern const int syslinux_mbr_mtime;
+
+/* Sector size assumptions... */
+#define SECTOR_BITS 9
+#define SECTOR_SIZE (1 << SECTOR_BITS)
/* This takes a boot sector and merges in the syslinux fields */
void syslinux_make_bootsect(void *);
*/
static inline uint8_t get_8(const uint8_t *p)
{
- return *(const uint8_t *)p;
+ return *p;
}
static inline uint16_t get_16(const uint16_t *p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint16_t *)p;
+ return *p;
#else
- return (uint16_t)p[0] + ((uint16_t)p[1] << 8);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint16_t)pp[0] + ((uint16_t)pp[1] << 8);
#endif
}
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint32_t *)p;
+ return *p;
#else
- return (uint32_t)p[0] + ((uint32_t)p[1] << 8) +
- ((uint32_t)p[2] << 16) + ((uint32_t)p[3] << 24);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint32_t)pp[0] + ((uint32_t)pp[1] << 8) +
+ ((uint32_t)pp[2] << 16) + ((uint32_t)pp[3] << 24);
#endif
}
+static inline void set_8(uint8_t *p, uint8_t v)
+{
+ *p = v;
+}
+
static inline void set_16(uint16_t *p, uint16_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
*(uint16_t *)p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
+ uint8_t *pp = (uint8_t *)p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
#endif
}
/* Littleendian and unaligned-capable */
*(uint32_t *)p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
- p[2] = ((v >> 16) & 0xff);
- p[3] = ((v >> 24) & 0xff);
+ uint8_t *pp = (uint8_t *)p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
+ pp[2] = ((v >> 16) & 0xff);
+ pp[3] = ((v >> 24) & 0xff);
#endif
}
-#define SECTOR_SHIFT 9 /* 512-byte sectors */
-#define SECTOR_SIZE (1 << SECTOR_SHIFT)
-
#define LDLINUX_MAGIC 0x3eb202fe
/* Patch area for disk-based installers */
}
/*
+ * Special handling for the MS-DOS derivative: syslinux_ldlinux
+ * is a "far" object...
+ */
+#ifdef __MSDOS__
+
+extern const char __payload_sseg[]; /* Symbol from linker */
+
+static inline __attribute__((const)) uint16_t ds(void)
+{
+ uint16_t v;
+ asm("movw %%ds,%0" : "=rm" (v));
+ return v;
+}
+
+static inline void *set_fs(const void *p)
+{
+ uint16_t seg;
+
+ seg = ds() + (size_t)__payload_sseg;
+ seg += (size_t)p >> 4;
+ asm volatile("movw %0,%%fs" : : "rm" (seg));
+ return (void *)((size_t)p & 0xf);
+}
+
+static inline uint8_t get_8_sl(const uint8_t *p)
+{
+ uint8_t v;
+
+ p = set_fs(p);
+ asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*p));
+ return v;
+}
+
+static inline uint16_t get_16_sl(const uint16_t *p)
+{
+ uint16_t v;
+
+ p = set_fs(p);
+ asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*p));
+ return v;
+}
+
+static inline uint32_t get_32_sl(const uint32_t *p)
+{
+ uint32_t v;
+
+ p = set_fs(p);
+ asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*p));
+ return v;
+}
+
+static inline void set_8_sl(uint8_t *p, uint8_t v)
+{
+ p = set_fs(p);
+ asm volatile("movb %1,%%fs:%0" : "=m" (*p) : "qi" (v));
+}
+
+static inline void set_16_sl(uint16_t *p, uint16_t v)
+{
+ p = set_fs(p);
+ asm volatile("movw %1,%%fs:%0" : "=m" (*p) : "ri" (v));
+}
+
+static inline void set_32_sl(uint32_t *p, uint32_t v)
+{
+ p = set_fs(p);
+ asm volatile("movl %1,%%fs:%0" : "=m" (*p) : "ri" (v));
+}
+
+#else
+
+/* Sane system ... */
+#define get_8_sl(x) get_8(x)
+#define get_16_sl(x) get_16(x)
+#define get_32_sl(x) get_32(x)
+#define set_8_sl(x,y) set_8(x,y)
+#define set_16_sl(x,y) set_16(x,y)
+#define set_32_sl(x,y) set_32(x,y)
+
+#endif
+
+/*
* This patches the boot sector and the beginning of ldlinux.sys
* based on an ldlinux.sys sector map passed in. Typically this is
* handled by writing ldlinux.sys, mapping it, and then overwrite it
* an OS which does block reallocation, then overwrite it with
* direct access since the location is known.
*
- * Return 0 if successful, otherwise -1.
+ * Returns the number of modified bytes in ldlinux.sys if successful,
+ * otherwise -1.
*/
int syslinux_patch(const uint32_t *sectors, int nsectors,
int stupid, int raid_mode)
uint32_t *wp;
int nsect = (syslinux_ldlinux_len+511) >> 9;
uint32_t csum;
- int i, dw, nptrs;
+ int i, dw, nptrs, rv;
if ( nsectors < nsect )
return -1;
set_32(&sbs->NextSector, *sectors++);
/* Search for LDLINUX_MAGIC to find the patch area */
- for (wp = (uint32_t *)syslinux_ldlinux; get_32(wp) != LDLINUX_MAGIC; wp++)
+ for (wp = (uint32_t *)syslinux_ldlinux; get_32_sl(wp) != LDLINUX_MAGIC; wp++)
;
patcharea = (struct patch_area *)wp;
/* Set up the totals */
dw = syslinux_ldlinux_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16(&patcharea->data_sectors, nsect); /* Not including ADVs */
- set_16(&patcharea->adv_sectors, 0); /* ADVs not supported yet */
- set_32(&patcharea->dwords, dw);
- set_32(&patcharea->currentdir, 0);
+ set_16_sl(&patcharea->data_sectors, nsect); /* Not including ADVs */
+ set_16_sl(&patcharea->adv_sectors, 0); /* ADVs not supported yet */
+ set_32_sl(&patcharea->dwords, dw);
+ set_32_sl(&patcharea->currentdir, 0);
/* Set the sector pointers */
- wp = (uint32_t *)((char *)syslinux_ldlinux+get_16(&patcharea->secptroffset));
- nptrs = get_16(&patcharea->secptrcnt);
+ wp = (uint32_t *)((char *)syslinux_ldlinux+get_16_sl(&patcharea->secptroffset));
+ nptrs = get_16_sl(&patcharea->secptrcnt);
+
+ while (nsect--) {
+ set_32_sl(wp++, *sectors++);
+ nptrs--;
+ }
+ while (nptrs--)
+ set_32_sl(wp++, 0);
- memset(wp, 0, nptrs*4);
- while ( nsect-- )
- set_32(wp++, *sectors++);
+ rv = (char *)wp - (char *)syslinux_ldlinux;
/* Now produce a checksum */
- set_32(&patcharea->checksum, 0);
+ set_32_sl(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
for (i = 0, wp = (uint32_t *)syslinux_ldlinux; i < dw; i++, wp++)
- csum -= get_32(wp); /* Negative checksum */
+ csum -= get_32_sl(wp); /* Negative checksum */
- set_32(&patcharea->checksum, csum);
+ set_32_sl(&patcharea->checksum, csum);
- return 0;
+ return rv;
}
#include <sys/ioctl.h>
#include <linux/fs.h> /* FIGETBSZ, FIBMAP */
-#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES, SECTOR_* */
+#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */
#ifndef FAT_IOCTL_SET_ATTRIBUTES
# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t)
#endif
+#undef SECTOR_SIZE
+#undef SECTOR_BITS
#include <paths.h>
#ifndef _PATH_MOUNT
char mntname[128];
char *ldlinux_name, **argp, *opt;
const char *subdir = NULL;
- uint32_t sectors[65]; /* 65 is maximum possible */
+ uint32_t *sectors;
+ int ldlinux_sectors;
int nsectors = 0;
const char *errmsg;
int mnt_cookie;
+ int patch_sectors;
+ int i;
int force = 0; /* -f (force) option */
int stupid = 0; /* -s (stupid) option */
/*
* Create a block map.
*/
+ ldlinux_sectors = (syslinux_ldlinux_len+SECTOR_SIZE-1) >> SECTOR_BITS;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
nsectors = make_block_map(sectors, syslinux_ldlinux_len, dev_fd, fd);
close(fd);
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_BITS;
/*
- * Write the now-patched first sector of ldlinux.sys
+ * Write the now-patched first sectors of ldlinux.sys
*/
- xpwrite(dev_fd, syslinux_ldlinux, SECTOR_SIZE,
- filesystem_offset+((off_t)sectors[0] << SECTOR_BITS));
+ for (i = 0; i < patch_sectors; i++) {
+ xpwrite(dev_fd, syslinux_ldlinux + i*SECTOR_SIZE, SECTOR_SIZE,
+ filesystem_offset+((off_t)sectors[i] << SECTOR_BITS));
+ }
/*
* To finish up, write the boot sector
int mtc_fd;
FILE *mtc, *mtp;
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
int32_t ldlinux_cluster;
int nsectors;
const char *errmsg;
+ int ldlinux_sectors, patch_sectors;
+ int i;
int force = 0; /* -f (force) option */
int stupid = 0; /* -s (stupid) option */
/*
* Now, use libfat to create a block map
*/
+ ldlinux_sectors = (syslinux_ldlinux_len+SECTOR_SIZE-1) >> SECTOR_BITS;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
fs = libfat_open(libfat_xpread, dev_fd);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while ( s && nsectors < 65 ) {
+ while ( s && nsectors < ldlinux_sectors ) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);
libfat_close(fs);
/* Patch ldlinux.sys and the boot sector */
- syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode);
+ patch_sectors = (i + 511) >> 9;
- /* Write the now-patched first sector of ldlinux.sys */
- xpwrite(dev_fd, syslinux_ldlinux, 512,
- filesystem_offset + ((off_t)sectors[0] << 9));
+ /* Write the now-patched first sectors of ldlinux.sys */
+ for (i = 0; i < patch_sectors; i++) {
+ xpwrite(dev_fd, syslinux_ldlinux + i*512, 512,
+ filesystem_offset + ((off_t)sectors[i] << 9));
+ }
/* Move ldlinux.sys to the desired location */
if (subdir) {
#include <winioctl.h>
-#define SECTOR_SIZE 512
#define PART_TABLE 0x1be
#define PART_SIZE 0x10
#define PART_COUNT 4
static char ldlinux_name[] = "?:\\ldlinux.sys" ;
const char *errmsg;
struct libfat_filesystem *fs;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
+ libfat_sector_t s, *secp;
+ libfat_sector_t *sectors;
+ int ldlinux_sectors;
uint32_t ldlinux_cluster;
int nsectors;
const char *bootsecfile = NULL;
}
/* Map the file (is there a better way to do this?) */
+ ldlinux_sectors = (syslinux_ldlinux_len+SECTOR_SIZE-1) >> SECTOR_BITS;
+ sectors = calloc(ldlinux_sectors, sizeof *sectors);
fs = libfat_open(libfat_readfile, (intptr_t)d_handle);
ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
secp = sectors;
nsectors = 0;
s = libfat_clustertosector(fs, ldlinux_cluster);
- while ( s && nsectors < 65 ) {
+ while ( s && nsectors < ldlinux_sectors ) {
*secp++ = s;
nsectors++;
s = libfat_nextsector(fs, s);