0.1 from Bellard

This commit is contained in:
Aren 2024-06-10 11:23:19 +03:00
parent fa20438104
commit cbf2807505
21 changed files with 13007 additions and 0 deletions

45
Makefile Normal file
View File

@ -0,0 +1,45 @@
# modify to your linux-2.4.26 kernel path (you must build the kernel first)
KERNEL_PATH=../linux-2.4.26
# modify to your TinyCC 0.9.21 path (you must build TinyCC first)
TCC_PATH=../..
CC=gcc
CFLAGS=-D__KERNEL__ -Wall -O2 -g -I$(KERNEL_PATH)/include -fno-builtin-printf -DCONFIG_TCCBOOT -mpreferred-stack-boundary=2 -march=i386 -falign-functions=0 -I.
all: tccboot initrd.img
#tccboot.user: tcc.o main.o ctype.o vsprintf.o lib.o malloc.o dtoa.o user.o
# $(CC) -static -nostdlib -o $@ $^
tccboot.out: head.o tcc.o main.o ctype.o vsprintf.o lib.o malloc.o \
dtoa.o gunzip.o
ld -e startup_32 -Ttext=0x100000 -N -o $@ $^
tccboot.bin: tccboot.out
objcopy -O binary -R .note -R .comment -S $< $@
tccboot: tccboot.bin
$(KERNEL_PATH)/arch/i386/boot/tools/build \
-b $(KERNEL_PATH)/arch/i386/boot/bbootsect \
$(KERNEL_PATH)/arch/i386/boot/bsetup \
$< CURRENT > $@
tcc.o: $(TCC_PATH)/tcc.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o: %.S
$(CC) -D__ASSEMBLY__ -D__KERNEL__ -I$(KERNEL_PATH)/include -c -o $@ $<
clean:
rm -f *~ *.o tccboot.out tccboot.bin example.romfs
cleanall: clean
rm -f tccboot example.romfs initrd.img
example.romfs: example/boot/tccargs example/hello.c
cd example ; genromfs -f ../example.romfs
initrd.img: example.romfs
gzip < $< > $@

64
README Normal file
View File

@ -0,0 +1,64 @@
Introduction:
------------
WARNING: don't try to play with TCCBOOT unless you are a kernel
hacker!
TCCBOOT is a bootloader which uses TinyCC to compile C and assembly
sources and boot the resulting executable. It is typically used to
compile the Linux kernel sources at boot time.
TCCBOOT boots the same way as a Linux kernel, so any boot loader which
can run a 'bzImage' Linux kernel image can run TCCBOOT. I only tested
it with ISOLINUX, but LILO or GRUB should work too.
TCCBOOT reads C or assembly sources from a gzipped ROMFS filesystem
stored in an Initial Ram Disk (initrd). It first reads the file
'boot/tccargs' which contains the TinyCC command line (same syntax as
the tcc executable). The TinyCC invocation should output one binary
image 'kernel'. This image is loaded at address 0x00100000. TCCBOOT
then does a jump to the address 0x00100000 in 32 bit flat mode. This
is compatible with the ABI of the 'vmlinux' kernel image.
Compilation:
-----------
TCCBOOT was only tested with Linux 2.4.26. In order to build TCCBOOT,
you must first compile a 2.4.26 kernel because for simplicity TCCBOOT
uses some binary files and headers from the Linux kernel. TCCBOOT also
needs the source code of TinyCC (tested with TinyCC version
0.9.21). You can modify the Makefile to give the needed paths.
Example:
-------
An "Hello World" ROMFS partition is included (initrd.img). You can
rebuild it from the example/ directory. You can test it with the QEMU
PC emulator with the 'qemu-tccboot' script.
Kernel compilation:
------------------
For your information, the patch 'linux-2.4.26-tcc.patch' gives the
necessary modifications to build a Linux kernel with TinyCC. The
corresponding kernel configuration is in file
linux-2.4.26-config. Patches are necessary for the following reasons:
- unsupported assembly directives: .rept, .endr, .subsection
- '#define __ASSEMBLY__' needed in assembly sources
- static variables cannot be seen from the inline assembly code
- typing/lvalue problems with '? :'
- no long long bit fields
- 'aligned' attribute not supported for whole structs, only for fields
- obscur preprocessor bug
Some of these problems could easily be fixed, but I am too lazy
now. It is sure that there are still many bugs in the kernel generated
by TinyCC/TCCBOOT, but at least it can boot and launch a shell.
License:
-------
TCCBOOT is distributed under the GNU General Public License.
Fabrice Bellard.

35
ctype.c Normal file
View File

@ -0,0 +1,35 @@
/*
* linux/lib/ctype.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#include <linux/ctype.h>
unsigned char _ctype[] = {
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */

3301
dtoa.c Normal file

File diff suppressed because it is too large Load Diff

17
example/boot/tccargs Normal file
View File

@ -0,0 +1,17 @@
# This file contains the TinyCC command line arguments needed to
# compile the hello.c program.
# the output binary (DO NOT CHANGE IT)
-o kernel
# no default libraries
-nostdlib
# no default includes paths
-nostdinc
# statically linked output
-static
# address of the start of the .text section
-Wl,-Ttext,000100000
# force binary output format
-Wl,--oformat,binary
# sources files
hello.c

32
example/hello.c Normal file
View File

@ -0,0 +1,32 @@
/* simple Hello World program on the QEMU serial port */
void puts(const char *s);
void _start(void)
{
puts("Hello World\n");
while (1);
}
void outb(int port, int val)
{
asm("outb %b1, %w0" : : "d" (port), "a" (val));
}
unsigned char inb(int port)
{
int val;
asm("inb %w1, %b0" : "=a"(val) : "d" (port));
return val;
}
void puts(const char *s)
{
while (*s) {
outb(0x3f8, *s++);
while ((inb(0x3f8 + 5) & 0x60) != 0x60);
}
}

109
gunzip.c Normal file
View File

