aout_loader.c
Go to the documentation of this file.00001
00002 struct exec {
00003 unsigned long a_midmag;
00004 unsigned long a_text;
00005 unsigned long a_data;
00006 unsigned long a_bss;
00007 unsigned long a_syms;
00008 unsigned long a_entry;
00009 unsigned long a_trsize;
00010 unsigned long a_drsize;
00011 };
00012
00013 struct aout_state {
00014 struct exec head;
00015 unsigned long curaddr;
00016 int segment;
00017 unsigned long loc;
00018 unsigned long skip;
00019 unsigned long toread;
00020 };
00021
00022 static struct aout_state astate;
00023
00024 static sector_t aout_download(unsigned char *data, unsigned int len, int eof);
00025 static inline os_download_t aout_probe(unsigned char *data, unsigned int len)
00026 {
00027 unsigned long start, mid, end, istart, iend;
00028 if (len < sizeof(astate.head)) {
00029 return 0;
00030 }
00031 memcpy(&astate.head, data, sizeof(astate.head));
00032 if ((astate.head.a_midmag & 0xffff) != 0x010BL) {
00033 return 0;
00034 }
00035
00036 printf("(a.out");
00037 aout_freebsd_probe();
00038 printf(")... ");
00039
00040 start = astate.head.a_entry;
00041 mid = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data;
00042 end = ((mid + 4095) & ~4095) + astate.head.a_bss;
00043 istart = 4096;
00044 iend = istart + (mid - start);
00045 if (!prep_segment(start, mid, end, istart, iend))
00046 return dead_download;
00047 astate.segment = -1;
00048 astate.loc = 0;
00049 astate.skip = 0;
00050 astate.toread = 0;
00051 return aout_download;
00052 }
00053
00054 static sector_t aout_download(unsigned char *data, unsigned int len, int eof)
00055 {
00056 unsigned int offset;
00057
00058 offset = 0;
00059
00060 #ifdef AOUT_LYNX_KDI
00061 astate.segment++;
00062 if (astate.segment == 0) {
00063 astate.curaddr = 0x100000;
00064 astate.head.a_entry = astate.curaddr + 0x20;
00065 }
00066 memcpy(phys_to_virt(astate.curaddr), data, len);
00067 astate.curaddr += len;
00068 return 0;
00069 #endif
00070
00071 do {
00072 if (astate.segment != -1) {
00073 if (astate.skip) {
00074 if (astate.skip >= len - offset) {
00075 astate.skip -= len - offset;
00076 break;
00077 }
00078 offset += astate.skip;
00079 astate.skip = 0;
00080 }
00081
00082 if (astate.toread) {
00083 if (astate.toread >= len - offset) {
00084 memcpy(phys_to_virt(astate.curaddr), data+offset,
00085 len - offset);
00086 astate.curaddr += len - offset;
00087 astate.toread -= len - offset;
00088 break;
00089 }
00090 memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread);
00091 offset += astate.toread;
00092 astate.toread = 0;
00093 }
00094 }
00095
00096
00097
00098 astate.segment++;
00099 switch (astate.segment) {
00100 case 0:
00101
00102 astate.curaddr = astate.head.a_entry;
00103 astate.skip = 4096;
00104 astate.toread = astate.head.a_text;
00105 break;
00106 case 1:
00107
00108
00109
00110
00111 astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr;
00112 astate.curaddr = (astate.curaddr + 4095) & ~4095;
00113 astate.toread = astate.head.a_data;
00114 break;
00115 case 2:
00116
00117 astate.curaddr = (astate.curaddr + 4095) & ~4095;
00118 astate.skip = 0;
00119 astate.toread = 0;
00120 memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss);
00121 goto aout_startkernel;
00122 default:
00123 break;
00124 }
00125 } while (offset < len);
00126
00127 astate.loc += len;
00128
00129 if (eof) {
00130 unsigned long entry;
00131
00132 aout_startkernel:
00133 entry = astate.head.a_entry;
00134 done(1);
00135
00136 aout_freebsd_boot();
00137 #ifdef AOUT_LYNX_KDI
00138 xstart32(entry);
00139 #endif
00140 printf("unexpected a.out variant\n");
00141 longjmp(restart_etherboot, -2);
00142 }
00143 return 0;
00144 }