Add better description.
[dragonfly.git] / sys / platform / pc32 / boot / dosboot / dosboot.c
1 /*\r
2  *      dosboot.c               Boot FreeBSD from DOS partition\r
3  *\r
4  *      (C) 1994 by Christian Gusenbauer (cg@fimp01.fim.uni-linz.ac.at)\r
5  *      All Rights Reserved.\r
6  * \r
7  *      Permission to use, copy, modify and distribute this software and its\r
8  *      documentation is hereby granted, provided that both the copyright\r
9  *      notice and this permission notice appear in all copies of the\r
10  *      software, derivative works or modified versions, and any portions\r
11  *      thereof, and that both notices appear in supporting documentation.\r
12  * \r
13  *      I ALLOW YOU USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. I DISCLAIM\r
14  *      ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE\r
15  *      USE OF THIS SOFTWARE.\r
16  * \r
17  *      Parts of this file are\r
18  *      Copyright (c) 1992, 1991 Carnegie Mellon University\r
19  *      All Rights Reserved.\r
20  * \r
21  *      Permission to use, copy, modify and distribute this software and its\r
22  *      documentation is hereby granted, provided that both the copyright\r
23  *      notice and this permission notice appear in all copies of the\r
24  *      software, derivative works or modified versions, and any portions\r
25  *      thereof, and that both notices appear in supporting documentation.\r
26  * \r
27  *      CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"\r
28  *      CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR\r
29  *      ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.\r
30  * \r
31  *      Carnegie Mellon requests users of this software to return to\r
32  * \r
33  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU\r
34  *  School of Computer Science\r
35  *  Carnegie Mellon University\r
36  *  Pittsburgh PA 15213-3890\r
37  * \r
38  *      any improvements or extensions that they make and grant Carnegie Mellon\r
39  *      the rights to redistribute these changes.\r
40  */\r
41 #include <bios.h>\r
42 #include <stdio.h>\r
43 #include <process.h>\r
44 \r
45 #include "protmod.h"\r
46 #include "param.h"\r
47 #include "boot.h"\r
48 #include "bootinfo.h"\r
49 #include "reboot.h"\r
50 \r
51 #include "exec.h"\r
52 \r
53 #define BUFSIZE 4096\r
54 \r
55 static struct exec head;\r
56 static long argv[10];\r
57 static long startaddr;\r
58 \r
59 int biosread(int dev, int track, int head, int sector, int cnt, unsigned char far *buffer)\r
60 {\r
61         struct _diskinfo_t di;\r
62         int r;\r
63 \r
64         di.drive = dev;                                         /* first hard disk */\r
65         di.head = head;                                         /* head # */\r
66         di.track = track;                                       /* track # */\r
67         di.sector = sector+1;                           /* sector # */\r
68         di.nsectors = cnt;                                      /* only 1 sector */\r
69         di.buffer = (void far *) buffer;    /* sector buffer */\r
70         r= _bios_disk(_DISK_READ, &di);\r
71         return r&0xFF00;\r
72 }\r
73 \r
74 static void dosxread(FILE *fp, unsigned long addr, long size)\r
75 {\r
76         extern char buf[BUFSIZE];\r
77 \r
78         int count = BUFSIZE;\r
79         while (size > 0l) {\r
80                 if (BUFSIZE > size)\r
81                         count = (int) size;\r
82                 fread(buf, count, 1, fp);\r
83                 pm_copy(buf, addr, count);\r
84                 size -= count;\r
85                 addr += count;\r
86         }\r
87 }\r
88 \r
89 static long loadprog(FILE *fp, long *hsize)\r
90 {\r
91         long int addr;  /* physical address.. not directly useable */\r
92         long int hmaddress, pad, i;\r
93         static int (*x_entry)() = 0;\r
94 \r
95         fread(&head, sizeof(head), 1, fp);\r
96         fseek(fp, 4096-sizeof(head), 1);\r
97         if (N_BADMAG(head)) {\r
98                 printf("Invalid format!\n");\r
99                 exit(0);\r
100         }\r
101 \r
102         startaddr = (long)head.a_entry;\r
103         addr = (startaddr & 0x00ffffffl); /* some MEG boundary */\r
104         printf("Booting @ 0x%lx\n", addr);\r
105         if(addr < 0x100000l)\r
106         {\r
107                 printf("Start address too low!\n");\r
108                 exit(0);\r
109         }\r
110 \r
111         poff = N_TXTOFF(head)+head.a_text+head.a_data+head.a_syms;\r
112         fseek(fp, poff, 0);\r
113         fread(&i, sizeof(i), 1, fp);\r
114         *hsize = head.a_text+head.a_data+head.a_bss;\r
115         *hsize = (*hsize+NBPG-1)&~(NBPG-1);\r
116         *hsize += i+4+head.a_syms;\r
117         addr=hmaddress=get_high_memory(*hsize);\r
118         if (!hmaddress) {\r
119                 printf("Sorry, can't allocate enough memory!\n");\r
120                 exit(0);\r
121         }\r
122 \r
123         poff = N_TXTOFF(head);\r
124         fseek(fp, poff, 0);\r
125 \r
126         /********************************************************/\r
127         /* LOAD THE TEXT SEGMENT                                */\r
128         /********************************************************/\r
129         printf("text=0x%lx ", head.a_text);\r
130         dosxread(fp, addr, head.a_text);\r
131         addr += head.a_text;\r
132 \r
133         /********************************************************/\r
134         /* Load the Initialised data after the text             */\r
135         /********************************************************/\r
136         while (addr & CLOFSET)\r
137                 pm_copy("\0", addr++, 1);\r
138 \r
139         printf("data=0x%lx ", head.a_data);\r
140         dosxread(fp, addr, head.a_data);\r
141         addr += head.a_data;\r
142 \r
143         /********************************************************/\r
144         /* Skip over the uninitialised data                     */\r
145         /* (but clear it)                                       */\r
146         /********************************************************/\r
147         printf("bss=0x%lx ", head.a_bss);\r
148         pbzero(addr, head.a_bss);\r
149         addr += head.a_bss;\r
150 \r
151         /* Pad to a page boundary. */\r
152         pad = (unsigned long)(addr-hmaddress+(startaddr & 0x00ffffffl)) % NBPG;\r
153         if (pad != 0) {\r
154                 pad = NBPG - pad;\r
155                 addr += pad;\r
156         }\r
157         bootinfo.bi_symtab = addr-hmaddress+(startaddr & 0x00ffffffl);\r
158 \r
159         /********************************************************/\r
160         /* Copy the symbol table size                           */\r
161         /********************************************************/\r
162         pm_copy((char *)&head.a_syms, addr, sizeof(head.a_syms));\r
163         addr += sizeof(head.a_syms);\r
164 \r
165         /********************************************************/\r
166         /* Load the symbol table                                */\r
167         /********************************************************/\r
168         printf("symbols=[+0x%lx+0x%lx+0x%lx", pad, (long) sizeof(head.a_syms),\r
169                (long) head.a_syms);\r
170         dosxread(fp, addr, head.a_syms);\r
171         addr += head.a_syms;\r
172 \r
173         /********************************************************/\r
174         /* Load the string table size                           */\r
175         /********************************************************/\r
176         fread((void *)&i, sizeof(long), 1, fp);\r
177         pm_copy((char *)&i, addr, sizeof(long));\r
178         i -= sizeof(long);\r
179         addr += sizeof(long);\r
180 \r
181         /********************************************************/\r
182         /* Load the string table                                */\r
183         /********************************************************/\r
184         printf("+0x%x+0x%lx] ", sizeof(long), i);\r
185         dosxread(fp, addr, i);\r
186         addr += i;\r
187 \r
188         bootinfo.bi_esymtab = addr-hmaddress+(startaddr & 0x00ffffffl);\r
189 \r
190         /*\r
191          * For backwards compatibility, use the previously-unused adaptor\r
192          * and controller bitfields to hold the slice number.\r
193          */\r
194         printf("total=0x%lx entry point=0x%lx\n",\r
195                 addr-hmaddress+(startaddr & 0x00ffffffl),\r
196                 startaddr & 0x00ffffffl);\r
197 \r
198         return hmaddress;\r
199 }\r
200 \r
201 void dosboot(long howto, char *kernel)\r
202 {\r
203         long hmaddress, size, bootdev;\r
204         FILE *fp;\r
205 \r
206         fp = fopen(kernel, "rb");                       /* open kernel for reading */\r
207         if (!fp) {\r
208                 fprintf(stderr, "Sorry, can't open %s!\n", kernel);\r
209                 return;\r
210         }\r
211         hmaddress = loadprog(fp, &size);\r
212         fclose(fp);\r
213 \r
214         bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);\r
215         startprog(hmaddress, size, ((long)startaddr & 0xffffffl),\r
216                           howto | RB_BOOTINFO, bootdev);\r
217 }\r