@ -0,0 +1,109 @@
#include "tccboot.h"
/*
* gzip declarations
*/
#define OF(args) args
#define STATIC static
#define memzero(s, n) memset ((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#define WSIZE 0x8000 /* Window size must be at least 32k, */
/* and a power of two */
static uch *inbuf; /* input buffer */
static uch window[WSIZE]; /* Sliding window buffer */
static unsigned insize = 0; /* valid bytes in inbuf */
static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
static unsigned outcnt = 0; /* 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 */
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
/* 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 **ptr)
{
}
static void gzip_release(void **ptr)
{
}
static long bytes_out;
static uch *output_data;
static const uint8_t *input_data;
static int input_len;
#include "inflate.c"
/* ===========================================================================
* 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)
{
if (insize != 0) {
error("ran out of input data\n");
}
inbuf = (uint8_t *)input_data;
insize = input_len;
inptr = 1;
return inbuf[0];
}
static void flush_window(void)
{
memcpy(output_data, window, outcnt);
output_data += outcnt;
bytes_out += outcnt;
outcnt = 0;
}
static void error(char *x)
{
fatal("%s", x);
}
int do_gunzip(uint8_t *dest, const uint8_t *src, int src_len)
{
input_data = src;
input_len = src_len;
output_data = dest;
bytes_out = 0;
gunzip();
return bytes_out;
}

128
head.S Normal file
View File

@ -0,0 +1,128 @@
/*
* linux/boot/head.S
*
* Copyright (C) 1991, 1992, 1993 Linus Torvalds
*/
/*
* head.S contains the 32-bit startup code.
*
* NOTE!!! Startup happens at absolute address 0x00001000, which is also where
* the page directory will exist. The startup code will be overwritten by
* the page directory. [According to comments etc elsewhere on a compressed
* kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
*
* Page 0 is deliberately kept safe, since System Management Mode code in
* laptops may need to access the BIOS data stored there. This is also
* useful for future device drivers that either access the BIOS via VM86
* mode.
*/
/*
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
*/
.text
#include <linux/linkage.h>
#include <asm/segment.h>
.globl startup_32
startup_32:
cld
cli
movl $(__KERNEL_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
lss SYMBOL_NAME(stack_start),%esp
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled
movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
je 1b
/*
* Initialize eflags. Some BIOS's leave bits like NT set. This would
* confuse the debugger if this code is traced.
* XXX - best to initialize before switching to protected mode.
*/
pushl $0
popfl
/*
* Clear BSS
*/
xorl %eax,%eax
movl $ SYMBOL_NAME(_edata),%edi
movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx
cld
rep
stosb
/*
* Do the decompression, and jump to the new kernel..
*/
subl $16,%esp # place for structure on the stack
movl %esp,%eax
pushl %esi # real mode pointer as second arg
pushl %eax # address of structure as first arg
call SYMBOL_NAME(compile_kernel)
orl %eax,%eax
jnz 3f
popl %esi # discard address
popl %esi # real mode pointer
xorl %ebx,%ebx
ljmp $(__KERNEL_CS), $0x100000
/*
* We come here, if we were loaded high.
* We need to move the move-in-place routine down to 0x1000
* and then start it with the buffer addresses in registers,
* which we got from the stack.
*/
3:
movl $move_routine_start,%esi
movl $0x1000,%edi
movl $move_routine_end,%ecx
subl %esi,%ecx
addl $3,%ecx
shrl $2,%ecx
cld
rep
movsl
popl %esi # discard the address
popl %ebx # real mode pointer
popl %esi # low_buffer_start
popl %ecx # lcount
popl %edx # high_buffer_start
popl %eax # hcount
movl $0x100000,%edi
cli # make sure we don't get interrupted
ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
/*
* Routine (template) for moving the decompressed kernel in place,
* if we were high loaded. This _must_ PIC-code !
*/
move_routine_start:
movl %ecx,%ebp
shrl $2,%ecx
rep
movsl
movl %ebp,%ecx
andl $3,%ecx
rep
movsb
movl %edx,%esi
movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
addl $3,%ecx
shrl $2,%ecx
rep
movsl
movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx
ljmp $(__KERNEL_CS), $0x100000
move_routine_end:

1180
inflate.c Normal file

File diff suppressed because it is too large Load Diff

BIN
initrd.img Normal file

Binary file not shown.

492
lib.c Normal file
View File

@ -0,0 +1,492 @@
#include "tccboot.h"
//#define ROMFS_DEBUG
char msg_buf[1024];
void puts(const char *s)
{
putstr(s);
putstr("\n");
}
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(msg_buf, sizeof(msg_buf), fmt, ap);
putstr(msg_buf);
va_end(ap);
return 0;
}
FILE *stderr;
int fprintf(FILE *f, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(msg_buf, sizeof(msg_buf), fmt, ap);
putstr(msg_buf);
va_end(ap);
return 0;
}
void getcwd(char *buf, size_t buf_size)
{
strcpy(buf, "/");
}
void fatal(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
putstr("tccboot: panic: ");
vsnprintf(msg_buf, sizeof(msg_buf), fmt, ap);
putstr(msg_buf);
putstr("\n");
va_end(ap);
exit(1);
}
/**********************************************************/
int errno;
long strtol(const char *nptr, char **endptr, int base)
{
return simple_strtol(nptr, endptr, base);
}
long long strtoll(const char *nptr, char **endptr, int base)
{
return simple_strtoll(nptr, endptr, base);
}
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
return simple_strtoul(nptr, endptr, base);
}
unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
return simple_strtoull(nptr, endptr, base);
}
int atoi(const char *s)
{
return strtol(s, NULL, 10);
}
/**********************************************************/
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
tv->tv_sec = 0;
tv->tv_usec = 0;
return 0;
}
time_t time(time_t *t)
{
if (t)
*t = 0;
return 0;
}
struct tm *localtime(const time_t *timep)
{
static struct tm static_tm;
return &static_tm;
}
int setjmp(jmp_buf buf)
{
return 0;
}
void longjmp(jmp_buf buf, int val)
{
exit(1);
}
/**********************************************************/
#define MALLOC_MAX_SIZE (128 * 1024 * 1024)
extern uint8_t _end;
uint8_t *malloc_ptr = &_end;
void *sbrk(int increment)
{
uint8_t *ptr, *new_ptr;
if (increment == 0)
return malloc_ptr;
ptr = malloc_ptr;
new_ptr = malloc_ptr + increment;
if (new_ptr > (&_end + MALLOC_MAX_SIZE)) {
errno = ENOMEM;
return (void *)-1;
}
malloc_ptr = new_ptr;
return ptr;
}
#if 0
#define MALLOC_ALIGN 4096
void free(void *ptr)
{
}
void *realloc(void *oldptr, size_t size)
{
void *ptr;
if (size == 0) {
free(oldptr);
return NULL;
} else {
ptr = malloc(size);
/* XXX: incorrect */
if (oldptr) {
memcpy(ptr, oldptr, size);
free(oldptr);
}
return ptr;
}
}
#endif
/**********************************************************/
uint8_t *romfs_base;
/* The basic structures of the romfs filesystem */
#define ROMBSIZE BLOCK_SIZE
#define ROMBSBITS BLOCK_SIZE_BITS
#define ROMBMASK (ROMBSIZE-1)
#define ROMFS_MAGIC 0x7275
#define ROMFS_MAXFN 128
#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
#define ROMSB_WORD0 __mk4('-','r','o','m')
#define ROMSB_WORD1 __mk4('1','f','s','-')
/* On-disk "super block" */
struct romfs_super_block {
uint32_t word0;
uint32_t word1;
uint32_t size;
uint32_t checksum;
char name[0]; /* volume name */
};
/* On disk inode */
struct romfs_inode {
uint32_t next; /* low 4 bits see ROMFH_ */
uint32_t spec;
uint32_t size;
uint32_t checksum;
char name[0];
};
#define ROMFH_TYPE 7
#define ROMFH_HRD 0
#define ROMFH_DIR 1
#define ROMFH_REG 2
#define ROMFH_SYM 3
#define ROMFH_BLK 4
#define ROMFH_CHR 5
#define ROMFH_SCK 6
#define ROMFH_FIF 7
#define ROMFH_EXEC 8
/* Alignment */
#define ROMFH_ALIGN 16
#define MAX_FILE_HANDLES 256
typedef struct FileHandle {
uint8_t *base;
unsigned long size, max_size;
unsigned long pos;
int is_rw;
} FileHandle;
static FileHandle file_handles[MAX_FILE_HANDLES];
static uint8_t *output_base;
static size_t output_max_size, output_size;
static uint8_t output_filename[128];
void set_output_file(const char *filename,
uint8_t *base, size_t size)
{
strcpy(output_filename, filename);
output_base = base;
output_max_size = size;
}
long get_output_file_size(void)
{
return output_size;
}
static inline int get_file_handle(void)
{
int i;
for(i = 0; i < MAX_FILE_HANDLES; i++) {
if (!file_handles[i].base)
return i;
}
errno = ENOMEM;
return -1;
}
int open(const char *filename, int access, ...)
{
struct romfs_super_block *sb;
unsigned long addr, next;
struct romfs_inode *inode;
int type, fd, len;
char dir[1024];
const char *p, *r;
if (access & O_CREAT) {
/* specific case for file creation */
if (strcmp(filename, output_filename) != 0)
return -EPERM;
fd = get_file_handle();
if (fd < 0)
return fd;
file_handles[fd].base = output_base;
file_handles[fd].max_size = output_max_size;
file_handles[fd].is_rw = 1;
file_handles[fd].pos = 0;
file_handles[fd].size = 0;
return fd;
}
show_filename(filename);
sb = (void *)romfs_base;
if (sb->word0 != ROMSB_WORD0 ||
sb->word1 != ROMSB_WORD1)
goto fail;
addr = ((unsigned long)sb->name + strlen(sb->name) + 1 + ROMFH_ALIGN - 1) &
~(ROMFH_ALIGN - 1);
inode = (void *)addr;
/* search the directory */
p = filename;
while (*p == '/')
p++;
for(;;) {
r = strchr(p, '/');
if (!r)
break;
len = r - p;
if (len > sizeof(dir) - 1)
goto fail;
memcpy(dir, p, len);
dir[len] = '\0';
p = r + 1;
#ifdef ROMFS_DEBUG
printf("dir=%s\n", dir);
#endif
for(;;) {
next = ntohl(inode->next);
type = next & 0xf;
next &= ~0xf;
if (!strcmp(dir, inode->name)) {
#ifdef ROMFS_DEBUG
printf("dirname=%s type=0x%x\n", inode->name, type);
#endif
if ((type & ROMFH_TYPE) == ROMFH_DIR) {
chdir:
addr = ((unsigned long)inode->name + strlen(inode->name) +
1 + ROMFH_ALIGN - 1) &
~(ROMFH_ALIGN - 1);
inode = (void *)addr;
break;
} else if ((type & ROMFH_TYPE) == ROMFH_HRD) {
addr = ntohl(inode->spec);
inode = (void *)(romfs_base + addr);
next = ntohl(inode->next);
type = next & 0xf;
if ((type & ROMFH_TYPE) != ROMFH_DIR)
goto fail;
goto chdir;
}
}
if (next == 0)
goto fail;
inode = (void *)(romfs_base + next);
}
}
for(;;) {
next = ntohl(inode->next);
type = next & 0xf;
next &= ~0xf;
#ifdef ROMFS_DEBUG
printf("name=%s type=0x%x\n", inode->name, type);
#endif
if ((type & ROMFH_TYPE) == ROMFH_REG) {
if (!strcmp(p, inode->name)) {
fd = get_file_handle();
if (fd < 0)
return fd;
addr = ((unsigned long)inode->name + strlen(inode->name) +
1 + ROMFH_ALIGN - 1) &
~(ROMFH_ALIGN - 1);
file_handles[fd].base = (void *)addr;
file_handles[fd].is_rw = 0;
file_handles[fd].pos = 0;
file_handles[fd].size = ntohl(inode->size);
return fd;
}
}
if (next == 0)
break;
inode = (void *)(romfs_base + next);
}
fail:
errno = ENOENT;
return -1;
}
int read(int fd, void *buf, size_t size)
{
FileHandle *fh = &file_handles[fd];
int len;
len = fh->size - fh->pos;
if (len > (int)size)
len = size;
memcpy(buf, fh->base + fh->pos, len);
fh->pos += len;
return len;
}
int write(int fd, const void *buf, size_t size)
{
FileHandle *fh = &file_handles[fd];
int len;
if (!fh->is_rw)
return -EIO;
len = fh->max_size - fh->pos;
if ((int)size > len) {
errno = ENOSPC;
return -1;
}
memcpy(fh->base + fh->pos, buf, size);
fh->pos += size;
if (fh->pos > fh->size) {
fh->size = fh->pos;
output_size = fh->pos;
}
return size;
}
long lseek(int fd, long offset, int whence)
{
FileHandle *fh = &file_handles[fd];
switch(whence) {
case SEEK_SET:
break;
case SEEK_END:
offset += fh->size;
break;
case SEEK_CUR:
offset += fh->pos;
break;
default:
errno = EINVAL;
return -1;
}
if (offset < 0) {
errno = EINVAL;
return -1;
}
fh->pos = offset;
return offset;
}
int close(int fd)
{
FileHandle *fh = &file_handles[fd];
fh->base = NULL;
return 0;
}
/**********************************************************/
float strtof(const char *nptr, char **endptr)
{
fatal("unimplemented: %s", __func__ );
}
long double strtold(const char *nptr, char **endptr)
{
fatal("unimplemented: %s", __func__ );
}
double ldexp(double x, int exp)
{
fatal("unimplemented: %s", __func__ );
}
FILE *fopen(const char *path, const char *mode)
{
fatal("unimplemented: %s", __func__ );
}
FILE *fdopen(int fildes, const char *mode)
{
FILE *f;
f = malloc(sizeof(FILE));
f->fd = fildes;
return f;
}
int fclose(FILE *stream)
{
close(stream->fd);
free(stream);
}
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
int ret;
if (nmemb == 1) {
ret = write(stream->fd, ptr, size);
if (ret < 0)
return ret;
} else {
ret = write(stream->fd, ptr, size * nmemb);
if (ret < 0)
return ret;
if (nmemb != 0)
ret /= nmemb;
}
return ret;
}
int fputc(int c, FILE *stream)
{
uint8_t ch = c;
write(stream->fd, &ch, 1);
return 0;
}

