(2006-08-06) rescue-bootcd
This commit is contained in:
27
extra/syslinux-3.09/memdisk/.depend
Normal file
27
extra/syslinux-3.09/memdisk/.depend
Normal file
@@ -0,0 +1,27 @@
|
||||
conio.s: conio.c ../com32/include/stdint.h memdisk.h \
|
||||
../com32/include/com32.h ../com32/include/klibc/compiler.h conio.h \
|
||||
../com32/include/stddef.h ../com32/include/bitsize/stddef.h \
|
||||
../com32/include/stdarg.h
|
||||
e820func.s: e820func.c ../com32/include/stdint.h memdisk.h \
|
||||
../com32/include/com32.h ../com32/include/klibc/compiler.h e820.h
|
||||
e820test.s: e820test.c ../com32/include/string.h \
|
||||
../com32/include/klibc/extern.h ../com32/include/stddef.h \
|
||||
../com32/include/bitsize/stddef.h ../com32/include/stdio.h \
|
||||
../com32/include/stdarg.h ../com32/include/stdlib.h \
|
||||
../com32/include/klibc/compiler.h ../com32/include/inttypes.h \
|
||||
../com32/include/stdint.h e820.h
|
||||
inflate.s: inflate.c
|
||||
msetup.s: msetup.c ../com32/include/stdint.h memdisk.h \
|
||||
../com32/include/com32.h ../com32/include/klibc/compiler.h conio.h \
|
||||
../com32/include/stddef.h ../com32/include/bitsize/stddef.h \
|
||||
../com32/include/stdarg.h e820.h
|
||||
setup.s: setup.c ../com32/include/stdint.h e820.h conio.h \
|
||||
../com32/include/stddef.h ../com32/include/bitsize/stddef.h \
|
||||
../com32/include/stdarg.h version.h memdisk.h ../com32/include/com32.h \
|
||||
../com32/include/klibc/compiler.h
|
||||
unzip.s: unzip.c ../com32/include/stdint.h memdisk.h \
|
||||
../com32/include/com32.h ../com32/include/klibc/compiler.h conio.h \
|
||||
../com32/include/stddef.h ../com32/include/bitsize/stddef.h \
|
||||
../com32/include/stdarg.h inflate.c
|
||||
memdisk.bin: memdisk.asm
|
||||
memdisk16.bin: memdisk16.asm
|
||||
121
extra/syslinux-3.09/memdisk/Makefile
Normal file
121
extra/syslinux-3.09/memdisk/Makefile
Normal file
@@ -0,0 +1,121 @@
|
||||
#ident "$Id: Makefile,v 1.29 2004/12/29 01:58:02 hpa Exp $"
|
||||
## -----------------------------------------------------------------------
|
||||
##
|
||||
## Copyright 2001-2004 H. Peter Anvin - All Rights Reserved
|
||||
##
|
||||
## 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.
|
||||
##
|
||||
## -----------------------------------------------------------------------
|
||||
|
||||
VERSION := $(shell cat ../version)
|
||||
|
||||
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
|
||||
then echo $(1); else echo $(2); fi)
|
||||
|
||||
M32 := $(call gcc_ok,-m32,)
|
||||
ALIGN := $(call gcc_ok,-falign-functions=0 -falign-jumps=0 -falign-loops=0,-malign-functions=0 -malign-jumps=0 -malign-loops=0)
|
||||
|
||||
CC = gcc $(M32)
|
||||
CFLAGS = -g -W -Wall -Wno-sign-compare \
|
||||
-Os -fomit-frame-pointer -march=i386 $(ALIGN) \
|
||||
-DVERSION='"$(VERSION)"' -DDATE='"$(DATE)"'
|
||||
LDFLAGS = -g
|
||||
INCLUDE = -I../com32/include
|
||||
LD = ld -m elf_i386
|
||||
NASM = nasm -O99
|
||||
NFLAGS = -dVERSION='"$(VERSION)"' -dDATE='"$(DATE)"'
|
||||
NINCLUDE =
|
||||
OBJCOPY = objcopy
|
||||
PERL = perl
|
||||
|
||||
# Important: init.o16 must be first!!
|
||||
OBJS16 = init.o16 init32.o
|
||||
OBJS32 = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
|
||||
unzip.o memdisk.o
|
||||
|
||||
CSRC = setup.c msetup.c e820func.c conio.c unzip.c
|
||||
SSRC =
|
||||
NASMSRC = memdisk.asm memdisk16.asm
|
||||
|
||||
all: memdisk e820test
|
||||
|
||||
# tidy, clean removes everything except the final binary
|
||||
tidy:
|
||||
rm -f *.o *.s *.o16 *.s16 *.bin *.lst *.elf e820test
|
||||
|
||||
clean: tidy
|
||||
|
||||
# spotless also removes the product binary
|
||||
spotless: clean
|
||||
rm -f memdisk .depend
|
||||
|
||||
%.o: %.asm
|
||||
$(NASM) $(NFLAGS) -f elf -l $*.lst -o $@ $<
|
||||
|
||||
%.o: %.s
|
||||
$(CC) -x assembler -c -o $@ $<
|
||||
|
||||
%.o16: %.s16
|
||||
$(CC) -x assembler -c -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
%.s16: %.s
|
||||
echo '.code16gcc' | cat - $< > $@
|
||||
|
||||
%.s: %.S
|
||||
$(CC) -x c $(INCLUDE) $(CFLAGS) -traditional -E -o $@ $<
|
||||
|
||||
%.s16: %.S16
|
||||
$(CC) -x c $(INCLUDE) $(CFLAGS) -traditional -E -o $@ $<
|
||||
|
||||
%.s: %.c
|
||||
$(CC) $(INCLUDE) $(CFLAGS) -S -o $@ $<
|
||||
|
||||
%.i: %.c
|
||||
$(CC) $(INCLUDE) $(CFLAGS) -E -o $@ $<
|
||||
|
||||
# Cancel default rule
|
||||
%.o: %.c
|
||||
|
||||
%.bin: %.asm
|
||||
$(NASM) -f bin $(NFLAGS) $(NINCLUDE) -o $@ -l $*.lst $<
|
||||
|
||||
memdisk16.elf: $(OBJS16)
|
||||
$(LD) -Ttext 0 -o $@ $^
|
||||
|
||||
memdisk32.elf: $(OBJS32)
|
||||
$(LD) -Ttext 0x100000 -o $@ $^
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
memdisk: memdisk16.bin memdisk32.bin postprocess.pl
|
||||
$(PERL) postprocess.pl $@ memdisk16.bin memdisk32.bin
|
||||
|
||||
e820test: e820func.o msetup.o e820test.o memdisk.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
memdisk.o: memdisk.bin
|
||||
$(LD) -r -b binary -o $@ $<
|
||||
|
||||
.depend:
|
||||
rm -f .depend
|
||||
for csrc in *.c ; do $(CC) $(INCLUDE) -MM $$csrc | sed -e 's/\.o/\.s/' >> .depend ; done
|
||||
for ssrc in $(SSRC) ; do $(CC) $(INCLUDE) -x c -traditional -MM $$ssrc | sed -e 's/\.S16\.o/\.o16/' >> .depend ; done
|
||||
for nsrc in $(NASMSRC) ; do $(NASM) -DDEPEND $(NINCLUDE) -o `echo $$nsrc | sed -e 's/\.asm/\.bin/'` -M $$nsrc >> .depend ; done
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
$(MAKE) .depend
|
||||
|
||||
# This file contains the version number, so add a dependency for it
|
||||
setup.s: ../version
|
||||
|
||||
# Include dependencies file
|
||||
include .depend
|
||||
365
extra/syslinux-3.09/memdisk/conio.c
Normal file
365
extra/syslinux-3.09/memdisk/conio.c
Normal file
@@ -0,0 +1,365 @@
|
||||
#ident "$Id: conio.c,v 1.8 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* conio.c
|
||||
*
|
||||
* Output to the screen
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memdisk.h"
|
||||
#include "conio.h"
|
||||
|
||||
int putchar(int ch)
|
||||
{
|
||||
com32sys_t regs;
|
||||
|
||||
if ( ch == '\n' ) {
|
||||
/* \n -> \r\n */
|
||||
putchar('\r');
|
||||
}
|
||||
|
||||
regs.eax.w[0] = 0x0e00|(ch&0xff);
|
||||
syscall(0x10, ®s, NULL);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
int puts(const char *s)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ( *s ) {
|
||||
putchar(*s);
|
||||
count++;
|
||||
s++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Oh, it's a waste of space, but oh-so-yummy for debugging. It's just
|
||||
* initialization code anyway, so it doesn't take up space when we're
|
||||
* actually running. This version of printf() does not include 64-bit
|
||||
* support. "Live with it."
|
||||
*
|
||||
* Most of this code was shamelessly snarfed from the Linux kernel, then
|
||||
* modified.
|
||||
*/
|
||||
|
||||
static inline int
|
||||
isdigit(int ch)
|
||||
{
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
static int skip_atoi(const char **s)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (isdigit(**s))
|
||||
i = i*10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int atou(const char *s)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while (isdigit(*s))
|
||||
i = i*10 + (*s++ - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
static int strnlen(const char *s, int maxlen)
|
||||
{
|
||||
const char *es = s;
|
||||
while ( *es && maxlen ) {
|
||||
es++; maxlen--;
|
||||
}
|
||||
|
||||
return (es-s);
|
||||
}
|
||||
|
||||
#define ZEROPAD 1 /* pad with zero */
|
||||
#define SIGN 2 /* unsigned/signed long */
|
||||
#define PLUS 4 /* show plus */
|
||||
#define SPACE 8 /* space if plus */
|
||||
#define LEFT 16 /* left justified */
|
||||
#define SPECIAL 32 /* 0x */
|
||||
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
|
||||
|
||||
#define do_div(n,base) ({ \
|
||||
int __res; \
|
||||
__res = ((unsigned long) n) % (unsigned) base; \
|
||||
n = ((unsigned long) n) / (unsigned) base; \
|
||||
__res; })
|
||||
|
||||
static char * number(char * str, long num, int base, int size, int precision
|
||||
,int type)
|
||||
{
|
||||
char c,sign,tmp[66];
|
||||
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
int i;
|
||||
|
||||
if (type & LARGE)
|
||||
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36)
|
||||
return 0;
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN) {
|
||||
if (num < 0) {
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
} else if (type & PLUS) {
|
||||
sign = '+';
|
||||
size--;
|
||||
} else if (type & SPACE) {
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
if (type & SPECIAL) {
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
i = 0;
|
||||
if (num == 0)
|
||||
tmp[i++]='0';
|
||||
else while (num != 0)
|
||||
tmp[i++] = digits[do_div(num,base)];
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
if (!(type&(ZEROPAD+LEFT)))
|
||||
while(size-->0)
|
||||
*str++ = ' ';
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
if (type & SPECIAL) {
|
||||
if (base==8)
|
||||
*str++ = '0';
|
||||
else if (base==16) {
|
||||
*str++ = '0';
|
||||
*str++ = digits[33];
|
||||
}
|
||||
}
|
||||
if (!(type & LEFT))
|
||||
while (size-- > 0)
|
||||
*str++ = c;
|
||||
while (i < precision--)
|
||||
*str++ = '0';
|
||||
while (i-- > 0)
|
||||
*str++ = tmp[i];
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Forward decl. needed for IP address printing stuff... */
|
||||
int sprintf(char * buf, const char *fmt, ...);
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
unsigned long num;
|
||||
int i, base;
|
||||
char * str;
|
||||
const char *s;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
|
||||
int field_width; /* width of output field */
|
||||
int precision; /* min. # of digits for integers; max
|
||||
number of chars for from string */
|
||||
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||
|
||||
for (str=buf ; *fmt ; ++fmt) {
|
||||
if (*fmt != '%') {
|
||||
*str++ = *fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process flags */
|
||||
flags = 0;
|
||||
repeat:
|
||||
++fmt; /* this also skips first '%' */
|
||||
switch (*fmt) {
|
||||
case '-': flags |= LEFT; goto repeat;
|
||||
case '+': flags |= PLUS; goto repeat;
|
||||
case ' ': flags |= SPACE; goto repeat;
|
||||
case '#': flags |= SPECIAL; goto repeat;
|
||||
case '0': flags |= ZEROPAD; goto repeat;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (isdigit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0) {
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the precision */
|
||||
precision = -1;
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
if (isdigit(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
/* get the conversion qualifier */
|
||||
qualifier = -1;
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
}
|
||||
|
||||
/* default base */
|
||||
base = 10;
|
||||
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
if (!(flags & LEFT))
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
*str++ = (unsigned char) va_arg(args, int);
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
len = strnlen(s, precision);
|
||||
|
||||
if (!(flags & LEFT))
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
for (i = 0; i < len; ++i)
|
||||
*str++ = *s++;
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1) {
|
||||
field_width = 2*sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
str = number(str,
|
||||
(unsigned long) va_arg(args, void *), 16,
|
||||
field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
|
||||
case 'n':
|
||||
if (qualifier == 'l') {
|
||||
long * ip = va_arg(args, long *);
|
||||
*ip = (str - buf);
|
||||
} else {
|
||||
int * ip = va_arg(args, int *);
|
||||
*ip = (str - buf);
|
||||
}
|
||||
continue;
|
||||
|
||||
case '%':
|
||||
*str++ = '%';
|
||||
continue;
|
||||
|
||||
/* integer number formats - set up the flags and "break" */
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= LARGE;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
*str++ = '%';
|
||||
if (*fmt)
|
||||
*str++ = *fmt;
|
||||
else
|
||||
--fmt;
|
||||
continue;
|
||||
}
|
||||
if (qualifier == 'l')
|
||||
num = va_arg(args, unsigned long);
|
||||
else if (qualifier == 'h') {
|
||||
num = (unsigned short) va_arg(args, int);
|
||||
if (flags & SIGN)
|
||||
num = (short) num;
|
||||
} else if (flags & SIGN)
|
||||
num = va_arg(args, int);
|
||||
else
|
||||
num = va_arg(args, unsigned int);
|
||||
str = number(str, num, base, field_width, precision, flags);
|
||||
}
|
||||
*str = '\0';
|
||||
return str-buf;
|
||||
}
|
||||
|
||||
int sprintf(char * buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i=vsprintf(buf,fmt,args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
int printf(const char *fmt, ...)
|
||||
{
|
||||
char printf_buf[1024];
|
||||
va_list args;
|
||||
int printed;
|
||||
|
||||
va_start(args, fmt);
|
||||
printed = vsprintf(printf_buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
puts(printf_buf);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
32
extra/syslinux-3.09/memdisk/conio.h
Normal file
32
extra/syslinux-3.09/memdisk/conio.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ident "$Id: conio.h,v 1.5 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* conio.h
|
||||
*
|
||||
* Limited console I/O
|
||||
*/
|
||||
|
||||
#ifndef CONIO_H
|
||||
#define CONIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int putchar(int);
|
||||
int puts(const char *);
|
||||
int printf(const char *, ...);
|
||||
unsigned int atou(const char *);
|
||||
|
||||
#endif
|
||||
BIN
extra/syslinux-3.09/memdisk/conio.o
Normal file
BIN
extra/syslinux-3.09/memdisk/conio.o
Normal file
Binary file not shown.
2995
extra/syslinux-3.09/memdisk/conio.s
Normal file
2995
extra/syslinux-3.09/memdisk/conio.s
Normal file
File diff suppressed because it is too large
Load Diff
34
extra/syslinux-3.09/memdisk/e820.h
Normal file
34
extra/syslinux-3.09/memdisk/e820.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ident "$Id: e820.h,v 1.4 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* e820.h
|
||||
*
|
||||
* Common routines for e820 memory map management
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct e820range {
|
||||
uint64_t start;
|
||||
uint32_t type;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct e820range ranges[];
|
||||
extern int nranges;
|
||||
extern uint32_t dos_mem, low_mem, high_mem;
|
||||
|
||||
extern void e820map_init(void);
|
||||
extern void insertrange(uint64_t, uint64_t, uint32_t);
|
||||
extern void get_mem(void);
|
||||
extern void parse_mem(void);
|
||||
13
extra/syslinux-3.09/memdisk/e820data
Normal file
13
extra/syslinux-3.09/memdisk/e820data
Normal file
@@ -0,0 +1,13 @@
|
||||
0000000000000000 000000000009bc00 1
|
||||
000000000009bc00 0000000000004400 2
|
||||
00000000000e9800 0000000000016800 2
|
||||
0000000000100000 0000000006ee0000 1
|
||||
0000000006fe0000 000000000000fc00 3
|
||||
0000000006fefc00 0000000000000400 4
|
||||
0000000006ff0000 0000000000002000 2
|
||||
0000000006ff2000 000000000000e000 1
|
||||
0000000007000000 0000000000100000 2
|
||||
00000000fff00000 0000000000100000 2
|
||||
|
||||
0000000000586000 0000000000168000 2
|
||||
000000000009ba00 0000000000000200 2
|
||||
105
extra/syslinux-3.09/memdisk/e820func.c
Normal file
105
extra/syslinux-3.09/memdisk/e820func.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#ident "$Id: e820func.c,v 1.7 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* e820func.c
|
||||
*
|
||||
* E820 range database manager
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memdisk.h" /* For memset() */
|
||||
#include "e820.h"
|
||||
|
||||
#define MAXRANGES 64
|
||||
/* All of memory starts out as one range of "indeterminate" type */
|
||||
struct e820range ranges[MAXRANGES];
|
||||
int nranges;
|
||||
|
||||
|
||||
void e820map_init(void)
|
||||
{
|
||||
memset(ranges, 0, sizeof(ranges));
|
||||
nranges = 1;
|
||||
ranges[1].type = -1;
|
||||
}
|
||||
|
||||
static void insertrange_at(int where, uint64_t start, uint32_t type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = nranges ; i > where ; i-- )
|
||||
ranges[i] = ranges[i-1];
|
||||
|
||||
ranges[where].start = start;
|
||||
ranges[where].type = type;
|
||||
|
||||
nranges++;
|
||||
ranges[nranges].start = 0ULL;
|
||||
ranges[nranges].type = (uint32_t)-1;
|
||||
}
|
||||
|
||||
void insertrange(uint64_t start, uint64_t len, uint32_t type)
|
||||
{
|
||||
uint64_t last;
|
||||
uint32_t oldtype;
|
||||
int i, j;
|
||||
|
||||
/* Remove this to make len == 0 mean all of memory */
|
||||
if ( len == 0 )
|
||||
return; /* Nothing to insert */
|
||||
|
||||
last = start+len-1; /* May roll over */
|
||||
|
||||
i = 0;
|
||||
oldtype = -2;
|
||||
while ( start > ranges[i].start && ranges[i].type != -1 ) {
|
||||
oldtype = ranges[i].type;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Consider the replacement policy. This current one is "overwrite." */
|
||||
|
||||
if ( start < ranges[i].start || ranges[i].type == -1 )
|
||||
insertrange_at(i++, start, type);
|
||||
|
||||
while ( i == 0 || last > ranges[i].start-1 ) {
|
||||
oldtype = ranges[i].type;
|
||||
ranges[i].type = type;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( last < ranges[i].start-1 )
|
||||
insertrange_at(i, last+1, oldtype);
|
||||
|
||||
/* Now the map is correct, but quite possibly not optimal. Scan the
|
||||
map for ranges which are redundant and remove them. */
|
||||
i = j = 1;
|
||||
oldtype = ranges[0].type;
|
||||
while ( i < nranges ) {
|
||||
if ( ranges[i].type == oldtype ) {
|
||||
i++;
|
||||
} else {
|
||||
oldtype = ranges[i].type;
|
||||
if ( i != j )
|
||||
ranges[j] = ranges[i];
|
||||
i++; j++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i != j ) {
|
||||
ranges[j] = ranges[i]; /* Termination sentinel copy */
|
||||
nranges -= (i-j);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
extra/syslinux-3.09/memdisk/e820func.o
Normal file
BIN
extra/syslinux-3.09/memdisk/e820func.o
Normal file
Binary file not shown.
1436
extra/syslinux-3.09/memdisk/e820func.s
Normal file
1436
extra/syslinux-3.09/memdisk/e820func.s
Normal file
File diff suppressed because it is too large
Load Diff
BIN
extra/syslinux-3.09/memdisk/e820test
Executable file
BIN
extra/syslinux-3.09/memdisk/e820test
Executable file
Binary file not shown.
89
extra/syslinux-3.09/memdisk/e820test.c
Normal file
89
extra/syslinux-3.09/memdisk/e820test.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#ident "$Id: e820test.c,v 1.8 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2003 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* e820hack.c
|
||||
*
|
||||
* Test of INT 15:E820 canonicalization/manipulation routine
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include "e820.h"
|
||||
|
||||
void *sys_bounce; /* Dummy */
|
||||
|
||||
extern void parse_mem(void);
|
||||
extern uint32_t dos_mem, low_mem, high_mem;
|
||||
|
||||
void __attribute__((noreturn)) die(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void printranges(void) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < nranges ; i++ ) {
|
||||
printf("%016llx %016llx %d\n",
|
||||
ranges[i].start,
|
||||
ranges[i+1].start - ranges[i].start,
|
||||
ranges[i].type);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint64_t start, len;
|
||||
uint32_t type;
|
||||
char line[BUFSIZ], *p;
|
||||
|
||||
e820map_init();
|
||||
printranges();
|
||||
|
||||
while ( fgets(line, BUFSIZ, stdin) ) {
|
||||
p = strchr(line, ':');
|
||||
p = p ? p+1 : line;
|
||||
if ( sscanf(p, " %llx %llx %d", &start, &len, &type) == 3 ) {
|
||||
putchar('\n');
|
||||
printf("%016llx %016llx %d <-\n", start, len, type);
|
||||
putchar('\n');
|
||||
insertrange(start, len, type);
|
||||
printranges();
|
||||
}
|
||||
}
|
||||
|
||||
parse_mem();
|
||||
|
||||
putchar('\n');
|
||||
printf("DOS mem = %#10x (%u K)\n", dos_mem, dos_mem >> 10);
|
||||
printf("Low mem = %#10x (%u K)\n", low_mem, low_mem >> 10);
|
||||
printf("High mem = %#10x (%u K)\n", high_mem, high_mem >> 10);
|
||||
putchar('\n');
|
||||
|
||||
/* Now, steal a chunk (2K) of DOS memory and make sure it registered OK */
|
||||
insertrange(dos_mem-2048, 2048, 2); /* Type 2 = reserved */
|
||||
|
||||
printranges();
|
||||
parse_mem();
|
||||
|
||||
putchar('\n');
|
||||
printf("DOS mem = %#10x (%u K)\n", dos_mem, dos_mem >> 10);
|
||||
printf("Low mem = %#10x (%u K)\n", low_mem, low_mem >> 10);
|
||||
printf("High mem = %#10x (%u K)\n", high_mem, high_mem >> 10);
|
||||
putchar('\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
extra/syslinux-3.09/memdisk/e820test.o
Normal file
BIN
extra/syslinux-3.09/memdisk/e820test.o
Normal file
Binary file not shown.
1469
extra/syslinux-3.09/memdisk/e820test.s
Normal file
1469
extra/syslinux-3.09/memdisk/e820test.s
Normal file
File diff suppressed because it is too large
Load Diff
1083
extra/syslinux-3.09/memdisk/inflate.c
Normal file
1083
extra/syslinux-3.09/memdisk/inflate.c
Normal file
File diff suppressed because it is too large
Load Diff
29
extra/syslinux-3.09/memdisk/memcpy.S
Normal file
29
extra/syslinux-3.09/memdisk/memcpy.S
Normal file
@@ -0,0 +1,29 @@
|
||||
# $Id: memcpy.S,v 1.1 2003/04/15 19:31:04 hpa Exp $
|
||||
#
|
||||
# memcpy.S
|
||||
#
|
||||
# Simple memcpy() implementation
|
||||
#
|
||||
|
||||
.text
|
||||
.globl memcpy
|
||||
.type memcpy, @function
|
||||
memcpy:
|
||||
cld
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
movl 12(%esp),%edi
|
||||
movl 16(%esp),%esi
|
||||
movl 20(%esp),%eax
|
||||
movl %eax,%ecx
|
||||
shrl $2,%ecx
|
||||
rep ; movsl
|
||||
movl %eax,%ecx
|
||||
andl $3,%ecx
|
||||
rep ; movsb
|
||||
movl 12(%esp),%eax
|
||||
popl %esi
|
||||
popl %edi
|
||||
ret
|
||||
|
||||
.size memcpy,.-memcpy
|
||||
BIN
extra/syslinux-3.09/memdisk/memcpy.o
Normal file
BIN
extra/syslinux-3.09/memdisk/memcpy.o
Normal file
Binary file not shown.
BIN
extra/syslinux-3.09/memdisk/memdisk
Normal file
BIN
extra/syslinux-3.09/memdisk/memdisk
Normal file
Binary file not shown.
759
extra/syslinux-3.09/memdisk/memdisk.asm
Normal file
759
extra/syslinux-3.09/memdisk/memdisk.asm
Normal file
@@ -0,0 +1,759 @@
|
||||
; -*- fundamental -*- (asm-mode sucks)
|
||||
; $Id: memdisk.asm,v 1.29 2005/04/29 06:08:03 hpa Exp $
|
||||
; ****************************************************************************
|
||||
;
|
||||
; memdisk.asm
|
||||
;
|
||||
; A program to emulate an INT 13h disk BIOS from a "disk" in extended
|
||||
; memory.
|
||||
;
|
||||
; Copyright (C) 2001-2004 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.
|
||||
;
|
||||
; ****************************************************************************
|
||||
|
||||
%ifndef DEPEND
|
||||
%include "../version.gen"
|
||||
%endif
|
||||
|
||||
; %define DEBUG_TRACERS ; Uncomment to get debugging tracers
|
||||
|
||||
%ifdef DEBUG_TRACERS
|
||||
|
||||
%macro TRACER 1
|
||||
call debug_tracer
|
||||
db %1
|
||||
%endmacro
|
||||
|
||||
%else ; DEBUG_TRACERS
|
||||
|
||||
%macro TRACER 1
|
||||
%endmacro
|
||||
|
||||
%endif ; DEBUG_TRACERS
|
||||
|
||||
%define CONFIG_READONLY 0x01
|
||||
%define CONFIG_RAW 0x02
|
||||
%define CONFIG_BIGRAW 0x08 ; MUST be 8!
|
||||
|
||||
org 0h
|
||||
|
||||
%define SECTORSIZE_LG2 9 ; log2(sector size)
|
||||
%define SECTORSIZE (1 << SECTORSIZE_LG2)
|
||||
|
||||
; Parameter registers definition; this is the definition
|
||||
; of the stack frame.
|
||||
%define P_DS word [bp+34]
|
||||
%define P_ES word [bp+32]
|
||||
%define P_EAX dword [bp+28]
|
||||
%define P_HAX word [bp+30]
|
||||
%define P_AX word [bp+28]
|
||||
%define P_AL byte [bp+28]
|
||||
%define P_AH byte [bp+29]
|
||||
%define P_ECX dword [bp+24]
|
||||
%define P_HCX word [bp+26]
|
||||
%define P_CX word [bp+24]
|
||||
%define P_CL byte [bp+24]
|
||||
%define P_CH byte [bp+25]
|
||||
%define P_EDX dword [bp+20]
|
||||
%define P_HDX word [bp+22]
|
||||
%define P_DX word [bp+20]
|
||||
%define P_DL byte [bp+20]
|
||||
%define P_DH byte [bp+21]
|
||||
%define P_EBX dword [bp+16]
|
||||
%define P_HBX word [bp+18]
|
||||
%define P_HBXL byte [bp+18]
|
||||
%define P_BX word [bp+16]
|
||||
%define P_BL byte [bp+16]
|
||||
%define P_BH byte [bp+17]
|
||||
%define P_EBP dword [bp+8]
|
||||
%define P_BP word [bp+8]
|
||||
%define P_ESI dword [bp+4]
|
||||
%define P_SI word [bp+4]
|
||||
%define P_EDI dword [bp]
|
||||
%define P_DI word [bp]
|
||||
|
||||
section .text
|
||||
; These pointers are used by the installer and
|
||||
; must be first in the binary
|
||||
Pointers: dw Int13Start
|
||||
dw Int15Start
|
||||
dw PatchArea
|
||||
dw TotalSize
|
||||
|
||||
Int13Start:
|
||||
; Swap stack
|
||||
mov [cs:Stack],esp
|
||||
mov [cs:SavedAX],ax
|
||||
mov ax,ss
|
||||
mov [cs:Stack+4],ax
|
||||
mov ax,cs
|
||||
mov ss,ax
|
||||
mov sp,[cs:MyStack]
|
||||
|
||||
; See if DL points to our class of device (FD, HD)
|
||||
push dx
|
||||
push dx
|
||||
xor dl,[cs:DriveNo]
|
||||
pop dx
|
||||
js .nomatch ; If SF=0, we have a class match here
|
||||
jz .our_drive ; If ZF=1, we have an exact match
|
||||
cmp dl,[cs:DriveNo]
|
||||
jb .nomatch ; Drive < Our drive
|
||||
dec dl ; Drive > Our drive, adjust drive #
|
||||
.nomatch:
|
||||
mov ax,[cs:SavedAX]
|
||||
pushf
|
||||
call far [cs:OldInt13]
|
||||
pushf
|
||||
push bp
|
||||
mov bp,sp
|
||||
cmp byte [cs:SavedAX+1],08h
|
||||
je .norestoredl
|
||||
cmp byte [cs:SavedAX+1],15h
|
||||
jne .restoredl
|
||||
test byte [bp+4],80h ; Hard disk?
|
||||
jnz .norestoredl
|
||||
.restoredl:
|
||||
mov dl,[bp+4]
|
||||
.norestoredl:
|
||||
push ax
|
||||
push ebx
|
||||
push ds
|
||||
mov ax,[bp+2] ; Flags
|
||||
lds ebx,[cs:Stack]
|
||||
mov [bx+4],al ; Arithmetric flags
|
||||
pop ds
|
||||
pop ebx
|
||||
pop ax
|
||||
pop bp
|
||||
lss esp,[cs:Stack]
|
||||
iret
|
||||
|
||||
.our_drive:
|
||||
; Set up standard entry frame
|
||||
push ds
|
||||
push es
|
||||
mov ds,ax
|
||||
mov es,ax
|
||||
mov ax,[SavedAX]
|
||||
pushad
|
||||
mov bp,sp ; Point BP to the entry stack frame
|
||||
TRACER 'F'
|
||||
; Note: AH == P_AH here
|
||||
cmp ah,Int13FuncsMax
|
||||
jae Invalid_jump
|
||||
xor al,al ; AL = 0 is standard entry condition
|
||||
mov di,ax
|
||||
shr di,7 ; Convert AH to an offset in DI
|
||||
call [Int13Funcs+di]
|
||||
|
||||
Done: ; Standard routine for return
|
||||
mov P_AX,ax
|
||||
DoneWeird:
|
||||
TRACER 'D'
|
||||
xor bx,bx
|
||||
mov es,bx
|
||||
mov bx,[StatusPtr]
|
||||
mov [es:bx],ah ; Save status
|
||||
and ah,ah
|
||||
|
||||
lds ebx,[Stack]
|
||||
; This sets the low byte (the arithmetric flags) of the
|
||||
; FLAGS on stack to either 00h (no flags) or 01h (CF)
|
||||
; depending on if AH was zero or not.
|
||||
setnz [bx+4] ; Set CF iff error
|
||||
popad
|
||||
pop es
|
||||
pop ds
|
||||
lss esp,[cs:Stack]
|
||||
iret
|
||||
|
||||
Reset:
|
||||
; Reset affects multiple drives, so we need to pass it on
|
||||
TRACER 'R'
|
||||
test dl,dl ; Always pass it on if we are resetting HD
|
||||
js .pass_on ; Bit 7 set
|
||||
; Some BIOSes get very unhappy if we pass a reset floppy
|
||||
; command to them and don't actually have any floppies.
|
||||
; This is a bug, but we have to deal with it nontheless.
|
||||
; Therefore, if we are the *ONLY* floppy drive, and the
|
||||
; user didn't request HD reset, then just drop the command.
|
||||
xor ax,ax ; Bottom of memory
|
||||
mov es,ax
|
||||
; BIOS equipment byte, top two bits + 1 == total # of floppies
|
||||
test byte [es:0x410],0C0h
|
||||
jz success
|
||||
; ... otherwise pass it to the BIOS
|
||||
.pass_on:
|
||||
pop ax ; Drop return address
|
||||
popad ; Restore all registers
|
||||
pop es
|
||||
pop ds
|
||||
lss esp,[cs:Stack] ; Restore the stack
|
||||
and dl,80h ; Clear all but the type bit
|
||||
jmp far [cs:OldInt13]
|
||||
|
||||
|
||||
Invalid:
|
||||
pop dx ; Drop return address
|
||||
Invalid_jump:
|
||||
TRACER 'I'
|
||||
mov ah,01h ; Unsupported function
|
||||
jmp short Done
|
||||
|
||||
GetDriveType:
|
||||
test byte [DriveNo],80h
|
||||
mov bl,02h ; Type 02h = floppy with changeline
|
||||
jz .floppy
|
||||
; Hard disks only...
|
||||
inc bx ; Type = 03h
|
||||
mov dx,[DiskSize] ; Return the disk size in sectors
|
||||
mov P_DX,dx
|
||||
mov cx,[DiskSize+2]
|
||||
mov P_CX,cx
|
||||
.floppy:
|
||||
mov P_AH,bl ; 02h floppy, 03h hard disk
|
||||
pop ax ; Drop return address
|
||||
xor ax,ax ; Success...
|
||||
jmp short DoneWeird ; But don't stick it into P_AX
|
||||
|
||||
GetStatus:
|
||||
xor ax,ax
|
||||
mov es,ax
|
||||
mov bx,[StatusPtr]
|
||||
mov ah,[bx] ; Copy last status
|
||||
ret
|
||||
|
||||
ReadMult:
|
||||
TRACER 'm'
|
||||
Read:
|
||||
TRACER 'R'
|
||||
call setup_regs
|
||||
do_copy:
|
||||
TRACER '<'
|
||||
call bcopy
|
||||
TRACER '>'
|
||||
movzx ax,P_AL ; AH = 0, AL = transfer count
|
||||
ret
|
||||
|
||||
WriteMult:
|
||||
TRACER 'M'
|
||||
Write:
|
||||
TRACER 'W'
|
||||
test byte [ConfigFlags],CONFIG_READONLY
|
||||
jnz .readonly
|
||||
call setup_regs
|
||||
xchg esi,edi ; Opposite direction of a Read!
|
||||
jmp short do_copy
|
||||
.readonly: mov ah,03h ; Write protected medium
|
||||
ret
|
||||
|
||||
; Verify integrity; just bounds-check
|
||||
Seek:
|
||||
Verify:
|
||||
call setup_regs ; Returns error if appropriate
|
||||
; And fall through to success
|
||||
|
||||
CheckIfReady: ; These are always-successful noop functions
|
||||
Recalibrate:
|
||||
InitWithParms:
|
||||
DetectChange:
|
||||
SetMode:
|
||||
success:
|
||||
xor ax,ax ; Always successful
|
||||
ret
|
||||
|
||||
GetParms:
|
||||
TRACER 'G'
|
||||
mov dl,[DriveCnt] ; Cached data
|
||||
mov P_DL,dl
|
||||
test byte [DriveNo],80h
|
||||
jnz .hd
|
||||
mov P_DI,DPT
|
||||
mov P_ES,cs
|
||||
mov bl,[DriveType]
|
||||
mov P_BL,bl
|
||||
.hd:
|
||||
mov ax,[Cylinders]
|
||||
dec ax ; We report the highest #, not the count
|
||||
xchg al,ah
|
||||
shl al,6
|
||||
or al,[Sectors]
|
||||
mov P_CX,ax
|
||||
mov ax,[Heads]
|
||||
dec ax
|
||||
mov P_DH,al
|
||||
|
||||
;
|
||||
; Is this MEMDISK installation check?
|
||||
;
|
||||
cmp P_HAX,'ME'
|
||||
jne .notic
|
||||
cmp P_HCX,'MD'
|
||||
jne .notic
|
||||
cmp P_HDX,'IS'
|
||||
jne .notic
|
||||
cmp P_HBX,'K?'
|
||||
jne .notic
|
||||
|
||||
; MEMDISK installation check...
|
||||
mov P_HAX,'!M'
|
||||
mov P_HCX,'EM'
|
||||
mov P_HDX,'DI'
|
||||
mov P_HBX,'SK'
|
||||
mov P_ES,cs
|
||||
mov P_DI,MemDisk_Info
|
||||
|
||||
.notic:
|
||||
xor ax,ax
|
||||
ret
|
||||
|
||||
; Set up registers as for a "Read", and compares against disk size
|
||||
setup_regs:
|
||||
|
||||
; Convert a CHS address in P_CX/P_DH into an LBA in eax
|
||||
; CH = cyl[7:0]
|
||||
; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8]
|
||||
; DH = head
|
||||
movzx ecx,P_CX
|
||||
movzx ebx,cl ; Sector number
|
||||
and bl,3Fh
|
||||
dec ebx ; Sector number is 1-based
|
||||
cmp bx,[Sectors]
|
||||
jae .overrun
|
||||
movzx edi,P_DH ; Head number
|
||||
movzx eax,word [Heads]
|
||||
cmp di,ax
|
||||
jae .overrun
|
||||
shr cl,6
|
||||
xchg cl,ch ; Now (E)CX <- cylinder number
|
||||
mul ecx ; eax <- Heads*cyl# (edx <- 0)
|
||||
add eax,edi
|
||||
mul dword [Sectors]
|
||||
add eax,ebx
|
||||
; Now eax = LBA, edx = 0
|
||||
|
||||
;
|
||||
; setup_regs continues...
|
||||
;
|
||||
; Note: edi[31:16] and ecx[31:16] = 0 already
|
||||
mov di,P_BX ; Get linear address of target buffer
|
||||
mov cx,P_ES
|
||||
shl ecx,4
|
||||
add edi,ecx ; EDI = address to fetch to
|
||||
movzx ecx,P_AL ; Sector count
|
||||
mov esi,eax
|
||||
add eax,ecx ; LBA of final sector + 1
|
||||
shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
|
||||
add esi,[DiskBuf] ; Get address in high memory
|
||||
cmp eax,[DiskSize] ; Check the high mark against limit
|
||||
ja .overrun
|
||||
shl ecx,SECTORSIZE_LG2-2 ; Convert count to 32-bit words
|
||||
ret
|
||||
|
||||
.overrun: pop ax ; Drop setup_regs return address
|
||||
mov ax,0200h ; Missing address mark
|
||||
ret ; Return to Done
|
||||
|
||||
int15_e820:
|
||||
cmp edx,534D4150h ; "SMAP"
|
||||
jne near oldint15
|
||||
cmp ecx,20 ; Need 20 bytes
|
||||
jb err86
|
||||
push ds
|
||||
push cs
|
||||
pop ds
|
||||
and ebx,ebx
|
||||
jne .renew
|
||||
mov ebx,E820Table
|
||||
.renew:
|
||||
add bx,12 ; Advance to next
|
||||
mov eax,[bx-4] ; Type
|
||||
and eax,eax ; Null type?
|
||||
jz .renew ; If so advance to next
|
||||
mov [es:di+16],eax
|
||||
mov eax,[bx-12] ; Start addr (low)
|
||||
mov [es:di],eax
|
||||
mov ecx,[bx-8] ; Start addr (high)
|
||||
mov [es:di+4],ecx
|
||||
mov eax,[bx] ; End addr (low)
|
||||
mov ecx,[bx+4] ; End addr (high)
|
||||
sub eax,[bx-12] ; Derive the length
|
||||
sbb ecx,[bx-8]
|
||||
mov [es:di+8],eax ; Length (low)
|
||||
mov [es:di+12],ecx ; Length (high)
|
||||
cmp dword [bx+8],-1 ; Type of next = end?
|
||||
jne .notdone
|
||||
xor ebx,ebx ; Done with table
|
||||
.notdone:
|
||||
mov eax,edx ; "SMAP"
|
||||
pop ds
|
||||
mov ecx,20 ; Bytes loaded
|
||||
int15_success:
|
||||
mov byte [bp+6], 02h ; Clear CF
|
||||
pop bp
|
||||
iret
|
||||
|
||||
err86:
|
||||
mov byte [bp+6], 03h ; Set CF
|
||||
mov ah,86h
|
||||
pop bp
|
||||
iret
|
||||
|
||||
Int15Start:
|
||||
push bp
|
||||
mov bp,sp
|
||||
cmp ax,0E820h
|
||||
je near int15_e820
|
||||
cmp ax,0E801h
|
||||
je int15_e801
|
||||
cmp ax,0E881h
|
||||
je int15_e881
|
||||
cmp ah,88h
|
||||
je int15_88
|
||||
oldint15: pop bp
|
||||
jmp far [cs:OldInt15]
|
||||
|
||||
int15_e801:
|
||||
mov ax,[cs:Mem1MB]
|
||||
mov cx,ax
|
||||
mov bx,[cs:Mem16MB]
|
||||
mov dx,bx
|
||||
jmp short int15_success
|
||||
|
||||
int15_e881:
|
||||
mov eax,[cs:Mem1MB]
|
||||
mov ecx,eax
|
||||
mov ebx,[cs:Mem16MB]
|
||||
mov edx,ebx
|
||||
jmp short int15_success
|
||||
|
||||
int15_88:
|
||||
mov ax,[cs:MemInt1588]
|
||||
jmp short int15_success
|
||||
|
||||
;
|
||||
; Routine to copy in/out of high memory
|
||||
; esi = linear source address
|
||||
; edi = linear target address
|
||||
; ecx = 32-bit word count
|
||||
;
|
||||
; Assumes cs = ds = es
|
||||
;
|
||||
bcopy:
|
||||
push eax
|
||||
push ebx
|
||||
push edx
|
||||
push ebp
|
||||
|
||||
test byte [ConfigFlags],CONFIG_RAW
|
||||
jz .anymode
|
||||
|
||||
smsw ax ; Unprivileged!
|
||||
test al,01h
|
||||
jnz .protmode
|
||||
|
||||
.realmode:
|
||||
TRACER 'r'
|
||||
; We're in real mode, do it outselves
|
||||
|
||||
pushfd
|
||||
push ds
|
||||
push es
|
||||
|
||||
cli
|
||||
cld
|
||||
|
||||
xor ebx,ebx
|
||||
mov bx,cs
|
||||
shl ebx,4
|
||||
lea edx,[Shaker+ebx]
|
||||
mov [Shaker+2],edx
|
||||
|
||||
; Test to see if A20 is enabled or not
|
||||
xor ax,ax
|
||||
mov ds,ax
|
||||
dec ax
|
||||
mov es,ax
|
||||
|
||||
mov ax,[0]
|
||||
mov bx,ax
|
||||
xor bx,[es:10h]
|
||||
not ax
|
||||
mov [0],ax
|
||||
mov dx,ax
|
||||
xor dx,[es:10h]
|
||||
not ax
|
||||
mov [0],ax
|
||||
|
||||
or dx,bx
|
||||
push dx ; Save A20 status
|
||||
jnz .skip_a20e
|
||||
|
||||
mov ax,2401h ; Enable A20
|
||||
int 15h
|
||||
.skip_a20e:
|
||||
mov dl,[ConfigFlags]
|
||||
and dx,CONFIG_BIGRAW
|
||||
add dx,8
|
||||
; DX = 16 for BIGRAW, 8 for RAW
|
||||
; 8 is selector for a 64K flat segment,
|
||||
; 16 is selector for a 4GB flat segment.
|
||||
|
||||
lgdt [cs:Shaker]
|
||||
mov eax,cr0
|
||||
or al,01h
|
||||
mov cr0,eax
|
||||
|
||||
mov bx,16 ; Large flat segment
|
||||
mov ds,bx
|
||||
mov es,bx
|
||||
|
||||
a32 rep movsd
|
||||
|
||||
; DX has the appropriate value to put in
|
||||
; the registers on return
|
||||
mov ds,dx
|
||||
mov es,dx
|
||||
|
||||
and al,~01h
|
||||
mov cr0,eax
|
||||
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
pop dx ; A20 status
|
||||
and dx,dx
|
||||
jnz .skip_a20d
|
||||
mov ax,2400h ; Disable A20
|
||||
int 15h
|
||||
.skip_a20d:
|
||||
popfd
|
||||
jmp .done
|
||||
|
||||
.protmode:
|
||||
TRACER 'p'
|
||||
.anymode:
|
||||
|
||||
.copy_loop:
|
||||
push esi
|
||||
push edi
|
||||
push ecx
|
||||
cmp ecx,4000h
|
||||
jna .safe_size
|
||||
mov ecx,4000h
|
||||
.safe_size:
|
||||
push ecx ; Transfer size this cycle
|
||||
mov eax, esi
|
||||
mov [Mover_src1], si
|
||||
shr eax, 16
|
||||
mov [Mover_src1+2], al
|
||||
mov [Mover_src2], ah
|
||||
mov eax, edi
|
||||
mov [Mover_dst1], di
|
||||
shr eax, 16
|
||||
mov [Mover_dst1+2], al
|
||||
mov [Mover_dst2], ah
|
||||
mov si,Mover
|
||||
mov ah, 87h
|
||||
shl cx,1 ; Convert to 16-bit words
|
||||
int 15h
|
||||
cli ; Some BIOSes enable interrupts on INT 15h
|
||||
pop eax ; Transfer size this cycle
|
||||
pop ecx
|
||||
pop edi
|
||||
pop esi
|
||||
jc .error
|
||||
lea esi,[esi+4*eax]
|
||||
lea edi,[edi+4*eax]
|
||||
sub ecx, eax
|
||||
jnz .copy_loop
|
||||
; CF = 0
|
||||
.error:
|
||||
.done:
|
||||
pop ebp
|
||||
pop edx
|
||||
pop ebx
|
||||
pop eax
|
||||
ret
|
||||
|
||||
%ifdef DEBUG_TRACERS
|
||||
debug_tracer: pushad
|
||||
pushfd
|
||||
mov bp,sp
|
||||
mov bx,[bp+9*4]
|
||||
mov al,[cs:bx]
|
||||
inc word [bp+9*4]
|
||||
mov ah,0Eh
|
||||
mov bx,7
|
||||
int 10h
|
||||
popfd
|
||||
popad
|
||||
ret
|
||||
%endif
|
||||
|
||||
section .data
|
||||
alignb 2
|
||||
Int13Funcs dw Reset ; 00h - RESET
|
||||
dw GetStatus ; 01h - GET STATUS
|
||||
dw Read ; 02h - READ
|
||||
dw Write ; 03h - WRITE
|
||||
dw Verify ; 04h - VERIFY
|
||||
dw Invalid ; 05h - FORMAT TRACK
|
||||
dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
|
||||
dw Invalid ; 07h - FORMAT DRIVE AT TRACK
|
||||
dw GetParms ; 08h - GET PARAMETERS
|
||||
dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
|
||||
dw Invalid ; 0Ah
|
||||
dw Invalid ; 0Bh
|
||||
dw Seek ; 0Ch - SEEK TO CYLINDER
|
||||
dw Reset ; 0Dh - RESET HARD DISKS
|
||||
dw Invalid ; 0Eh
|
||||
dw Invalid ; 0Fh
|
||||
dw CheckIfReady ; 10h - CHECK IF READY
|
||||
dw Recalibrate ; 11h - RECALIBRATE
|
||||
dw Invalid ; 12h
|
||||
dw Invalid ; 13h
|
||||
dw Invalid ; 14h
|
||||
dw GetDriveType ; 15h - GET DRIVE TYPE
|
||||
dw DetectChange ; 16h - DETECT DRIVE CHANGE
|
||||
%if 0
|
||||
dw Invalid ; 17h
|
||||
dw Invalid ; 18h
|
||||
dw Invalid ; 19h
|
||||
dw Invalid ; 1Ah
|
||||
dw Invalid ; 1Bh
|
||||
dw Invalid ; 1Ch
|
||||
dw Invalid ; 1Dh
|
||||
dw Invalid ; 1Eh
|
||||
dw Invalid ; 1Fh
|
||||
dw Invalid ; 20h
|
||||
dw ReadMult ; 21h - READ MULTIPLE
|
||||
dw WriteMult ; 22h - WRITE MULTIPLE
|
||||
dw SetMode ; 23h - SET CONTROLLER FEATURES
|
||||
dw SetMode ; 24h - SET MULTIPLE MODE
|
||||
dw Invalid ; 25h - IDENTIFY DRIVE
|
||||
dw Invalid ; 26h
|
||||
dw Invalid ; 27h
|
||||
dw Invalid ; 28h
|
||||
dw Invalid ; 29h
|
||||
dw Invalid ; 2Ah
|
||||
dw Invalid ; 2Bh
|
||||
dw Invalid ; 2Ch
|
||||
dw Invalid ; 2Dh
|
||||
dw Invalid ; 2Eh
|
||||
dw Invalid ; 2Fh
|
||||
dw Invalid ; 30h
|
||||
dw Invalid ; 31h
|
||||
dw Invalid ; 32h
|
||||
dw Invalid ; 33h
|
||||
dw Invalid ; 34h
|
||||
dw Invalid ; 35h
|
||||
dw Invalid ; 36h
|
||||
dw Invalid ; 37h
|
||||
dw Invalid ; 38h
|
||||
dw Invalid ; 39h
|
||||
dw Invalid ; 3Ah
|
||||
dw Invalid ; 3Bh
|
||||
dw Invalid ; 3Ch
|
||||
dw Invalid ; 3Dh
|
||||
dw Invalid ; 3Eh
|
||||
dw Invalid ; 3Fh
|
||||
dw Invalid ; 40h
|
||||
dw EDDPresence ; 41h - EDD PRESENCE DETECT
|
||||
dw EDDRead ; 42h - EDD READ
|
||||
dw EDDWrite ; 43h - EDD WRITE
|
||||
dw EDDVerify ; 44h - EDD VERIFY
|
||||
dw Invalid ; 45h - EDD LOCK/UNLOCK MEDIA
|
||||
dw Invalid ; 46h - EDD EJECT
|
||||
dw EDDSeek ; 47h - EDD SEEK
|
||||
dw EDDGetParms ; 48h - EDD GET PARAMETERS
|
||||
%endif
|
||||
|
||||
Int13FuncsEnd equ $
|
||||
Int13FuncsMax equ (Int13FuncsEnd-Int13Funcs) >> 1
|
||||
|
||||
alignb 8, db 0
|
||||
Shaker dw ShakerEnd-$
|
||||
dd 0 ; Pointer to self
|
||||
dw 0
|
||||
|
||||
Shaker_RMDS: dd 0x0000ffff ; 64K data segment
|
||||
dd 0x00009300
|
||||
|
||||
Shaker_DS: dd 0x0000ffff ; 4GB data segment
|
||||
dd 0x008f9300
|
||||
|
||||
ShakerEnd equ $
|
||||
|
||||
alignb 8, db 0
|
||||
|
||||
|
||||
Mover dd 0, 0, 0, 0 ; Must be zero
|
||||
dw 0ffffh ; 64 K segment size
|
||||
Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
|
||||
db 93h ; Access rights
|
||||
db 00h ; Extended access rights
|
||||
Mover_src2: db 0 ; High 8 bits of source addy
|
||||
dw 0ffffh ; 64 K segment size
|
||||
Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
|
||||
db 93h ; Access rights
|
||||
db 00h ; Extended access rights
|
||||
Mover_dst2: db 0 ; High 8 bits of source addy
|
||||
Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
|
||||
|
||||
alignb 4, db 0
|
||||
MemDisk_Info equ $ ; Pointed to by installation check
|
||||
MDI_Bytes dw 27 ; Total bytes in MDI structure
|
||||
MDI_Version db VER_MINOR, VER_MAJOR ; MEMDISK version
|
||||
|
||||
PatchArea equ $ ; This gets filled in by the installer
|
||||
|
||||
DiskBuf dd 0 ; Linear address of high memory disk
|
||||
DiskSize dd 0 ; Size of disk in blocks
|
||||
CommandLine dw 0, 0 ; Far pointer to saved command line
|
||||
|
||||
OldInt13 dd 0 ; INT 13h in chain
|
||||
OldInt15 dd 0 ; INT 15h in chain
|
||||
|
||||
OldDosMem dw 0 ; Old position of DOS mem end
|
||||
BootLoaderID db 0 ; Boot loader ID from header
|
||||
; ---- MDI structure ends here ---
|
||||
db 0, 0, 0 ; pad
|
||||
|
||||
MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
|
||||
|
||||
Cylinders dw 0 ; Cylinder count
|
||||
Heads dw 0 ; Head count
|
||||
Sectors dd 0 ; Sector count (zero-extended)
|
||||
|
||||
Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
|
||||
Mem16MB dd 0 ; 16MB-4G memory amount (64K)
|
||||
|
||||
DriveNo db 0 ; Our drive number
|
||||
DriveType db 0 ; Our drive type (floppies)
|
||||
DriveCnt db 0 ; Drive count (from the BIOS)
|
||||
|
||||
ConfigFlags db 0 ; Bit 0 - readonly
|
||||
|
||||
MyStack dw 0 ; Offset of stack
|
||||
StatusPtr dw 0 ; Where to save status (zeroseg ptr)
|
||||
|
||||
DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
|
||||
|
||||
; End patch area
|
||||
|
||||
Stack dd 0 ; Saved SS:ESP on invocation
|
||||
dw 0
|
||||
SavedAX dw 0 ; AX saved on invocation
|
||||
|
||||
alignb 4, db 0 ; We *MUST* end on a dword boundary
|
||||
|
||||
E820Table equ $ ; The installer loads the E820 table here
|
||||
TotalSize equ $ ; End pointer
|
||||
BIN
extra/syslinux-3.09/memdisk/memdisk.bin
Normal file
BIN
extra/syslinux-3.09/memdisk/memdisk.bin
Normal file
Binary file not shown.
186
extra/syslinux-3.09/memdisk/memdisk.doc
Normal file
186
extra/syslinux-3.09/memdisk/memdisk.doc
Normal file
@@ -0,0 +1,186 @@
|
||||
$Id: memdisk.doc,v 1.17 2005/04/29 06:04:45 hpa Exp $
|
||||
[This documentation is rather crufty at the moment.]
|
||||
|
||||
MEMDISK is meant to allow booting legacy operating systems via PXE,
|
||||
and as a workaround for BIOSes where ISOLINUX image support doesn't
|
||||
work.
|
||||
|
||||
MEMDISK simulates a disk by claiming a chunk of high memory for the
|
||||
disk and a (very small - 2K typical) chunk of low (DOS) memory for the
|
||||
driver itself, then hooking the INT 13h (disk driver) and INT 15h
|
||||
(memory query) BIOS interrupts.
|
||||
|
||||
To use it, type on the SYSLINUX command line:
|
||||
|
||||
memdisk initrd=diskimg.img
|
||||
|
||||
... where diskimg.img is the disk image you want to boot from.
|
||||
|
||||
[Obviously, the memdisk binary as well as your disk image file need to
|
||||
be present in the boot image directory.]
|
||||
|
||||
... or add to your syslinux.cfg/pxelinux.cfg/isolinux.cfg something like:
|
||||
|
||||
label dos
|
||||
kernel memdisk
|
||||
append initrd=dosboot.img
|
||||
|
||||
Note the following:
|
||||
|
||||
a) The disk image can be uncompressed or compressed with gzip or zip.
|
||||
|
||||
b) If the disk image is one of the following sizes, it's assumed to be a
|
||||
floppy image:
|
||||
|
||||
368,640 bytes - 360K floppy
|
||||
737,280 bytes - 720K floppy
|
||||
1,222,800 bytes - 1200K floppy
|
||||
1,474,560 bytes - 1440K floppy
|
||||
1,720,320 bytes - 1680K floppy (common extended format)
|
||||
1,763,328 bytes - 1722K floppy (common extended format)
|
||||
2,949,120 bytes - 2880K floppy
|
||||
3,932,160 bytes - 3840K floppy (extended format)
|
||||
|
||||
For any other size, the image is assumed to be a hard disk image,
|
||||
and should typically have an MBR and a partition table. It may
|
||||
optionally have a DOSEMU geometry header; in which case the header
|
||||
is used to determine the C/H/S geometry of the disk. Otherwise,
|
||||
the geometry is determined by examining the partition table, so the
|
||||
entire image should be partitioned for proper operation (it may be
|
||||
divided between multiple partitions, however.)
|
||||
|
||||
You can also specify the geometry manually with the following command
|
||||
line options:
|
||||
|
||||
c=<number> Specify number of cylinders (max 1024[*])
|
||||
h=<number> Specify number of heads (max 256[*])
|
||||
s=<number> Specify number of sectors (max 63)
|
||||
floppy The image is a floppy image
|
||||
harddisk The image is a hard disk image
|
||||
|
||||
[*] MS-DOS only allows max 255 heads, and only allows 255 cylinders
|
||||
on floppy disks.
|
||||
|
||||
c) The disk is normally writable (although, of course, there is
|
||||
nothing backing it up, so it only lasts until reset.) If you want,
|
||||
you can mimic a write-protected disk by specifying the command line
|
||||
option:
|
||||
|
||||
ro Disk is readonly
|
||||
|
||||
d) MEMDISK normally uses the BIOS "INT 15h mover" API to access high
|
||||
memory. This is well-behaved with extended memory managers which load
|
||||
later. Unfortunately it appears that the "DOS boot disk" from
|
||||
WinME/XP *deliberately* crash the system when this API is invoked.
|
||||
The following command-line options tells MEMDISK to enter protected
|
||||
mode directly, whenever possible:
|
||||
|
||||
raw Use raw access to protected mode memory.
|
||||
|
||||
bigraw Use raw access to protected mode memory, and leave the
|
||||
CPU in "big real" mode afterwards.
|
||||
|
||||
|
||||
Some interesting things to note:
|
||||
|
||||
If you're using MEMDISK to boot DOS from a CD-ROM (using ISOLINUX),
|
||||
you might find the generic El Torito CD-ROM driver by Gary Tong and
|
||||
Bart Lagerweij useful:
|
||||
|
||||
http://www.nu2.nu/eltorito/
|
||||
|
||||
|
||||
Similarly, if you're booting DOS over the network using PXELINUX, you
|
||||
can use the "keeppxe" option and use the generic PXE (UNDI) NDIS
|
||||
network driver, which is part of the PROBOOT.EXE distribution from
|
||||
Intel:
|
||||
|
||||
http://www.intel.com/support/network/adapter/1000/software.htm
|
||||
|
||||
|
||||
Additional technical information:
|
||||
|
||||
Starting with version 2.08, MEMDISK now supports an installation check
|
||||
API. This works as follows:
|
||||
|
||||
EAX = 454D08xxh ("ME") (08h = parameter query)
|
||||
ECX = 444Dxxxxh ("MD")
|
||||
EDX = 5349xxnnh ("IS") (nn = drive #)
|
||||
EBX = 3F4Bxxxxh ("K?")
|
||||
INT 13h
|
||||
|
||||
If drive nn is a MEMDISK, the registers will contain:
|
||||
|
||||
EAX = 4D21xxxxh ("!M")
|
||||
ECX = 4D45xxxxh ("EM")
|
||||
EDX = 4944xxxxh ("DI")
|
||||
EBX = 4B53xxxxh ("SK")
|
||||
|
||||
ES:DI -> MEMDISK info structures
|
||||
|
||||
The low parts of EAX/ECX/EDX/EBX have the normal return values for INT
|
||||
13h, AH=08h, i.e. information of the disk geometry etc.
|
||||
|
||||
See Ralf Brown's interrupt list,
|
||||
http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/files.html or
|
||||
http://www.ctyme.com/rbrown.htm, for a detailed description.
|
||||
|
||||
The MEMDISK info structure currently contains:
|
||||
|
||||
[ES:DI] word Total size of structure (currently 27 bytes)
|
||||
[ES:DI+2] byte MEMDISK minor version
|
||||
[ES:DI+3] byte MEMDISK major version
|
||||
[ES:DI+4] dword Pointer to MEMDISK data in high memory
|
||||
[ES:DI+8] dword Size of MEMDISK data in 512-byte sectors
|
||||
[ES:DI+12] 16:16 Far pointer to command line
|
||||
[ES:DI+16] 16:16 Old INT 13h pointer
|
||||
[ES:DI+20] 16:16 Old INT 15h pointer
|
||||
[ES:DI+24] word Amount of DOS memory before MEMDISK loaded
|
||||
[ES:DI+26] byte Boot loader ID
|
||||
|
||||
MEMDISK 3.00 and higher has the size of this structure as 27; earlier
|
||||
versions had size 26 and did not include the boot loader ID.
|
||||
|
||||
In addition, the following fields are available at [ES:0]:
|
||||
|
||||
[ES:0] word Offset of INT 13h routine (segment == ES)
|
||||
[ES:2] word Offset of INT 15h routine (segment == ES)
|
||||
|
||||
The program mdiskchk.c in the sample directory is an example on how
|
||||
this API can be used.
|
||||
|
||||
The following code can be used to "disable" MEMDISK. Note that it
|
||||
does not free the handler in DOS memory, and that running this from
|
||||
DOS will probably crash your machine (DOS doesn't like drives
|
||||
suddenly disappearing from underneath):
|
||||
|
||||
mov eax, 454D0800h
|
||||
mov ecx, 444D0000h
|
||||
mov edx, 53490000h + drive #
|
||||
mov ebx, 3F4B0000h
|
||||
int 13h
|
||||
|
||||
shr eax, 16
|
||||
cmp ax, 4D21h
|
||||
jne not_memdisk
|
||||
shr ecx, 16
|
||||
cmp cx, 4D45h
|
||||
jne not_memdisk
|
||||
shr edx, 16
|
||||
cmp dx, 4944h
|
||||
jne not_memdisk
|
||||
shr ebx, 16
|
||||
cmp bx, 4B53h
|
||||
jne not_memdisk
|
||||
|
||||
cli
|
||||
mov bx,[es:0] ; INT 13h handler offset
|
||||
mov eax,[es:di+16] ; Old INT 13h handler
|
||||
mov byte [es:bx], 0EAh ; FAR JMP
|
||||
mov [es:bx+1], eax
|
||||
|
||||
mov bx,[es:2] ; INT 15h handler offset
|
||||
mov eax,[es:di+20] ; Old INT 15h handler
|
||||
mov byte [es:bx], 0EAh ; FAR JMP
|
||||
mov [es:bx+1], eax
|
||||
sti
|
||||
74
extra/syslinux-3.09/memdisk/memdisk.h
Normal file
74
extra/syslinux-3.09/memdisk/memdisk.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ident "$Id: memdisk.h,v 1.9 2005/03/08 18:39:32 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2003 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* memdisk.h
|
||||
*
|
||||
* Miscellaneous header definitions
|
||||
*/
|
||||
|
||||
#ifndef MEMDISK_H
|
||||
#define MEMDISK_H
|
||||
|
||||
/* We use the com32 interface for calling 16-bit code */
|
||||
#include <com32.h>
|
||||
|
||||
/* The real-mode segment */
|
||||
#define LOW_SEG 0x0800
|
||||
|
||||
typedef void (*syscall_t)(uint8_t, com32sys_t *, com32sys_t *);
|
||||
extern syscall_t syscall;
|
||||
extern void *sys_bounce;
|
||||
|
||||
/* What to call when we're dead */
|
||||
extern void __attribute__((noreturn)) die(void);
|
||||
|
||||
/* Standard routines */
|
||||
#define memcpy(a,b,c) __builtin_memcpy(a,b,c)
|
||||
#define memset(a,b,c) __builtin_memset(a,b,c)
|
||||
#define strcpy(a,b) __builtin_strcpy(a,b)
|
||||
#define strlen(a) __builtin_strlen(a)
|
||||
|
||||
/* memcpy() but returns a pointer to end of buffer */
|
||||
static inline void *
|
||||
memcpy_endptr(void *__d, const void *__s, unsigned int __n)
|
||||
{
|
||||
memcpy(__d, __s, __n);
|
||||
return (void *)((char *)__d + __n);
|
||||
}
|
||||
|
||||
/* memcmp() */
|
||||
static inline int
|
||||
memcmp(const void *__a, const void *__b, unsigned int __n)
|
||||
{
|
||||
const unsigned char *__aa = __a;
|
||||
const unsigned char *__bb = __b;
|
||||
int __d;
|
||||
|
||||
while ( __n ) {
|
||||
__d = *__bb++ - *__aa++;
|
||||
if ( __d )
|
||||
return __d;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompression */
|
||||
extern int check_zip(void *indata, uint32_t size, uint32_t *zbytes_p,
|
||||
uint32_t *dbytes_p, uint32_t *orig_crc,
|
||||
uint32_t *offset_p);
|
||||
extern void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
|
||||
uint32_t orig_crc, void *target);
|
||||
|
||||
#endif
|
||||
764
extra/syslinux-3.09/memdisk/memdisk.lst
Normal file
764
extra/syslinux-3.09/memdisk/memdisk.lst
Normal file
@@ -0,0 +1,764 @@
|
||||
1 ; -*- fundamental -*- (asm-mode sucks)
|
||||
2 ; $Id: memdisk.asm,v 1.29 2005/04/29 06:08:03 hpa Exp $
|
||||
3 ; ****************************************************************************
|
||||
4 ;
|
||||
5 ; memdisk.asm
|
||||
6 ;
|
||||
7 ; A program to emulate an INT 13h disk BIOS from a "disk" in extended
|
||||
8 ; memory.
|
||||
9 ;
|
||||
10 ; Copyright (C) 2001-2004 H. Peter Anvin
|
||||
11 ;
|
||||
12 ; This program is free software; you can redistribute it and/or modify
|
||||
13 ; it under the terms of the GNU General Public License as published by
|
||||
14 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
||||
15 ; Boston MA 02111-1307, USA; either version 2 of the License, or
|
||||
16 ; (at your option) any later version; incorporated herein by reference.
|
||||
17 ;
|
||||
18 ; ****************************************************************************
|
||||
19
|
||||
20 %ifndef DEPEND
|
||||
21 %include "../version.gen"
|
||||
22 <1> %define VERSION "3.09"
|
||||
23 <1> %define VER_MAJOR 3
|
||||
24 <1> %define VER_MINOR 9
|
||||
25 %endif
|
||||
26
|
||||
27 ; %define DEBUG_TRACERS ; Uncomment to get debugging tracers
|
||||
28
|
||||
29 %ifdef DEBUG_TRACERS
|
||||
30
|
||||
31 %macro TRACER 1
|
||||
32 call debug_tracer
|
||||
33 db %1
|
||||
34 %endmacro
|
||||
35
|
||||
36 %else ; DEBUG_TRACERS
|
||||
37
|
||||
38 %macro TRACER 1
|
||||
39 %endmacro
|
||||
40
|
||||
41 %endif ; DEBUG_TRACERS
|
||||
42
|
||||
43 %define CONFIG_READONLY 0x01
|
||||
44 %define CONFIG_RAW 0x02
|
||||
45 %define CONFIG_BIGRAW 0x08 ; MUST be 8!
|
||||
46
|
||||
47 org 0h
|
||||
48
|
||||
49 %define SECTORSIZE_LG2 9 ; log2(sector size)
|
||||
50 %define SECTORSIZE (1 << SECTORSIZE_LG2)
|
||||
51
|
||||
52 ; Parameter registers definition; this is the definition
|
||||
53 ; of the stack frame.
|
||||
54 %define P_DS word [bp+34]
|
||||
55 %define P_ES word [bp+32]
|
||||
56 %define P_EAX dword [bp+28]
|
||||
57 %define P_HAX word [bp+30]
|
||||
58 %define P_AX word [bp+28]
|
||||
59 %define P_AL byte [bp+28]
|
||||
60 %define P_AH byte [bp+29]
|
||||
61 %define P_ECX dword [bp+24]
|
||||
62 %define P_HCX word [bp+26]
|
||||
63 %define P_CX word [bp+24]
|
||||
64 %define P_CL byte [bp+24]
|
||||
65 %define P_CH byte [bp+25]
|
||||
66 %define P_EDX dword [bp+20]
|
||||
67 %define P_HDX word [bp+22]
|
||||
68 %define P_DX word [bp+20]
|
||||
69 %define P_DL byte [bp+20]
|
||||
70 %define P_DH byte [bp+21]
|
||||
71 %define P_EBX dword [bp+16]
|
||||
72 %define P_HBX word [bp+18]
|
||||
73 %define P_HBXL byte [bp+18]
|
||||
74 %define P_BX word [bp+16]
|
||||
75 %define P_BL byte [bp+16]
|
||||
76 %define P_BH byte [bp+17]
|
||||
77 %define P_EBP dword [bp+8]
|
||||
78 %define P_BP word [bp+8]
|
||||
79 %define P_ESI dword [bp+4]
|
||||
80 %define P_SI word [bp+4]
|
||||
81 %define P_EDI dword [bp]
|
||||
82 %define P_DI word [bp]
|
||||
83
|
||||
84 section .text
|
||||
85 ; These pointers are used by the installer and
|
||||
86 ; must be first in the binary
|
||||
87 00000000 [0800] Pointers: dw Int13Start
|
||||
88 00000002 [8602] dw Int15Start
|
||||
89 00000004 [7C00] dw PatchArea
|
||||
90 00000006 [C800] dw TotalSize
|
||||
91
|
||||
92 Int13Start:
|
||||
93 ; Swap stack
|
||||
94 00000008 2E668926[C000] mov [cs:Stack],esp
|
||||
95 0000000E 2EA3[C600] mov [cs:SavedAX],ax
|
||||
96 00000012 8CD0 mov ax,ss
|
||||
97 00000014 2EA3[C400] mov [cs:Stack+4],ax
|
||||
98 00000018 8CC8 mov ax,cs
|
||||
99 0000001A 8ED0 mov ss,ax
|
||||
100 0000001C 2E8B26[AC00] mov sp,[cs:MyStack]
|
||||
101
|
||||
102 ; See if DL points to our class of device (FD, HD)
|
||||
103 00000021 52 push dx
|
||||
104 00000022 52 push dx
|
||||
105 00000023 2E3216[A800] xor dl,[cs:DriveNo]
|
||||
106 00000028 5A pop dx
|
||||
107 00000029 780B js .nomatch ; If SF=0, we have a class match here
|
||||
108 0000002B 744D jz .our_drive ; If ZF=1, we have an exact match
|
||||
109 0000002D 2E3A16[A800] cmp dl,[cs:DriveNo]
|
||||
110 00000032 7202 jb .nomatch ; Drive < Our drive
|
||||
111 00000034 FECA dec dl ; Drive > Our drive, adjust drive #
|
||||
112 .nomatch:
|
||||
113 00000036 2EA1[C600] mov ax,[cs:SavedAX]
|
||||
114 0000003A 9C pushf
|
||||
115 0000003B 2EFF1E[8800] call far [cs:OldInt13]
|
||||
116 00000040 9C pushf
|
||||
117 00000041 55 push bp
|
||||
118 00000042 89E5 mov bp,sp
|
||||
119 00000044 2E803E[C700]08 cmp byte [cs:SavedAX+1],08h
|
||||
120 0000004A 7411 je .norestoredl
|
||||
121 0000004C 2E803E[C700]15 cmp byte [cs:SavedAX+1],15h
|
||||
122 00000052 7506 jne .restoredl
|
||||
123 00000054 F6460480 test byte [bp+4],80h ; Hard disk?
|
||||
124 00000058 7503 jnz .norestoredl
|
||||
125 .restoredl:
|
||||
126 0000005A 8A5604 mov dl,[bp+4]
|
||||
127 .norestoredl:
|
||||
128 0000005D 50 push ax
|
||||
129 0000005E 6653 push ebx
|
||||
130 00000060 1E push ds
|
||||
131 00000061 8B4602 mov ax,[bp+2] ; Flags
|
||||
132 00000064 2E66C51E[C000] lds ebx,[cs:Stack]
|
||||
133 0000006A 884704 mov [bx+4],al ; Arithmetric flags
|
||||
134 0000006D 1F pop ds
|
||||
135 0000006E 665B pop ebx
|
||||
136 00000070 58 pop ax
|
||||
137 00000071 5D pop bp
|
||||
138 00000072 2E660FB226[C000] lss esp,[cs:Stack]
|
||||
139 00000079 CF iret
|
||||
140
|
||||
141 .our_drive:
|
||||
142 ; Set up standard entry frame
|
||||
143 0000007A 1E push ds
|
||||
144 0000007B 06 push es
|
||||
145 0000007C 8ED8 mov ds,ax
|
||||
146 0000007E 8EC0 mov es,ax
|
||||
147 00000080 A1[C600] mov ax,[SavedAX]
|
||||
148 00000083 6660 pushad
|
||||
149 00000085 89E5 mov bp,sp ; Point BP to the entry stack frame
|
||||
150 TRACER 'F'
|
||||
151 ; Note: AH == P_AH here
|
||||
152 00000087 80FC17 cmp ah,Int13FuncsMax
|
||||
153 0000008A 7355 jae Invalid_jump
|
||||
154 0000008C 30C0 xor al,al ; AL = 0 is standard entry condition
|
||||
155 0000008E 89C7 mov di,ax
|
||||
156 00000090 C1EF07 shr di,7 ; Convert AH to an offset in DI
|
||||
157 00000093 FF95[0000] call [Int13Funcs+di]
|
||||
158
|
||||
159 Done: ; Standard routine for return
|
||||
160 00000097 89461C mov P_AX,ax
|
||||
161 DoneWeird:
|
||||
162 TRACER 'D'
|
||||
163 0000009A 31DB xor bx,bx
|
||||
164 0000009C 8EC3 mov es,bx
|
||||
165 0000009E 8B1E[AE00] mov bx,[StatusPtr]
|
||||
166 000000A2 268827 mov [es:bx],ah ; Save status
|
||||
167 000000A5 20E4 and ah,ah
|
||||
168
|
||||
169 000000A7 66C51E[C000] lds ebx,[Stack]
|
||||
170 ; This sets the low byte (the arithmetric flags) of the
|
||||
171 ; FLAGS on stack to either 00h (no flags) or 01h (CF)
|
||||
172 ; depending on if AH was zero or not.
|
||||
173 000000AC 0F954704 setnz [bx+4] ; Set CF iff error
|
||||
174 000000B0 6661 popad
|
||||
175 000000B2 07 pop es
|
||||
176 000000B3 1F pop ds
|
||||
177 000000B4 2E660FB226[C000] lss esp,[cs:Stack]
|
||||
178 000000BB CF iret
|
||||
179
|
||||
180 Reset:
|
||||
181 ; Reset affects multiple drives, so we need to pass it on
|
||||
182 TRACER 'R'
|
||||
183 000000BC 84D2 test dl,dl ; Always pass it on if we are resetting HD
|
||||
184 000000BE 780C js .pass_on ; Bit 7 set
|
||||
185 ; Some BIOSes get very unhappy if we pass a reset floppy
|
||||
186 ; command to them and don't actually have any floppies.
|
||||
187 ; This is a bug, but we have to deal with it nontheless.
|
||||
188 ; Therefore, if we are the *ONLY* floppy drive, and the
|
||||
189 ; user didn't request HD reset, then just drop the command.
|
||||
190 000000C0 31C0 xor ax,ax ; Bottom of memory
|
||||
191 000000C2 8EC0 mov es,ax
|
||||
192 ; BIOS equipment byte, top two bits + 1 == total # of floppies
|
||||
193 000000C4 26F6061004C0 test byte [es:0x410],0C0h
|
||||
194 000000CA 7464 jz success
|
||||
195 ; ... otherwise pass it to the BIOS
|
||||
196 .pass_on:
|
||||
197 000000CC 58 pop ax ; Drop return address
|
||||
198 000000CD 6661 popad ; Restore all registers
|
||||
199 000000CF 07 pop es
|
||||
200 000000D0 1F pop ds
|
||||
201 000000D1 2E660FB226[C000] lss esp,[cs:Stack] ; Restore the stack
|
||||
202 000000D8 80E280 and dl,80h ; Clear all but the type bit
|
||||
203 000000DB 2EFF2E[8800] jmp far [cs:OldInt13]
|
||||
204
|
||||
205
|
||||
206 Invalid:
|
||||
207 000000E0 5A pop dx ; Drop return address
|
||||
208 Invalid_jump:
|
||||
209 TRACER 'I'
|
||||
210 000000E1 B401 mov ah,01h ; Unsupported function
|
||||
211 000000E3 EBB2 jmp short Done
|
||||
212
|
||||
213 GetDriveType:
|
||||
214 000000E5 F606[A800]80 test byte [DriveNo],80h
|
||||
215 000000EA B302 mov bl,02h ; Type 02h = floppy with changeline
|
||||
216 000000EC 740F jz .floppy
|
||||
217 ; Hard disks only...
|
||||
218 000000EE 43 inc bx ; Type = 03h
|
||||
219 000000EF 8B16[8000] mov dx,[DiskSize] ; Return the disk size in sectors
|
||||
220 000000F3 895614 mov P_DX,dx
|
||||
221 000000F6 8B0E[8200] mov cx,[DiskSize+2]
|
||||
222 000000FA 894E18 mov P_CX,cx
|
||||
223 .floppy:
|
||||
224 000000FD 885E1D mov P_AH,bl ; 02h floppy, 03h hard disk
|
||||
225 00000100 58 pop ax ; Drop return address
|
||||
226 00000101 31C0 xor ax,ax ; Success...
|
||||
227 00000103 EB95 jmp short DoneWeird ; But don't stick it into P_AX
|
||||
228
|
||||
229 GetStatus:
|
||||
230 00000105 31C0 xor ax,ax
|
||||
231 00000107 8EC0 mov es,ax
|
||||
232 00000109 8B1E[AE00] mov bx,[StatusPtr]
|
||||
233 0000010D 8A27 mov ah,[bx] ; Copy last status
|
||||
234 0000010F C3 ret
|
||||
235
|
||||
236 ReadMult:
|
||||
237 TRACER 'm'
|
||||
238 Read:
|
||||
239 TRACER 'R'
|
||||
240 00000110 E88F00 call setup_regs
|
||||
241 do_copy:
|
||||
242 TRACER '<'
|
||||
243 00000113 E8B701 call bcopy
|
||||
244 TRACER '>'
|
||||
245 00000116 0FB6461C movzx ax,P_AL ; AH = 0, AL = transfer count
|
||||
246 0000011A C3 ret
|
||||
247
|
||||
248 WriteMult:
|
||||
249 TRACER 'M'
|
||||
250 Write:
|
||||
251 TRACER 'W'
|
||||
252 0000011B F606[AB00]01 test byte [ConfigFlags],CONFIG_READONLY
|
||||
253 00000120 7508 jnz .readonly
|
||||
254 00000122 E87D00 call setup_regs
|
||||
255 00000125 6687F7 xchg esi,edi ; Opposite direction of a Read!
|
||||
256 00000128 EBE9 jmp short do_copy
|
||||
257 0000012A B403 .readonly: mov ah,03h ; Write protected medium
|
||||
258 0000012C C3 ret
|
||||
259
|
||||
260 ; Verify integrity; just bounds-check
|
||||
261 Seek:
|
||||
262 Verify:
|
||||
263 0000012D E87200 call setup_regs ; Returns error if appropriate
|
||||
264 ; And fall through to success
|
||||
265
|
||||
266 CheckIfReady: ; These are always-successful noop functions
|
||||
267 Recalibrate:
|
||||
268 InitWithParms:
|
||||
269 DetectChange:
|
||||
270 SetMode:
|
||||
271 success:
|
||||
272 00000130 31C0 xor ax,ax ; Always successful
|
||||
273 00000132 C3 ret
|
||||
274
|
||||
275 GetParms:
|
||||
276 TRACER 'G'
|
||||
277 00000133 8A16[AA00] mov dl,[DriveCnt] ; Cached data
|
||||
278 00000137 885614 mov P_DL,dl
|
||||
279 0000013A F606[A800]80 test byte [DriveNo],80h
|
||||
280 0000013F 750F jnz .hd
|
||||
281 00000141 C74600[B000] mov P_DI,DPT
|
||||
282 00000146 8C4E20 mov P_ES,cs
|
||||
283 00000149 8A1E[A900] mov bl,[DriveType]
|
||||
284 0000014D 885E10 mov P_BL,bl
|
||||
285 .hd:
|
||||
286 00000150 A1[9800] mov ax,[Cylinders]
|
||||
287 00000153 48 dec ax ; We report the highest #, not the count
|
||||
288 00000154 86C4 xchg al,ah
|
||||
289 00000156 C0E006 shl al,6
|
||||
290 00000159 0A06[9C00] or al,[Sectors]
|
||||
291 0000015D 894618 mov P_CX,ax
|
||||
292 00000160 A1[9A00] mov ax,[Heads]
|
||||
293 00000163 48 dec ax
|
||||
294 00000164 884615 mov P_DH,al
|
||||
295
|
||||
296 ;
|
||||
297 ; Is this MEMDISK installation check?
|
||||
298 ;
|
||||
299 00000167 817E1E4D45 cmp P_HAX,'ME'
|
||||
300 0000016C 7531 jne .notic
|
||||
301 0000016E 817E1A4D44 cmp P_HCX,'MD'
|
||||
302 00000173 752A jne .notic
|
||||
303 00000175 817E164953 cmp P_HDX,'IS'
|
||||
304 0000017A 7523 jne .notic
|
||||
305 0000017C 817E124B3F cmp P_HBX,'K?'
|
||||
306 00000181 751C jne .notic
|
||||
307
|
||||
308 ; MEMDISK installation check...
|
||||
309 00000183 C7461E214D mov P_HAX,'!M'
|
||||
310 00000188 C7461A454D mov P_HCX,'EM'
|
||||
311 0000018D C746164449 mov P_HDX,'DI'
|
||||
312 00000192 C74612534B mov P_HBX,'SK'
|
||||
313 00000197 8C4E20 mov P_ES,cs
|
||||
314 0000019A C74600[7800] mov P_DI,MemDisk_Info
|
||||
315
|
||||
316 .notic:
|
||||
317 0000019F 31C0 xor ax,ax
|
||||
318 000001A1 C3 ret
|
||||
319
|
||||
320 ; Set up registers as for a "Read", and compares against disk size
|
||||
321 setup_regs:
|
||||
322
|
||||
323 ; Convert a CHS address in P_CX/P_DH into an LBA in eax
|
||||
324 ; CH = cyl[7:0]
|
||||
325 ; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8]
|
||||
326 ; DH = head
|
||||
327 000001A2 660FB74E18 movzx ecx,P_CX
|
||||
328 000001A7 660FB6D9 movzx ebx,cl ; Sector number
|
||||
329 000001AB 80E33F and bl,3Fh
|
||||
330 000001AE 664B dec ebx ; Sector number is 1-based
|
||||
331 000001B0 3B1E[9C00] cmp bx,[Sectors]
|
||||
332 000001B4 734F jae .overrun
|
||||
333 000001B6 660FB67E15 movzx edi,P_DH ; Head number
|
||||
334 000001BB 660FB706[9A00] movzx eax,word [Heads]
|
||||
335 000001C1 39C7 cmp di,ax
|
||||
336 000001C3 7340 jae .overrun
|
||||
337 000001C5 C0E906 shr cl,6
|
||||
338 000001C8 86CD xchg cl,ch ; Now (E)CX <- cylinder number
|
||||
339 000001CA 66F7E1 mul ecx ; eax <- Heads*cyl# (edx <- 0)
|
||||
340 000001CD 6601F8 add eax,edi
|
||||
341 000001D0 66F726[9C00] mul dword [Sectors]
|
||||
342 000001D5 6601D8 add eax,ebx
|
||||
343 ; Now eax = LBA, edx = 0
|
||||
344
|
||||
345 ;
|
||||
346 ; setup_regs continues...
|
||||
347 ;
|
||||
348 ; Note: edi[31:16] and ecx[31:16] = 0 already
|
||||
349 000001D8 8B7E10 mov di,P_BX ; Get linear address of target buffer
|
||||
350 000001DB 8B4E20 mov cx,P_ES
|
||||
351 000001DE 66C1E104 shl ecx,4
|
||||
352 000001E2 6601CF add edi,ecx ; EDI = address to fetch to
|
||||
353 000001E5 660FB64E1C movzx ecx,P_AL ; Sector count
|
||||
354 000001EA 6689C6 mov esi,eax
|
||||
355 000001ED 6601C8 add eax,ecx ; LBA of final sector + 1
|
||||
356 000001F0 66C1E609 shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
|
||||
357 000001F4 660336[7C00] add esi,[DiskBuf] ; Get address in high memory
|
||||
358 000001F9 663B06[8000] cmp eax,[DiskSize] ; Check the high mark against limit
|
||||
359 000001FE 7705 ja .overrun
|
||||
360 00000200 66C1E107 shl ecx,SECTORSIZE_LG2-2 ; Convert count to 32-bit words
|
||||
361 00000204 C3 ret
|
||||
362
|
||||
363 00000205 58 .overrun: pop ax ; Drop setup_regs return address
|
||||
364 00000206 B80002 mov ax,0200h ; Missing address mark
|
||||
365 00000209 C3 ret ; Return to Done
|
||||
366
|
||||
367 int15_e820:
|
||||
368 0000020A 6681FA50414D53 cmp edx,534D4150h ; "SMAP"
|
||||
369 00000211 0F858A00 jne near oldint15
|
||||
370 00000215 6683F914 cmp ecx,20 ; Need 20 bytes
|
||||
371 00000219 7263 jb err86
|
||||
372 0000021B 1E push ds
|
||||
373 0000021C 0E push cs
|
||||
374 0000021D 1F pop ds
|
||||
375 0000021E 6621DB and ebx,ebx
|
||||
376 00000221 7506 jne .renew
|
||||
377 00000223 66BB[C8000000] mov ebx,E820Table
|
||||
378 .renew:
|
||||
379 00000229 83C30C add bx,12 ; Advance to next
|
||||
380 0000022C 668B47FC mov eax,[bx-4] ; Type
|
||||
381 00000230 6621C0 and eax,eax ; Null type?
|
||||
382 00000233 74F4 jz .renew ; If so advance to next
|
||||
383 00000235 2666894510 mov [es:di+16],eax
|
||||
384 0000023A 668B47F4 mov eax,[bx-12] ; Start addr (low)
|
||||
385 0000023E 26668905 mov [es:di],eax
|
||||
386 00000242 668B4FF8 mov ecx,[bx-8] ; Start addr (high)
|
||||
387 00000246 2666894D04 mov [es:di+4],ecx
|
||||
388 0000024B 668B07 mov eax,[bx] ; End addr (low)
|
||||
389 0000024E 668B4F04 mov ecx,[bx+4] ; End addr (high)
|
||||
390 00000252 662B47F4 sub eax,[bx-12] ; Derive the length
|
||||
391 00000256 661B4FF8 sbb ecx,[bx-8]
|
||||
392 0000025A 2666894508 mov [es:di+8],eax ; Length (low)
|
||||
393 0000025F 2666894D0C mov [es:di+12],ecx ; Length (high)
|
||||
394 00000264 66837F08FF cmp dword [bx+8],-1 ; Type of next = end?
|
||||
395 00000269 7503 jne .notdone
|
||||
396 0000026B 6631DB xor ebx,ebx ; Done with table
|
||||
397 .notdone:
|
||||
398 0000026E 6689D0 mov eax,edx ; "SMAP"
|
||||
399 00000271 1F pop ds
|
||||
400 00000272 66B914000000 mov ecx,20 ; Bytes loaded
|
||||
401 int15_success:
|
||||
402 00000278 C6460602 mov byte [bp+6], 02h ; Clear CF
|
||||
403 0000027C 5D pop bp
|
||||
404 0000027D CF iret
|
||||
405
|
||||
406 err86:
|
||||
407 0000027E C6460603 mov byte [bp+6], 03h ; Set CF
|
||||
408 00000282 B486 mov ah,86h
|
||||
409 00000284 5D pop bp
|
||||
410 00000285 CF iret
|
||||
411
|
||||
412 Int15Start:
|
||||
413 00000286 55 push bp
|
||||
414 00000287 89E5 mov bp,sp
|
||||
415 00000289 3D20E8 cmp ax,0E820h
|
||||
416 0000028C 0F847AFF je near int15_e820
|
||||
417 00000290 3D01E8 cmp ax,0E801h
|
||||
418 00000293 7410 je int15_e801
|
||||
419 00000295 3D81E8 cmp ax,0E881h
|
||||
420 00000298 741A je int15_e881
|
||||
421 0000029A 80FC88 cmp ah,88h
|
||||
422 0000029D 7428 je int15_88
|
||||
423 0000029F 5D oldint15: pop bp
|
||||
424 000002A0 2EFF2E[8C00] jmp far [cs:OldInt15]
|
||||
425
|
||||
426 int15_e801:
|
||||
427 000002A5 2EA1[A000] mov ax,[cs:Mem1MB]
|
||||
428 000002A9 89C1 mov cx,ax
|
||||
429 000002AB 2E8B1E[A400] mov bx,[cs:Mem16MB]
|
||||
430 000002B0 89DA mov dx,bx
|
||||
431 000002B2 EBC4 jmp short int15_success
|
||||
432
|
||||
433 int15_e881:
|
||||
434 000002B4 2E66A1[A000] mov eax,[cs:Mem1MB]
|
||||
435 000002B9 6689C1 mov ecx,eax
|
||||
436 000002BC 2E668B1E[A400] mov ebx,[cs:Mem16MB]
|
||||
437 000002C2 6689DA mov edx,ebx
|
||||
438 000002C5 EBB1 jmp short int15_success
|
||||
439
|
||||
440 int15_88:
|
||||
441 000002C7 2EA1[9600] mov ax,[cs:MemInt1588]
|
||||
442 000002CB EBAB jmp short int15_success
|
||||
443
|
||||
444 ;
|
||||
445 ; Routine to copy in/out of high memory
|
||||
446 ; esi = linear source address
|
||||
447 ; edi = linear target address
|
||||
448 ; ecx = 32-bit word count
|
||||
449 ;
|
||||
450 ; Assumes cs = ds = es
|
||||
451 ;
|
||||
452 bcopy:
|
||||
453 000002CD 6650 push eax
|
||||
454 000002CF 6653 push ebx
|
||||
455 000002D1 6652 push edx
|
||||
456 000002D3 6655 push ebp
|
||||
457
|
||||
458 000002D5 F606[AB00]02 test byte [ConfigFlags],CONFIG_RAW
|
||||
459 000002DA 0F848D00 jz .anymode
|
||||
460
|
||||
461 000002DE 0F01E0 smsw ax ; Unprivileged!
|
||||
462 000002E1 A801 test al,01h
|
||||
463 000002E3 0F858400 jnz .protmode
|
||||
464
|
||||
465 .realmode:
|
||||
466 TRACER 'r'
|
||||
467 ; We're in real mode, do it outselves
|
||||
468
|
||||
469 000002E7 669C pushfd
|
||||
470 000002E9 1E push ds
|
||||
471 000002EA 06 push es
|
||||
472
|
||||
473 000002EB FA cli
|
||||
474 000002EC FC cld
|
||||
475
|
||||
476 000002ED 6631DB xor ebx,ebx
|
||||
477 000002F0 8CCB mov bx,cs
|
||||
478 000002F2 66C1E304 shl ebx,4
|
||||
479 000002F6 66678D93[30000000] lea edx,[Shaker+ebx]
|
||||
480 000002FE 668916[3200] mov [Shaker+2],edx
|
||||
481
|
||||
482 ; Test to see if A20 is enabled or not
|
||||
483 00000303 31C0 xor ax,ax
|
||||
484 00000305 8ED8 mov ds,ax
|
||||
485 00000307 48 dec ax
|
||||
486 00000308 8EC0 mov es,ax
|
||||
487
|
||||
488 0000030A A10000 mov ax,[0]
|
||||
489 0000030D 89C3 mov bx,ax
|
||||
490 0000030F 26331E1000 xor bx,[es:10h]
|
||||
491 00000314 F7D0 not ax
|
||||
492 00000316 A30000 mov [0],ax
|
||||
493 00000319 89C2 mov dx,ax
|
||||
494 0000031B 2633161000 xor dx,[es:10h]
|
||||
495 00000320 F7D0 not ax
|
||||
496 00000322 A30000 mov [0],ax
|
||||
497
|
||||
498 00000325 09DA or dx,bx
|
||||
499 00000327 52 push dx ; Save A20 status
|
||||
500 00000328 7505 jnz .skip_a20e
|
||||
501
|
||||
502 0000032A B80124 mov ax,2401h ; Enable A20
|
||||
503 0000032D CD15 int 15h
|
||||
504 .skip_a20e:
|
||||
505 0000032F 8A16[AB00] mov dl,[ConfigFlags]
|
||||
506 00000333 83E208 and dx,CONFIG_BIGRAW
|
||||
507 00000336 83C208 add dx,8
|
||||
508 ; DX = 16 for BIGRAW, 8 for RAW
|
||||
509 ; 8 is selector for a 64K flat segment,
|
||||
510 ; 16 is selector for a 4GB flat segment.
|
||||
511
|
||||
512 00000339 2E0F0116[3000] lgdt [cs:Shaker]
|
||||
513 0000033F 0F20C0 mov eax,cr0
|
||||
514 00000342 0C01 or al,01h
|
||||
515 00000344 0F22C0 mov cr0,eax
|
||||
516
|
||||
517 00000347 BB1000 mov bx,16 ; Large flat segment
|
||||
518 0000034A 8EDB mov ds,bx
|
||||
519 0000034C 8EC3 mov es,bx
|
||||
520
|
||||
521 0000034E 67F366A5 a32 rep movsd
|
||||
522
|
||||
523 ; DX has the appropriate value to put in
|
||||
524 ; the registers on return
|
||||
525 00000352 8EDA mov ds,dx
|
||||
526 00000354 8EC2 mov es,dx
|
||||
527
|
||||
528 00000356 24FE and al,~01h
|
||||
529 00000358 0F22C0 mov cr0,eax
|
||||
530
|
||||
531 0000035B 07 pop es
|
||||
532 0000035C 1F pop ds
|
||||
533
|
||||
534 0000035D 5A pop dx ; A20 status
|
||||
535 0000035E 21D2 and dx,dx
|
||||
536 00000360 7505 jnz .skip_a20d
|
||||
537 00000362 B80024 mov ax,2400h ; Disable A20
|
||||
538 00000365 CD15 int 15h
|
||||
539 .skip_a20d:
|
||||
540 00000367 669D popfd
|
||||
541 00000369 EB5E jmp .done
|
||||
542
|
||||
543 .protmode:
|
||||
544 TRACER 'p'
|
||||
545 .anymode:
|
||||
546
|
||||
547 .copy_loop:
|
||||
548 0000036B 6656 push esi
|
||||
549 0000036D 6657 push edi
|
||||
550 0000036F 6651 push ecx
|
||||
551 00000371 6681F900400000 cmp ecx,4000h
|
||||
552 00000378 7606 jna .safe_size
|
||||
553 0000037A 66B900400000 mov ecx,4000h
|
||||
554 .safe_size:
|
||||
555 00000380 6651 push ecx ; Transfer size this cycle
|
||||
556 00000382 6689F0 mov eax, esi
|
||||
557 00000385 8936[5A00] mov [Mover_src1], si
|
||||
558 00000389 66C1E810 shr eax, 16
|
||||
559 0000038D A2[5C00] mov [Mover_src1+2], al
|
||||
560 00000390 8826[5F00] mov [Mover_src2], ah
|
||||
561 00000394 6689F8 mov eax, edi
|
||||
562 00000397 893E[6200] mov [Mover_dst1], di
|
||||
563 0000039B 66C1E810 shr eax, 16
|
||||
564 0000039F A2[6400] mov [Mover_dst1+2], al
|
||||
565 000003A2 8826[6700] mov [Mover_dst2], ah
|
||||
566 000003A6 BE[4800] mov si,Mover
|
||||
567 000003A9 B487 mov ah, 87h
|
||||
568 000003AB D1E1 shl cx,1 ; Convert to 16-bit words
|
||||
569 000003AD CD15 int 15h
|
||||
570 000003AF FA cli ; Some BIOSes enable interrupts on INT 15h
|
||||
571 000003B0 6658 pop eax ; Transfer size this cycle
|
||||
572 000003B2 6659 pop ecx
|
||||
573 000003B4 665F pop edi
|
||||
574 000003B6 665E pop esi
|
||||
575 000003B8 720F jc .error
|
||||
576 000003BA 66678D3486 lea esi,[esi+4*eax]
|
||||
577 000003BF 66678D3C87 lea edi,[edi+4*eax]
|
||||
578 000003C4 6629C1 sub ecx, eax
|
||||
579 000003C7 75A2 jnz .copy_loop
|
||||
580 ; CF = 0
|
||||
581 .error:
|
||||
582 .done:
|
||||
583 000003C9 665D pop ebp
|
||||
584 000003CB 665A pop edx
|
||||
585 000003CD 665B pop ebx
|
||||
586 000003CF 6658 pop eax
|
||||
587 000003D1 C3 ret
|
||||
588
|
||||
589 %ifdef DEBUG_TRACERS
|
||||
590 debug_tracer: pushad
|
||||
591 pushfd
|
||||
592 mov bp,sp
|
||||
593 mov bx,[bp+9*4]
|
||||
594 mov al,[cs:bx]
|
||||
595 inc word [bp+9*4]
|
||||
596 mov ah,0Eh
|
||||
597 mov bx,7
|
||||
598 int 10h
|
||||
599 popfd
|
||||
600 popad
|
||||
601 ret
|
||||
602 %endif
|
||||
603
|
||||
604 section .data
|
||||
605 alignb 2
|
||||
606 00000000 [BC00] Int13Funcs dw Reset ; 00h - RESET
|
||||
607 00000002 [0501] dw GetStatus ; 01h - GET STATUS
|
||||
608 00000004 [1001] dw Read ; 02h - READ
|
||||
609 00000006 [1B01] dw Write ; 03h - WRITE
|
||||
610 00000008 [2D01] dw Verify ; 04h - VERIFY
|
||||
611 0000000A [E000] dw Invalid ; 05h - FORMAT TRACK
|
||||
612 0000000C [E000] dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
|
||||
613 0000000E [E000] dw Invalid ; 07h - FORMAT DRIVE AT TRACK
|
||||
614 00000010 [3301] dw GetParms ; 08h - GET PARAMETERS
|
||||
615 00000012 [3001] dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
|
||||
616 00000014 [E000] dw Invalid ; 0Ah
|
||||
617 00000016 [E000] dw Invalid ; 0Bh
|
||||
618 00000018 [2D01] dw Seek ; 0Ch - SEEK TO CYLINDER
|
||||
619 0000001A [BC00] dw Reset ; 0Dh - RESET HARD DISKS
|
||||
620 0000001C [E000] dw Invalid ; 0Eh
|
||||
621 0000001E [E000] dw Invalid ; 0Fh
|
||||
622 00000020 [3001] dw CheckIfReady ; 10h - CHECK IF READY
|
||||
623 00000022 [3001] dw Recalibrate ; 11h - RECALIBRATE
|
||||
624 00000024 [E000] dw Invalid ; 12h
|
||||
625 00000026 [E000] dw Invalid ; 13h
|
||||
626 00000028 [E000] dw Invalid ; 14h
|
||||
627 0000002A [E500] dw GetDriveType ; 15h - GET DRIVE TYPE
|
||||
628 0000002C [3001] dw DetectChange ; 16h - DETECT DRIVE CHANGE
|
||||
629 %if 0
|
||||
630 dw Invalid ; 17h
|
||||
631 dw Invalid ; 18h
|
||||
632 dw Invalid ; 19h
|
||||
633 dw Invalid ; 1Ah
|
||||
634 dw Invalid ; 1Bh
|
||||
635 dw Invalid ; 1Ch
|
||||
636 dw Invalid ; 1Dh
|
||||
637 dw Invalid ; 1Eh
|
||||
638 dw Invalid ; 1Fh
|
||||
639 dw Invalid ; 20h
|
||||
640 dw ReadMult ; 21h - READ MULTIPLE
|
||||
641 dw WriteMult ; 22h - WRITE MULTIPLE
|
||||
642 dw SetMode ; 23h - SET CONTROLLER FEATURES
|
||||
643 dw SetMode ; 24h - SET MULTIPLE MODE
|
||||
644 dw Invalid ; 25h - IDENTIFY DRIVE
|
||||
645 dw Invalid ; 26h
|
||||
646 dw Invalid ; 27h
|
||||
647 dw Invalid ; 28h
|
||||
648 dw Invalid ; 29h
|
||||
649 dw Invalid ; 2Ah
|
||||
650 dw Invalid ; 2Bh
|
||||
651 dw Invalid ; 2Ch
|
||||
652 dw Invalid ; 2Dh
|
||||
653 dw Invalid ; 2Eh
|
||||
654 dw Invalid ; 2Fh
|
||||
655 dw Invalid ; 30h
|
||||
656 dw Invalid ; 31h
|
||||
657 dw Invalid ; 32h
|
||||
658 dw Invalid ; 33h
|
||||
659 dw Invalid ; 34h
|
||||
660 dw Invalid ; 35h
|
||||
661 dw Invalid ; 36h
|
||||
662 dw Invalid ; 37h
|
||||
663 dw Invalid ; 38h
|
||||
664 dw Invalid ; 39h
|
||||
665 dw Invalid ; 3Ah
|
||||
666 dw Invalid ; 3Bh
|
||||
667 dw Invalid ; 3Ch
|
||||
668 dw Invalid ; 3Dh
|
||||
669 dw Invalid ; 3Eh
|
||||
670 dw Invalid ; 3Fh
|
||||
671 dw Invalid ; 40h
|
||||
672 dw EDDPresence ; 41h - EDD PRESENCE DETECT
|
||||
673 dw EDDRead ; 42h - EDD READ
|
||||
674 dw EDDWrite ; 43h - EDD WRITE
|
||||
675 dw EDDVerify ; 44h - EDD VERIFY
|
||||
676 dw Invalid ; 45h - EDD LOCK/UNLOCK MEDIA
|
||||
677 dw Invalid ; 46h - EDD EJECT
|
||||
678 dw EDDSeek ; 47h - EDD SEEK
|
||||
679 dw EDDGetParms ; 48h - EDD GET PARAMETERS
|
||||
680 %endif
|
||||
681
|
||||
682 Int13FuncsEnd equ $
|
||||
683 Int13FuncsMax equ (Int13FuncsEnd-Int13Funcs) >> 1
|
||||
684
|
||||
685 0000002E 00<rept> alignb 8, db 0
|
||||
686 00000030 1800 Shaker dw ShakerEnd-$
|
||||
687 00000032 00000000 dd 0 ; Pointer to self
|
||||
688 00000036 0000 dw 0
|
||||
689
|
||||
690 00000038 FFFF0000 Shaker_RMDS: dd 0x0000ffff ; 64K data segment
|
||||
691 0000003C 00930000 dd 0x00009300
|
||||
692
|
||||
693 00000040 FFFF0000 Shaker_DS: dd 0x0000ffff ; 4GB data segment
|
||||
694 00000044 00938F00 dd 0x008f9300
|
||||
695
|
||||
696 ShakerEnd equ $
|
||||
697
|
||||
698 alignb 8, db 0
|
||||
699
|
||||
700
|
||||
701 00000048 000000000000000000- Mover dd 0, 0, 0, 0 ; Must be zero
|
||||
702 00000051 00000000000000
|
||||
703 00000058 FFFF dw 0ffffh ; 64 K segment size
|
||||
704 0000005A 000000 Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
|
||||
705 0000005D 93 db 93h ; Access rights
|
||||
706 0000005E 00 db 00h ; Extended access rights
|
||||
707 0000005F 00 Mover_src2: db 0 ; High 8 bits of source addy
|
||||
708 00000060 FFFF dw 0ffffh ; 64 K segment size
|
||||
709 00000062 000000 Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
|
||||
710 00000065 93 db 93h ; Access rights
|
||||
711 00000066 00 db 00h ; Extended access rights
|
||||
712 00000067 00 Mover_dst2: db 0 ; High 8 bits of source addy
|
||||
713 00000068 000000000000000000- Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
|
||||
714 00000071 00000000000000
|
||||
715
|
||||
716 alignb 4, db 0
|
||||
717 MemDisk_Info equ $ ; Pointed to by installation check
|
||||
718 00000078 1B00 MDI_Bytes dw 27 ; Total bytes in MDI structure
|
||||
719 0000007A 0903 MDI_Version db VER_MINOR, VER_MAJOR ; MEMDISK version
|
||||
720
|
||||
721 PatchArea equ $ ; This gets filled in by the installer
|
||||
722
|
||||
723 0000007C 00000000 DiskBuf dd 0 ; Linear address of high memory disk
|
||||
724 00000080 00000000 DiskSize dd 0 ; Size of disk in blocks
|
||||
725 00000084 00000000 CommandLine dw 0, 0 ; Far pointer to saved command line
|
||||
726
|
||||
727 00000088 00000000 OldInt13 dd 0 ; INT 13h in chain
|
||||
728 0000008C 00000000 OldInt15 dd 0 ; INT 15h in chain
|
||||
729
|
||||
730 00000090 0000 OldDosMem dw 0 ; Old position of DOS mem end
|
||||
731 00000092 00 BootLoaderID db 0 ; Boot loader ID from header
|
||||
732 ; ---- MDI structure ends here ---
|
||||
733 00000093 000000 db 0, 0, 0 ; pad
|
||||
734
|
||||
735 00000096 0000 MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
|
||||
736
|
||||
737 00000098 0000 Cylinders dw 0 ; Cylinder count
|
||||
738 0000009A 0000 Heads dw 0 ; Head count
|
||||
739 0000009C 00000000 Sectors dd 0 ; Sector count (zero-extended)
|
||||
740
|
||||
741 000000A0 00000000 Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
|
||||
742 000000A4 00000000 Mem16MB dd 0 ; 16MB-4G memory amount (64K)
|
||||
743
|
||||
744 000000A8 00 DriveNo db 0 ; Our drive number
|
||||
745 000000A9 00 DriveType db 0 ; Our drive type (floppies)
|
||||
746 000000AA 00 DriveCnt db 0 ; Drive count (from the BIOS)
|
||||
747
|
||||
748 000000AB 00 ConfigFlags db 0 ; Bit 0 - readonly
|
||||
749
|
||||
750 000000AC 0000 MyStack dw 0 ; Offset of stack
|
||||
751 000000AE 0000 StatusPtr dw 0 ; Where to save status (zeroseg ptr)
|
||||
752
|
||||
753 000000B0 00<rept> DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
|
||||
754
|
||||
755 ; End patch area
|
||||
756
|
||||
757 000000C0 00000000 Stack dd 0 ; Saved SS:ESP on invocation
|
||||
758 000000C4 0000 dw 0
|
||||
759 000000C6 0000 SavedAX dw 0 ; AX saved on invocation
|
||||
760
|
||||
761 alignb 4, db 0 ; We *MUST* end on a dword boundary
|
||||
762
|
||||
763 E820Table equ $ ; The installer loads the E820 table here
|
||||
764 TotalSize equ $ ; End pointer
|
||||
BIN
extra/syslinux-3.09/memdisk/memdisk.o
Normal file
BIN
extra/syslinux-3.09/memdisk/memdisk.o
Normal file
Binary file not shown.
768
extra/syslinux-3.09/memdisk/memdisk16.asm
Normal file
768
extra/syslinux-3.09/memdisk/memdisk16.asm
Normal file
@@ -0,0 +1,768 @@
|
||||
;; -*- fundamental -*-
|
||||
;; $Id: memdisk16.asm,v 1.3 2004/12/14 22:46:25 hpa Exp $
|
||||
;; -----------------------------------------------------------------------
|
||||
;;
|
||||
;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
||||
;;
|
||||
;; 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.
|
||||
;;
|
||||
;; -----------------------------------------------------------------------
|
||||
|
||||
;;
|
||||
;; init16.asm
|
||||
;;
|
||||
;; Routine to initialize and to trampoline into 32-bit
|
||||
;; protected memory. This code is derived from bcopy32.inc and
|
||||
;; com32.inc in the main SYSLINUX distribution.
|
||||
;;
|
||||
|
||||
MY_CS equ 0x0800 ; Segment address to use
|
||||
CS_BASE equ (MY_CS << 4) ; Corresponding address
|
||||
|
||||
; Low memory bounce buffer
|
||||
BOUNCE_SEG equ (MY_CS+0x1000)
|
||||
|
||||
%define DO_WBINVD 0
|
||||
|
||||
%define STACK_HEAP_SIZE (128*1024)
|
||||
|
||||
section .rodata align=16
|
||||
section .data align=16
|
||||
section .bss align=16
|
||||
|
||||
;; -----------------------------------------------------------------------
|
||||
;; Kernel image header
|
||||
;; -----------------------------------------------------------------------
|
||||
|
||||
section .text ; Must be first in image
|
||||
bits 16
|
||||
|
||||
cmdline times 497 db 0 ; We put the command line here
|
||||
setup_sects db 0
|
||||
root_flags dw 0
|
||||
syssize dw 0
|
||||
swap_dev dw 0
|
||||
ram_size dw 0
|
||||
vid_mode dw 0
|
||||
root_dev dw 0
|
||||
boot_flag dw 0xAA55
|
||||
|
||||
_start: jmp short start
|
||||
|
||||
db "HdrS" ; Header signature
|
||||
dw 0x0203 ; Header version number
|
||||
|
||||
realmode_swtch dw 0, 0 ; default_switch, SETUPSEG
|
||||
start_sys_seg dw 0x1000 ; obsolete
|
||||
version_ptr dw memdisk_version-0x200 ; version string ptr
|
||||
type_of_loader db 0 ; Filled in by boot loader
|
||||
loadflags db 1 ; Please load high
|
||||
setup_move_size dw 0 ; Unused
|
||||
code32_start dd 0x100000 ; 32-bit start address
|
||||
ramdisk_image dd 0 ; Loaded ramdisk image address
|
||||
ramdisk_size dd 0 ; Size of loaded ramdisk
|
||||
bootsect_kludge dw 0, 0
|
||||
heap_end_ptr dw 0
|
||||
pad1 dw 0
|
||||
cmd_line_ptr dd 0 ; Command line
|
||||
ramdisk_max dd 0xffffffff ; Highest allowed ramdisk address
|
||||
|
||||
section .rodata
|
||||
memdisk_version:
|
||||
db "MEMDISK ", VERSION, " ", DATE, 0
|
||||
|
||||
;; -----------------------------------------------------------------------
|
||||
;; End kernel image header
|
||||
;; -----------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; Move ourselves down into memory to reduce the risk of conflicts;
|
||||
; then canonicalize CS to match the other segments.
|
||||
;
|
||||
section .text
|
||||
bits 16
|
||||
start:
|
||||
mov ax,MY_CS
|
||||
mov es,ax
|
||||
movzx cx,byte [setup_sects]
|
||||
inc cx ; Add one for the boot sector
|
||||
shl cx,7 ; Convert to dwords
|
||||
xor si,si
|
||||
xor di,di
|
||||
mov fs,si ; fs <- 0
|
||||
cld
|
||||
rep movsd
|
||||
mov ds,ax
|
||||
mov ss,ax
|
||||
xor esp,esp ; Stack at top of 64K segment
|
||||
jmp MY_CS:.next
|
||||
.next:
|
||||
|
||||
;
|
||||
; Copy the command line, if there is one
|
||||
;
|
||||
copy_cmdline:
|
||||
xor di,di ; Bottom of our own segment (= "boot sector")
|
||||
mov eax,[cmd_line_ptr]
|
||||
and eax,eax
|
||||
jz .endcmd ; No command line
|
||||
mov si,ax
|
||||
shr eax,4 ; Convert to segment
|
||||
and si,0x000F ; Starting offset only
|
||||
mov gs,ax
|
||||
mov cx,496 ; Max number of bytes
|
||||
.copycmd:
|
||||
gs lodsb
|
||||
and al,al
|
||||
jz .endcmd
|
||||
stosb
|
||||
loop .copycmd
|
||||
.endcmd:
|
||||
xor al,al
|
||||
stosb
|
||||
|
||||
;
|
||||
; Now jump to 32-bit code
|
||||
;
|
||||
sti
|
||||
call init32
|
||||
;
|
||||
; When init32 returns, we have been set up, the new boot sector loaded,
|
||||
; and we should go and and run the newly loaded boot sector
|
||||
;
|
||||
; The setup function returns (in AL) the drive number which should be
|
||||
; put into DL
|
||||
;
|
||||
mov dx,ax
|
||||
|
||||
cli
|
||||
xor esi,esi ; No partition table involved
|
||||
mov ds,si ; Make all the segments consistent
|
||||
mov es,si
|
||||
mov fs,si
|
||||
mov gs,si
|
||||
mov ss,si
|
||||
mov esp,0x7C00 ; Good place for SP to start out
|
||||
jmp 0:0x7C00
|
||||
|
||||
;
|
||||
; We enter protected mode, set up a flat 32-bit environment, run rep movsd
|
||||
; and then exit. IMPORTANT: This code assumes cs == MY_CS.
|
||||
;
|
||||
; This code is probably excessively anal-retentive in its handling of
|
||||
; segments, but this stuff is painful enough as it is without having to rely
|
||||
; on everything happening "as it ought to."
|
||||
;
|
||||
section .rodata
|
||||
|
||||
; desc base, limit, flags
|
||||
%macro desc 3
|
||||
dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
%endmacro
|
||||
|
||||
align 8, db 0
|
||||
call32_gdt: dw call32_gdt_size-1 ; Null descriptor - contains GDT
|
||||
.adj1: dd call32_gdt+CS_BASE ; pointer for LGDT instruction
|
||||
dw 0
|
||||
|
||||
; 0008: Code segment, use16, readable, dpl 0, base CS_BASE, 64K
|
||||
desc CS_BASE, 0xffff, 0x009b
|
||||
|
||||
; 0010: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K
|
||||
desc CS_BASE, 0xffff, 0x0093
|
||||
|
||||
; 0018: Data segment, use16, read/write, dpl 0, base 0, 4G
|
||||
desc 0, 0xfffff, 0x809b
|
||||
|
||||
; 0020: Code segment, use32, read/write, dpl 0, base 0, 4G
|
||||
desc 0, 0xfffff, 0xc09b
|
||||
|
||||
; 0028: Data segment, use32, read/write, dpl 0, base 0, 4G
|
||||
desc 0, 0xfffff, 0xc093
|
||||
|
||||
call32_gdt_size: equ $-call32_gdt
|
||||
|
||||
err_a20: db 'ERROR: A20 gate not responding!',13,10,0
|
||||
|
||||
section .bss
|
||||
alignb 4
|
||||
SavedSSSP resd 1 ; Place to save SS:SP
|
||||
Return resd 1 ; Return value
|
||||
A20Test resw 1 ; Space to test A20
|
||||
A20Tries resb 1
|
||||
|
||||
section .data
|
||||
alignb 4
|
||||
Target dd 0 ; Target address
|
||||
Target_Seg dw 20h ; Target CS
|
||||
|
||||
A20Type dw 0 ; Default = unknown
|
||||
|
||||
section .text
|
||||
bits 16
|
||||
;
|
||||
; Routines to enable and disable (yuck) A20. These routines are gathered
|
||||
; from tips from a couple of sources, including the Linux kernel and
|
||||
; http://www.x86.org/. The need for the delay to be as large as given here
|
||||
; is indicated by Donnie Barnes of RedHat, the problematic system being an
|
||||
; IBM ThinkPad 760EL.
|
||||
;
|
||||
; We typically toggle A20 twice for every 64K transferred.
|
||||
;
|
||||
%define io_delay call _io_delay
|
||||
%define IO_DELAY_PORT 80h ; Invalid port (we hope!)
|
||||
%define disable_wait 32 ; How long to wait for a disable
|
||||
|
||||
%define A20_DUNNO 0 ; A20 type unknown
|
||||
%define A20_NONE 1 ; A20 always on?
|
||||
%define A20_BIOS 2 ; A20 BIOS enable
|
||||
%define A20_KBC 3 ; A20 through KBC
|
||||
%define A20_FAST 4 ; A20 through port 92h
|
||||
|
||||
align 2, db 0
|
||||
A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast
|
||||
A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast
|
||||
a20_adjust_cnt equ ($-A20List)/2
|
||||
|
||||
slow_out: out dx, al ; Fall through
|
||||
|
||||
_io_delay: out IO_DELAY_PORT,al
|
||||
out IO_DELAY_PORT,al
|
||||
ret
|
||||
|
||||
enable_a20:
|
||||
pushad
|
||||
mov byte [A20Tries],255 ; Times to try to make this work
|
||||
|
||||
try_enable_a20:
|
||||
|
||||
;
|
||||
; Flush the caches
|
||||
;
|
||||
%if DO_WBINVD
|
||||
call try_wbinvd
|
||||
%endif
|
||||
|
||||
;
|
||||
; If the A20 type is known, jump straight to type
|
||||
;
|
||||
mov bp,[A20Type]
|
||||
add bp,bp ; Convert to word offset
|
||||
.adj4: jmp word [bp+A20List]
|
||||
|
||||
;
|
||||
; First, see if we are on a system with no A20 gate
|
||||
;
|
||||
a20_dunno:
|
||||
a20_none:
|
||||
mov byte [A20Type], A20_NONE
|
||||
call a20_test
|
||||
jnz a20_done
|
||||
|
||||
;
|
||||
; Next, try the BIOS (INT 15h AX=2401h)
|
||||
;
|
||||
a20_bios:
|
||||
mov byte [A20Type], A20_BIOS
|
||||
mov ax,2401h
|
||||
pushf ; Some BIOSes muck with IF
|
||||
int 15h
|
||||
popf
|
||||
|
||||
call a20_test
|
||||
jnz a20_done
|
||||
|
||||
;
|
||||
; Enable the keyboard controller A20 gate
|
||||
;
|
||||
a20_kbc:
|
||||
mov dl, 1 ; Allow early exit
|
||||
call empty_8042
|
||||
jnz a20_done ; A20 live, no need to use KBC
|
||||
|
||||
mov byte [A20Type], A20_KBC ; Starting KBC command sequence
|
||||
|
||||
mov al,0D1h ; Command write
|
||||
out 064h, al
|
||||
call empty_8042_uncond
|
||||
|
||||
mov al,0DFh ; A20 on
|
||||
out 060h, al
|
||||
call empty_8042_uncond
|
||||
|
||||
; Verify that A20 actually is enabled. Do that by
|
||||
; observing a word in low memory and the same word in
|
||||
; the HMA until they are no longer coherent. Note that
|
||||
; we don't do the same check in the disable case, because
|
||||
; we don't want to *require* A20 masking (SYSLINUX should
|
||||
; work fine without it, if the BIOS does.)
|
||||
.kbc_wait: push cx
|
||||
xor cx,cx
|
||||
.kbc_wait_loop:
|
||||
call a20_test
|
||||
jnz a20_done_pop
|
||||
loop .kbc_wait_loop
|
||||
|
||||
pop cx
|
||||
;
|
||||
; Running out of options here. Final attempt: enable the "fast A20 gate"
|
||||
;
|
||||
a20_fast:
|
||||
mov byte [A20Type], A20_FAST ; Haven't used the KBC yet
|
||||
in al, 092h
|
||||
or al,02h
|
||||
and al,~01h ; Don't accidentally reset the machine!
|
||||
out 092h, al
|
||||
|
||||
.fast_wait: push cx
|
||||
xor cx,cx
|
||||
.fast_wait_loop:
|
||||
call a20_test
|
||||
jnz a20_done_pop
|
||||
loop .fast_wait_loop
|
||||
|
||||
pop cx
|
||||
|
||||
;
|
||||
; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up
|
||||
; and report failure to the user.
|
||||
;
|
||||
|
||||
dec byte [A20Tries]
|
||||
jnz try_enable_a20
|
||||
|
||||
|
||||
; Error message time
|
||||
mov si,err_a20
|
||||
print_err:
|
||||
lodsb
|
||||
and al,al
|
||||
jz die
|
||||
mov bx,7
|
||||
mov ah,0xe
|
||||
int 10h
|
||||
jmp print_err
|
||||
|
||||
|
||||
die:
|
||||
sti
|
||||
.hlt: hlt
|
||||
jmp short .hlt
|
||||
|
||||
;
|
||||
; A20 unmasked, proceed...
|
||||
;
|
||||
a20_done_pop: pop cx
|
||||
a20_done: popad
|
||||
ret
|
||||
|
||||
;
|
||||
; This routine tests if A20 is enabled (ZF = 0). This routine
|
||||
; must not destroy any register contents.
|
||||
;
|
||||
a20_test:
|
||||
push es
|
||||
push cx
|
||||
push ax
|
||||
mov cx,0FFFFh ; HMA = segment 0FFFFh
|
||||
mov es,cx
|
||||
mov cx,32 ; Loop count
|
||||
mov ax,[A20Test]
|
||||
.a20_wait: inc ax
|
||||
mov [A20Test],ax
|
||||
io_delay ; Serialize, and fix delay
|
||||
cmp ax,[es:A20Test+CS_BASE+10h]
|
||||
loopz .a20_wait
|
||||
.a20_done: pop ax
|
||||
pop cx
|
||||
pop es
|
||||
ret
|
||||
|
||||
disable_a20:
|
||||
pushad
|
||||
;
|
||||
; Flush the caches
|
||||
;
|
||||
%if DO_WBINVD
|
||||
call try_wbinvd
|
||||
%endif
|
||||
|
||||
mov bp,[A20Type]
|
||||
add bp,bp ; Convert to word offset
|
||||
.adj5: jmp word [bp+A20DList]
|
||||
|
||||
a20d_bios:
|
||||
mov ax,2400h
|
||||
pushf ; Some BIOSes muck with IF
|
||||
int 15h
|
||||
popf
|
||||
jmp short a20d_snooze
|
||||
|
||||
;
|
||||
; Disable the "fast A20 gate"
|
||||
;
|
||||
a20d_fast:
|
||||
in al, 092h
|
||||
and al,~03h
|
||||
out 092h, al
|
||||
jmp short a20d_snooze
|
||||
|
||||
;
|
||||
; Disable the keyboard controller A20 gate
|
||||
;
|
||||
a20d_kbc:
|
||||
call empty_8042_uncond
|
||||
mov al,0D1h
|
||||
out 064h, al ; Command write
|
||||
call empty_8042_uncond
|
||||
mov al,0DDh ; A20 off
|
||||
out 060h, al
|
||||
call empty_8042_uncond
|
||||
; Wait a bit for it to take effect
|
||||
a20d_snooze:
|
||||
push cx
|
||||
mov cx, disable_wait
|
||||
.delayloop: call a20_test
|
||||
jz .disabled
|
||||
loop .delayloop
|
||||
.disabled: pop cx
|
||||
a20d_dunno:
|
||||
a20d_none:
|
||||
popad
|
||||
ret
|
||||
|
||||
;
|
||||
; Routine to empty the 8042 KBC controller. If dl != 0
|
||||
; then we will test A20 in the loop and exit if A20 is
|
||||
; suddenly enabled.
|
||||
;
|
||||
empty_8042_uncond:
|
||||
xor dl,dl
|
||||
empty_8042:
|
||||
call a20_test
|
||||
jz .a20_on
|
||||
and dl,dl
|
||||
jnz .done
|
||||
.a20_on: io_delay
|
||||
in al, 064h ; Status port
|
||||
test al,1
|
||||
jz .no_output
|
||||
io_delay
|
||||
in al, 060h ; Read input
|
||||
jmp short empty_8042
|
||||
.no_output:
|
||||
test al,2
|
||||
jnz empty_8042
|
||||
io_delay
|
||||
.done: ret
|
||||
|
||||
;
|
||||
; Execute a WBINVD instruction if possible on this CPU
|
||||
;
|
||||
%if DO_WBINVD
|
||||
try_wbinvd:
|
||||
wbinvd
|
||||
ret
|
||||
%endif
|
||||
|
||||
section .bss
|
||||
alignb 4
|
||||
PMESP resd 1 ; Protected mode %esp
|
||||
|
||||
section .idt nobits align=4096
|
||||
alignb 4096
|
||||
pm_idt resb 4096 ; Protected-mode IDT, followed by interrupt stubs
|
||||
|
||||
|
||||
|
||||
|
||||
pm_entry: equ 0x100000
|
||||
|
||||
section .rodata
|
||||
align 4, db 0
|
||||
call32_pmidt:
|
||||
dw 8*256 ; Limit
|
||||
dd pm_idt+CS_BASE ; Address
|
||||
|
||||
call32_rmidt:
|
||||
dw 0ffffh ; Limit
|
||||
dd 0 ; Address
|
||||
|
||||
section .text
|
||||
;
|
||||
; This is the main entrypoint in this function
|
||||
;
|
||||
init32:
|
||||
mov ebx,call32_call_start+CS_BASE ; Where to go in PM
|
||||
|
||||
call32_enter_pm:
|
||||
mov ax,cs
|
||||
mov ds,ax
|
||||
cli
|
||||
mov [SavedSSSP],sp
|
||||
mov [SavedSSSP+2],ss
|
||||
cld
|
||||
call a20_test
|
||||
jnz .a20ok
|
||||
call enable_a20
|
||||
|
||||
.a20ok:
|
||||
lgdt [call32_gdt] ; Set up GDT
|
||||
lidt [call32_pmidt] ; Set up the IDT
|
||||
mov eax,cr0
|
||||
or al,1
|
||||
mov cr0,eax ; Enter protected mode
|
||||
jmp 20h:dword .in_pm+CS_BASE
|
||||
|
||||
bits 32
|
||||
.in_pm:
|
||||
xor eax,eax ; Available for future use...
|
||||
mov fs,eax
|
||||
mov gs,eax
|
||||
|
||||
mov al,28h ; Set up data segments
|
||||
mov es,eax
|
||||
mov ds,eax
|
||||
mov ss,eax
|
||||
|
||||
mov esp,[PMESP+CS_BASE] ; Load protmode %esp if available
|
||||
jmp ebx ; Go to where we need to go
|
||||
|
||||
;
|
||||
; This is invoked before first dispatch of the 32-bit code, in 32-bit mode
|
||||
;
|
||||
call32_call_start:
|
||||
;
|
||||
; Point the stack into low memory
|
||||
; We have: this segment, bounce buffer, then stack+heap
|
||||
;
|
||||
mov esp, CS_BASE + 0x20000 + STACK_HEAP_SIZE
|
||||
and esp, ~0xf
|
||||
|
||||
;
|
||||
; Set up the protmode IDT and the interrupt jump buffers
|
||||
;
|
||||
mov edi,pm_idt+CS_BASE
|
||||
|
||||
; Form an interrupt gate descriptor
|
||||
; WARNING: This is broken if pm_idt crosses a 64K boundary;
|
||||
; however, it can't because of the alignment constraints.
|
||||
mov ebx,pm_idt+CS_BASE+8*256
|
||||
mov eax,0x0020ee00
|
||||
xchg ax,bx
|
||||
xor ecx,ecx
|
||||
inc ch ; ecx <- 256
|
||||
|
||||
push ecx
|
||||
.make_idt:
|
||||
stosd
|
||||
add eax,8
|
||||
xchg eax,ebx
|
||||
stosd
|
||||
xchg eax,ebx
|
||||
loop .make_idt
|
||||
|
||||
pop ecx
|
||||
|
||||
; Each entry in the interrupt jump buffer contains
|
||||
; the following instructions:
|
||||
;
|
||||
; 00000000 60 pushad
|
||||
; 00000001 B0xx mov al,<interrupt#>
|
||||
; 00000003 E9xxxxxxxx jmp call32_handle_interrupt
|
||||
|
||||
mov eax,0xe900b060
|
||||
mov ebx,call32_handle_interrupt+CS_BASE
|
||||
sub ebx,edi
|
||||
|
||||
.make_ijb:
|
||||
stosd
|
||||
sub [edi-2],cl ; Interrupt #
|
||||
xchg eax,ebx
|
||||
sub eax,8
|
||||
stosd
|
||||
xchg eax,ebx
|
||||
loop .make_ijb
|
||||
|
||||
; Now everything is set up for interrupts...
|
||||
|
||||
push dword (BOUNCE_SEG << 4) ; Bounce buffer address
|
||||
push dword call32_syscall+CS_BASE ; Syscall entry point
|
||||
sti ; Interrupts OK now
|
||||
call pm_entry-CS_BASE ; Run the program...
|
||||
|
||||
; ... on return ...
|
||||
mov [Return+CS_BASE],eax
|
||||
|
||||
; ... fall through to call32_exit ...
|
||||
|
||||
call32_exit:
|
||||
mov bx,call32_done ; Return to command loop
|
||||
|
||||
call32_enter_rm:
|
||||
cli
|
||||
cld
|
||||
mov [PMESP+CS_BASE],esp ; Save exit %esp
|
||||
xor esp,esp ; Make sure the high bits are zero
|
||||
jmp 08h:.in_pm16 ; Return to 16-bit mode first
|
||||
|
||||
bits 16
|
||||
.in_pm16:
|
||||
mov ax,10h ; Real-mode-like segment
|
||||
mov es,ax
|
||||
mov ds,ax
|
||||
mov ss,ax
|
||||
mov fs,ax
|
||||
mov gs,ax
|
||||
|
||||
lidt [call32_rmidt] ; Real-mode IDT (rm needs no GDT)
|
||||
mov eax,cr0
|
||||
and al,~1
|
||||
mov cr0,eax
|
||||
jmp MY_CS:.in_rm
|
||||
|
||||
.in_rm: ; Back in real mode
|
||||
mov ax,cs ; Set up sane segments
|
||||
mov ds,ax
|
||||
mov es,ax
|
||||
mov fs,ax
|
||||
mov gs,ax
|
||||
lss sp,[SavedSSSP] ; Restore stack
|
||||
jmp bx ; Go to whereever we need to go...
|
||||
|
||||
call32_done:
|
||||
call disable_a20
|
||||
sti
|
||||
mov ax,[Return]
|
||||
ret
|
||||
|
||||
;
|
||||
; 16-bit support code
|
||||
;
|
||||
bits 16
|
||||
|
||||
;
|
||||
; 16-bit interrupt-handling code
|
||||
;
|
||||
call32_int_rm:
|
||||
pushf ; Flags on stack
|
||||
push cs ; Return segment
|
||||
push word .cont ; Return address
|
||||
push dword edx ; Segment:offset of IVT entry
|
||||
retf ; Invoke IVT routine
|
||||
.cont: ; ... on resume ...
|
||||
mov ebx,call32_int_resume+CS_BASE
|
||||
jmp call32_enter_pm ; Go back to PM
|
||||
|
||||
;
|
||||
; 16-bit system call handling code
|
||||
;
|
||||
call32_sys_rm:
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popad
|
||||
popfd
|
||||
retf ; Invoke routine
|
||||
.return:
|
||||
pushfd
|
||||
pushad
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
mov ebx,call32_sys_resume+CS_BASE
|
||||
jmp call32_enter_pm
|
||||
|
||||
;
|
||||
; 32-bit support code
|
||||
;
|
||||
bits 32
|
||||
|
||||
;
|
||||
; This is invoked on getting an interrupt in protected mode. At
|
||||
; this point, we need to context-switch to real mode and invoke
|
||||
; the interrupt routine.
|
||||
;
|
||||
; When this gets invoked, the registers are saved on the stack and
|
||||
; AL contains the register number.
|
||||
;
|
||||
call32_handle_interrupt:
|
||||
movzx eax,al
|
||||
xor ebx,ebx ; Actually makes the code smaller
|
||||
mov edx,[ebx+eax*4] ; Get the segment:offset of the routine
|
||||
mov bx,call32_int_rm
|
||||
jmp call32_enter_rm ; Go to real mode
|
||||
|
||||
call32_int_resume:
|
||||
popad
|
||||
iret
|
||||
|
||||
;
|
||||
; Syscall invocation. We manifest a structure on the real-mode stack,
|
||||
; containing the call32sys_t structure from <call32.h> as well as
|
||||
; the following entries (from low to high address):
|
||||
; - Target offset
|
||||
; - Target segment
|
||||
; - Return offset
|
||||
; - Return segment (== real mode cs)
|
||||
; - Return flags
|
||||
;
|
||||
call32_syscall:
|
||||
pushfd ; Save IF among other things...
|
||||
pushad ; We only need to save some, but...
|
||||
cld
|
||||
|
||||
movzx edi,word [SavedSSSP+CS_BASE]
|
||||
movzx eax,word [SavedSSSP+CS_BASE+2]
|
||||
sub edi,54 ; Allocate 54 bytes
|
||||
mov [SavedSSSP+CS_BASE],di
|
||||
shl eax,4
|
||||
add edi,eax ; Create linear address
|
||||
|
||||
mov esi,[esp+11*4] ; Source regs
|
||||
xor ecx,ecx
|
||||
mov cl,11 ; 44 bytes to copy
|
||||
rep movsd
|
||||
|
||||
movzx eax,byte [esp+10*4] ; Interrupt number
|
||||
; ecx == 0 here; adding it to the EA makes the
|
||||
; encoding smaller
|
||||
mov eax,[ecx+eax*4] ; Get IVT entry
|
||||
stosd ; Save in stack frame
|
||||
mov eax,call32_sys_rm.return + (MY_CS << 16) ; Return seg:offs
|
||||
stosd ; Save in stack frame
|
||||
mov eax,[edi-12] ; Return flags
|
||||
and eax,0x200cd7 ; Mask (potentially) unsafe flags
|
||||
mov [edi-12],eax ; Primary flags entry
|
||||
stosw ; Return flags
|
||||
|
||||
mov bx,call32_sys_rm
|
||||
jmp call32_enter_rm ; Go to real mode
|
||||
|
||||
; On return, the 44-byte return structure is on the
|
||||
; real-mode stack.
|
||||
call32_sys_resume:
|
||||
movzx esi,word [SavedSSSP+CS_BASE]
|
||||
movzx eax,word [SavedSSSP+CS_BASE+2]
|
||||
mov edi,[esp+12*4] ; Dest regs
|
||||
shl eax,4
|
||||
add esi,eax ; Create linear address
|
||||
and edi,edi ; NULL pointer?
|
||||
jnz .do_copy
|
||||
.no_copy: mov edi,esi ; Do a dummy copy-to-self
|
||||
.do_copy: xor ecx,ecx
|
||||
mov cl,11 ; 44 bytes
|
||||
rep movsd ; Copy register block
|
||||
|
||||
add dword [SavedSSSP+CS_BASE],44 ; Remove from stack
|
||||
|
||||
popad
|
||||
popfd
|
||||
ret ; Return to 32-bit program
|
||||
BIN
extra/syslinux-3.09/memdisk/memdisk16.bin
Normal file
BIN
extra/syslinux-3.09/memdisk/memdisk16.bin
Normal file
Binary file not shown.
785
extra/syslinux-3.09/memdisk/memdisk16.lst
Normal file
785
extra/syslinux-3.09/memdisk/memdisk16.lst
Normal file
@@ -0,0 +1,785 @@
|
||||
1 ;; -*- fundamental -*-
|
||||
2 ;; $Id: memdisk16.asm,v 1.3 2004/12/14 22:46:25 hpa Exp $
|
||||
3 ;; -----------------------------------------------------------------------
|
||||
4 ;;
|
||||
5 ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
||||
6 ;;
|
||||
7 ;; This program is free software; you can redistribute it and/or modify
|
||||
8 ;; it under the terms of the GNU General Public License as published by
|
||||
9 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
||||
10 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
||||
11 ;; (at your option) any later version; incorporated herein by reference.
|
||||
12 ;;
|
||||
13 ;; -----------------------------------------------------------------------
|
||||
14
|
||||
15 ;;
|
||||
16 ;; init16.asm
|
||||
17 ;;
|
||||
18 ;; Routine to initialize and to trampoline into 32-bit
|
||||
19 ;; protected memory. This code is derived from bcopy32.inc and
|
||||
20 ;; com32.inc in the main SYSLINUX distribution.
|
||||
21 ;;
|
||||
22
|
||||
23 MY_CS equ 0x0800 ; Segment address to use
|
||||
24 CS_BASE equ (MY_CS << 4) ; Corresponding address
|
||||
25
|
||||
26 ; Low memory bounce buffer
|
||||
27 BOUNCE_SEG equ (MY_CS+0x1000)
|
||||
28
|
||||
29 %define DO_WBINVD 0
|
||||
30
|
||||
31 %define STACK_HEAP_SIZE (128*1024)
|
||||
32
|
||||
33 section .rodata align=16
|
||||
34 section .data align=16
|
||||
35 section .bss align=16
|
||||
36
|
||||
37 ;; -----------------------------------------------------------------------
|
||||
38 ;; Kernel image header
|
||||
39 ;; -----------------------------------------------------------------------
|
||||
40
|
||||
41 section .text ; Must be first in image
|
||||
42 bits 16
|
||||
43
|
||||
44 00000000 00<rept> cmdline times 497 db 0 ; We put the command line here
|
||||
45 000001F1 00 setup_sects db 0
|
||||
46 000001F2 0000 root_flags dw 0
|
||||
47 000001F4 0000 syssize dw 0
|
||||
48 000001F6 0000 swap_dev dw 0
|
||||
49 000001F8 0000 ram_size dw 0
|
||||
50 000001FA 0000 vid_mode dw 0
|
||||
51 000001FC 0000 root_dev dw 0
|
||||
52 000001FE 55AA boot_flag dw 0xAA55
|
||||
53
|
||||
54 00000200 EB2E _start: jmp short start
|
||||
55
|
||||
56 00000202 48647253 db "HdrS" ; Header signature
|
||||
57 00000206 0302 dw 0x0203 ; Header version number
|
||||
58
|
||||
59 00000208 00000000 realmode_swtch dw 0, 0 ; default_switch, SETUPSEG
|
||||
60 0000020C 0010 start_sys_seg dw 0x1000 ; obsolete
|
||||
61 0000020E [00FE] version_ptr dw memdisk_version-0x200 ; version string ptr
|
||||
62 00000210 00 type_of_loader db 0 ; Filled in by boot loader
|
||||
63 00000211 01 loadflags db 1 ; Please load high
|
||||
64 00000212 0000 setup_move_size dw 0 ; Unused
|
||||
65 00000214 00001000 code32_start dd 0x100000 ; 32-bit start address
|
||||
66 00000218 00000000 ramdisk_image dd 0 ; Loaded ramdisk image address
|
||||
67 0000021C 00000000 ramdisk_size dd 0 ; Size of loaded ramdisk
|
||||
68 00000220 00000000 bootsect_kludge dw 0, 0
|
||||
69 00000224 0000 heap_end_ptr dw 0
|
||||
70 00000226 0000 pad1 dw 0
|
||||
71 00000228 00000000 cmd_line_ptr dd 0 ; Command line
|
||||
72 0000022C FFFFFFFF ramdisk_max dd 0xffffffff ; Highest allowed ramdisk address
|
||||
73
|
||||
74 section .rodata
|
||||
75 memdisk_version:
|
||||
76 00000000 4D454D4449534B2033- db "MEMDISK ", VERSION, " ", DATE, 0
|
||||
77 00000009 2E3039203078343165-
|
||||
78 00000012 666662636100
|
||||
79
|
||||
80 ;; -----------------------------------------------------------------------
|
||||
81 ;; End kernel image header
|
||||
82 ;; -----------------------------------------------------------------------
|
||||
83
|
||||
84 ;
|
||||
85 ; Move ourselves down into memory to reduce the risk of conflicts;
|
||||
86 ; then canonicalize CS to match the other segments.
|
||||
87 ;
|
||||
88 section .text
|
||||
89 bits 16
|
||||
90 start:
|
||||
91 00000230 B80008 mov ax,MY_CS
|
||||
92 00000233 8EC0 mov es,ax
|
||||
93 00000235 0FB60E[F101] movzx cx,byte [setup_sects]
|
||||
94 0000023A 41 inc cx ; Add one for the boot sector
|
||||
95 0000023B C1E107 shl cx,7 ; Convert to dwords
|
||||
96 0000023E 31F6 xor si,si
|
||||
97 00000240 31FF xor di,di
|
||||
98 00000242 8EE6 mov fs,si ; fs <- 0
|
||||
99 00000244 FC cld
|
||||
100 00000245 F366A5 rep movsd
|
||||
101 00000248 8ED8 mov ds,ax
|
||||
102 0000024A 8ED0 mov ss,ax
|
||||
103 0000024C 6631E4 xor esp,esp ; Stack at top of 64K segment
|
||||
104 0000024F EA[5402]0008 jmp MY_CS:.next
|
||||
105 .next:
|
||||
106
|
||||
107 ;
|
||||
108 ; Copy the command line, if there is one
|
||||
109 ;
|
||||
110 copy_cmdline:
|
||||
111 00000254 31FF xor di,di ; Bottom of our own segment (= "boot sector")
|
||||
112 00000256 66A1[2802] mov eax,[cmd_line_ptr]
|
||||
113 0000025A 6621C0 and eax,eax
|
||||
114 0000025D 7417 jz .endcmd ; No command line
|
||||
115 0000025F 89C6 mov si,ax
|
||||
116 00000261 66C1E804 shr eax,4 ; Convert to segment
|
||||
117 00000265 83E60F and si,0x000F ; Starting offset only
|
||||
118 00000268 8EE8 mov gs,ax
|
||||
119 0000026A B9F001 mov cx,496 ; Max number of bytes
|
||||
120 .copycmd:
|
||||
121 0000026D 65AC gs lodsb
|
||||
122 0000026F 20C0 and al,al
|
||||
123 00000271 7403 jz .endcmd
|
||||
124 00000273 AA stosb
|
||||
125 00000274 E2F7 loop .copycmd
|
||||
126 .endcmd:
|
||||
127 00000276 30C0 xor al,al
|
||||
128 00000278 AA stosb
|
||||
129
|
||||
130 ;
|
||||
131 ; Now jump to 32-bit code
|
||||
132 ;
|
||||
133 00000279 FB sti
|
||||
134 0000027A E83D01 call init32
|
||||
135 ;
|
||||
136 ; When init32 returns, we have been set up, the new boot sector loaded,
|
||||
137 ; and we should go and and run the newly loaded boot sector
|
||||
138 ;
|
||||
139 ; The setup function returns (in AL) the drive number which should be
|
||||
140 ; put into DL
|
||||
141 ;
|
||||
142 0000027D 89C2 mov dx,ax
|
||||
143
|
||||
144 0000027F FA cli
|
||||
145 00000280 6631F6 xor esi,esi ; No partition table involved
|
||||
146 00000283 8EDE mov ds,si ; Make all the segments consistent
|
||||
147 00000285 8EC6 mov es,si
|
||||
148 00000287 8EE6 mov fs,si
|
||||
149 00000289 8EEE mov gs,si
|
||||
150 0000028B 8ED6 mov ss,si
|
||||
151 0000028D 66BC007C0000 mov esp,0x7C00 ; Good place for SP to start out
|
||||
152 00000293 EA007C0000 jmp 0:0x7C00
|
||||
153
|
||||
154 ;
|
||||
155 ; We enter protected mode, set up a flat 32-bit environment, run rep movsd
|
||||
156 ; and then exit. IMPORTANT: This code assumes cs == MY_CS.
|
||||
157 ;
|
||||
158 ; This code is probably excessively anal-retentive in its handling of
|
||||
159 ; segments, but this stuff is painful enough as it is without having to rely
|
||||
160 ; on everything happening "as it ought to."
|
||||
161 ;
|
||||
162 section .rodata
|
||||
163
|
||||
164 ; desc base, limit, flags
|
||||
165 %macro desc 3
|
||||
166 dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
167 dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
168 %endmacro
|
||||
169
|
||||
170 align 8, db 0
|
||||
171 00000018 2F00 call32_gdt: dw call32_gdt_size-1 ; Null descriptor - contains GDT
|
||||
172 0000001A [18800000] .adj1: dd call32_gdt+CS_BASE ; pointer for LGDT instruction
|
||||
173 0000001E 0000 dw 0
|
||||
174
|
||||
175 ; 0008: Code segment, use16, readable, dpl 0, base CS_BASE, 64K
|
||||
176 desc CS_BASE, 0xffff, 0x009b
|
||||
177 00000020 FFFF0080 <1> dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
178 00000024 009B0000 <1> dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
179
|
||||
180 ; 0010: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K
|
||||
181 desc CS_BASE, 0xffff, 0x0093
|
||||
182 00000028 FFFF0080 <1> dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
183 0000002C 00930000 <1> dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
184
|
||||
185 ; 0018: Data segment, use16, read/write, dpl 0, base 0, 4G
|
||||
186 desc 0, 0xfffff, 0x809b
|
||||
187 00000030 FFFF0000 <1> dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
188 00000034 009B8F00 <1> dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
189
|
||||
190 ; 0020: Code segment, use32, read/write, dpl 0, base 0, 4G
|
||||
191 desc 0, 0xfffff, 0xc09b
|
||||
192 00000038 FFFF0000 <1> dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
193 0000003C 009BCF00 <1> dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
194
|
||||
195 ; 0028: Data segment, use32, read/write, dpl 0, base 0, 4G
|
||||
196 desc 0, 0xfffff, 0xc093
|
||||
197 00000040 FFFF0000 <1> dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)
|
||||
198 00000044 0093CF00 <1> dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)
|
||||
199
|
||||
200 call32_gdt_size: equ $-call32_gdt
|
||||
201
|
||||
202 00000048 4552524F523A204132- err_a20: db 'ERROR: A20 gate not responding!',13,10,0
|
||||
203 00000051 302067617465206E6F-
|
||||
204 0000005A 7420726573706F6E64-
|
||||
205 00000063 696E67210D0A00
|
||||
206
|
||||
207 section .bss
|
||||
208 alignb 4
|
||||
209 00000000 <res 00000004> SavedSSSP resd 1 ; Place to save SS:SP
|
||||
210 00000004 <res 00000004> Return resd 1 ; Return value
|
||||
211 00000008 <res 00000002> A20Test resw 1 ; Space to test A20
|
||||
212 0000000A <res 00000001> A20Tries resb 1
|
||||
213
|
||||
214 section .data
|
||||
215 alignb 4
|
||||
216 00000000 00000000 Target dd 0 ; Target address
|
||||
217 00000004 2000 Target_Seg dw 20h ; Target CS
|
||||
218
|
||||
219 00000006 0000 A20Type dw 0 ; Default = unknown
|
||||
220
|
||||
221 section .text
|
||||
222 bits 16
|
||||
223 ;
|
||||
224 ; Routines to enable and disable (yuck) A20. These routines are gathered
|
||||
225 ; from tips from a couple of sources, including the Linux kernel and
|
||||
226 ; http://www.x86.org/. The need for the delay to be as large as given here
|
||||
227 ; is indicated by Donnie Barnes of RedHat, the problematic system being an
|
||||
228 ; IBM ThinkPad 760EL.
|
||||
229 ;
|
||||
230 ; We typically toggle A20 twice for every 64K transferred.
|
||||
231 ;
|
||||
232 %define io_delay call _io_delay
|
||||
233 %define IO_DELAY_PORT 80h ; Invalid port (we hope!)
|
||||
234 %define disable_wait 32 ; How long to wait for a disable
|
||||
235
|
||||
236 %define A20_DUNNO 0 ; A20 type unknown
|
||||
237 %define A20_NONE 1 ; A20 always on?
|
||||
238 %define A20_BIOS 2 ; A20 BIOS enable
|
||||
239 %define A20_KBC 3 ; A20 through KBC
|
||||
240 %define A20_FAST 4 ; A20 through port 92h
|
||||
241
|
||||
242 align 2, db 0
|
||||
243 00000298 [C302][C302][CD02]- A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast
|
||||
244 0000029E [DE02][0303]
|
||||
245 000002A2 [9403][9403][6603]- A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast
|
||||
246 000002A8 [7703][6F03]
|
||||
247 a20_adjust_cnt equ ($-A20List)/2
|
||||
248
|
||||
249 000002AC EE slow_out: out dx, al ; Fall through
|
||||
250
|
||||
251 000002AD E680 _io_delay: out IO_DELAY_PORT,al
|
||||
252 000002AF E680 out IO_DELAY_PORT,al
|
||||
253 000002B1 C3 ret
|
||||
254
|
||||
255 enable_a20:
|
||||
256 000002B2 6660 pushad
|
||||
257 000002B4 C606[0A00]FF mov byte [A20Tries],255 ; Times to try to make this work
|
||||
258
|
||||
259 try_enable_a20:
|
||||
260
|
||||
261 ;
|
||||
262 ; Flush the caches
|
||||
263 ;
|
||||
264 %if DO_WBINVD
|
||||
265 call try_wbinvd
|
||||
266 %endif
|
||||
267
|
||||
268 ;
|
||||
269 ; If the A20 type is known, jump straight to type
|
||||
270 ;
|
||||
271 000002B9 8B2E[0600] mov bp,[A20Type]
|
||||
272 000002BD 01ED add bp,bp ; Convert to word offset
|
||||
273 000002BF FFA6[9802] .adj4: jmp word [bp+A20List]
|
||||
274
|
||||
275 ;
|
||||
276 ; First, see if we are on a system with no A20 gate
|
||||
277 ;
|
||||
278 a20_dunno:
|
||||
279 a20_none:
|
||||
280 000002C3 C606[0600]01 mov byte [A20Type], A20_NONE
|
||||
281 000002C8 E86F00 call a20_test
|
||||
282 000002CB 756A jnz a20_done
|
||||
283
|
||||
284 ;
|
||||
285 ; Next, try the BIOS (INT 15h AX=2401h)
|
||||
286 ;
|
||||
287 a20_bios:
|
||||
288 000002CD C606[0600]02 mov byte [A20Type], A20_BIOS
|
||||
289 000002D2 B80124 mov ax,2401h
|
||||
290 000002D5 9C pushf ; Some BIOSes muck with IF
|
||||
291 000002D6 CD15 int 15h
|
||||
292 000002D8 9D popf
|
||||
293
|
||||
294 000002D9 E85E00 call a20_test
|
||||
295 000002DC 7559 jnz a20_done
|
||||
296
|
||||
297 ;
|
||||
298 ; Enable the keyboard controller A20 gate
|
||||
299 ;
|
||||
300 a20_kbc:
|
||||
301 000002DE B201 mov dl, 1 ; Allow early exit
|
||||
302 000002E0 E8B600 call empty_8042
|
||||
303 000002E3 7552 jnz a20_done ; A20 live, no need to use KBC
|
||||
304
|
||||
305 000002E5 C606[0600]03 mov byte [A20Type], A20_KBC ; Starting KBC command sequence
|
||||
306
|
||||
307 000002EA B0D1 mov al,0D1h ; Command write
|
||||
308 000002EC E664 out 064h, al
|
||||
309 000002EE E8A600 call empty_8042_uncond
|
||||
310
|
||||
311 000002F1 B0DF mov al,0DFh ; A20 on
|
||||
312 000002F3 E660 out 060h, al
|
||||
313 000002F5 E89F00 call empty_8042_uncond
|
||||
314
|
||||
315 ; Verify that A20 actually is enabled. Do that by
|
||||
316 ; observing a word in low memory and the same word in
|
||||
317 ; the HMA until they are no longer coherent. Note that
|
||||
318 ; we don't do the same check in the disable case, because
|
||||
319 ; we don't want to *require* A20 masking (SYSLINUX should
|
||||
320 ; work fine without it, if the BIOS does.)
|
||||
321 000002F8 51 .kbc_wait: push cx
|
||||
322 000002F9 31C9 xor cx,cx
|
||||
323 .kbc_wait_loop:
|
||||
324 000002FB E83C00 call a20_test
|
||||
325 000002FE 7536 jnz a20_done_pop
|
||||
326 00000300 E2F9 loop .kbc_wait_loop
|
||||
327
|
||||
328 00000302 59 pop cx
|
||||
329 ;
|
||||
330 ; Running out of options here. Final attempt: enable the "fast A20 gate"
|
||||
331 ;
|
||||
332 a20_fast:
|
||||
333 00000303 C606[0600]04 mov byte [A20Type], A20_FAST ; Haven't used the KBC yet
|
||||
334 00000308 E492 in al, 092h
|
||||
335 0000030A 0C02 or al,02h
|
||||
336 0000030C 24FE and al,~01h ; Don't accidentally reset the machine!
|
||||
337 0000030E E692 out 092h, al
|
||||
338
|
||||
339 00000310 51 .fast_wait: push cx
|
||||
340 00000311 31C9 xor cx,cx
|
||||
341 .fast_wait_loop:
|
||||
342 00000313 E82400 call a20_test
|
||||
343 00000316 751E jnz a20_done_pop
|
||||
344 00000318 E2F9 loop .fast_wait_loop
|
||||
345
|
||||
346 0000031A 59 pop cx
|
||||
347
|
||||
348 ;
|
||||
349 ; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up
|
||||
350 ; and report failure to the user.
|
||||
351 ;
|
||||
352
|
||||
353 0000031B FE0E[0A00] dec byte [A20Tries]
|
||||
354 0000031F 7598 jnz try_enable_a20
|
||||
355
|
||||
356
|
||||
357 ; Error message time
|
||||
358 00000321 BE[4800] mov si,err_a20
|
||||
359 print_err:
|
||||
360 00000324 AC lodsb
|
||||
361 00000325 20C0 and al,al
|
||||
362 00000327 7409 jz die
|
||||
363 00000329 BB0700 mov bx,7
|
||||
364 0000032C B40E mov ah,0xe
|
||||
365 0000032E CD10 int 10h
|
||||
366 00000330 EBF2 jmp print_err
|
||||
367
|
||||
368
|
||||
369 die:
|
||||
370 00000332 FB sti
|
||||
371 00000333 F4 .hlt: hlt
|
||||
372 00000334 EBFD jmp short .hlt
|
||||
373
|
||||
374 ;
|
||||
375 ; A20 unmasked, proceed...
|
||||
376 ;
|
||||
377 00000336 59 a20_done_pop: pop cx
|
||||
378 00000337 6661 a20_done: popad
|
||||
379 00000339 C3 ret
|
||||
380
|
||||
381 ;
|
||||
382 ; This routine tests if A20 is enabled (ZF = 0). This routine
|
||||
383 ; must not destroy any register contents.
|
||||
384 ;
|
||||
385 a20_test:
|
||||
386 0000033A 06 push es
|
||||
387 0000033B 51 push cx
|
||||
388 0000033C 50 push ax
|
||||
389 0000033D B9FFFF mov cx,0FFFFh ; HMA = segment 0FFFFh
|
||||
390 00000340 8EC1 mov es,cx
|
||||
391 00000342 B92000 mov cx,32 ; Loop count
|
||||
392 00000345 A1[0800] mov ax,[A20Test]
|
||||
393 00000348 40 .a20_wait: inc ax
|
||||
394 00000349 A3[0800] mov [A20Test],ax
|
||||
395 0000034C E85EFF io_delay ; Serialize, and fix delay
|
||||
396 0000034F 263B06[1880] cmp ax,[es:A20Test+CS_BASE+10h]
|
||||
397 00000354 E1F2 loopz .a20_wait
|
||||
398 00000356 58 .a20_done: pop ax
|
||||
399 00000357 59 pop cx
|
||||
400 00000358 07 pop es
|
||||
401 00000359 C3 ret
|
||||
402
|
||||
403 disable_a20:
|
||||
404 0000035A 6660 pushad
|
||||
405 ;
|
||||
406 ; Flush the caches
|
||||
407 ;
|
||||
408 %if DO_WBINVD
|
||||
409 call try_wbinvd
|
||||
410 %endif
|
||||
411
|
||||
412 0000035C 8B2E[0600] mov bp,[A20Type]
|
||||
413 00000360 01ED add bp,bp ; Convert to word offset
|
||||
414 00000362 FFA6[A202] .adj5: jmp word [bp+A20DList]
|
||||
415
|
||||
416 a20d_bios:
|
||||
417 00000366 B80024 mov ax,2400h
|
||||
418 00000369 9C pushf ; Some BIOSes muck with IF
|
||||
419 0000036A CD15 int 15h
|
||||
420 0000036C 9D popf
|
||||
421 0000036D EB19 jmp short a20d_snooze
|
||||
422
|
||||
423 ;
|
||||
424 ; Disable the "fast A20 gate"
|
||||
425 ;
|
||||
426 a20d_fast:
|
||||
427 0000036F E492 in al, 092h
|
||||
428 00000371 24FC and al,~03h
|
||||
429 00000373 E692 out 092h, al
|
||||
430 00000375 EB11 jmp short a20d_snooze
|
||||
431
|
||||
432 ;
|
||||
433 ; Disable the keyboard controller A20 gate
|
||||
434 ;
|
||||
435 a20d_kbc:
|
||||
436 00000377 E81D00 call empty_8042_uncond
|
||||
437 0000037A B0D1 mov al,0D1h
|
||||
438 0000037C E664 out 064h, al ; Command write
|
||||
439 0000037E E81600 call empty_8042_uncond
|
||||
440 00000381 B0DD mov al,0DDh ; A20 off
|
||||
441 00000383 E660 out 060h, al
|
||||
442 00000385 E80F00 call empty_8042_uncond
|
||||
443 ; Wait a bit for it to take effect
|
||||
444 a20d_snooze:
|
||||
445 00000388 51 push cx
|
||||
446 00000389 B92000 mov cx, disable_wait
|
||||
447 0000038C E8ABFF .delayloop: call a20_test
|
||||
448 0000038F 7402 jz .disabled
|
||||
449 00000391 E2F9 loop .delayloop
|
||||
450 00000393 59 .disabled: pop cx
|
||||
451 a20d_dunno:
|
||||
452 a20d_none:
|
||||
453 00000394 6661 popad
|
||||
454 00000396 C3 ret
|
||||
455
|
||||
456 ;
|
||||
457 ; Routine to empty the 8042 KBC controller. If dl != 0
|
||||
458 ; then we will test A20 in the loop and exit if A20 is
|
||||
459 ; suddenly enabled.
|
||||
460 ;
|
||||
461 empty_8042_uncond:
|
||||
462 00000397 30D2 xor dl,dl
|
||||
463 empty_8042:
|
||||
464 00000399 E89EFF call a20_test
|
||||
465 0000039C 7404 jz .a20_on
|
||||
466 0000039E 20D2 and dl,dl
|
||||
467 000003A0 7517 jnz .done
|
||||
468 000003A2 E808FF .a20_on: io_delay
|
||||
469 000003A5 E464 in al, 064h ; Status port
|
||||
470 000003A7 A801 test al,1
|
||||
471 000003A9 7407 jz .no_output
|
||||
472 000003AB E8FFFE io_delay
|
||||
473 000003AE E460 in al, 060h ; Read input
|
||||
474 000003B0 EBE7 jmp short empty_8042
|
||||
475 .no_output:
|
||||
476 000003B2 A802 test al,2
|
||||
477 000003B4 75E3 jnz empty_8042
|
||||
478 000003B6 E8F4FE io_delay
|
||||
479 000003B9 C3 .done: ret
|
||||
480
|
||||
481 ;
|
||||
482 ; Execute a WBINVD instruction if possible on this CPU
|
||||
483 ;
|
||||
484 %if DO_WBINVD
|
||||
485 try_wbinvd:
|
||||
486 wbinvd
|
||||
487 ret
|
||||
488 %endif
|
||||
489
|
||||
490 section .bss
|
||||
491 0000000B <res 00000001> alignb 4
|
||||
492 0000000C <res 00000004> PMESP resd 1 ; Protected mode %esp
|
||||
493
|
||||
494 section .idt nobits align=4096
|
||||
495 alignb 4096
|
||||
496 00000000 <res 00001000> pm_idt resb 4096 ; Protected-mode IDT, followed by interrupt stubs
|
||||
497
|
||||
498
|
||||
499
|
||||
500
|
||||
501 pm_entry: equ 0x100000
|
||||
502
|
||||
503 section .rodata
|
||||
504 0000006A 00<rept> align 4, db 0
|
||||
505 call32_pmidt:
|
||||
506 0000006C 0008 dw 8*256 ; Limit
|
||||
507 0000006E [00800000] dd pm_idt+CS_BASE ; Address
|
||||
508
|
||||
509 call32_rmidt:
|
||||
510 00000072 FFFF dw 0ffffh ; Limit
|
||||
511 00000074 00000000 dd 0 ; Address
|
||||
512
|
||||
513 section .text
|
||||
514 ;
|
||||
515 ; This is the main entrypoint in this function
|
||||
516 ;
|
||||
517 init32:
|
||||
518 000003BA 66BB[06840000] mov ebx,call32_call_start+CS_BASE ; Where to go in PM
|
||||
519
|
||||
520 call32_enter_pm:
|
||||
521 000003C0 8CC8 mov ax,cs
|
||||
522 000003C2 8ED8 mov ds,ax
|
||||
523 000003C4 FA cli
|
||||
524 000003C5 8926[0000] mov [SavedSSSP],sp
|
||||
525 000003C9 8C16[0200] mov [SavedSSSP+2],ss
|
||||
526 000003CD FC cld
|
||||
527 000003CE E869FF call a20_test
|
||||
528 000003D1 7503 jnz .a20ok
|
||||
529 000003D3 E8DCFE call enable_a20
|
||||
530
|
||||
531 .a20ok:
|
||||
532 000003D6 0F0116[1800] lgdt [call32_gdt] ; Set up GDT
|
||||
533 000003DB 0F011E[6C00] lidt [call32_pmidt] ; Set up the IDT
|
||||
534 000003E0 0F20C0 mov eax,cr0
|
||||
535 000003E3 0C01 or al,1
|
||||
536 000003E5 0F22C0 mov cr0,eax ; Enter protected mode
|
||||
537 000003E8 66EA[F0830000]2000 jmp 20h:dword .in_pm+CS_BASE
|
||||
538
|
||||
539 bits 32
|
||||
540 .in_pm:
|
||||
541 000003F0 31C0 xor eax,eax ; Available for future use...
|
||||
542 000003F2 8EE0 mov fs,eax
|
||||
543 000003F4 8EE8 mov gs,eax
|
||||
544
|
||||
545 000003F6 B028 mov al,28h ; Set up data segments
|
||||
546 000003F8 8EC0 mov es,eax
|
||||
547 000003FA 8ED8 mov ds,eax
|
||||
548 000003FC 8ED0 mov ss,eax
|
||||
549
|
||||
550 000003FE 8B25[0C800000] mov esp,[PMESP+CS_BASE] ; Load protmode %esp if available
|
||||
551 00000404 FFE3 jmp ebx ; Go to where we need to go
|
||||
552
|
||||
553 ;
|
||||
554 ; This is invoked before first dispatch of the 32-bit code, in 32-bit mode
|
||||
555 ;
|
||||
556 call32_call_start:
|
||||
557 ;
|
||||
558 ; Point the stack into low memory
|
||||
559 ; We have: this segment, bounce buffer, then stack+heap
|
||||
560 ;
|
||||
561 00000406 BC00800400 mov esp, CS_BASE + 0x20000 + STACK_HEAP_SIZE
|
||||
562 0000040B 83E4F0 and esp, ~0xf
|
||||
563
|
||||
564 ;
|
||||
565 ; Set up the protmode IDT and the interrupt jump buffers
|
||||
566 ;
|
||||
567 0000040E BF[00800000] mov edi,pm_idt+CS_BASE
|
||||
568
|
||||
569 ; Form an interrupt gate descriptor
|
||||
570 ; WARNING: This is broken if pm_idt crosses a 64K boundary;
|
||||
571 ; however, it can't because of the alignment constraints.
|
||||
572 00000413 BB[00880000] mov ebx,pm_idt+CS_BASE+8*256
|
||||
573 00000418 B800EE2000 mov eax,0x0020ee00
|
||||
574 0000041D 6693 xchg ax,bx
|
||||
575 0000041F 31C9 xor ecx,ecx
|
||||
576 00000421 FEC5 inc ch ; ecx <- 256
|
||||
577
|
||||
578 00000423 51 push ecx
|
||||
579 .make_idt:
|
||||
580 00000424 AB stosd
|
||||
581 00000425 83C008 add eax,8
|
||||
582 00000428 93 xchg eax,ebx
|
||||
583 00000429 AB stosd
|
||||
584 0000042A 93 xchg eax,ebx
|
||||
585 0000042B E2F7 loop .make_idt
|
||||
586
|
||||
587 0000042D 59 pop ecx
|
||||
588
|
||||
589 ; Each entry in the interrupt jump buffer contains
|
||||
590 ; the following instructions:
|
||||
591 ;
|
||||
592 ; 00000000 60 pushad
|
||||
593 ; 00000001 B0xx mov al,<interrupt#>
|
||||
594 ; 00000003 E9xxxxxxxx jmp call32_handle_interrupt
|
||||
595
|
||||
596 0000042E B860B000E9 mov eax,0xe900b060
|
||||
597 00000433 BB[D7840000] mov ebx,call32_handle_interrupt+CS_BASE
|
||||
598 00000438 29FB sub ebx,edi
|
||||
599
|
||||
600 .make_ijb:
|
||||
601 0000043A AB stosd
|
||||
602 0000043B 284FFE sub [edi-2],cl ; Interrupt #
|
||||
603 0000043E 93 xchg eax,ebx
|
||||
604 0000043F 83E808 sub eax,8
|
||||
605 00000442 AB stosd
|
||||
606 00000443 93 xchg eax,ebx
|
||||
607 00000444 E2F4 loop .make_ijb
|
||||
608
|
||||
609 ; Now everything is set up for interrupts...
|
||||
610
|
||||
611 00000446 6800800100 push dword (BOUNCE_SEG << 4) ; Bounce buffer address
|
||||
612 0000044B 68[EA840000] push dword call32_syscall+CS_BASE ; Syscall entry point
|
||||
613 00000450 FB sti ; Interrupts OK now
|
||||
614 00000451 E8(00800F00) call pm_entry-CS_BASE ; Run the program...
|
||||
615
|
||||
616 ; ... on return ...
|
||||
617 00000456 A3[04800000] mov [Return+CS_BASE],eax
|
||||
618
|
||||
619 ; ... fall through to call32_exit ...
|
||||
620
|
||||
621 call32_exit:
|
||||
622 0000045B 66BB[A004] mov bx,call32_done ; Return to command loop
|
||||
623
|
||||
624 call32_enter_rm:
|
||||
625 0000045F FA cli
|
||||
626 00000460 FC cld
|
||||
627 00000461 8925[0C800000] mov [PMESP+CS_BASE],esp ; Save exit %esp
|
||||
628 00000467 31E4 xor esp,esp ; Make sure the high bits are zero
|
||||
629 00000469 EA[70040000]0800 jmp 08h:.in_pm16 ; Return to 16-bit mode first
|
||||
630
|
||||
631 bits 16
|
||||
632 .in_pm16:
|
||||
633 00000470 B81000 mov ax,10h ; Real-mode-like segment
|
||||
634 00000473 8EC0 mov es,ax
|
||||
635 00000475 8ED8 mov ds,ax
|
||||
636 00000477 8ED0 mov ss,ax
|
||||
637 00000479 8EE0 mov fs,ax
|
||||
638 0000047B 8EE8 mov gs,ax
|
||||
639
|
||||
640 0000047D 0F011E[7200] lidt [call32_rmidt] ; Real-mode IDT (rm needs no GDT)
|
||||
641 00000482 0F20C0 mov eax,cr0
|
||||
642 00000485 24FE and al,~1
|
||||
643 00000487 0F22C0 mov cr0,eax
|
||||
644 0000048A EA[8F04]0008 jmp MY_CS:.in_rm
|
||||
645
|
||||
646 .in_rm: ; Back in real mode
|
||||
647 0000048F 8CC8 mov ax,cs ; Set up sane segments
|
||||
648 00000491 8ED8 mov ds,ax
|
||||
649 00000493 8EC0 mov es,ax
|
||||
650 00000495 8EE0 mov fs,ax
|
||||
651 00000497 8EE8 mov gs,ax
|
||||
652 00000499 0FB226[0000] lss sp,[SavedSSSP] ; Restore stack
|
||||
653 0000049E FFE3 jmp bx ; Go to whereever we need to go...
|
||||
654
|
||||
655 call32_done:
|
||||
656 000004A0 E8B7FE call disable_a20
|
||||
657 000004A3 FB sti
|
||||
658 000004A4 A1[0400] mov ax,[Return]
|
||||
659 000004A7 C3 ret
|
||||
660
|
||||
661 ;
|
||||
662 ; 16-bit support code
|
||||
663 ;
|
||||
664 bits 16
|
||||
665
|
||||
666 ;
|
||||
667 ; 16-bit interrupt-handling code
|
||||
668 ;
|
||||
669 call32_int_rm:
|
||||
670 000004A8 9C pushf ; Flags on stack
|
||||
671 000004A9 0E push cs ; Return segment
|
||||
672 000004AA 68[B004] push word .cont ; Return address
|
||||
673 000004AD 6652 push dword edx ; Segment:offset of IVT entry
|
||||
674 000004AF CB retf ; Invoke IVT routine
|
||||
675 .cont: ; ... on resume ...
|
||||
676 000004B0 66BB[E8840000] mov ebx,call32_int_resume+CS_BASE
|
||||
677 000004B6 E907FF jmp call32_enter_pm ; Go back to PM
|
||||
678
|
||||
679 ;
|
||||
680 ; 16-bit system call handling code
|
||||
681 ;
|
||||
682 call32_sys_rm:
|
||||
683 000004B9 0FA9 pop gs
|
||||
684 000004BB 0FA1 pop fs
|
||||
685 000004BD 07 pop es
|
||||
686 000004BE 1F pop ds
|
||||
687 000004BF 6661 popad
|
||||
688 000004C1 669D popfd
|
||||
689 000004C3 CB retf ; Invoke routine
|
||||
690 .return:
|
||||
691 000004C4 669C pushfd
|
||||
692 000004C6 6660 pushad
|
||||
693 000004C8 1E push ds
|
||||
694 000004C9 06 push es
|
||||
695 000004CA 0FA0 push fs
|
||||
696 000004CC 0FA8 push gs
|
||||
697 000004CE 66BB[39850000] mov ebx,call32_sys_resume+CS_BASE
|
||||
698 000004D4 E9E9FE jmp call32_enter_pm
|
||||
699
|
||||
700 ;
|
||||
701 ; 32-bit support code
|
||||
702 ;
|
||||
703 bits 32
|
||||
704
|
||||
705 ;
|
||||
706 ; This is invoked on getting an interrupt in protected mode. At
|
||||
707 ; this point, we need to context-switch to real mode and invoke
|
||||
708 ; the interrupt routine.
|
||||
709 ;
|
||||
710 ; When this gets invoked, the registers are saved on the stack and
|
||||
711 ; AL contains the register number.
|
||||
712 ;
|
||||
713 call32_handle_interrupt:
|
||||
714 000004D7 0FB6C0 movzx eax,al
|
||||
715 000004DA 31DB xor ebx,ebx ; Actually makes the code smaller
|
||||
716 000004DC 8B1483 mov edx,[ebx+eax*4] ; Get the segment:offset of the routine
|
||||
717 000004DF 66BB[A804] mov bx,call32_int_rm
|
||||
718 000004E3 E977FFFFFF jmp call32_enter_rm ; Go to real mode
|
||||
719
|
||||
720 call32_int_resume:
|
||||
721 000004E8 61 popad
|
||||
722 000004E9 CF iret
|
||||
723
|
||||
724 ;
|
||||
725 ; Syscall invocation. We manifest a structure on the real-mode stack,
|
||||
726 ; containing the call32sys_t structure from <call32.h> as well as
|
||||
727 ; the following entries (from low to high address):
|
||||
728 ; - Target offset
|
||||
729 ; - Target segment
|
||||
730 ; - Return offset
|
||||
731 ; - Return segment (== real mode cs)
|
||||
732 ; - Return flags
|
||||
733 ;
|
||||
734 call32_syscall:
|
||||
735 000004EA 9C pushfd ; Save IF among other things...
|
||||
736 000004EB 60 pushad ; We only need to save some, but...
|
||||
737 000004EC FC cld
|
||||
738
|
||||
739 000004ED 0FB73D[00800000] movzx edi,word [SavedSSSP+CS_BASE]
|
||||
740 000004F4 0FB705[02800000] movzx eax,word [SavedSSSP+CS_BASE+2]
|
||||
741 000004FB 83EF36 sub edi,54 ; Allocate 54 bytes
|
||||
742 000004FE 66893D[00800000] mov [SavedSSSP+CS_BASE],di
|
||||
743 00000505 C1E004 shl eax,4
|
||||
744 00000508 01C7 add edi,eax ; Create linear address
|
||||
745
|
||||
746 0000050A 8B74242C mov esi,[esp+11*4] ; Source regs
|
||||
747 0000050E 31C9 xor ecx,ecx
|
||||
748 00000510 B10B mov cl,11 ; 44 bytes to copy
|
||||
749 00000512 F3A5 rep movsd
|
||||
750
|
||||
751 00000514 0FB6442428 movzx eax,byte [esp+10*4] ; Interrupt number
|
||||
752 ; ecx == 0 here; adding it to the EA makes the
|
||||
753 ; encoding smaller
|
||||
754 00000519 8B0481 mov eax,[ecx+eax*4] ; Get IVT entry
|
||||
755 0000051C AB stosd ; Save in stack frame
|
||||
756 0000051D B8[C4040008] mov eax,call32_sys_rm.return + (MY_CS << 16) ; Return seg:offs
|
||||
757 00000522 AB stosd ; Save in stack frame
|
||||
758 00000523 8B47F4 mov eax,[edi-12] ; Return flags
|
||||
759 00000526 25D70C2000 and eax,0x200cd7 ; Mask (potentially) unsafe flags
|
||||
760 0000052B 8947F4 mov [edi-12],eax ; Primary flags entry
|
||||
761 0000052E 66AB stosw ; Return flags
|
||||
762
|
||||
763 00000530 66BB[B904] mov bx,call32_sys_rm
|
||||
764 00000534 E926FFFFFF jmp call32_enter_rm ; Go to real mode
|
||||
765
|
||||
766 ; On return, the 44-byte return structure is on the
|
||||
767 ; real-mode stack.
|
||||
768 call32_sys_resume:
|
||||
769 00000539 0FB735[00800000] movzx esi,word [SavedSSSP+CS_BASE]
|
||||
770 00000540 0FB705[02800000] movzx eax,word [SavedSSSP+CS_BASE+2]
|
||||
771 00000547 8B7C2430 mov edi,[esp+12*4] ; Dest regs
|
||||
772 0000054B C1E004 shl eax,4
|
||||
773 0000054E 01C6 add esi,eax ; Create linear address
|
||||
774 00000550 21FF and edi,edi ; NULL pointer?
|
||||
775 00000552 7502 jnz .do_copy
|
||||
776 00000554 89F7 .no_copy: mov edi,esi ; Do a dummy copy-to-self
|
||||
777 00000556 31C9 .do_copy: xor ecx,ecx
|
||||
778 00000558 B10B mov cl,11 ; 44 bytes
|
||||
779 0000055A F3A5 rep movsd ; Copy register block
|
||||
780
|
||||
781 0000055C 8305[00800000]2C add dword [SavedSSSP+CS_BASE],44 ; Remove from stack
|
||||
782
|
||||
783 00000563 61 popad
|
||||
784 00000564 9D popfd
|
||||
785 00000565 C3 ret ; Return to 32-bit program
|
||||
BIN
extra/syslinux-3.09/memdisk/memdisk32.bin
Executable file
BIN
extra/syslinux-3.09/memdisk/memdisk32.bin
Executable file
Binary file not shown.
BIN
extra/syslinux-3.09/memdisk/memdisk32.elf
Executable file
BIN
extra/syslinux-3.09/memdisk/memdisk32.elf
Executable file
Binary file not shown.
30
extra/syslinux-3.09/memdisk/memset.S
Normal file
30
extra/syslinux-3.09/memdisk/memset.S
Normal file
@@ -0,0 +1,30 @@
|
||||
# $Id: memset.S,v 1.1 2003/04/14 22:28:30 hpa Exp $
|
||||
#
|
||||
# memset.S
|
||||
#
|
||||
# Simple memset() implementation
|
||||
#
|
||||
|
||||
.text
|
||||
.globl memset
|
||||
.type memset, @function
|
||||
memset:
|
||||
cld
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
movl 12(%esp),%edi
|
||||
movzbl 16(%esp),%eax
|
||||
movl 20(%esp),%esi
|
||||
imull $0x01010101,%eax
|
||||
movl %esi,%ecx
|
||||
shrl $2,%ecx
|
||||
rep ; stosl
|
||||
movl %esi,%ecx
|
||||
andl $3,%ecx
|
||||
rep ; stosb
|
||||
movl 12(%esp),%eax
|
||||
popl %esi
|
||||
popl %edi
|
||||
ret
|
||||
|
||||
.size memcpy,.-memcpy
|
||||
BIN
extra/syslinux-3.09/memdisk/memset.o
Normal file
BIN
extra/syslinux-3.09/memdisk/memset.o
Normal file
Binary file not shown.
169
extra/syslinux-3.09/memdisk/msetup.c
Normal file
169
extra/syslinux-3.09/memdisk/msetup.c
Normal file
@@ -0,0 +1,169 @@
|
||||
#ident "$Id: msetup.c,v 1.12 2004/12/14 22:46:25 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2003 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* msetup.c
|
||||
*
|
||||
* Initialization code for memory-based disk
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memdisk.h"
|
||||
#include "conio.h"
|
||||
#include "e820.h"
|
||||
|
||||
static inline int get_e820(void)
|
||||
{
|
||||
struct e820_info {
|
||||
uint64_t base;
|
||||
uint64_t len;
|
||||
uint32_t type;
|
||||
} *buf = sys_bounce;
|
||||
uint32_t copied;
|
||||
int range_count = 0;
|
||||
com32sys_t regs;
|
||||
|
||||
memset(®s, 0, sizeof regs);
|
||||
|
||||
do {
|
||||
regs.eax.l = 0x0000e820;
|
||||
regs.ecx.l = sizeof(*buf);
|
||||
regs.edx.l = 0x534d4150;
|
||||
regs.edi.w[0] = OFFS(buf);
|
||||
regs.es = SEG(buf);
|
||||
|
||||
syscall(0x15, ®s, ®s);
|
||||
copied = (regs.eflags.l & 1) ? 0 : regs.ecx.l;
|
||||
|
||||
if ( regs.eax.l != 0x534d4150 || copied < 20 )
|
||||
break;
|
||||
|
||||
printf("e820: %08x%08x %08x%08x %d\n",
|
||||
(uint32_t)(buf->base >> 32), (uint32_t)buf->base,
|
||||
(uint32_t)(buf->len >> 32), (uint32_t)buf->len,
|
||||
buf->type);
|
||||
|
||||
insertrange(buf->base, buf->len, buf->type);
|
||||
range_count++;
|
||||
|
||||
} while ( regs.ebx.l );
|
||||
|
||||
return !range_count;
|
||||
}
|
||||
|
||||
static inline void get_dos_mem(void)
|
||||
{
|
||||
com32sys_t regs;
|
||||
|
||||
memset(®s, 0, sizeof regs);
|
||||
syscall(0x12, ®s, ®s);
|
||||
insertrange(0, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1);
|
||||
printf(" DOS: %d K\n", regs.eax.w[0]);
|
||||
}
|
||||
|
||||
static inline int get_e801(void)
|
||||
{
|
||||
int err;
|
||||
com32sys_t regs;
|
||||
|
||||
memset(®s, 0, sizeof regs);
|
||||
|
||||
regs.eax.w[0] = 0xe801;
|
||||
syscall(0x15, ®s, ®s);
|
||||
|
||||
if ( !(err = regs.eflags.l & 1) ) {
|
||||
if ( regs.eax.w[0] ) {
|
||||
insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1);
|
||||
}
|
||||
if ( regs.ebx.w[0] ) {
|
||||
insertrange(0x1000000, (uint64_t)((uint32_t)regs.ebx.w[0] << 16), 1);
|
||||
}
|
||||
|
||||
printf("e801: %04x %04x\n", regs.eax.w[0], regs.ebx.w[0]);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int get_88(void)
|
||||
{
|
||||
com32sys_t regs;
|
||||
int err;
|
||||
|
||||
memset(®s, 0, sizeof regs);
|
||||
|
||||
regs.eax.b[1] = 0x88;
|
||||
syscall(0x15, ®s, ®s);
|
||||
|
||||
|
||||
if ( !(err = regs.eflags.l & 1) ) {
|
||||
if ( regs.eax.w[0] ) {
|
||||
insertrange(0x100000, (uint64_t)((uint32_t)regs.eax.w[0] << 10), 1);
|
||||
}
|
||||
|
||||
printf(" 88: %04x\n", regs.eax.w[0]);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t dos_mem = 0; /* 0-1MB */
|
||||
uint32_t low_mem = 0; /* 1-16MB */
|
||||
uint32_t high_mem = 0; /* 16+ MB */
|
||||
|
||||
void get_mem(void)
|
||||
{
|
||||
if ( get_e820() ) {
|
||||
get_dos_mem();
|
||||
if ( get_e801() ) {
|
||||
if ( get_88() ) {
|
||||
puts("MEMDISK: Unable to obtain memory map\n");
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PW(x) (1ULL << (x))
|
||||
|
||||
void parse_mem(void)
|
||||
{
|
||||
struct e820range *ep;
|
||||
|
||||
dos_mem = low_mem = high_mem = 0;
|
||||
|
||||
/* Derive "dos mem", "high mem", and "low mem" from the range array */
|
||||
for ( ep = ranges ; ep->type != -1 ; ep++ ) {
|
||||
if ( ep->type == 1 ) {
|
||||
/* Only look at memory ranges */
|
||||
if ( ep->start == 0 ) {
|
||||
if ( ep[1].start > PW(20) )
|
||||
dos_mem = PW(20);
|
||||
else
|
||||
dos_mem = ep[1].start;
|
||||
}
|
||||
if ( ep->start <= PW(20) && ep[1].start > PW(20) ) {
|
||||
if ( ep[1].start > PW(24) )
|
||||
low_mem = PW(24) - PW(20);
|
||||
else
|
||||
low_mem = ep[1].start - PW(20);
|
||||
}
|
||||
if ( ep->start <= PW(24) && ep[1].start > PW(24) ) {
|
||||
if ( ep[1].start > PW(32) )
|
||||
high_mem = PW(32) - PW(24);
|
||||
else
|
||||
high_mem = ep[1].start - PW(24);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
extra/syslinux-3.09/memdisk/msetup.o
Normal file
BIN
extra/syslinux-3.09/memdisk/msetup.o
Normal file
Binary file not shown.
2288
extra/syslinux-3.09/memdisk/msetup.s
Normal file
2288
extra/syslinux-3.09/memdisk/msetup.s
Normal file
File diff suppressed because it is too large
Load Diff
58
extra/syslinux-3.09/memdisk/postprocess.pl
Executable file
58
extra/syslinux-3.09/memdisk/postprocess.pl
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/perl
|
||||
## -----------------------------------------------------------------------
|
||||
##
|
||||
## Copyright 2001 H. Peter Anvin - All Rights Reserved
|
||||
##
|
||||
## 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.
|
||||
##
|
||||
## -----------------------------------------------------------------------
|
||||
## $Id: postprocess.pl,v 1.4 2004/12/14 22:46:25 hpa Exp $
|
||||
|
||||
#
|
||||
# Postprocess the memdisk binary.
|
||||
#
|
||||
|
||||
eval { use bytes; };
|
||||
|
||||
($out,$file16,$file32) = @ARGV;
|
||||
|
||||
open(OUT, "> $out\0") or die "$0: Cannot create file: $out\n";
|
||||
eval { binmode OUT; };
|
||||
open(FILE, "< $file16\0") or die "$0: Cannot open file: $file16\n";
|
||||
eval { binmode FILE };
|
||||
|
||||
@info = stat(FILE);
|
||||
$size = $info[7];
|
||||
|
||||
$sectors = ($size + 511) >> 9;
|
||||
$xsize = $sectors << 9;
|
||||
|
||||
read(FILE, $f16, $size);
|
||||
|
||||
print OUT $f16;
|
||||
|
||||
if ( $size != $xsize ) {
|
||||
# Pad to a sector boundary
|
||||
print OUT "\0" x ($xsize-$size);
|
||||
}
|
||||
|
||||
seek(OUT, 0x1f1, SEEK_SET); # setup_sects
|
||||
# All sectors are setup except the first
|
||||
print OUT pack("C", $sectors-1);
|
||||
|
||||
seek(OUT, $xsize, SEEK_SET);
|
||||
close(FILE);
|
||||
|
||||
open(FILE, "+< $file32\0") or die "$0: Cannot open file: $file32\n";
|
||||
|
||||
while ( ($n = read(FILE, $f32, 65536)) > 0 ) {
|
||||
print OUT $f32;
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
close(OUT);
|
||||
|
||||
761
extra/syslinux-3.09/memdisk/setup.c
Normal file
761
extra/syslinux-3.09/memdisk/setup.c
Normal file
@@ -0,0 +1,761 @@
|
||||
#ident "$Id: setup.c,v 1.50 2005/04/29 06:04:45 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2001-2004 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h>
|
||||
#include "e820.h"
|
||||
#include "conio.h"
|
||||
#include "version.h"
|
||||
#include "memdisk.h"
|
||||
|
||||
const char memdisk_version[] =
|
||||
"MEMDISK " VERSION " " DATE;
|
||||
const char copyright[] =
|
||||
"Copyright " FIRSTYEAR "-" COPYYEAR " H. Peter Anvin";
|
||||
|
||||
extern const char _binary_memdisk_bin_start[], _binary_memdisk_bin_end[];
|
||||
extern const char _binary_memdisk_bin_size[]; /* Weird, I know */
|
||||
|
||||
struct memdisk_header {
|
||||
uint16_t int13_offs;
|
||||
uint16_t int15_offs;
|
||||
uint16_t patch_offs;
|
||||
uint16_t total_size;
|
||||
};
|
||||
|
||||
/* The Disk Parameter Table may be required */
|
||||
typedef union {
|
||||
struct hd_dpt {
|
||||
uint16_t max_cyl; /* Max cylinder */
|
||||
uint8_t max_head; /* Max head */
|
||||
uint8_t junk1[5]; /* Obsolete junk, leave at zero */
|
||||
uint8_t ctrl; /* Control byte */
|
||||
uint8_t junk2[7]; /* More obsolete junk */
|
||||
} hd;
|
||||
struct fd_dpt {
|
||||
uint8_t specify1; /* "First specify byte" */
|
||||
uint8_t specify2; /* "Second specify byte" */
|
||||
uint8_t delay; /* Delay until motor turn off */
|
||||
uint8_t sectors; /* Sectors/track */
|
||||
|
||||
uint8_t bps; /* Bytes/sector (02h = 512) */
|
||||
uint8_t isgap; /* Length of intersector gap */
|
||||
uint8_t dlen; /* Data length (0FFh) */
|
||||
uint8_t fgap; /* Formatting gap */
|
||||
|
||||
uint8_t ffill; /* Format fill byte */
|
||||
uint8_t settle; /* Head settle time (ms) */
|
||||
uint8_t mstart; /* Motor start time */
|
||||
uint8_t _pad1; /* Padding */
|
||||
|
||||
uint32_t old_fd_dpt; /* Extension: pointer to old INT 1Eh */
|
||||
} fd;
|
||||
} dpt_t;
|
||||
|
||||
struct patch_area {
|
||||
uint32_t diskbuf;
|
||||
uint32_t disksize;
|
||||
uint16_t cmdline_off, cmdline_seg;
|
||||
|
||||
uint32_t oldint13;
|
||||
uint32_t oldint15;
|
||||
|
||||
uint16_t olddosmem;
|
||||
uint8_t bootloaderid;
|
||||
|
||||
uint8_t _pad[3];
|
||||
uint16_t memint1588;
|
||||
|
||||
uint16_t cylinders;
|
||||
uint16_t heads;
|
||||
uint32_t sectors;
|
||||
|
||||
uint32_t mem1mb;
|
||||
uint32_t mem16mb;
|
||||
|
||||
uint8_t driveno;
|
||||
uint8_t drivetype;
|
||||
uint8_t drivecnt;
|
||||
uint8_t configflags;
|
||||
#define CONFIG_READONLY 0x01
|
||||
#define CONFIG_RAW 0x02
|
||||
#define CONFIG_BIGRAW 0x08 /* MUST be 8! */
|
||||
|
||||
uint16_t mystack;
|
||||
uint16_t statusptr;
|
||||
|
||||
dpt_t dpt;
|
||||
};
|
||||
|
||||
/* This is the header in the boot sector/setup area */
|
||||
struct setup_header {
|
||||
char cmdline[0x1f1];
|
||||
uint8_t setup_secs;
|
||||
uint16_t syssize;
|
||||
uint16_t swap_dev;
|
||||
uint16_t ram_size;
|
||||
uint16_t vid_mode;
|
||||
uint16_t root_dev;
|
||||
uint16_t boot_flag;
|
||||
uint16_t jump;
|
||||
char header[4];
|
||||
uint16_t version;
|
||||
uint32_t realmode_swtch;
|
||||
uint32_t start_sys;
|
||||
uint8_t type_of_loader;
|
||||
uint8_t loadflags;
|
||||
uint16_t setup_move_size;
|
||||
uint32_t code32_start;
|
||||
uint32_t ramdisk_image;
|
||||
uint32_t ramdisk_size;
|
||||
uint32_t bootsect_kludge;
|
||||
uint16_t head_end_ptr;
|
||||
uint16_t pad1;
|
||||
uint32_t cmd_line_ptr;
|
||||
uint32_t initrd_addr_max;
|
||||
};
|
||||
|
||||
const struct setup_header * const shdr = (struct setup_header *)(LOW_SEG << 4);
|
||||
|
||||
/* Access to high memory */
|
||||
|
||||
/* Access to objects in the zero page */
|
||||
static inline void
|
||||
wrz_8(uint32_t addr, uint8_t data)
|
||||
{
|
||||
*((uint8_t *)addr) = data;
|
||||
}
|
||||
static inline void
|
||||
wrz_16(uint32_t addr, uint16_t data)
|
||||
{
|
||||
*((uint16_t *)addr) = data;
|
||||
}
|
||||
static inline void
|
||||
wrz_32(uint32_t addr, uint32_t data)
|
||||
{
|
||||
*((uint32_t *)addr) = data;
|
||||
}
|
||||
static inline uint8_t
|
||||
rdz_8(uint32_t addr)
|
||||
{
|
||||
return *((uint8_t *)addr);
|
||||
}
|
||||
static inline uint16_t
|
||||
rdz_16(uint32_t addr)
|
||||
{
|
||||
return *((uint16_t *)addr);
|
||||
}
|
||||
static inline uint32_t
|
||||
rdz_32(uint32_t addr)
|
||||
{
|
||||
return *((uint32_t *)addr);
|
||||
}
|
||||
|
||||
/* Addresses in the zero page */
|
||||
#define BIOS_INT13 (0x13*4) /* INT 13h vector */
|
||||
#define BIOS_INT15 (0x15*4) /* INT 15h vector */
|
||||
#define BIOS_INT1E (0x1E*4) /* INT 1Eh vector */
|
||||
#define BIOS_INT40 (0x40*4) /* INT 13h vector */
|
||||
#define BIOS_INT41 (0x41*4) /* INT 41h vector */
|
||||
#define BIOS_INT46 (0x46*4) /* INT 46h vector */
|
||||
#define BIOS_BASEMEM 0x413 /* Amount of DOS memory */
|
||||
#define BIOS_EQUIP 0x410 /* BIOS equipment list */
|
||||
#define BIOS_HD_COUNT 0x475 /* Number of hard drives present */
|
||||
|
||||
/*
|
||||
* Routine to seek for a command-line item and return a pointer
|
||||
* to the data portion, if present
|
||||
*/
|
||||
|
||||
/* Magic return values */
|
||||
#define CMD_NOTFOUND ((char *)-1) /* Not found */
|
||||
#define CMD_BOOL ((char *)-2) /* Found boolean option */
|
||||
#define CMD_HASDATA(X) ((int)(X) >= 0)
|
||||
|
||||
const char *getcmditem(const char *what)
|
||||
{
|
||||
const char *p;
|
||||
const char *wp = what;
|
||||
int match = 0;
|
||||
|
||||
for ( p = shdr->cmdline ; *p ; p++ ) {
|
||||
switch ( match ) {
|
||||
case 0: /* Ground state */
|
||||
if ( *p == ' ' )
|
||||
break;
|
||||
|
||||
wp = what;
|
||||
match = 1;
|
||||
/* Fall through */
|
||||
|
||||
case 1: /* Matching */
|
||||
if ( *wp == '\0' ) {
|
||||
if ( *p == '=' )
|
||||
return p+1;
|
||||
else if ( *p == ' ' )
|
||||
return CMD_BOOL;
|
||||
else {
|
||||
match = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( *p != *wp++ )
|
||||
match = 2;
|
||||
break;
|
||||
|
||||
case 2: /* Mismatch, skip rest of option */
|
||||
if ( *p == ' ' )
|
||||
match = 0; /* Next option */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for matching string at end of line */
|
||||
if ( match == 1 && *wp == '\0' )
|
||||
return CMD_BOOL;
|
||||
|
||||
return CMD_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if this is a gzip image
|
||||
*/
|
||||
#define UNZIP_ALIGN 512
|
||||
|
||||
extern void _end; /* Symbol signalling end of data */
|
||||
|
||||
void unzip_if_needed(uint32_t *where_p, uint32_t *size_p)
|
||||
{
|
||||
uint32_t where = *where_p;
|
||||
uint32_t size = *size_p;
|
||||
uint32_t zbytes;
|
||||
uint32_t startrange, endrange;
|
||||
uint32_t gzdatasize, gzwhere;
|
||||
uint32_t orig_crc, offset;
|
||||
uint32_t target = 0;
|
||||
int i, okmem;
|
||||
|
||||
/* Is it a gzip image? */
|
||||
if (check_zip ((void *)where, size, &zbytes, &gzdatasize,
|
||||
&orig_crc, &offset) == 0) {
|
||||
|
||||
if (offset + zbytes > size) {
|
||||
/* Assertion failure; check_zip is supposed to guarantee this
|
||||
never happens. */
|
||||
puts("internal error: check_zip returned nonsense\n");
|
||||
die();
|
||||
}
|
||||
|
||||
/* Find a good place to put it: search memory ranges in descending order
|
||||
until we find one that is legal and fits */
|
||||
okmem = 0;
|
||||
for ( i = nranges-1 ; i >= 0 ; i-- ) {
|
||||
/* We can't use > 4G memory (32 bits only.) Truncate to 2^32-1
|
||||
so we don't have to deal with funny wraparound issues. */
|
||||
|
||||
/* Must be memory */
|
||||
if ( ranges[i].type != 1 )
|
||||
continue;
|
||||
|
||||
/* Range start */
|
||||
if ( ranges[i].start >= 0xFFFFFFFF )
|
||||
continue;
|
||||
startrange = (uint32_t)ranges[i].start;
|
||||
|
||||
/* Range end (0 for end means 2^64) */
|
||||
endrange = ((ranges[i+1].start >= 0xFFFFFFFF ||
|
||||
ranges[i+1].start == 0)
|
||||
? 0xFFFFFFFF : (uint32_t)ranges[i+1].start);
|
||||
|
||||
/* Make sure we don't overwrite ourselves */
|
||||
if ( startrange < (uint32_t)&_end )
|
||||
startrange = (uint32_t)&_end;
|
||||
|
||||
/* Allow for alignment */
|
||||
startrange = (ranges[i].start + (UNZIP_ALIGN-1)) & ~(UNZIP_ALIGN-1);
|
||||
|
||||
/* In case we just killed the whole range... */
|
||||
if ( startrange >= endrange )
|
||||
continue;
|
||||
|
||||
/* Must be large enough... don't rely on gzwhere for this (wraparound) */
|
||||
if ( endrange-startrange < gzdatasize )
|
||||
continue;
|
||||
|
||||
/* This is where the gz image should be put if we put it in this range */
|
||||
gzwhere = (endrange - gzdatasize) & ~(UNZIP_ALIGN-1);
|
||||
|
||||
/* Cast to uint64_t just in case we're flush with the top byte */
|
||||
if ( (uint64_t)where+size >= gzwhere && where < endrange ) {
|
||||
/* Need to move source data to avoid compressed/uncompressed overlap */
|
||||
uint32_t newwhere;
|
||||
|
||||
if ( gzwhere-startrange < size )
|
||||
continue; /* Can't fit both old and new */
|
||||
|
||||
newwhere = (gzwhere - size) & ~(UNZIP_ALIGN-1);
|
||||
printf("Moving compressed data from 0x%08x to 0x%08x\n",
|
||||
where, newwhere);
|
||||
|
||||
/* Our memcpy() is OK, because we always move from a higher
|
||||
address to a lower one */
|
||||
memcpy((void *)newwhere, (void *)where, size);
|
||||
where = newwhere;
|
||||
}
|
||||
|
||||
target = gzwhere;
|
||||
okmem = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !okmem ) {
|
||||
printf("Not enough memory to decompress image (need 0x%08x bytes)\n",
|
||||
gzdatasize);
|
||||
die();
|
||||
}
|
||||
|
||||
printf("gzip image: decompressed addr 0x%08x, len 0x%08x: ",
|
||||
target, gzdatasize);
|
||||
|
||||
*size_p = gzdatasize;
|
||||
*where_p = (uint32_t)unzip((void *)(where + offset), zbytes,
|
||||
gzdatasize, orig_crc, (void *)target);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the "geometry" of the disk in question
|
||||
*/
|
||||
struct geometry {
|
||||
uint32_t sectors; /* 512-byte sector count */
|
||||
uint32_t c, h, s; /* C/H/S geometry */
|
||||
uint32_t offset; /* Byte offset for disk */
|
||||
uint8_t type; /* Type byte for INT 13h AH=08h */
|
||||
uint8_t driveno; /* Drive no */
|
||||
};
|
||||
|
||||
static const struct geometry geometries[] =
|
||||
{
|
||||
{ 360*2, 40, 2, 9, 0, 0x01, 0 }, /* 360 K */
|
||||
{ 720*2, 80, 2, 9, 0, 0x03, 0 }, /* 720 K*/
|
||||
{ 1200*2, 80, 2, 15, 0, 0x02, 0 }, /* 1200 K */
|
||||
{ 1440*2, 80, 2, 18, 0, 0x04, 0 }, /* 1440 K */
|
||||
{ 1680*2, 80, 2, 21, 0, 0x04, 0 }, /* 1680 K */
|
||||
{ 1722*2, 82, 2, 21, 0, 0x04, 0 }, /* 1722 K */
|
||||
{ 2880*2, 80, 2, 36, 0, 0x06, 0 }, /* 2880 K */
|
||||
{ 3840*2, 80, 2, 48, 0, 0x06, 0 }, /* 3840 K */
|
||||
};
|
||||
#define known_geometries (sizeof(geometries)/sizeof(struct geometry))
|
||||
|
||||
/* Format of a DOS partition table entry */
|
||||
struct ptab_entry {
|
||||
uint8_t active;
|
||||
uint8_t start_h, start_s, start_c;
|
||||
uint8_t type;
|
||||
uint8_t end_h, end_s, end_c;
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
/* Format of a DOSEMU header */
|
||||
struct dosemu_header {
|
||||
uint8_t magic[7]; /* DOSEMU\0 */
|
||||
uint32_t h;
|
||||
uint32_t s;
|
||||
uint32_t c;
|
||||
uint32_t offset;
|
||||
uint8_t pad[105];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define FOUR(a,b,c,d) (((a) << 24)|((b) << 16)|((c) << 8)|(d))
|
||||
|
||||
const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
|
||||
{
|
||||
static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0, 0x80 };
|
||||
struct ptab_entry ptab[4]; /* Partition table buffer */
|
||||
struct dosemu_header dosemu;
|
||||
unsigned int sectors, v;
|
||||
unsigned int max_c, max_h, max_s;
|
||||
unsigned int c, h, s, offset;
|
||||
int i;
|
||||
int drive_specified;
|
||||
const char *p;
|
||||
|
||||
printf("command line: %s\n", shdr->cmdline);
|
||||
|
||||
offset = 0;
|
||||
if ( CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)) )
|
||||
offset = v;
|
||||
|
||||
sectors = (size-offset) >> 9;
|
||||
for ( i = 0 ; i < known_geometries ; i++ ) {
|
||||
if ( sectors == geometries[i].sectors ) {
|
||||
hd_geometry = geometries[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hd_geometry.sectors = sectors;
|
||||
hd_geometry.offset = offset;
|
||||
|
||||
/* Do we have a DOSEMU header? */
|
||||
memcpy(&dosemu, (char *)where+hd_geometry.offset, sizeof dosemu);
|
||||
if ( !memcmp("DOSEMU", dosemu.magic, 7) ) {
|
||||
/* Always a hard disk unless overruled by command-line options */
|
||||
hd_geometry.driveno = 0x80;
|
||||
hd_geometry.type = 0;
|
||||
hd_geometry.c = dosemu.c;
|
||||
hd_geometry.h = dosemu.h;
|
||||
hd_geometry.s = dosemu.s;
|
||||
hd_geometry.offset += dosemu.offset;
|
||||
sectors = (size-hd_geometry.offset) >> 9;
|
||||
}
|
||||
|
||||
if ( CMD_HASDATA(p = getcmditem("c")) && (v = atou(p)) )
|
||||
hd_geometry.c = v;
|
||||
if ( CMD_HASDATA(p = getcmditem("h")) && (v = atou(p)) )
|
||||
hd_geometry.h = v;
|
||||
if ( CMD_HASDATA(p = getcmditem("s")) && (v = atou(p)) )
|
||||
hd_geometry.s = v;
|
||||
|
||||
if ( getcmditem("floppy") != CMD_NOTFOUND ) {
|
||||
hd_geometry.driveno = 0;
|
||||
if ( hd_geometry.type == 0 )
|
||||
hd_geometry.type = 0x10; /* ATAPI floppy, e.g. LS-120 */
|
||||
drive_specified = 1;
|
||||
} else if ( getcmditem("harddisk") != CMD_NOTFOUND ) {
|
||||
hd_geometry.driveno = 0x80;
|
||||
hd_geometry.type = 0;
|
||||
drive_specified = 1;
|
||||
}
|
||||
|
||||
if ( (hd_geometry.c == 0) || (hd_geometry.h == 0) ||
|
||||
(hd_geometry.s == 0) ) {
|
||||
/* Hard disk image, need to examine the partition table for geometry */
|
||||
memcpy(&ptab, (char *)where+hd_geometry.offset+(512-2-4*16), sizeof ptab);
|
||||
|
||||
max_c = max_h = 0; max_s = 1;
|
||||
for ( i = 0 ; i < 4 ; i++ ) {
|
||||
if ( ptab[i].type ) {
|
||||
c = ptab[i].start_c + (ptab[i].start_s >> 6);
|
||||
s = (ptab[i].start_s & 0x3f);
|
||||
h = ptab[i].start_h;
|
||||
|
||||
if ( max_c < c ) max_c = c;
|
||||
if ( max_h < h ) max_h = h;
|
||||
if ( max_s < s ) max_s = s;
|
||||
|
||||
c = ptab[i].end_c + (ptab[i].end_s >> 6);
|
||||
s = (ptab[i].end_s & 0x3f);
|
||||
h = ptab[i].end_h;
|
||||
|
||||
if ( max_c < c ) max_c = c;
|
||||
if ( max_h < h ) max_h = h;
|
||||
if ( max_s < s ) max_s = s;
|
||||
}
|
||||
}
|
||||
|
||||
max_c++; max_h++; /* Convert to count (1-based) */
|
||||
|
||||
if ( !hd_geometry.h )
|
||||
hd_geometry.h = max_h;
|
||||
if ( !hd_geometry.s )
|
||||
hd_geometry.s = max_s;
|
||||
if ( !hd_geometry.c )
|
||||
hd_geometry.c = sectors/(hd_geometry.h*hd_geometry.s);
|
||||
}
|
||||
|
||||
if ( (size-hd_geometry.offset) & 0x1ff ) {
|
||||
puts("MEMDISK: Image has fractional end sector\n");
|
||||
}
|
||||
if ( sectors % (hd_geometry.h*hd_geometry.s) ) {
|
||||
puts("MEMDISK: Image seems to have fractional end cylinder\n");
|
||||
}
|
||||
if ( (hd_geometry.c*hd_geometry.h*hd_geometry.s) > sectors ) {
|
||||
puts("MEMDISK: Image appears to be truncated\n");
|
||||
}
|
||||
|
||||
return &hd_geometry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump here if all hope is gone...
|
||||
*/
|
||||
void __attribute__((noreturn)) die(void)
|
||||
{
|
||||
asm volatile("sti");
|
||||
for(;;)
|
||||
asm volatile("hlt");
|
||||
}
|
||||
|
||||
#define STACK_NEEDED 512 /* Number of bytes of stack */
|
||||
|
||||
/*
|
||||
* Actual setup routine
|
||||
* Returns the drive number (which is then passed in %dl to the
|
||||
* called routine.)
|
||||
*/
|
||||
syscall_t syscall;
|
||||
void *sys_bounce;
|
||||
|
||||
uint32_t setup(syscall_t cs_syscall, void *cs_bounce)
|
||||
{
|
||||
unsigned int bin_size = (int) &_binary_memdisk_bin_size;
|
||||
struct memdisk_header *hptr;
|
||||
struct patch_area *pptr;
|
||||
uint16_t driverseg;
|
||||
uint32_t driverptr, driveraddr;
|
||||
uint16_t dosmem_k;
|
||||
uint32_t stddosmem;
|
||||
const struct geometry *geometry;
|
||||
int total_size, cmdlinelen;
|
||||
com32sys_t regs;
|
||||
uint32_t ramdisk_image, ramdisk_size;
|
||||
|
||||
/* Set up global variables */
|
||||
syscall = cs_syscall;
|
||||
sys_bounce = cs_bounce;
|
||||
|
||||
/* Show signs of life */
|
||||
printf("%s %s\n", memdisk_version, copyright);
|
||||
|
||||
if ( !shdr->ramdisk_image || !shdr->ramdisk_size ) {
|
||||
puts("MEMDISK: No ramdisk image specified!\n");
|
||||
die();
|
||||
}
|
||||
|
||||
ramdisk_image = shdr->ramdisk_image;
|
||||
ramdisk_size = shdr->ramdisk_size;
|
||||
|
||||
e820map_init(); /* Initialize memory data structure */
|
||||
get_mem(); /* Query BIOS for memory map */
|
||||
parse_mem(); /* Parse memory map */
|
||||
|
||||
printf("Ramdisk at 0x%08x, length 0x%08x\n",
|
||||
ramdisk_image, ramdisk_size);
|
||||
|
||||
unzip_if_needed(&ramdisk_image, &ramdisk_size);
|
||||
|
||||
geometry = get_disk_image_geometry(ramdisk_image, ramdisk_size);
|
||||
|
||||
printf("Disk is %s, %u K, C/H/S = %u/%u/%u\n",
|
||||
geometry->driveno ? "hard disk" : "floppy",
|
||||
geometry->sectors >> 1,
|
||||
geometry->c, geometry->h, geometry->s);
|
||||
|
||||
/* Reserve the ramdisk memory */
|
||||
insertrange(ramdisk_image, ramdisk_size, 2);
|
||||
parse_mem(); /* Recompute variables */
|
||||
|
||||
/* Figure out where it needs to go */
|
||||
hptr = (struct memdisk_header *) &_binary_memdisk_bin_start;
|
||||
pptr = (struct patch_area *)(_binary_memdisk_bin_start + hptr->patch_offs);
|
||||
|
||||
dosmem_k = rdz_16(BIOS_BASEMEM);
|
||||
pptr->olddosmem = dosmem_k;
|
||||
stddosmem = dosmem_k << 10;
|
||||
/* If INT 15 E820 and INT 12 disagree, go with the most conservative */
|
||||
if ( stddosmem > dos_mem )
|
||||
stddosmem = dos_mem;
|
||||
|
||||
pptr->driveno = geometry->driveno;
|
||||
pptr->drivetype = geometry->type;
|
||||
pptr->cylinders = geometry->c;
|
||||
pptr->heads = geometry->h;
|
||||
pptr->sectors = geometry->s;
|
||||
pptr->disksize = geometry->sectors;
|
||||
pptr->diskbuf = ramdisk_image + geometry->offset;
|
||||
pptr->statusptr = (geometry->driveno & 0x80) ? 0x474 : 0x441;
|
||||
|
||||
pptr->bootloaderid = shdr->type_of_loader;
|
||||
|
||||
pptr->configflags = 0;
|
||||
/* Set config flags */
|
||||
if ( getcmditem("ro") != CMD_NOTFOUND ) {
|
||||
puts("Marking disk readonly\n");
|
||||
pptr->configflags |= CONFIG_READONLY;
|
||||
}
|
||||
if ( getcmditem("raw") != CMD_NOTFOUND ) {
|
||||
puts("Using raw access to high memory\n");
|
||||
pptr->configflags |= CONFIG_RAW;
|
||||
}
|
||||
if ( getcmditem("bigraw") != CMD_NOTFOUND ) {
|
||||
puts("Using raw access to high memory - assuming big real mode\n");
|
||||
pptr->configflags |= CONFIG_BIGRAW|CONFIG_RAW;
|
||||
}
|
||||
|
||||
/* Set up a drive parameter table */
|
||||
if ( geometry->driveno & 0x80 ) {
|
||||
/* Hard disk */
|
||||
pptr->dpt.hd.max_cyl = geometry->c-1;
|
||||
pptr->dpt.hd.max_head = geometry->h-1;
|
||||
pptr->dpt.hd.ctrl = (geometry->h > 8) ? 0x08: 0;
|
||||
} else {
|
||||
/* Floppy - most of these fields are bogus and mimic
|
||||
a 1.44 MB floppy drive */
|
||||
pptr->dpt.fd.specify1 = 0xdf;
|
||||
pptr->dpt.fd.specify2 = 0x02;
|
||||
pptr->dpt.fd.delay = 0x25;
|
||||
pptr->dpt.fd.sectors = geometry->s;
|
||||
pptr->dpt.fd.bps = 0x02;
|
||||
pptr->dpt.fd.isgap = 0x12;
|
||||
pptr->dpt.fd.dlen = 0xff;
|
||||
pptr->dpt.fd.fgap = 0x6c;
|
||||
pptr->dpt.fd.ffill = 0xf6;
|
||||
pptr->dpt.fd.settle = 0x0f;
|
||||
pptr->dpt.fd.mstart = 0x05;
|
||||
|
||||
pptr->dpt.fd.old_fd_dpt = rdz_32(BIOS_INT1E);
|
||||
}
|
||||
|
||||
/* The size is given by hptr->total_size plus the size of the E820
|
||||
map -- 12 bytes per range; we may need as many as 2 additional
|
||||
ranges (each insertrange() can worst-case turn 1 area into 3)
|
||||
plus the terminating range, over what nranges currently show. */
|
||||
cmdlinelen = strlen(shdr->cmdline)+1;
|
||||
total_size = hptr->total_size; /* Actual memdisk code */
|
||||
total_size += (nranges+3)*sizeof(ranges[0]); /* E820 memory ranges */
|
||||
total_size += cmdlinelen; /* Command line */
|
||||
total_size += STACK_NEEDED; /* Stack */
|
||||
printf("Total size needed = %u bytes, allocating %uK\n",
|
||||
total_size, (total_size+0x3ff) >> 10);
|
||||
|
||||
if ( total_size > dos_mem ) {
|
||||
puts("MEMDISK: Insufficient low memory\n");
|
||||
die();
|
||||
}
|
||||
|
||||
driveraddr = stddosmem - total_size;
|
||||
driveraddr &= ~0x3FF;
|
||||
|
||||
printf("Old dos memory at 0x%05x (map says 0x%05x), loading at 0x%05x\n",
|
||||
stddosmem, dos_mem, driveraddr);
|
||||
|
||||
/* Reserve this range of memory */
|
||||
wrz_16(BIOS_BASEMEM, driveraddr >> 10);
|
||||
insertrange(driveraddr, dos_mem-driveraddr, 2);
|
||||
parse_mem();
|
||||
|
||||
pptr->mem1mb = low_mem >> 10;
|
||||
pptr->mem16mb = high_mem >> 16;
|
||||
if ( low_mem == (15 << 20) ) {
|
||||
/* lowmem maxed out */
|
||||
uint32_t int1588mem = (high_mem >> 10)+(low_mem >> 10);
|
||||
pptr->memint1588 = (int1588mem > 0xffff) ? 0xffff : int1588mem;
|
||||
} else {
|
||||
pptr->memint1588 = low_mem >> 10;
|
||||
}
|
||||
|
||||
printf("1588: 0x%04x 15E801: 0x%04x 0x%04x\n",
|
||||
pptr->memint1588, pptr->mem1mb, pptr->mem16mb);
|
||||
|
||||
driverseg = driveraddr >> 4;
|
||||
driverptr = driverseg << 16;
|
||||
|
||||
/* Anything beyond the end is for the stack */
|
||||
pptr->mystack = (uint16_t)(stddosmem-driveraddr);
|
||||
|
||||
pptr->oldint13 = rdz_32(BIOS_INT13);
|
||||
pptr->oldint15 = rdz_32(BIOS_INT15);
|
||||
|
||||
/* Adjust the E820 table: if there are null ranges (type 0)
|
||||
at the end, change them to type end of list (-1).
|
||||
This is necessary for the driver to be able to report end
|
||||
of list correctly. */
|
||||
while ( nranges && ranges[nranges-1].type == 0 ) {
|
||||
ranges[--nranges].type = -1;
|
||||
}
|
||||
|
||||
/* Query drive parameters of this type */
|
||||
memset(®s, 0, sizeof regs);
|
||||
regs.es = 0;
|
||||
regs.eax.b[1] = 0x08;
|
||||
regs.edx.b[0] = geometry->driveno;
|
||||
syscall(0x13, ®s, ®s);
|
||||
|
||||
if ( regs.eflags.l & 1 ) {
|
||||
printf("INT 13 08: Failure, assuming this is the only drive\n");
|
||||
pptr->drivecnt = 1;
|
||||
} else {
|
||||
printf("INT 13 08: Success, count = %u, BPT = %04x:%04x\n",
|
||||
regs.edx.b[0], regs.es, regs.edi.w[0]);
|
||||
pptr->drivecnt = regs.edx.b[0]+1;
|
||||
}
|
||||
|
||||
/* Pointer to the command line */
|
||||
pptr->cmdline_off = bin_size + (nranges+1)*sizeof(ranges[0]);
|
||||
pptr->cmdline_seg = driverseg;
|
||||
|
||||
/* Copy driver followed by E820 table followed by command line */
|
||||
{
|
||||
unsigned char *dpp = (unsigned char *)(driverseg << 4);
|
||||
dpp = memcpy_endptr(dpp, &_binary_memdisk_bin_start, bin_size);
|
||||
dpp = memcpy_endptr(dpp, ranges, (nranges+1)*sizeof(ranges[0]));
|
||||
dpp = memcpy_endptr(dpp, shdr->cmdline, cmdlinelen+1);
|
||||
}
|
||||
|
||||
/* Install the interrupt handlers */
|
||||
printf("old: int13 = %08x int15 = %08x\n",
|
||||
rdz_32(BIOS_INT13), rdz_32(BIOS_INT15));
|
||||
|
||||
wrz_32(BIOS_INT13, driverptr+hptr->int13_offs);
|
||||
wrz_32(BIOS_INT15, driverptr+hptr->int15_offs);
|
||||
|
||||
printf("new: int13 = %08x int15 = %08x\n",
|
||||
rdz_32(BIOS_INT13), rdz_32(BIOS_INT15));
|
||||
|
||||
/* Update various BIOS magic data areas (gotta love this shit) */
|
||||
|
||||
if ( geometry->driveno & 0x80 ) {
|
||||
/* Update BIOS hard disk count */
|
||||
wrz_8(BIOS_HD_COUNT, rdz_8(BIOS_HD_COUNT)+1);
|
||||
} else {
|
||||
/* Update BIOS floppy disk count */
|
||||
uint8_t equip = rdz_8(BIOS_EQUIP);
|
||||
if ( equip & 1 ) {
|
||||
if ( (equip & (3 << 6)) != (3 << 6) ) {
|
||||
equip += (1 << 6);
|
||||
}
|
||||
} else {
|
||||
equip |= 1;
|
||||
equip &= ~(3 << 6);
|
||||
}
|
||||
wrz_8(BIOS_EQUIP, equip);
|
||||
}
|
||||
|
||||
/* Reboot into the new "disk"; this is also a test for the interrupt hooks */
|
||||
puts("Loading boot sector... ");
|
||||
|
||||
memset(®s, 0, sizeof regs);
|
||||
// regs.es = 0;
|
||||
regs.eax.w[0] = 0x0201; /* Read sector */
|
||||
regs.ebx.w[0] = 0x7c00; /* 0000:7C00 */
|
||||
regs.ecx.w[0] = 1; /* One sector */
|
||||
regs.edx.w[0] = geometry->driveno;
|
||||
syscall(0x13, ®s, ®s);
|
||||
|
||||
if ( regs.eflags.l & 1 ) {
|
||||
puts("MEMDISK: Failed to load new boot sector\n");
|
||||
die();
|
||||
}
|
||||
|
||||
if ( getcmditem("pause") != CMD_NOTFOUND ) {
|
||||
puts("press any key to boot... ");
|
||||
regs.eax.w[0] = 0;
|
||||
syscall(0x16, ®s, NULL);
|
||||
}
|
||||
|
||||
puts("booting...\n");
|
||||
|
||||
/* On return the assembly code will jump to the boot vector */
|
||||
return geometry->driveno;
|
||||
}
|
||||
BIN
extra/syslinux-3.09/memdisk/setup.o
Normal file
BIN
extra/syslinux-3.09/memdisk/setup.o
Normal file
Binary file not shown.
6231
extra/syslinux-3.09/memdisk/setup.s
Normal file
6231
extra/syslinux-3.09/memdisk/setup.s
Normal file
File diff suppressed because it is too large
Load Diff
9
extra/syslinux-3.09/memdisk/start32.S
Normal file
9
extra/syslinux-3.09/memdisk/start32.S
Normal file
@@ -0,0 +1,9 @@
|
||||
# $Id: start32.S,v 1.1 2003/04/15 19:29:59 hpa Exp $
|
||||
#
|
||||
# Simple stub to get us to the right point in the 32-bit code;
|
||||
# this module must be linked first
|
||||
#
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
jmp setup
|
||||
BIN
extra/syslinux-3.09/memdisk/start32.o
Normal file
BIN
extra/syslinux-3.09/memdisk/start32.o
Normal file
Binary file not shown.
13
extra/syslinux-3.09/memdisk/testdata1
Normal file
13
extra/syslinux-3.09/memdisk/testdata1
Normal file
@@ -0,0 +1,13 @@
|
||||
0000000000000000 000000000009bc00 1
|
||||
000000000009bc00 0000000000004400 2
|
||||
00000000000e9800 0000000000016800 2
|
||||
0000000000100000 0000000006ee0000 1
|
||||
0000000006fe0000 000000000000fc00 3
|
||||
0000000006fefc00 0000000000000400 4
|
||||
0000000006ff0000 0000000000002000 2
|
||||
0000000006ff2000 000000000000e000 1
|
||||
0000000007000000 0000000000100000 2
|
||||
00000000fff00000 0000000000100000 2
|
||||
|
||||
0000000000586000 0000000000168000 2
|
||||
000000000009ba00 0000000000000200 2
|
||||
10
extra/syslinux-3.09/memdisk/testdata2
Normal file
10
extra/syslinux-3.09/memdisk/testdata2
Normal file
@@ -0,0 +1,10 @@
|
||||
0000000000000000 000000000009bc00 1
|
||||
000000000009bc00 0000000000004400 2
|
||||
00000000000e9800 0000000000016800 2
|
||||
0000000000100000 0000000006ee0000 1
|
||||
0000000006fe0000 000000000000fc00 3
|
||||
0000000006fefc00 0000000000000400 4
|
||||
0000000006ff0000 0000000000002000 2
|
||||
0000000006ff2000 000000000000e000 1
|
||||
0000000007000000 0000000000100000 2
|
||||
00000000fff00000 0000000000100000 2
|
||||
14
extra/syslinux-3.09/memdisk/testdata3
Normal file
14
extra/syslinux-3.09/memdisk/testdata3
Normal file
@@ -0,0 +1,14 @@
|
||||
0000000000000000 000000000009bc00 1
|
||||
000000000009bc00 0000000000004400 2
|
||||
00000000000e9800 0000000000016800 2
|
||||
0000000000100000 0000000006ee0000 1
|
||||
0000000006fe0000 000000000000fc00 3
|
||||
0000000006fefc00 0000000000000400 4
|
||||
0000002000000000 0000001000000000 1
|
||||
0000000006ff0000 0000000000002000 2
|
||||
0000000006ff2000 000000000000e000 1
|
||||
0000000007000000 0000000000100000 2
|
||||
00000000fff00000 0000000000100000 2
|
||||
|
||||
0000000000586000 0000000000168000 2
|
||||
000000000009ba00 0000000000000200 2
|
||||
390
extra/syslinux-3.09/memdisk/unzip.c
Normal file
390
extra/syslinux-3.09/memdisk/unzip.c
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* unzip.c
|
||||
*
|
||||
* This is a collection of several routines from gzip-1.0.3
|
||||
* adapted for Linux.
|
||||
*
|
||||
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
|
||||
* puts by Nick Holloway 1993, better puts by Martin Mares 1995
|
||||
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
|
||||
*
|
||||
* Adapted for MEMDISK by H. Peter Anvin, April 2003
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memdisk.h"
|
||||
#include "conio.h"
|
||||
|
||||
/*
|
||||
* gzip declarations
|
||||
*/
|
||||
|
||||
#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
#define memzero(s, n) memset ((s), 0, (n))
|
||||
|
||||
typedef uint8_t uch;
|
||||
typedef uint16_t ush;
|
||||
typedef uint32_t ulg;
|
||||
|
||||
#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
/* and a power of two */
|
||||
|
||||
static uch *inbuf; /* input pointer */
|
||||
static uch window[WSIZE]; /* sliding output window buffer */
|
||||
|
||||
static unsigned insize; /* total input bytes read */
|
||||
static unsigned inbytes; /* valid bytes in inbuf */
|
||||
static unsigned outcnt; /* bytes in output buffer */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
# define Trace(x) fprintf x
|
||||
# define Tracev(x) {if (verbose) fprintf x ;}
|
||||
# define Tracevv(x) {if (verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
static int fill_inbuf(void);
|
||||
static void flush_window(void);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
extern ulg crc_32_tab[256];
|
||||
|
||||
/* Get byte from input buffer */
|
||||
static inline uch get_byte(void)
|
||||
{
|
||||
if ( inbytes ) {
|
||||
uch b = *inbuf++;
|
||||
inbytes--;
|
||||
return b;
|
||||
} else {
|
||||
return fill_inbuf(); /* Input buffer underrun */
|
||||
}
|
||||
}
|
||||
|
||||
/* Unget byte from input buffer */
|
||||
static inline void unget_byte(void)
|
||||
{
|
||||
inbytes++;
|
||||
inbuf--;
|
||||
}
|
||||
|
||||
static ulg bytes_out = 0; /* Number of bytes output */
|
||||
static uch *output_data; /* Output data pointer */
|
||||
static ulg output_size; /* Number of output bytes expected */
|
||||
|
||||
static void *malloc(int size);
|
||||
static void free(void *where);
|
||||
|
||||
static ulg free_mem_ptr, free_mem_end_ptr;
|
||||
|
||||
#include "inflate.c"
|
||||
|
||||
static void *malloc(int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (size < 0) error("malloc error");
|
||||
|
||||
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
|
||||
|
||||
p = (void *)free_mem_ptr;
|
||||
free_mem_ptr += size;
|
||||
|
||||
if (free_mem_ptr >= free_mem_end_ptr)
|
||||
error("out of memory");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void free(void *where)
|
||||
{
|
||||
/* Don't care */
|
||||
(void)where;
|
||||
}
|
||||
|
||||
static void gzip_mark(void **ptr)
|
||||
{
|
||||
*ptr = (void *) free_mem_ptr;
|
||||
}
|
||||
|
||||
static void gzip_release(void **ptr)
|
||||
{
|
||||
free_mem_ptr = (long) *ptr;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Fill the input buffer. This is called only when the buffer is empty
|
||||
* and at least one byte is really needed.
|
||||
*/
|
||||
static int fill_inbuf(void)
|
||||
{
|
||||
/* This should never happen. We have already pointed the algorithm
|
||||
to all the data we have. */
|
||||
printf("failed\nDecompression error: ran out of input data\n");
|
||||
die();
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
* (Used for the decompressed data only.)
|
||||
*/
|
||||
static void flush_window(void)
|
||||
{
|
||||
ulg c = crc; /* temporary variable */
|
||||
unsigned n;
|
||||
uch *in, *out, ch;
|
||||
|
||||
if ( bytes_out+outcnt > output_size )
|
||||
error("output buffer overrun");
|
||||
|
||||
in = window;
|
||||
out = output_data;
|
||||
for (n = 0; n < outcnt; n++) {
|
||||
ch = *out++ = *in++;
|
||||
c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
crc = c;
|
||||
output_data = out;
|
||||
bytes_out += (ulg)outcnt;
|
||||
outcnt = 0;
|
||||
}
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
printf("failed\nDecompression error: %s\n", x);
|
||||
die();
|
||||
}
|
||||
|
||||
/* GZIP header */
|
||||
struct gzip_header {
|
||||
uint16_t magic;
|
||||
uint8_t method;
|
||||
uint8_t flags;
|
||||
uint32_t timestamp;
|
||||
uint8_t extra_flags;
|
||||
uint8_t os_type;
|
||||
} __attribute__ ((packed));
|
||||
/* (followed by optional and variable length "extra", "original name",
|
||||
and "comment" fields) */
|
||||
|
||||
struct gzip_trailer {
|
||||
uint32_t crc;
|
||||
uint32_t dbytes;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* PKZIP header. See
|
||||
* <http://www.pkware.com/products/enterprise/white_papers/appnote.html>.
|
||||
*/
|
||||
struct pkzip_header {
|
||||
uint32_t magic;
|
||||
uint16_t version;
|
||||
uint16_t flags;
|
||||
uint16_t method;
|
||||
uint16_t modified_time;
|
||||
uint16_t modified_date;
|
||||
uint32_t crc;
|
||||
uint32_t zbytes;
|
||||
uint32_t dbytes;
|
||||
uint16_t filename_len;
|
||||
uint16_t extra_len;
|
||||
} __attribute__ ((packed));
|
||||
/* (followed by optional and variable length "filename" and "extra"
|
||||
fields) */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
/* pkzip flag byte */
|
||||
#define PK_ENCRYPTED 0x01 /* bit 0 set: file is encrypted */
|
||||
#define PK_DATADESC 0x08 /* bit 3 set: file has trailing "data
|
||||
descriptor" */
|
||||
#define PK_UNSUPPORTED 0xFFF0 /* All other bits must be zero */
|
||||
|
||||
|
||||
/* Return 0 if (indata, size) points to a ZIP file, and fill in
|
||||
compressed data size, uncompressed data size, CRC, and offset of
|
||||
data.
|
||||
|
||||
If indata is not a ZIP file, return -1. */
|
||||
int check_zip(void *indata, uint32_t size, uint32_t *zbytes_p,
|
||||
uint32_t *dbytes_p, uint32_t *orig_crc, uint32_t *offset_p) {
|
||||
struct gzip_header *gzh = (struct gzip_header *)indata;
|
||||
struct pkzip_header *pkzh = (struct pkzip_header *)indata;
|
||||
uint32_t offset;
|
||||
|
||||
if (gzh->magic == 0x8b1f) {
|
||||
struct gzip_trailer *gzt = indata + size - sizeof (struct gzip_trailer);
|
||||
/* We only support method #8, DEFLATED */
|
||||
if (gzh->method != 8) {
|
||||
error("gzip file uses invalid method");
|
||||
return -1;
|
||||
}
|
||||
if (gzh->flags & ENCRYPTED) {
|
||||
error("gzip file is encrypted; not supported");
|
||||
return -1;
|
||||
}
|
||||
if (gzh->flags & CONTINUATION) {
|
||||
error("gzip file is a continuation file; not supported");
|
||||
return -1;
|
||||
}
|
||||
if (gzh->flags & RESERVED) {
|
||||
error("gzip file has unsupported flags");
|
||||
return -1;
|
||||
}
|
||||
offset = sizeof (*gzh);
|
||||
if (gzh->flags & EXTRA_FIELD) {
|
||||
/* Skip extra field */
|
||||
unsigned len = *(unsigned *)(indata + offset);
|
||||
offset += 2 + len;
|
||||
}
|
||||
if (gzh->flags & ORIG_NAME) {
|
||||
/* Discard the old name */
|
||||
uint8_t *p = indata;
|
||||
while (p[offset] != 0 && offset < size) {
|
||||
offset++;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (gzh->flags & COMMENT) {
|
||||
/* Discard the comment */
|
||||
uint8_t *p = indata;
|
||||
while (p[offset] != 0 && offset < size) {
|
||||
offset++;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (offset > size) {
|
||||
error ("gzip file corrupt");
|
||||
return -1;
|
||||
}
|
||||
*zbytes_p = size - offset - sizeof (struct gzip_trailer);
|
||||
*dbytes_p = gzt->dbytes;
|
||||
*orig_crc = gzt->crc;
|
||||
*offset_p = offset;
|
||||
return 0;
|
||||
}
|
||||
else if (pkzh->magic == 0x04034b50UL) {
|
||||
/* Magic number matches pkzip file. */
|
||||
|
||||
offset = sizeof (*pkzh);
|
||||
if (pkzh->flags & PK_ENCRYPTED) {
|
||||
error("pkzip file is encrypted; not supported");
|
||||
return -1;
|
||||
}
|
||||
if (pkzh->flags & PK_DATADESC) {
|
||||
error("pkzip file uses data_descriptor field; not supported");
|
||||
return -1;
|
||||
}
|
||||
if (pkzh->flags & PK_UNSUPPORTED) {
|
||||
error("pkzip file has unsupported flags");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We only support method #8, DEFLATED */
|
||||
if (pkzh->method != 8) {
|
||||
error("pkzip file uses invalid method");
|
||||
return -1;
|
||||
}
|
||||
/* skip header */
|
||||
offset = sizeof (*pkzh);
|
||||
/* skip filename */
|
||||
offset += pkzh->filename_len;
|
||||
/* skip extra field */
|
||||
offset += pkzh->extra_len;
|
||||
|
||||
if (offset + pkzh->zbytes > size) {
|
||||
error ("pkzip file corrupt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*zbytes_p = pkzh->zbytes;
|
||||
*dbytes_p = pkzh->dbytes;
|
||||
*orig_crc = pkzh->crc;
|
||||
*offset_p = offset;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* Magic number does not match. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
error ("Internal error in check_zip");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decompress the image, trying to flush the end of it as close
|
||||
* to end_mem as possible. Return a pointer to the data block,
|
||||
* and change datalen.
|
||||
*/
|
||||
extern void _end;
|
||||
|
||||
void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
|
||||
uint32_t orig_crc, void *target)
|
||||
{
|
||||
/* Set up the heap; it's the 64K after the bounce buffer */
|
||||
free_mem_ptr = (ulg)sys_bounce + 0x10000;
|
||||
free_mem_end_ptr = free_mem_ptr + 0x10000;
|
||||
|
||||
/* Set up input buffer */
|
||||
inbuf = indata;
|
||||
/* Sometimes inflate() looks beyond the end of the compressed data,
|
||||
but it always backs up before it is done. So we give it 4 bytes
|
||||
of slack. */
|
||||
insize = inbytes = zbytes + 4;
|
||||
|
||||
/* Set up output buffer */
|
||||
outcnt = 0;
|
||||
output_data = target;
|
||||
output_size = dbytes;
|
||||
bytes_out = 0;
|
||||
|
||||
makecrc();
|
||||
gunzip();
|
||||
|
||||
/* Verify that gunzip() consumed the entire input. */
|
||||
if (inbytes != 4)
|
||||
error("compressed data length error");
|
||||
|
||||
/* Check the uncompressed data length and CRC. */
|
||||
if ( bytes_out != dbytes )
|
||||
error("uncompressed data length error");
|
||||
|
||||
if (orig_crc != CRC_VALUE)
|
||||
error("crc error");
|
||||
|
||||
puts("ok\n");
|
||||
|
||||
return target;
|
||||
}
|
||||
BIN
extra/syslinux-3.09/memdisk/unzip.o
Normal file
BIN
extra/syslinux-3.09/memdisk/unzip.o
Normal file
Binary file not shown.
6999
extra/syslinux-3.09/memdisk/unzip.s
Normal file
6999
extra/syslinux-3.09/memdisk/unzip.s
Normal file
File diff suppressed because it is too large
Load Diff
26
extra/syslinux-3.09/memdisk/version.h
Normal file
26
extra/syslinux-3.09/memdisk/version.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ident "$Id: version.h,v 1.5 2005/01/03 08:31:59 hpa Exp $"
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 2002 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* version.h
|
||||
*
|
||||
* MEMDISK version data
|
||||
*/
|
||||
|
||||
#ifndef MEMDISK_VERSION_H
|
||||
#define MEMDISK_VERSION_H
|
||||
|
||||
#define FIRSTYEAR "2001"
|
||||
#define COPYYEAR "2005"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user