aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dos/Makefile7
-rw-r--r--dos/com16.ld5
-rw-r--r--dos/int2526.S76
-rw-r--r--dos/mystuff.h10
-rw-r--r--dos/syslinux.c62
5 files changed, 119 insertions, 41 deletions
diff --git a/dos/Makefile b/dos/Makefile
index 56d2e076..9d8ce33c 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -30,7 +30,8 @@ SRCS = syslinux.c \
../libinstaller/mbr_bin.c \
$(wildcard ../libfat/*.c)
OBJS = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
-LIBOBJS = conio.o memcpy.o memset.o skipatou.o atou.o malloc.o free.o \
+LIBOBJS = int2526.o conio.o memcpy.o memset.o skipatou.o atou.o \
+ malloc.o free.o \
argv.o printf.o __divdi3.o __udivmoddi4.o
VPATH = .:../libfat:../libinstaller
@@ -49,8 +50,8 @@ spotless: clean
installer:
-syslinux.elf: $(OBJS) libcom.a
- $(LD) $(LDFLAGS) -o $@ $^
+syslinux.elf: $(OBJS) libcom.a com16.ld
+ $(LD) $(LDFLAGS) -o $@ $(filter-out %.ld,$^)
libcom.a: $(LIBOBJS)
-rm -f $@
diff --git a/dos/com16.ld b/dos/com16.ld
index 08a1e95e..5f82b73a 100644
--- a/dos/com16.ld
+++ b/dos/com16.ld
@@ -123,5 +123,8 @@ SECTIONS
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
- /DISCARD/ : { *(.note.GNU-stack) }
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.eh_frame)
+ }
}
diff --git a/dos/int2526.S b/dos/int2526.S
new file mode 100644
index 00000000..bcb7707e
--- /dev/null
+++ b/dos/int2526.S
@@ -0,0 +1,76 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * int 0x25 and 0x26 direct sector access
+ *
+ * Use assembly wrapper functions for these system calls, since unlike
+ * int 0x21 calls they are "dirty" and can destroy unrelated registers.
+ *
+ * NOTE: these all assume the data buffer is in the data segment, i.e.
+ * %ds == %es == dio.bufseg.
+ *
+ * Usage: int int25_read_sector(drive, dio)
+ * Usage: int int26_write_sector(drive, dio)
+ */
+
+ .code16gcc
+ .text
+
+ .globl int25_read_sector
+ .type int25_read_sector, @function
+int25_read_sector:
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ decw %ax /* AL = drive number (0 = A:) */
+ movw %dx, %bx /* BX = dio structure */
+ movw 6(%bx), %dx /* DX = data buffer */
+ movw $-1, %cx
+ int $0x25
+ jc 1f
+ xorw %ax, %ax /* Error code: 0 = no error */
+1:
+ popfw
+ movzwl %ax, %eax
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ebp
+ retl
+
+ .globl int26_write_sector
+ .type int26_write_sector, @function
+int26_write_sector:
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ decw %ax /* AL = drive number (0 = A:) */
+ movw %dx, %bx /* BX = dio structure */
+ movw 6(%bx), %dx /* DX = data buffer */
+ movw $-1, %cx
+ int $0x26
+ jc 1f
+ xorw %ax, %ax /* Error code: 0 = no error */
+1:
+ popfw
+ movzwl %ax, %eax
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ebp
+ retl
diff --git a/dos/mystuff.h b/dos/mystuff.h
index fbf4e75b..25344413 100644
--- a/dos/mystuff.h
+++ b/dos/mystuff.h
@@ -1,6 +1,8 @@
#ifndef MYSTUFF_H
#define MYSTUFF_H
+#include <inttypes.h>
+
#define NULL ((void *)0)
unsigned int skip_atou(const char **s);
@@ -11,4 +13,12 @@ static inline int isdigit(int ch)
return (ch >= '0') && (ch <= '9');
}
+struct diskio {
+ uint32_t startsector;
+ uint16_t sectors;
+ uint16_t bufoffs, bufseg;
+} __attribute__ ((packed));
+int int25_read_sector(unsigned char drive, struct diskio *dio);
+int int26_write_sector(unsigned char drive, struct diskio *dio);
+
#endif /* MYSTUFF_H */
diff --git a/dos/syslinux.c b/dos/syslinux.c
index 1cdf418b..650c48f6 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -152,15 +152,8 @@ uint16_t data_segment(void)
return ds;
}
-struct diskio {
- uint32_t startsector;
- uint16_t sectors;
- uint16_t bufoffs, bufseg;
-} __attribute__ ((packed));
-
void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
{
- uint8_t err;
uint16_t errnum;
struct diskio dio;
@@ -171,21 +164,19 @@ void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
dio.bufoffs = (uintptr_t) buf;
dio.bufseg = data_segment();
- if (dos_version >= 0x0710) {
- asm volatile("int $0x21 ; setc %0"
- : "=bcdm" (err), "=a" (errnum)
- : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
- "S" (1), "m" (dio)
- : "memory");
- } else {
- asm volatile("int $0x26 ; setc %0 ; popfw"
- : "=bcdm" (err), "=a" (errnum)
- : "a" (drive-1), "b" (&dio), "c" (-1), "d" (buf),
- "m" (dio)
- : "esi", "memory");
- }
+ /* Try FAT32-aware system call first */
+ asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
+ "1:"
+ : "=a" (errnum)
+ : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
+ "S" (1), "m" (dio)
+ : "memory");
- if (err) {
+ /* If not supported, try the legacy system call (int2526.S) */
+ if (errnum == 0x0001)
+ errnum = int26_write_sector(drive, &dio);
+
+ if (errnum) {
dprintf("rv = %04x\n", errnum);
die("sector write error");
}
@@ -193,7 +184,6 @@ void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
void read_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
{
- uint8_t err;
uint16_t errnum;
struct diskio dio;
@@ -204,20 +194,18 @@ void read_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
dio.bufoffs = (uintptr_t) buf;
dio.bufseg = data_segment();
- if (dos_version >= 0x0710) {
- asm volatile("int $0x21 ; setc %0"
- : "=bcdm" (err), "=a" (errnum)
- : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
- "S" (0), "m" (dio));
- } else {
- asm volatile("int $0x25 ; setc %0 ; popfw"
- : "=bcdm" (err), "=a" (errnum)
- : "a" (drive-1), "b" (&dio), "c" (-1), "d" (buf),
- "m" (dio)
- : "esi");
- }
+ /* Try FAT32-aware system call first */
+ asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
+ "1:"
+ : "=a" (errnum)
+ : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
+ "S" (0), "m" (dio));
- if (err) {
+ /* If not supported, try the legacy system call (int2526.S) */
+ if (errnum == 0x0001)
+ errnum = int25_read_sector(drive, &dio);
+
+ if (errnum) {
dprintf("rv = %04x\n", errnum);
die("sector read error");
}
@@ -411,7 +399,7 @@ static int do_lock(uint8_t level)
uint8_t err;
#if 0
/* DOS 7.10 = Win95 OSR2 = first version with FAT32 */
- uint16_t lock_call = (dos_version >= 0x0710) ? 0x484A : 0x084A;
+ uint16_t lock_call = (dos_version >= 0x070a) ? 0x484A : 0x084A;
#else
uint16_t lock_call = 0x084A; /* MSDN says this is OK for all filesystems */
#endif
@@ -486,7 +474,7 @@ void unlock_device(int level)
#if 0
/* DOS 7.10 = Win95 OSR2 = first version with FAT32 */
- unlock_call = (dos_version >= 0x0710) ? 0x486A : 0x086A;
+ unlock_call = (dos_version >= 0x070a) ? 0x486A : 0x086A;
#else
unlock_call = 0x086A; /* MSDN says this is OK for all filesystems */
#endif