551
linux-2.4.26-config Normal file
View File

@ -0,0 +1,551 @@
#
# Automatically generated by make menuconfig: don't edit
#
CONFIG_X86=y
# CONFIG_SBUS is not set
CONFIG_UID16=y
#
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
#
# Loadable module support
#
# CONFIG_MODULES is not set
#
# Processor type and features
#
# CONFIG_M386 is not set
CONFIG_M486=y
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MELAN is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP2 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INVLPG=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_XADD=y
CONFIG_X86_BSWAP=y
CONFIG_X86_POPAD_OK=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_X86_L1_CACHE_SHIFT=4
CONFIG_X86_USE_STRING_486=y
CONFIG_X86_ALIGNMENT_16=y
CONFIG_X86_PPRO_FENCE=y
# CONFIG_X86_F00F_WORKS_OK is not set
# CONFIG_X86_MCE is not set
# CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set
# CONFIG_MICROCODE is not set
# CONFIG_X86_MSR is not set
# CONFIG_X86_CPUID is not set
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
# CONFIG_HIGHMEM is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
# CONFIG_SMP is not set
# CONFIG_X86_UP_APIC is not set
# CONFIG_X86_UP_IOAPIC is not set
# CONFIG_X86_TSC_DISABLE is not set
#
# General setup
#
CONFIG_NET=y
# CONFIG_PCI is not set
# CONFIG_ISA is not set
# CONFIG_EISA is not set
# CONFIG_MCA is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
# CONFIG_HOTPLUG_PCI is not set
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_KCORE_ELF=y
# CONFIG_KCORE_AOUT is not set
# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_OOM_KILLER is not set
# CONFIG_PM is not set
# CONFIG_APM is not set
#
# ACPI Support
#
# CONFIG_ACPI is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play configuration
#
# CONFIG_PNP is not set
# CONFIG_ISAPNP is not set
#
# Block devices
#
CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_CISS_MONITOR_THREAD is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
# CONFIG_BLK_STATS is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_BLK_DEV_LVM is not set
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
#
# Appletalk devices
#
# CONFIG_DEV_APPLETALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
# CONFIG_PHONE_IXJ is not set
# CONFIG_PHONE_IXJ_PCMCIA is not set
#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y
#
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_ATARAID is not set
# CONFIG_BLK_DEV_ATARAID_PDC is not set
# CONFIG_BLK_DEV_ATARAID_HPT is not set
# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
# CONFIG_BLK_DEV_ATARAID_SII is not set
#
# SCSI support
#
# CONFIG_SCSI is not set
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
# CONFIG_FUSION_BOOT is not set
# CONFIG_FUSION_ISENSE is not set
# CONFIG_FUSION_CTL is not set
# CONFIG_FUSION_LAN is not set
#
# I2O device support
#
# CONFIG_I2O is not set
# CONFIG_I2O_BLOCK is not set
# CONFIG_I2O_LAN is not set
# CONFIG_I2O_SCSI is not set
# CONFIG_I2O_PROC is not set
#
# Network device support
#
CONFIG_NETDEVICES=y
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_SUNLANCE is not set
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_FDDI is not set
# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# IrDA (infrared) support
#
# CONFIG_IRDA is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# Input core support
#
# CONFIG_INPUT is not set
# CONFIG_INPUT_KEYBDEV is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_UINPUT is not set
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
# I2C support
#
# CONFIG_I2C is not set
#
# Mice
#
# CONFIG_BUSMOUSE is not set
CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
# CONFIG_MK712_MOUSE is not set
#
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_IPMI_PANIC_EVENT is not set
# CONFIG_IPMI_DEVICE_INTERFACE is not set
# CONFIG_IPMI_KCS is not set
# CONFIG_IPMI_WATCHDOG is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_SCx200 is not set
# CONFIG_SCx200_GPIO is not set
# CONFIG_AMD_RNG is not set
# CONFIG_INTEL_RNG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_AMD_PM768 is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
#
# Direct Rendering Manager (XFree86 DRI support)
#
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
# CONFIG_OBMOUSE is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_QFMT_V2 is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BEFS_DEBUG is not set
# CONFIG_BFS_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
# CONFIG_JBD_DEBUG is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_TMPFS=y
CONFIG_RAMFS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_QNX4FS_RW is not set
CONFIG_ROMFS_FS=y
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_XFS_FS is not set
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_RT is not set
# CONFIG_XFS_TRACE is not set
# CONFIG_XFS_DEBUG is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_TCP is not set
# CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
# CONFIG_NCPFS_IOCTL_LOCKING is not set
# CONFIG_NCPFS_STRONG is not set
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_ZISOFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_SMB_NLS is not set
# CONFIG_NLS is not set
#
# Console drivers
#
CONFIG_VGA_CONSOLE=y
# CONFIG_VIDEO_SELECT is not set
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB is not set
#
# Support for USB gadgets
#
# CONFIG_USB_GADGET is not set
#
# Bluetooth support
#
# CONFIG_BLUEZ is not set
#
# Kernel hacking
#
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_HIGHMEM is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_IOVIRT is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_FRAME_POINTER is not set
CONFIG_LOG_BUF_SHIFT=0
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_CRC32=y
# CONFIG_ZLIB_INFLATE is not set
# CONFIG_ZLIB_DEFLATE is not set

