diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-11-13 19:18:57 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-11-13 19:18:57 -0800 |
commit | 56e6eae7f4af352aaf33840fd652474098486ea6 (patch) | |
tree | 4aa99c521212075adc71767b2bf7687aab99a09a | |
parent | ccbdc9f17eabb64aa772eefa7b7cb3a3aaeb5658 (diff) | |
parent | fcd383ae04ef0382ad93b83ba82112104aa986e0 (diff) | |
download | syslinux-56e6eae7f4af352aaf33840fd652474098486ea6.tar.gz |
Merge branch 'master' of ssh://terminus.zytor.com/pub/git/syslinux/syslinux
-rw-r--r-- | dos/Makefile | 7 | ||||
-rw-r--r-- | dos/com16.ld | 5 | ||||
-rw-r--r-- | dos/int2526.S | 76 | ||||
-rw-r--r-- | dos/mystuff.h | 10 | ||||
-rw-r--r-- | dos/syslinux.c | 62 |
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 |