home *** CD-ROM | disk | FTP | other *** search
- #include "protocol.h"
- #include "bootinc.h"
-
- /* Copyright 1993 Jamie Honan
- May be freely copied, sold, modified.
- */
-
- /* #define NOLOAD */
- /* #define DEBUG */
-
- typedef struct load_header
- {
- unsigned long magic;
- unsigned char hlength;
- unsigned char hflags1;
- unsigned char hflags2;
- unsigned char hflags3;
- struct load_header far * locn;
- void far * execute;
- char dummy[494]; /* bring us up to 510 */
- unsigned char field55;
- unsigned char fieldAA;
- } LOAD_HEADER;
-
- #define SKIP_LENGTH(u) (((u & 0xf)<<2) + ((u & 0xf0)>>2))
- #define OUR_LENGTH(u) ((u & 0xf)<<2)
-
- typedef struct load_record
- {
- unsigned char rlength;
- unsigned char rtag1;
- unsigned char rtag2;
- unsigned char rflags;
- unsigned long address;
- unsigned long ilength;
- unsigned long mlength;
- } LOAD_RECORD;
-
- #define FLAG_B0 1
- #define FLAG_B1 2
-
- #define FLAG_EOF 4
-
- static LOAD_HEADER far *hptr;
- static LOAD_RECORD far *rptr;
-
- #define HOLE_END 0x100000
- #define START_EXTD 0x100000
- #define HOLE_START 0x98000
-
- #define LOWEST 0x10000
-
- static int is_magic_format;
- static unsigned long datagoes;
- static unsigned long laststart;
- static unsigned long lastend;
- static unsigned long remaining;
- static void (far *execute_point) (void far *headp);
-
- static unsigned long top_memory;
-
- static EXTD_MOVE moveptr;
- static char *lastdata;
-
- #ifdef NOLOAD
- char keepit[512];
- #endif
-
- static void
- prv(char *str)
- {
- n_printf("%s datagoes %lx remaining %lx lastdata %x laststart %lx lastend %lx ",
- str, datagoes, remaining, lastdata, laststart, lastend);
- n_printf("rptr->flags %x\n", rptr->rflags);
- }
-
- static int
- mem_range(unsigned long ptr, unsigned long len)
- {
- /* can do anything, as long as they don't write to it */
- if (!len)
- return 1;
- if (ptr >= HOLE_START && ptr < HOLE_END)
- return 0;
- if (ptr < LOWEST)
- return 0;
- if (ptr >= top_memory)
- return 0;
- ptr += len;
- if (ptr >= HOLE_START && ptr < HOLE_END)
- return 0;
- if (ptr > top_memory)
- return 0;
- return 1;
- }
-
- static int
- mem_range86(void far *ptr, unsigned int len)
- {
- unsigned long v;
-
- v = far2long(ptr);
- if (v + len >= HOLE_START)
- return 0;
- return mem_range(v, len);
- }
-
- static int
- new_rptr()
- {
- unsigned long mem;
-
- #ifdef DEBUG
- prv("start rptr");
- #endif
- if (OUR_LENGTH(rptr->rlength) < 16)
- {
- /* illegal */
- return 3003;
- }
- mem = rptr->address;
- if (rptr->rflags & FLAG_B1)
- {
- if (rptr->rflags & FLAG_B0)
- {
- /* B0 B1
- 1 1
- load address is subtracted from the start of
- the last image loaded. If the first image, then
- subtract from the start of where the 512 bytes were
- placed
- */
- if (mem > laststart)
- {
- n_printf("Address %lx\n", rptr->address);
- return 3005; /* overflow */
- }
- mem = laststart - mem;
- }
- else
- {
- /* B0 B1
- 0 1
- subtract the load address from the one past the
- last writeable location in memory. Thus 1 would
- be the last location one could write in memory.
- */
- if (mem > top_memory)
- {
- n_printf("Address %lx\n", rptr->address);
- return 3005; /* overflow */
- }
- mem = top_memory - mem;
- }
- }
- else
- {
- if (rptr->rflags & FLAG_B0)
- {
- /* B0 B1
- 1 0
- add the load address to the location one past the last byte
- of the memory area required by the last image loaded.
- If the first image, then add to 512 plus the location
- where the 512 bytes were placed
- */
- mem += lastend;
- }
- else
- {
- /* B0 B1
- 0 0
- load address is an absolute 32 number
- */
- }
- }
-
- if (!mem_range(mem, rptr->ilength))
- {
- n_printf("Address %lx\n", rptr->address);
- /* illegal place to put things */
- return 3002;
- }
- laststart = datagoes = mem;
- lastend = laststart + rptr->mlength;
- remaining = rptr->ilength;
- n_printf(" %ld bytes (%ld blocks) at 0x%lx\n",
- remaining, n_ldiv(remaining, 512), datagoes);
- #ifdef DEBUG
- prv("end rptr");
- #endif
- return 0;
- }
-
-
- int decode_header(void *ptr)
- {
- #ifdef TEST
- top_memory = 0x740000L;
- #else
- top_memory = n_mamount();
- #endif
- if (top_memory)
- top_memory = n_lmul(top_memory, 1024) + START_EXTD;
- else
- top_memory = HOLE_START;
-
- hptr = MK_FP(segds(), ptr);
- if (hptr->magic != 0x1B031336)
- {
- is_magic_format = 0;
- if (hptr->field55 == 0x55 && hptr->fieldAA == 0xAA)
- {
- /* can execute it */
- #ifndef NOLOAD
- fmemcpy(MK_FP(0, 0x7c00), hptr, 512);
- execute_point = MK_FP(0, 0x7c00);
- #endif
- datagoes = LOWEST;
- laststart = LOWEST;
- if (top_memory > START_EXTD)
- {
- remaining = top_memory
- - (HOLE_END - HOLE_START) - LOWEST;
- }
- else
- {
- remaining = HOLE_START - LOWEST;
- }
- lastend = laststart + remaining;
- return 0;
- }
- else
- {
- return 3000;
- }
- }
- if (OUR_LENGTH(hptr->hlength) < 16)
- {
- /* illegal */
- return 3001;
- }
- /* we have the magic number */
- is_magic_format = 1;
-
- /* if we are dos, we can try to relocate the whole program
- I don't like our chances
- */
- if (!mem_range86(hptr->locn, 512))
- {
- n_printf("Address %lp\n", hptr->locn);
- /* attempt to place the 512 in an illegal place */
- return 3002;
- }
- #ifdef DEBUG
- n_printf("Placing image header at %lp\n", hptr->locn);
- n_printf("execute address is %lp\n", hptr->execute);
- #endif
- #ifdef NOLOAD
- fmemcpy(MK_FP(segds(), keepit), hptr, 512);
- hptr = MK_FP(segds(), keepit);
- #else
- execute_point = hptr->execute;
- fmemcpy(hptr->locn, hptr, 512);
- hptr = hptr->locn;
- #endif
- rptr = (LOAD_RECORD far *)(((char far *)hptr) + SKIP_LENGTH(hptr->hlength));
- laststart = far2long(hptr);
- lastend = laststart + 512;
- return new_rptr();
- }
-
- static int
- put_ext_data(unsigned long dest, char *data, int length)
- {
- if (data != lastdata)
- {
- /* don't want to have to do this every time */
- lastdata = data;
- /* cheat */
- *(unsigned long *)(&moveptr.s_segaddr[0]) =
- far2long(MK_FP(segds(), data));
- }
- /* cheat */
- *(unsigned long *)(&moveptr.d_segaddr[0]) = dest;
- moveptr.s_seglength = moveptr.d_seglength = length;
- moveptr.s_access = moveptr.d_access = 0x93;
- #ifdef DEBUG
- if (debug)
- n_printf("Placing extended image data at %lx\n", dest);
- return 0;
- #else
- return n_lmove(&moveptr, (length + 1) / 2);
- #endif
- }
-
- int
- place_data(char *data, int len)
- {
- int xlen;
- int v;
-
- while(len > 0)
- {
- xlen = len;
- if (remaining == 0)
- {
- if (!is_magic_format)
- {
- return 3004;
- }
- if (rptr->rflags & FLAG_EOF)
- return 3004;
- rptr = (LOAD_RECORD far *)(((char far *)rptr) + SKIP_LENGTH(rptr->rlength));
- v = new_rptr();
- if (v)
- return v;
- continue;
- }
- if (xlen > remaining)
- xlen = remaining;
- if (datagoes >= HOLE_START && datagoes < HOLE_END)
- {
- laststart = datagoes = HOLE_END;
- /* doesn't have any meaning */
- lastend = laststart + remaining;
- }
- if (datagoes < HOLE_START)
- {
- if (datagoes + xlen > HOLE_START)
- {
- xlen = HOLE_START - datagoes;
- }
- #ifdef DEBUG
- if (debug)
- n_printf("Placing < 640K image data at %lx\n", datagoes);
- #endif
- #ifndef NOLOAD
- lmemcpy(datagoes, data, xlen);
- #endif
- }
- else
- {
- v = put_ext_data(datagoes, data, xlen);
- if (v)
- return 3010 + v;
- }
- data += xlen;
- datagoes += xlen;
- len -= xlen;
- remaining -= xlen;
- }
- return 0;
- }
-
- void warp_speed_Mr_spock(void)
- {
- if (!execute_point)
- return;
- (*execute_point)(hptr);
- }
-
- #ifdef TEST
-
- long image[] = {
- 0x1B031336, /* magic number */
- 0x4, /* length of header is 16 bytes, no vendor info */
- 0x90000000, /* location in ds:bx format */
- 0x90000200, /* execute address in cs:ip format */
-
- /* 2048 setup.S bytes */
- 0x4, /* flags, not end, absolute address, 16 bytes this
- record, no vendor info */
- 0x90200, /* load address - note format */
- 0x800, /* 4 * 512 byte blocks for linux */
- 0x800,
-
- /* kernel image */
- 0x4, /* flags, not end, absolute address, 16 bytes this
- record, no vendor info */
- 0x10000, /* load address - note format */
- 0x80000, /* 512K (this could be shorter */
- 0x80000,
-
- /* ramdisk for root file system */
- 0x04000004, /* flags = last, absolute address, 16 bytes this
- record, no vendor info */
- 0x100000, /* load address - in extended memory */
- 0x80000, /* 512K for instance */
- 0x80000
-
- };
-
- char zb[512];
-
- long ls[128];
-
- int testmove(unsigned long dest, char *data, int length)
- {
- *(unsigned long *)(&moveptr.s_segaddr[0]) =
- far2long(MK_FP(segds(), data));
- /* cheat */
- *(unsigned long *)(&moveptr.d_segaddr[0]) = dest;
- moveptr.s_seglength = moveptr.d_seglength = length;
- moveptr.s_access = moveptr.d_access = 0x93;
- return n_lmove(&moveptr, (length + 1) / 2);
- }
-
- main()
- {
- int v;
- int x;
-
- n_printf("Test image stuff\n");
- v = testmove(far2long(ls), image, sizeof(image));
- n_printf("result %d\n", v);
- for(v = 0; v < 12; v++)
- n_printf("%d is %lx\n", v, ls[v]);
- dos_exit(0);
-
- v = decode_header(image);
- if (v)
- {
- netposterr(v);
- dos_exit(1);
- }
- while (((v = place_data(zb, 512))) == 0)
- {
- x = monitor_check();
- if (x)
- {
- if (x > 1)
- {
- v = 2000;
- break;
- }
- prv("mon check");
- }
- }
- prv("end proc");
- netposterr(v);
- dos_exit(0);
- }
-
- #endif
-
-