427
linux-2.4.26-tcc.patch Normal file
View File

@ -0,0 +1,427 @@
diff -ruNw /tmp/linux-2.4.26/arch/i386/kernel/entry.S linux-2.4.26/arch/i386/kernel/entry.S
--- /tmp/linux-2.4.26/arch/i386/kernel/entry.S 2003-06-13 16:51:29.000000000 +0200
+++ linux-2.4.26/arch/i386/kernel/entry.S 2004-10-23 22:19:02.000000000 +0200
@@ -1,3 +1,4 @@
+#define __ASSEMBLY__
/*
* linux/arch/i386/entry.S
*
@@ -664,6 +665,21 @@
.long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */
.long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address */
+#if 0
.rept NR_syscalls-(.-sys_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall)
.endr
+#else
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+#endif
diff -ruNw /tmp/linux-2.4.26/arch/i386/kernel/head.S linux-2.4.26/arch/i386/kernel/head.S
--- /tmp/linux-2.4.26/arch/i386/kernel/head.S 2003-11-28 19:26:19.000000000 +0100
+++ linux-2.4.26/arch/i386/kernel/head.S 2004-10-25 21:18:30.000000000 +0200
@@ -1,3 +1,4 @@
+#define __ASSEMBLY__
/*
* linux/arch/i386/kernel/head.S -- the 32-bit startup code.
*
@@ -41,6 +42,8 @@
*
* On entry, %esi points to the real-mode code as a 32-bit pointer.
*/
+.globl _start
+_start:
startup_32:
/*
* Set segments to known values
diff -ruNw /tmp/linux-2.4.26/arch/i386/kernel/i387.c linux-2.4.26/arch/i386/kernel/i387.c
--- /tmp/linux-2.4.26/arch/i386/kernel/i387.c 2003-08-25 13:44:39.000000000 +0200
+++ linux-2.4.26/arch/i386/kernel/i387.c 2004-10-14 04:17:43.000000000 +0200
@@ -25,7 +25,7 @@
#define HAVE_HWFP 1
#endif
-static union i387_union empty_fpu_state;
+union i387_union empty_fpu_state;
void __init boot_init_fpu(void)
{
diff -ruNw /tmp/linux-2.4.26/arch/i386/kernel/process.c linux-2.4.26/arch/i386/kernel/process.c
--- /tmp/linux-2.4.26/arch/i386/kernel/process.c 2004-02-18 14:36:30.000000000 +0100
+++ linux-2.4.26/arch/i386/kernel/process.c 2004-10-25 21:30:36.000000000 +0200
@@ -52,7 +52,7 @@
#include <linux/irq.h>
-asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_fork(void) /* __asm__("ret_from_fork") */ ;
int hlt_counter;
@@ -217,7 +217,7 @@
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};
-static struct
+struct
{
unsigned short size __attribute__ ((packed));
unsigned long long * base __attribute__ ((packed));
diff -ruNw /tmp/linux-2.4.26/arch/i386/kernel/setup.c linux-2.4.26/arch/i386/kernel/setup.c
--- /tmp/linux-2.4.26/arch/i386/kernel/setup.c 2004-04-14 15:05:25.000000000 +0200
+++ linux-2.4.26/arch/i386/kernel/setup.c 2004-10-17 19:38:37.000000000 +0200
@@ -1392,7 +1392,7 @@
*/
extern void vide(void);
-__asm__(".align 4\nvide: ret");
+__asm__(".align 4\n.globl vide\nvide: ret");
static int __init init_amd(struct cpuinfo_x86 *c)
{
diff -ruNw /tmp/linux-2.4.26/arch/i386/mm/init.c linux-2.4.26/arch/i386/mm/init.c
--- /tmp/linux-2.4.26/arch/i386/mm/init.c 2004-04-14 15:05:25.000000000 +0200
+++ linux-2.4.26/arch/i386/mm/init.c 2004-10-23 22:35:47.000000000 +0200
@@ -36,6 +36,7 @@
#include <asm/fixmap.h>
#include <asm/e820.h>
#include <asm/apic.h>
+#include <asm-generic/tlb.h>
#include <asm/tlb.h>
mmu_gather_t mmu_gathers[NR_CPUS];
diff -ruNw /tmp/linux-2.4.26/arch/i386/mm/pageattr.c linux-2.4.26/arch/i386/mm/pageattr.c
--- /tmp/linux-2.4.26/arch/i386/mm/pageattr.c 2002-11-29 00:53:09.000000000 +0100
+++ linux-2.4.26/arch/i386/mm/pageattr.c 2004-10-14 00:43:58.000000000 +0200
@@ -44,8 +44,12 @@
addr = address & LARGE_PAGE_MASK;
pbase = (pte_t *)page_address(base);
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
- pbase[i] = mk_pte_phys(addr,
- addr == address ? prot : PAGE_KERNEL);
+ pgprot_t prot1;
+ if (addr == address)
+ prot1 = prot;
+ else
+ prot1 = PAGE_KERNEL;
+ pbase[i] = mk_pte_phys(addr, prot1);
}
return base;
}
diff -ruNw /tmp/linux-2.4.26/drivers/ide/ide-lib.c linux-2.4.26/drivers/ide/ide-lib.c
--- /tmp/linux-2.4.26/drivers/ide/ide-lib.c 2003-06-13 16:51:33.000000000 +0200
+++ linux-2.4.26/drivers/ide/ide-lib.c 2004-10-23 23:00:51.000000000 +0200
@@ -171,7 +171,7 @@
BUG();
return min(speed, speed_max[mode]);
#else /* !CONFIG_BLK_DEV_IDEDMA */
- return min(speed, XFER_PIO_4);
+ return min((int)speed, XFER_PIO_4);
#endif /* CONFIG_BLK_DEV_IDEDMA */
}
diff -ruNw /tmp/linux-2.4.26/fs/partitions/efi.h linux-2.4.26/fs/partitions/efi.h
--- /tmp/linux-2.4.26/fs/partitions/efi.h 2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.26/fs/partitions/efi.h 2004-10-25 21:32:29.000000000 +0200
@@ -85,9 +85,13 @@
} __attribute__ ((packed)) gpt_header;
typedef struct _gpt_entry_attributes {
+#if 0
u64 required_to_function:1;
u64 reserved:47;
u64 type_guid_specific:16;
+#else
+ u64 required;
+#endif
} __attribute__ ((packed)) gpt_entry_attributes;
typedef struct _gpt_entry {
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/bugs.h linux-2.4.26/include/asm-i386/bugs.h
--- /tmp/linux-2.4.26/include/asm-i386/bugs.h 2002-08-03 02:39:45.000000000 +0200
+++ linux-2.4.26/include/asm-i386/bugs.h 2004-10-25 21:31:34.000000000 +0200
@@ -50,8 +50,8 @@
__setup("no387", no_387);
-static double __initdata x = 4195835.0;
-static double __initdata y = 3145727.0;
+double __initdata x = 4195835.0;
+double __initdata y = 3145727.0;
/*
* This used to check for exceptions..
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/byteorder.h linux-2.4.26/include/asm-i386/byteorder.h
--- /tmp/linux-2.4.26/include/asm-i386/byteorder.h 2003-06-13 16:51:38.000000000 +0200
+++ linux-2.4.26/include/asm-i386/byteorder.h 2004-10-23 23:08:08.000000000 +0200
@@ -42,8 +42,10 @@
__u64 u;
} v;
v.u = val;
-#ifdef CONFIG_X86_BSWAP
- asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+#if defined(CONFIG_X86_BSWAP) && 0
+ /* XXX: constraint bug
+ bswap %eax ; bswap (%ecx) ; xchgl %eax,(%ecx) */
+ asm("bswap %0 ; bswap %1 ; xchgl %0,%1"
: "=r" (v.s.a), "=r" (v.s.b)
: "0" (v.s.a), "1" (v.s.b));
#else
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/hw_irq.h linux-2.4.26/include/asm-i386/hw_irq.h
--- /tmp/linux-2.4.26/include/asm-i386/hw_irq.h 2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.26/include/asm-i386/hw_irq.h 2004-10-23 23:08:08.000000000 +0200
@@ -156,6 +156,7 @@
asmlinkage void call_do_IRQ(void); \
__asm__( \
"\n" __ALIGN_STR"\n" \
+ ".globl common_interrupt\n\t" \
"common_interrupt:\n\t" \
SAVE_ALL \
SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
@@ -176,6 +177,7 @@
asmlinkage void IRQ_NAME(nr); \
__asm__( \
"\n"__ALIGN_STR"\n" \
+".globl " SYMBOL_NAME_STR(IRQ) #nr "_interrupt\n\t"\
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $"#nr"-256\n\t" \
"jmp common_interrupt");
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/page.h linux-2.4.26/include/asm-i386/page.h
--- /tmp/linux-2.4.26/include/asm-i386/page.h 2002-08-03 02:39:45.000000000 +0200
+++ linux-2.4.26/include/asm-i386/page.h 2004-10-23 23:08:08.000000000 +0200
@@ -95,7 +95,7 @@
* undefined" opcode for parsing in the trap handler.
*/
-#if 1 /* Set to zero for a slightly smaller kernel */
+#if 0 /* Set to zero for a slightly smaller kernel */
#define BUG() \
__asm__ __volatile__( "ud2\n" \
"\t.word %c0\n" \
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/processor.h linux-2.4.26/include/asm-i386/processor.h
--- /tmp/linux-2.4.26/include/asm-i386/processor.h 2004-02-18 14:36:32.000000000 +0100
+++ linux-2.4.26/include/asm-i386/processor.h 2004-10-23 23:08:08.000000000 +0200
@@ -300,6 +300,7 @@
long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
long padding[56];
+ int dummy[0] __attribute__ ((aligned (16)));
} __attribute__ ((aligned (16)));
struct i387_soft_struct {
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/semaphore.h linux-2.4.26/include/asm-i386/semaphore.h
--- /tmp/linux-2.4.26/include/asm-i386/semaphore.h 2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.26/include/asm-i386/semaphore.h 2004-10-25 21:31:34.000000000 +0200
@@ -207,7 +207,7 @@
"2:\tcall __up_wakeup\n\t"
"jmp 1b\n"
LOCK_SECTION_END
- ".subsection 0\n"
+ /* ".subsection 0\n" */
:"=m" (sem->count)
:"c" (sem)
:"memory");
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/string.h linux-2.4.26/include/asm-i386/string.h
--- /tmp/linux-2.4.26/include/asm-i386/string.h 2001-11-22 20:46:18.000000000 +0100
+++ linux-2.4.26/include/asm-i386/string.h 2004-10-23 23:08:08.000000000 +0200
@@ -178,7 +178,7 @@
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
- :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
+ :"=r" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
return __res;
}
diff -ruNw /tmp/linux-2.4.26/include/asm-i386/system.h linux-2.4.26/include/asm-i386/system.h
--- /tmp/linux-2.4.26/include/asm-i386/system.h 2004-04-14 15:05:40.000000000 +0200
+++ linux-2.4.26/include/asm-i386/system.h 2004-10-25 21:30:22.000000000 +0200
@@ -28,7 +28,7 @@
"popl %%esi\n\t" \
:"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
"=b" (last) \
- :"m" (next->thread.esp),"m" (next->thread.eip), \
+ :"g" (next->thread.esp),"g" (next->thread.eip), \
"a" (prev), "d" (next), \
"b" (prev)); \
} while (0)
@@ -313,7 +313,7 @@
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
/* interrupt control.. */
-#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
+#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0" : "=g" (x) /* no input */)
#define __restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
#define __cli() __asm__ __volatile__("cli": : :"memory")
#define __sti() __asm__ __volatile__("sti": : :"memory")
diff -ruNw /tmp/linux-2.4.26/include/linux/byteorder/generic.h linux-2.4.26/include/linux/byteorder/generic.h
--- /tmp/linux-2.4.26/include/linux/byteorder/generic.h 2003-11-28 19:26:21.000000000 +0100
+++ linux-2.4.26/include/linux/byteorder/generic.h 2004-10-17 22:09:20.000000000 +0200
@@ -86,8 +86,8 @@
*/
#define cpu_to_le64 __cpu_to_le64
#define le64_to_cpu __le64_to_cpu
-#define cpu_to_le32 __cpu_to_le32
-#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le32(x) __cpu_to_le32(x)
+#define le32_to_cpu(x) __le32_to_cpu(x)
#define cpu_to_le16 __cpu_to_le16
#define le16_to_cpu __le16_to_cpu
#define cpu_to_be64 __cpu_to_be64
diff -ruNw /tmp/linux-2.4.26/include/linux/linkage.h linux-2.4.26/include/linux/linkage.h
--- /tmp/linux-2.4.26/include/linux/linkage.h 2000-12-11 21:49:54.000000000 +0100
+++ linux-2.4.26/include/linux/linkage.h 2004-10-23 23:08:08.000000000 +0200
@@ -19,11 +19,7 @@
#define SYMBOL_NAME_STR(X) #X
#define SYMBOL_NAME(X) X
-#ifdef __STDC__
-#define SYMBOL_NAME_LABEL(X) X##:
-#else
-#define SYMBOL_NAME_LABEL(X) X/**/:
-#endif
+#define SYMBOL_NAME_LABEL(X) X:
#ifdef __arm__
#define __ALIGN .align 0
diff -ruNw /tmp/linux-2.4.26/include/linux/spinlock.h linux-2.4.26/include/linux/spinlock.h
--- /tmp/linux-2.4.26/include/linux/spinlock.h 2004-02-18 14:36:32.000000000 +0100
+++ linux-2.4.26/include/linux/spinlock.h 2004-10-25 21:31:34.000000000 +0200
@@ -41,6 +41,7 @@
#include <linux/stringify.h>
+#if 0
#define LOCK_SECTION_NAME \
".text.lock." __stringify(KBUILD_BASENAME)
@@ -51,6 +52,11 @@
LOCK_SECTION_NAME ":\n\t" \
".endif\n\t"
+#else
+#define LOCK_SECTION_NAME ".text.lock"
+#define LOCK_SECTION_START(extra) ".section " LOCK_SECTION_NAME "\n\t"
+#endif
+
#define LOCK_SECTION_END \
".previous\n\t"
diff -ruNw /tmp/linux-2.4.26/include/linux/wait.h linux-2.4.26/include/linux/wait.h
--- /tmp/linux-2.4.26/include/linux/wait.h 2003-08-25 13:44:44.000000000 +0200
+++ linux-2.4.26/include/linux/wait.h 2004-10-25 21:31:34.000000000 +0200
@@ -64,14 +64,14 @@
# define wq_lock_t spinlock_t
# define WAITQUEUE_RW_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
-# define wq_read_lock spin_lock
-# define wq_read_lock_irqsave spin_lock_irqsave
-# define wq_read_unlock spin_unlock
-# define wq_read_unlock_irqrestore spin_unlock_irqrestore
-# define wq_write_lock_irq spin_lock_irq
-# define wq_write_lock_irqsave spin_lock_irqsave
-# define wq_write_unlock_irqrestore spin_unlock_irqrestore
-# define wq_write_unlock spin_unlock
+# define wq_read_lock(lock) spin_lock(lock)
+# define wq_read_lock_irqsave(lock, flags) spin_lock_irqsave(lock, flags)
+# define wq_read_unlock(lock) spin_unlock(lock)
+# define wq_read_unlock_irqrestore(lock, flags) spin_unlock_irqrestore(lock, flags)
+# define wq_write_lock_irq(lock) spin_lock_irq(lock)
+# define wq_write_lock_irqsave(lock, flags) spin_lock_irqsave(lock, flags)
+# define wq_write_unlock_irqrestore(lock, flags) spin_unlock_irqrestore(lock, flags)
+# define wq_write_unlock(lock) spin_unlock(lock)
#endif
struct __wait_queue_head {
diff -ruNw /tmp/linux-2.4.26/net/core/dev.c linux-2.4.26/net/core/dev.c
--- /tmp/linux-2.4.26/net/core/dev.c 2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26/net/core/dev.c 2004-10-14 03:27:45.000000000 +0200
@@ -2013,8 +2013,17 @@
ret = 0;
if ((old_flags^flags)&IFF_UP) /* Bit is different ? */
{
- ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
+ int (*dev_func)(struct net_device *);
+#if 0
+ ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
+#else
+ if (old_flags & IFF_UP)
+ dev_func = dev_close;
+ else
+ dev_func = dev_open;
+ ret = dev_func(dev);
+#endif
if (ret == 0)
dev_mc_upload(dev);
}
diff -ruNw /tmp/linux-2.4.26/net/ipv4/raw.c linux-2.4.26/net/ipv4/raw.c
--- /tmp/linux-2.4.26/net/ipv4/raw.c 2003-08-25 13:44:44.000000000 +0200
+++ linux-2.4.26/net/ipv4/raw.c 2004-10-23 22:53:26.000000000 +0200
@@ -311,6 +311,10 @@
u32 daddr;
u8 tos;
int err;
+ int (*getfrag)(const void *,
+ char *,
+ unsigned int,
+ unsigned int);
/* This check is ONLY to check for arithmetic overflow
on integer(!) len. Not more! Real check will be made
@@ -426,8 +430,11 @@
rfh.dst = &rt->u.dst;
if (!ipc.addr)
ipc.addr = rt->rt_dst;
- err = ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag :
- raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags);
+ if (sk->protinfo.af_inet.hdrincl)
+ getfrag =raw_getrawfrag;
+ else
+ getfrag = raw_getfrag;
+ err = ip_build_xmit(sk, getfrag, &rfh, len, &ipc, rt, msg->msg_flags);
done:
if (free)
diff -ruNw /tmp/linux-2.4.26/net/ipv4/udp.c linux-2.4.26/net/ipv4/udp.c
--- /tmp/linux-2.4.26/net/ipv4/udp.c 2004-04-14 15:05:41.000000000 +0200
+++ linux-2.4.26/net/ipv4/udp.c 2004-10-23 22:54:30.000000000 +0200
@@ -441,6 +441,10 @@
u32 daddr;
u8 tos;
int err;
+ int (*getfrag)(const void *,
+ char *,
+ unsigned int,
+ unsigned int);
/* This check is ONLY to check for arithmetic overflow
on integer(!) len. Not more! Real check will be made
@@ -560,11 +564,12 @@
/* RFC1122: OK. Provides the checksumming facility (MUST) as per */
/* 4.1.3.4. It's configurable by the application via setsockopt() */
/* (MAY) and it defaults to on (MUST). */
-
+ if (sk->no_check == UDP_CSUM_NOXMIT)
+ getfrag = udp_getfrag_nosum;
+ else
+ getfrag = udp_getfrag;
err = ip_build_xmit(sk,
- (sk->no_check == UDP_CSUM_NOXMIT ?
- udp_getfrag_nosum :
- udp_getfrag),
+ getfrag,
&ufh, ulen, &ipc, rt, msg->msg_flags);
out:

253
main.c Normal file
View File

@ -0,0 +1,253 @@
#include "tccboot.h"
#include <linux/tty.h>
#include <asm/io.h>
#define TCCARGS_FILE "/boot/tccargs"
#define KERNEL_MAX_SIZE (8 * 1024 * 1024)
#define INITRD_MAX_SIZE (20 * 1024 * 1024)
#define INITRD_MIN_ADDR 0x800000
#define KERNEL_FILENAME "kernel"
//#define DEBUG_INITRD_ADDR
#define MAX_ARGS 1024
struct moveparams {
uint8_t *low_buffer_start; int lcount;
uint8_t *high_buffer_start; int hcount;
};
static unsigned char *real_mode; /* Pointer to real-mode data */
#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
#ifndef STANDARD_MEMORY_BIOS_CALL
#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
#endif
#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
#define INITRD_START (*(unsigned long *) (real_mode+0x218))
#define INITRD_SIZE (*(unsigned long *) (real_mode+0x21c))
#define STACK_SIZE (256 * 1024)
long user_stack [STACK_SIZE];
struct {
long * a;
short b;
} stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS };
static char *vidmem = (char *)0xb8000;
static int vidport;
static int lines, cols;
void video_init(void)
{
if (SCREEN_INFO.orig_video_mode == 7) {
vidmem = (char *) 0xb0000;
vidport = 0x3b4;
} else {
vidmem = (char *) 0xb8000;
vidport = 0x3d4;
}
lines = SCREEN_INFO.orig_video_lines;
cols = SCREEN_INFO.orig_video_cols;
}
static void scroll(void)
{
int i;
memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
vidmem[i] = ' ';
}
void putstr(const char *s)
{
int x,y,pos;
char c;
x = SCREEN_INFO.orig_x;
y = SCREEN_INFO.orig_y;
while ( ( c = *s++ ) != '\0' ) {
if ( c == '\n' ) {
x = 0;
if ( ++y >= lines ) {
scroll();
y--;
}
} else if (c == '\r') {
x = 0;
} else {
vidmem [ ( x + cols * y ) * 2 ] = c;
if ( ++x >= cols ) {
x = 0;
if ( ++y >= lines ) {
scroll();
y--;
}
}
}
}
SCREEN_INFO.orig_x = x;
SCREEN_INFO.orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */
outb_p(14, vidport);
outb_p(0xff & (pos >> 9), vidport+1);
outb_p(15, vidport);
outb_p(0xff & (pos >> 1), vidport+1);
}
void exit(int val)
{
printf("\n\n -- System halted");
while (1);
}
char *tcc_args[MAX_ARGS];
static int expand_args(char ***pargv, const char *str)
{
const char *s1;
char **argv, *arg;
int argc, len;
argc = 0;
argv = tcc_args;
argv[argc++] = "tcc";
for(;;) {
while (isspace(*str))
str++;
if (*str == '\0')
break;
if (*str == '#') {
while (*str != '\n')
str++;
continue;
}
s1 = str;
while (*str != '\0' && !isspace(*str))
str++;
len = str - s1;
arg = malloc(len + 1);
memcpy(arg, s1, len);
arg[len] = '\0';
argv[argc++] = arg;
}
*pargv = argv;
return argc;
}
void show_filename(const char *filename)
{
int len;
static int counter;
char counter_ch[4] = "-\\|/";
len = strlen(filename);
if (len >= 2 && filename[len - 2] == '.' && filename[len - 1] == 'c') {
printf("%c %-50s\r", counter_ch[counter], filename);
counter = (counter + 1) & 3;
}
}
int compile_kernel(struct moveparams *mv, void *rmode)
{
int fd, len;
char *args_buf;
char **argv;
int argc, ret, romfs_len;
uint8_t *kernel_ptr, *initrd_ptr;
unsigned long romfs_base1;
real_mode = rmode;
video_init();
/* this is risky, but normally the initrd is not mapped inside the
malloc structures. However, it can overlap with its new
location */
if (!INITRD_SIZE || !INITRD_START)
fatal("the kernel source must be in a ROMFS filesystem stored as Initial Ram Disk (INITRD)");
len = INITRD_SIZE;
/* NOTE: it is very important to move initrd first to avoid
destroying it later */
initrd_ptr = memalign(16, len);
memmove(initrd_ptr, (void *)INITRD_START, len);
if (initrd_ptr[0] == 037 && ((initrd_ptr[1] == 0213) ||
(initrd_ptr[1] == 0236))) {
printf("Decompressing initrd...\n");
romfs_base = memalign(16, INITRD_MAX_SIZE);
romfs_len = do_gunzip(romfs_base, initrd_ptr, len);
/* realloc it to minimize memory usage */
romfs_base = realloc(romfs_base, romfs_len);
free(initrd_ptr);
} else {
romfs_base = initrd_ptr;
romfs_len = len;
}
kernel_ptr = malloc(KERNEL_MAX_SIZE);
set_output_file("kernel", kernel_ptr, KERNEL_MAX_SIZE);
#ifdef DEBUG_INITRD_ADDR
printf("romfs_base=%p romfs_len=%d kernel_ptr=%p\n",
romfs_base, romfs_len, kernel_ptr);
#endif
printf("Compiling kernel...\n");
fd = open("/boot/tccargs", O_RDONLY);
if (fd < 0)
fatal("Could not find '%s'", TCCARGS_FILE);
len = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
args_buf = malloc(len + 1);
len = read(fd, args_buf, len);
close(fd);
args_buf[len] = '\0';
argc = expand_args(&argv, args_buf);
argv[argc] = NULL;
free(args_buf);
#if 0
{
int i;
for(i=0;i<argc;i++) {
printf("%d: '%s'\n", i, argv[i]);
}
}
#endif
ret = main(argc, argv);
printf("%-50s\n", "");
printf("Ok, booting the kernel.\n");
mv->lcount = 0;
mv->hcount = get_output_file_size();
mv->high_buffer_start = kernel_ptr;
/* relocate the uncompressed initrd so that the kernel cannot
overwrite it */
romfs_base1 = ((unsigned long)(mv->high_buffer_start) +
mv->hcount + PAGE_SIZE - 1) &
~(PAGE_SIZE - 1);
if (romfs_base1 < INITRD_MIN_ADDR)
romfs_base1 = INITRD_MIN_ADDR;
if (!(kernel_ptr >= romfs_base + romfs_len &&
(unsigned long)romfs_base >= INITRD_MIN_ADDR) &&
(unsigned long)romfs_base < romfs_base1) {
memmove((void *)romfs_base1, romfs_base, romfs_len);
romfs_base = (void *)romfs_base1;
}
#ifdef DEBUG_INITRD_ADDR
printf("initrd_start=%p initrd_size=%d\n", romfs_base, romfs_len);
#endif
INITRD_START = (unsigned long)romfs_base;
INITRD_SIZE = romfs_len;
return 1;
}

