|
|
coherent
/*
* execute.c -- Attempt to run a loadable file.
* Returns only if it fails.
* Takes the inode for the file to be loaded, and a command line vector
* to pass in.
*/
#include <coff.h>
#include <canon.h>
#include <sys/typed.h>
#include <sys/inode.h>
#include <sys/dir.h>
#ifdef TEST
#define MAIN
#endif
#include "tboot.h"
#undef MAIN
void
execute( argv )
char *argv[];
{
extern uint16 myds; /* My data segment, from Setup.s. */
char *cmd_name; /* File to boot. */
char response[BLOCK]; /* Command typed at prompt. */
struct inode imageinode; /* Inode structure for the boot image. */
ino_t imageinum; /* inode number of the boot image. */
uint16 filemagic; /* Magic number from file. */
struct load_segment imagetable[MAX_SEGS]; /* How to load a file. */
struct load_segment *cur_segment; /* Pointer for walking imagetable. */
uint16 data_seg; /* Data segment register for image. */
uint16 boot_value; /* Offset of boot_gift into
* load image data segment.
*/
uint16 cpu_type; /* What kind of CPU are we running on? */
cpu_type = get_cpu_type();
/*
* Extract the command name from the command line.
*/
cmd_name = argv[0];
/*
* Try to find the requested file.
*/
if (0 == (imageinum = namei(cmd_name)) ) {
puts("No such file: ");
puts(cmd_name);
puts("\r\n");
return;
}
/*
* Try to open that inode.
*/
if (0 == iopen(&imageinode, imageinum)) {
puts("Can't open ");
puts(cmd_name);
puts(". Type \"dir\" for a list of files.\r\n");
return;
}
/*
* Read the magic number.
*/
iread(&imageinode, &filemagic, (fsize_t) 0, (uint16) sizeof (uint16));
canint(filemagic); /* Harmless on 80386. */
/*
* COFF executables probably should not be run on anything less
* than a 386.
*/
if (ISCOFF(filemagic)) {
if (!IS_I386(cpu_type)) {
puts("This is not a 386 or 486--");
puts("you probably can not run this file.\r\n");
puts("Continue anyway? ");
gets(response, BLOCK);
if ( 0 != strcmp(response, "y") &&
0 != strcmp(response, "Y") &&
0 != strcmp(response, "yes") &&
0 != strcmp(response, "YES") &&
0 != strcmp(response, "sure") ) {
return;
}
}
} /* Is it COFF? */
/*
* If we haven't explicitly set sys_base, default it based
* on the type of file we are loading.
*/
if (!sys_base_set) {
VERBOSE( {puts("Assuming default sys_base.\r\n");} );
sys_base = object_sys_base(filemagic);
}
/*
* Try to read the information we need to actually load this file.
*/
if (! object2load(filemagic, &imageinode, imagetable, &data_seg)) {
puts("File ");
puts(cmd_name);
puts(" is not an executable.\r\n");
puts(".\r\n");
return;
}
/* ASSERTION: imageinode and imagetable describe a valid executable. */
VERBOSE( {
puts("OK! Loading ");
puts(cmd_name);
puts("...\r\n");
} );
/* Now actually load everything into memory. */
for (cur_segment = &imagetable[0]; cur_segment->valid; ++cur_segment) {
puts(cur_segment->message);
/*
* Make sure that this segment will not overwrite tboot.
*/
if (seg_too_high(cur_segment)) {
puts("This segment would overwrite tboot.\r\n");
puts("Aborting...\r\n");
return;
}
ifread(&imageinode,
cur_segment->load_toseg,
cur_segment->load_tooffset,
cur_segment->load_offset,
cur_segment->load_length);
}
/* Does the program we just loaded want more info? */
/* Look up the variable "boot_gift" in the image. */
puts("\r\nPlease wait...\r\n");
boot_value = object_nlist(filemagic, cmd_name, "boot_gift");
if (0 != boot_value) {
VERBOSE( { puts("Preparing arguments.\r\n"); } );
/* Yes, this program can accept more information. */
prepare_gift(data_seg, boot_value, argv);
}
VERBOSE( {
puts("\r\nRunning ");
puts(cmd_name);
puts("...\r\n");
} );
if (want_monitor) {
puts("The kernel is ready to run.\r\n");
puts("SYS_START: ");
print16(SYS_START);
puts(" sys_base: ");
print16(sys_base);
puts(" data_seg: ");
print16(data_seg);
puts("\r\n");
monitor();
}
/* Run the image (the kernel). */
gotoker(SYS_START, sys_base, data_seg);
} /* execute() */
/*
* int
* seg_too_high( struct load_segment *lseg )
* Check to see if a segment will overlap tboot.
* Returns TRUE if it would, FALSE otherwise.
*/
int
seg_too_high( lseg )
struct load_segment *lseg;
{
uint32 load_top;
load_top = (lseg->load_toseg << 4) +
lseg->load_tooffset +
lseg->load_length;
#if 0
printf("%x:%x + %lx = %lx\n",
lseg->load_toseg,
lseg->load_tooffset,
lseg->load_length,
load_top);
#endif /* 0 */
return ( load_top >= ( ((uint32) RBOOTS) << 4 ) );
} /* seg_too_high() */
#ifdef TEST
int boot_gift; /* Lie. */
main()
{
struct load_segment lseg;
lseg.load_toseg = 0x200;
lseg.load_tooffset = 0;
lseg.load_length = 128L*1024L;
if (seg_too_high(&lseg)) {
printf("BAD: %x:%x + %lx > %lx.\n",
lseg.load_toseg,
lseg.load_tooffset,
lseg.load_length,
(((unsigned long)RBOOTS) << 4) );
} else {
printf("OK: %x:%x + %lx < %lx.\n",
lseg.load_toseg,
lseg.load_tooffset,
lseg.load_length,
(((unsigned long)RBOOTS) << 4) );
}
} /* main() */
#endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.