summaryrefslogtreecommitdiff
path: root/bootblocks/bzimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootblocks/bzimage.c')
-rw-r--r--bootblocks/bzimage.c197
1 files changed, 164 insertions, 33 deletions
diff --git a/bootblocks/bzimage.c b/bootblocks/bzimage.c
index 2e7c835..baf027b 100644
--- a/bootblocks/bzimage.c
+++ b/bootblocks/bzimage.c
@@ -4,6 +4,7 @@
*/
#include <stdio.h>
+#include <dos.h>
#include "i86_funcs.h"
#include "readfs.h"
@@ -13,9 +14,18 @@ char * append_line = 0; /* A preset append line value */
static char * initrd_name = 0; /* Name of init_ramdisk to load */
static int vga_mode = -1; /* SVGA_MODE = normal */
+static int is_zimage = 0;
+static int image_length; /* Length of image in sectors */
+static long image_size; /* Length of image file in bytes */
+
static char * read_cmdfile();
static char * input_cmd();
+#define ZIMAGE_LOAD_SEG 0x1000 /* Segment that zImage data is loaded */
+#define COMMAND_LINE_POS 0x4000 /* Offset in segment 0x9000 of command line */
+
+int has_command_line = 0;
+
cmd_bzimage(ptr)
char * ptr;
{
@@ -58,12 +68,13 @@ char * command_line;
printf("Loading %s\n", fname);
- if( read_block(buffer) < 0 || check_magics(buffer) < 0 )
+ if( read_block(buffer) < 0 || check_magics(fname, buffer) < 0 )
{
- printf("File %s isn't a bzImage.\n", fname);
+ printf("Cannot execute file %s\n", fname);
return -1;
}
+#ifndef __ELKS__
if( boot_mem_top < 0x9500 )
{
printf("There must be 640k of boot memory to load Linux\n");
@@ -74,7 +85,7 @@ char * command_line;
* I expect we could lookup the size in the gzip header but
* this is probably close enough (3*the size of the bzimage)
*/
- len = file_length() * 3 / 1024;
+ len = (image_size=file_length()) * 3 / 1024;
if( main_mem_top < len )
{
printf("This kernel needs at least %ld.%ldM of main memory\n",
@@ -83,12 +94,29 @@ char * command_line;
}
if( main_mem_top < 3072 )
printf("RTFM warning: Linux really needs at least 4MB of memory.\n");
+#endif
- low_sects = buffer[497] + 1; /* setup sects + boot sector */
+ low_sects = buffer[497] + 1; /* setup sects + boot sector */
+ image_length = (file_length()+511)/512 - low_sects;
address = 0x900;
+#ifndef __ELKS__
+ if( is_zimage )
+ {
+ relocator(8); /* Need space in low memory */
+
+ if( image_length > (__get_cs()>>5) - ZIMAGE_LOAD_SEG/32 )
+ {
+ printf("This zImage file is too large, maximum is %ld bytes\n",
+ ((__get_cs()>>5) - ZIMAGE_LOAD_SEG/32 + low_sects)*512L );
+ return -1;
+ }
+ }
+#endif
+
/* load the blocks */
rewind_file();
+ reset_crc();
for(len = file_length(); len>0; len-=1024)
{
int v;
@@ -109,6 +137,7 @@ char * command_line;
return -1;
}
+ if( len > 1024 ) addcrc(buffer, 1024); else addcrc(buffer, (int)len);
for(v=0; v<1024; v+=512)
{
if( putsect(buffer+v, address) < 0 )
@@ -119,10 +148,15 @@ char * command_line;
if( low_sects )
{
low_sects--;
- if( low_sects == 0 ) address = 0x1000;
+ if( low_sects == 0 )
+ {
+ if( is_zimage ) address = ZIMAGE_LOAD_SEG/16;
+ else address = 0x1000;
+ }
}
}
}
+ display_crc();
/* Yesss, loaded! */
printf("Loaded, "); fflush(stdout);
@@ -135,6 +169,14 @@ char * command_line;
if( load_initrd(address) < 0 )
return -1;
+ check_crc();
+
+ if( is_zimage )
+ {
+ printf("Sorry, zImage's don't seem to be working at the moment.\n");
+ if( !keep_going() ) return -1;
+ }
+
printf("Starting ...\n");
if( x86 < 3 )
@@ -156,9 +198,39 @@ char * command_line;
if( !keep_going() ) return -1;
}
- /* Patch setup to deactivate safety switch */
+#ifdef __ELKS__
+ printf("Cannot start.\n");
+ return -1;
+#endif
+
__set_es(0x9000);
- __poke_es(0x210, 0xFF);
+
+ /* Save pointer to command line */
+ if( has_command_line )
+ {
+ __doke_es(0x0020, 0xA33F);
+ __doke_es(0x0022, COMMAND_LINE_POS);
+ }
+
+#if ZIMAGE_LOAD_SEG != 0x1000
+ if( is_zimage )
+ {
+#if ZIMAGE_LOAD_SEG != 0x100
+ /* Tell setup that we've loaded the kernel somewhere */
+ __poke_es(0x20C, ZIMAGE_LOAD_SEG);
+#else
+ /* Tell setup it's a bzImage _even_ tho it's a _zImage_ because we have
+ * actually loaded it where it's supposed to end up!
+ */
+ __poke_es(0x211, __peek_es(0x211)|1);
+
+ __poke_es(0x210, 0xFF); /* Patch setup to deactivate safety switch */
+#endif
+ }
+#endif
+
+ if( !is_zimage )
+ __poke_es(0x210, 0xFF); /* Patch setup to deactivate safety switch */
/* Set SVGA_MODE if not 'normal' */
if( vga_mode != -1 ) __doke_es(506, vga_mode);
@@ -178,6 +250,8 @@ char * command_line;
mov ax,$9000
mov bx,$4000-12 ! Fix this to use boot_mem_top
mov es,ax
+ mov fs,ax
+ mov gs,ax
mov ds,ax
mov ss,ax
mov sp,bx
@@ -186,51 +260,63 @@ char * command_line;
}
}
-check_magics(buffer)
+check_magics(fname, buffer)
+char * fname;
char * buffer;
{
+ is_zimage = 0;
+
/* Boot sector magic number */
- if( *(unsigned short*)(buffer+510) != 0xAA55 ) return -1;
+ if( *(unsigned short*)(buffer+510) != 0xAA55 ||
/* Setup start */
- if( memcmp(buffer+0x202, "HdrS", 4) != 0 ) return -1;
+ memcmp(buffer+0x202, "HdrS", 4) != 0 ||
/* Setup version */
- if( *(unsigned short*)(buffer+0x206) < 0x200 ) return -1;
-
- /* Check load flags for bzImage */
- if( (buffer[0x211] & 1) == 0 ) return -1;
+ *(unsigned short*)(buffer+0x206) < 0x200 )
+ {
+ printf("File %s is not a linux Image file\n", fname);
+ return -1;
+ }
- /* Code 32 start address */
- if( *(unsigned long*)(buffer+0x214) != 0x100000 ) return -1;
+ /* Code 32 start address for zImage */
+ if( *(unsigned long*)(buffer+0x214) == 0x1000 )
+ {
+ printf("File %s is a zImage file\n", fname);
+ is_zimage = 1;
+ return 0;
+ }
+ else
+ /* Code 32 start address bzImage */
+ if( *(unsigned long*)(buffer+0x214) != 0x100000 )
+ {
+ printf("File %s is not a bzImage file\n", fname);
+ return -1;
+ }
+ printf("File %s is a bzImage file\n", fname);
return 0;
}
+#ifndef __ELKS__
putsect(buffer, address)
char * buffer;
unsigned int address;
{
int rv, tc=3;
+ /* In real mode memory, just put it directly */
+ if( address < 0xA00 )
+ {
+ __movedata(__get_ds(), buffer, address*16, 0, 512);
+ return 0;
+ }
+
retry:
tc--;
#if 1
if( x86_emu )
- {
-static unsigned int last_address = 0;
- if( address <= last_address )
- printf("Problem %d<=%d\n", address, last_address);
- if( address < 0xA00 )
- {
- int i;
- __set_es(address*16);
- for(i=0; i<512; i++)
- __poke_es(i, buffer[i]);
- }
- else
- printf("In EMU can't write to 0x%x\n", address);
- return 0;
- }
+ return 0; /* In an EMU we can't write to high mem but
+ we'll pretend we can for debuggering */
#endif
if( (rv=ext_put(buffer, address, 512)) != 0 )
{
@@ -261,6 +347,7 @@ static unsigned int last_address = 0;
}
return 0;
}
+#endif
static char *
read_cmdfile(iname, extno)
@@ -353,6 +440,8 @@ static char * image_str = "BOOT_IMAGE=";
char * free_app = 0;
char * free_dfl = 0;
+ has_command_line = 0;
+
if( append == 0 )
append = free_app = read_cmdfile(image, 2);
@@ -447,11 +536,18 @@ static char * image_str = "BOOT_IMAGE=";
len = 2048;
}
+#ifdef __ELKS__
+ fprintf(stderr, "Command line: '%s'\n", ptr+1);
+#else
+/*
__set_es(0x9000);
__doke_es(0x0020, 0xA33F);
- __doke_es(0x0022, 0x4000);
+ __doke_es(0x0022, COMMAND_LINE_POS);
+*/
- __movedata(__get_ds(), (unsigned)ptr+1, 0x9000, 0x4000, len);
+ __movedata(__get_ds(), (unsigned)ptr+1, 0x9000, COMMAND_LINE_POS, len);
+ has_command_line = 1;
+#endif
free(ptr);
@@ -555,3 +651,38 @@ unsigned int k_top;
return 0;
}
+
+check_crc()
+{
+ char buffer[512];
+ int low_sects;
+ unsigned int address = 0x900;
+ long len;
+
+ if( !is_zimage ) return;
+
+ reset_crc();
+
+ __movedata(address*16, 0, __get_ds(), buffer, 512);
+ low_sects = buffer[497] + 1; /* setup sects + boot sector */
+
+ for(len=image_size; len>0; len-=512)
+ {
+ if( address >= 0xA00 ) return;
+ __movedata(address*16, 0, __get_ds(), buffer, 512);
+
+ if( len > 512 ) addcrc(buffer, 512); else addcrc(buffer, (int)len);
+
+ address += 2;
+ if( low_sects )
+ {
+ low_sects--;
+ if( low_sects == 0 )
+ {
+ if( is_zimage ) address = ZIMAGE_LOAD_SEG/16;
+ else address = 0x1000;
+ }
+ }
+ }
+ display_crc();
+}