5482
malloc.c Normal file

File diff suppressed because it is too large Load Diff

6
qemu-tccboot Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
~/qemu-current/i386-softmmu/qemu -snapshot -user-net -serial stdio \
-kernel tccboot \
-initrd initrd.img \
-append "root=/dev/hda" \
-hda example.romfs

BIN
tccboot Normal file

Binary file not shown.

90
tccboot.h Normal file
View File

@ -0,0 +1,90 @@
#include <stdarg.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <asm/byteorder.h>
#include <asm/page.h>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
typedef struct FILE {
int fd;
} FILE;
struct tm {
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/
};
void *sbrk(int increment);
void *malloc(size_t size);
void *memalign(size_t alignment, size_t n);
void free(void *ptr);
int printf(const char *fmt, ...);
int fprintf(FILE *f, const char *fmt, ...);
uint8_t *load_image(const char *filename);
void *realloc(void *ptr, size_t size);
int open(const char *filename, int access, ...);
int read(int fd, void *buf, size_t size);
int close(int fd);
long lseek(int fd, long offset, int whence);
int write(int fd, const void *buf, size_t size);
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fildes, const char *mode);
int fclose(FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fputc(int c, FILE *stream);
long strtol(const char *nptr, char **endptr, int base);
long long strtoll(const char *nptr, char **endptr, int base);
unsigned long strtoul(const char *nptr, char **endptr, int base);
unsigned long long strtoull(const char *nptr, char **endptr, int base);
int atoi(const char *s);
float strtof(const char *nptr, char **endptr);
double strtod(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
double ldexp(double x, int exp);
int gettimeofday(struct timeval *tv, struct timezone *tz);
time_t time(time_t *t);
struct tm *localtime(const time_t *timep);
void exit(int val);
void getcwd(char *buf, size_t buf_size);
typedef int jmp_buf[6];
int setjmp(jmp_buf buf);
void longjmp(jmp_buf buf, int val);
int main(int argc, char **argv);
void fatal(const char *fmt, ...) __attribute__((noreturn)) ;
void romfs_init(void);
void show_filename(const char *filename);
void set_output_file(const char *filename,
uint8_t *base, size_t size);
long get_output_file_size(void);
void putstr(const char *s);
int do_gunzip(uint8_t *dest, const uint8_t *src, int src_len);
extern uint8_t *romfs_base;
extern int errno;
extern FILE *stderr;

4
test.c Normal file
View File

@ -0,0 +1,4 @@
int _start(void)
{
while(1);
}

50
user.c Normal file
View File

@ -0,0 +1,50 @@
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <linux/unistd.h>
#define __NR_linux_open __NR_open
#define __NR_linux_lseek __NR_lseek
#define __NR_linux_read __NR_read
#define __NR_linux_write __NR_write
#define __NR_linux_close __NR_close
#define __NR_linux_exit __NR_exit
_syscall3(int,linux_open,const char *,filename,int,access,int,mode)
_syscall3(int,linux_lseek,int,fd,int,offset,int,whence)
_syscall3(int,linux_read,int,fd,void *,buf,int,size)
_syscall3(int,linux_write,int,fd,const void *,buf,int,size)
_syscall1(int,linux_close,int,fd)
_syscall1(int,linux_exit,int,val)
void exit(int val)
{
linux_exit(val);
}
void putstr(const char *s)
{
linux_write(1, s, strlen(s));
}
uint8_t *load_image(const char *filename)
{
int fd, size;
uint8_t *p;
fd = linux_open(filename, O_RDONLY, 0);
if (fd < 0) {
return NULL;
}
size = linux_lseek(fd, 0, SEEK_END);
linux_lseek(fd, 0, SEEK_SET);
p = malloc(size + 15);
p = (void *)((unsigned long)p & ~15);
linux_read(fd, p, size);
linux_close(fd);
return p;
}

741
vsprintf.c Normal file
View File

@ -0,0 +1,741 @@
/*
* linux/lib/vsprintf.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
* Wirzenius wrote this portably, Torvalds fucked it up :-)
*/
/*
* Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
* - changed to provide snprintf and vsnprintf functions
*/
#include <stdarg.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <asm/div64.h>
#include <asm/page.h>
/**
* simple_strtoul - convert a string to an unsigned long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
{
unsigned long result = 0,value;
if (!base) {
base = 10;
if (*cp == '0') {
base = 8;
cp++;
if ((*cp == 'x') && isxdigit(cp[1])) {
cp++;
base = 16;
}
}
}
while (isxdigit(*cp) &&
(value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
result = result*base + value;
cp++;
}
if (endp)
*endp = (char *)cp;
return result;
}
/**
* simple_strtol - convert a string to a signed long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
long simple_strtol(const char *cp,char **endp,unsigned int base)
{
if(*cp=='-')
return -simple_strtoul(cp+1,endp,base);
return simple_strtoul(cp,endp,base);
}
/**
* simple_strtoull - convert a string to an unsigned long long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
{
unsigned long long result = 0,value;
if (!base) {
base = 10;
if (*cp == '0') {
base = 8;
cp++;
if ((*cp == 'x') && isxdigit(cp[1])) {
cp++;
base = 16;
}
}
}
while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
? toupper(*cp) : *cp)-'A'+10) < base) {
result = result*base + value;
cp++;
}
if (endp)
*endp = (char *)cp;
return result;
}
/**
* simple_strtoll - convert a string to a signed long long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
long long simple_strtoll(const char *cp,char **endp,unsigned int base)
{
if(*cp=='-')
return -simple_strtoull(cp+1,endp,base);
return simple_strtoull(cp,endp,base);
}
static int skip_atoi(const char **s)
{
int i=0;
while (isdigit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}
#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' */
static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
const char *digits;
static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i;
digits = (type & LARGE) ? large_digits : small_digits;
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) {
if (buf <= end)
*buf = ' ';
++buf;
}
}
if (sign) {
if (buf <= end)
*buf = sign;
++buf;
}
if (type & SPECIAL) {
if (base==8) {
if (buf <= end)
*buf = '0';
++buf;
} else if (base==16) {
if (buf <= end)
*buf = '0';
++buf;
if (buf <= end)
*buf = digits[33];
++buf;
}
}
if (!(type & LEFT)) {
while (size-- > 0) {
if (buf <= end)
*buf = c;
++buf;
}
}
while (i < precision--) {
if (buf <= end)
*buf = '0';
++buf;
}
while (i-- > 0) {
if (buf <= end)
*buf = tmp[i];
++buf;
}
while (size-- > 0) {
if (buf <= end)
*buf = ' ';
++buf;
}
return buf;
}
/**
* vsnprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @size: The size of the buffer, including the trailing null space
* @fmt: The format string to use
* @args: Arguments for the format string
*
* Call this function if you are already dealing with a va_list.
* You probably want snprintf instead.
*/
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
int len;
unsigned long long num;
int i, base;
char *str, *end, c;
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 */
/* 'z' support added 23/7/1999 S.H. */
/* 'z' changed to 'Z' --davidm 1/25/99 */
/* Reject out-of-range values early */
if (unlikely((int) size < 0)) {
#if 0
/* There can be only one.. */
static int warn = 1;
if (warn) {
printk(KERN_WARNING "improper call of vsnprintf!\n");
dump_stack();
warn = 0;
}
#endif
return 0;
}
str = buf;
end = buf + size - 1;
if (end < buf - 1) {
end = ((void *) -1);
size = end - buf + 1;
}
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
if (str <= end)
*str = *fmt;
++str;
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' ||
*fmt =='Z' || *fmt == 'z') {
qualifier = *fmt;
++fmt;
if (qualifier == 'l' && *fmt == 'l') {
qualifier = 'L';
++fmt;
}
}
/* default base */
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & LEFT)) {
while (--field_width > 0) {
if (str <= end)
*str = ' ';
++str;
}
}
c = (unsigned char) va_arg(args, int);
if (str <= end)
*str = c;
++str;
while (--field_width > 0) {
if (str <= end)
*str = ' ';
++str;
}
continue;
case 's':
s = va_arg(args, char *);
if ((unsigned long)s < PAGE_SIZE)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT)) {
while (len < field_width--) {
if (str <= end)
*str = ' ';
++str;
}
}
for (i = 0; i < len; ++i) {
if (str <= end)
*str = *s;
++str; ++s;
}
while (len < field_width--) {
if (str <= end)
*str = ' ';
++str;
}
continue;
case 'p':
if (field_width == -1) {
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
str = number(str, end,
(unsigned long) va_arg(args, void *),
16, field_width, precision, flags);
continue;
case 'n':
/* FIXME:
* What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
} else if (qualifier == 'Z' || qualifier == 'z') {
size_t * ip = va_arg(args, size_t *);
*ip = (str - buf);
} else {
int * ip = va_arg(args, int *);
*ip = (str - buf);
}
continue;
case '%':
if (str <= end)
*str = '%';
++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:
if (str <= end)
*str = '%';
++str;
if (*fmt) {
if (str <= end)
*str = *fmt;
++str;
} else {
--fmt;
}
continue;
}
if (qualifier == 'L')
num = va_arg(args, long long);
else if (qualifier == 'l') {
num = va_arg(args, unsigned long);
if (flags & SIGN)
num = (signed long) num;
} else if (qualifier == 'Z' || qualifier == 'z') {
num = va_arg(args, size_t);
} else if (qualifier == 'h') {
num = (unsigned short) va_arg(args, int);
if (flags & SIGN)
num = (signed short) num;
} else {
num = va_arg(args, unsigned int);
if (flags & SIGN)
num = (signed int) num;
}
str = number(str, end, num, base,
field_width, precision, flags);
}
if (str <= end)
*str = '\0';
else if (size > 0)
/* don't write out a null byte if the buf size is zero */
*end = '\0';
/* the trailing null byte doesn't count towards the total
* ++str;
*/
return str-buf;
}
/**
* snprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @size: The size of the buffer, including the trailing null space
* @fmt: The format string to use
* @...: Arguments for the format string
*/
int snprintf(char * buf, size_t size, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i=vsnprintf(buf,size,fmt,args);
va_end(args);
return i;
}
/**
* vsprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @fmt: The format string to use
* @args: Arguments for the format string
*
* Call this function if you are already dealing with a va_list.
* You probably want sprintf instead.
*/
int vsprintf(char *buf, const char *fmt, va_list args)
{
return vsnprintf(buf, (~0U)>>1, fmt, args);
}
/**
* sprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @fmt: The format string to use
* @...: Arguments for the format string
*/
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;
}
/**
* vsscanf - Unformat a buffer into a list of arguments
* @buf: input buffer
* @fmt: format of buffer
* @args: arguments
*/
int vsscanf(const char * buf, const char * fmt, va_list args)
{
const char *str = buf;
char *next;
char digit;
int num = 0;
int qualifier;
int base;
int field_width;
int is_sign = 0;
while(*fmt && *str) {
/* skip any white space in format */
/* white space in format matchs any amount of
* white space, including none, in the input.
*/
if (isspace(*fmt)) {
while (isspace(*fmt))
++fmt;
while (isspace(*str))
++str;
}
/* anything that is not a conversion must match exactly */
if (*fmt != '%' && *fmt) {
if (*fmt++ != *str++)
break;
continue;
}
if (!*fmt)
break;
++fmt;
/* skip this conversion.
* advance both strings to next white space
*/
if (*fmt == '*') {
while (!isspace(*fmt) && *fmt)
fmt++;
while (!isspace(*str) && *str)
str++;
continue;
}
/* get field width */
field_width = -1;
if (isdigit(*fmt))
field_width = skip_atoi(&fmt);
/* get conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt == 'Z' || *fmt == 'z') {
qualifier = *fmt;
fmt++;
}
base = 10;
is_sign = 0;
if (!*fmt || !*str)
break;
switch(*fmt++) {
case 'c':
{
char *s = (char *) va_arg(args,char*);
if (field_width == -1)
field_width = 1;
do {
*s++ = *str++;
} while (--field_width > 0 && *str);
num++;
}
continue;
case 's':
{
char *s = (char *) va_arg(args, char *);
if(field_width == -1)
field_width = INT_MAX;
/* first, skip leading white space in buffer */
while (isspace(*str))
str++;
/* now copy until next white space */
while (*str && !isspace(*str) && field_width--) {
*s++ = *str++;
}
*s = '\0';
num++;
}
continue;
case 'n':
/* return number of characters read so far */
{
int *i = (int *)va_arg(args,int*);
*i = str - buf;
}
continue;
case 'o':
base = 8;
break;
case 'x':
case 'X':
base = 16;
break;
case 'i':
base = 0;
case 'd':
is_sign = 1;
case 'u':
break;
case '%':
/* looking for '%' in str */
if (*str++ != '%')
return num;
continue;
default:
/* invalid format; stop here */
return num;
}
/* have some sort of integer conversion.
* first, skip white space in buffer.
*/
while (isspace(*str))
str++;
digit = *str;
if (is_sign && digit == '-')
digit = *(str + 1);
if (!digit
|| (base == 16 && !isxdigit(digit))
|| (base == 10 && !isdigit(digit))
|| (base == 8 && (!isdigit(digit) || digit > '7'))
|| (base == 0 && !isdigit(digit)))
break;
switch(qualifier) {
case 'h':
if (is_sign) {
short *s = (short *) va_arg(args,short *);
*s = (short) simple_strtol(str,&next,base);
} else {
unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
*s = (unsigned short) simple_strtoul(str, &next, base);
}
break;
case 'l':
if (is_sign) {
long *l = (long *) va_arg(args,long *);
*l = simple_strtol(str,&next,base);
} else {
unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
*l = simple_strtoul(str,&next,base);
}
break;
case 'L':
if (is_sign) {
long long *l = (long long*) va_arg(args,long long *);
*l = simple_strtoll(str,&next,base);
} else {
unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
*l = simple_strtoull(str,&next,base);
}
break;
case 'Z':
case 'z':
{
size_t *s = (size_t*) va_arg(args,size_t*);
*s = (size_t) simple_strtoul(str,&next,base);
}
break;
default:
if (is_sign) {
int *i = (int *) va_arg(args, int*);
*i = (int) simple_strtol(str,&next,base);
} else {
unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
*i = (unsigned int) simple_strtoul(str,&next,base);
}
break;
}
num++;
if (!next)
break;
str = next;
}
return num;
}
/**
* sscanf - Unformat a buffer into a list of arguments
* @buf: input buffer
* @fmt: formatting of buffer
* @...: resulting arguments
*/
int sscanf(const char * buf, const char * fmt, ...)
{
va_list args;
int i;
va_start(args,fmt);
i = vsscanf(buf,fmt,args);
va_end(args);
return i;
}