Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / i386 / boot / kzipboot / boot.c
1 /*
2  * FreeBSD kernel unpacker.
3  * 1993 by Serge Vakulenko
4  * modified for FreeBSD 2.1 by Gary Jennejohn - 12FEB95
5  */
6
7 #include <sys/types.h>
8 #include <sys/reboot.h>         /* for RB_SERIAL */
9
10 #include <machine/cpufunc.h>    /* for inb/outb */
11
12 short *videomem;
13 int curs;
14 int cols;
15 int lines;
16 unsigned int port;
17
18 unsigned char bios[0x100];
19
20 extern int end, edata;
21 void *storage;
22 void *inbuf;
23 void *outbuf;
24 void *window;
25
26 void decompress_kernel (void *dest);
27
28 int memcmp (const void *arg1, const void *arg2, unsigned len)
29 {
30         unsigned char *a = (unsigned char*) arg1;
31         unsigned char *b = (unsigned char*) arg2;
32
33         for (; len-- > 0; ++a, ++b)
34                 if (*a < *b)
35                         return (-1);
36                 else if (*a > *b)
37                         return (1);
38         return (0);
39 }
40
41 void *memcpy (void *to, const void *from, unsigned len)
42 {
43         char *f = (char*) from;
44         char *t = (char*) to;
45
46         while (len-- > 0)
47                 *t++ = *f++;
48         return (to);
49 }
50
51 void serial_putchar (unsigned char c)
52 {
53         unsigned char stat;
54
55         if (c == '\n')
56                 serial_putchar('\r');
57         do {
58                  stat = inb (COMCONSOLE+5);
59         } while (!(stat & 0x20));
60
61         outb (COMCONSOLE, c);
62 }
63
64 void putchar (unsigned char c)
65 {
66         switch (c) {
67         case '\n':      curs = (curs + cols) / cols * cols;     break;
68         default:        videomem[curs++] = 0x0700 | c;          break;
69         }
70         while (curs >= cols*lines) {
71                 int col;
72
73                 memcpy (videomem, videomem+cols, (lines-1) * cols * 2);
74                 for (col = 0; col < cols; col++)
75                         videomem[(lines - 1) * cols + col] = 0x720;
76                 curs -= cols;
77         }
78         /* set cursor position */
79         outb (port, 0x0e); outb (port+1, curs>>8);
80         outb (port, 0x0f); outb (port+1, curs);
81 }
82
83 int use_serial;
84
85 void putstr (char *s)
86 {
87         while (*s) {
88                 if (use_serial)
89                         serial_putchar (*s++);
90                 else
91                         putchar (*s++);
92         }
93 }
94
95 void error (char *s)
96 {
97         putstr ("\n\n");
98         putstr (s);
99         putstr ("\n\n -- System halted");
100         while (1);                      /* Halt */
101 }
102
103 void boot (int howto)
104 {
105         int l, c, *p;
106
107         /* clear bss */
108         for (p = &edata; p < &end; ++p)
109                 *p = 0;
110
111         inbuf   = (void *)0x20000;
112         outbuf  = (void *)0x30000;
113         window  = (void *)0x40000;
114         storage = (void *)0x50000;
115
116         if (!(use_serial = (howto & RB_SERIAL))) {
117                 /* Test for monochrome video adapter */
118                 if ((*((unsigned char*) 0x410) & 0x30) == 0x30)
119                         videomem = (void*) 0xb0000;     /* monochrome */
120                 else
121                         videomem = (void*) 0xb8000;     /* color */
122
123                 port = *(unsigned short*) 0x463;
124                 cols = *(unsigned short*) 0x44a;
125                 lines = 1 + *(unsigned char*) 0x484;
126                 c = *(unsigned char*) 0x450;
127                 l = *(unsigned char*) 0x451;
128
129                 if (lines < 25)
130                         lines = 25;
131                 curs = l*cols + c;
132                 if (curs > lines*cols)
133                         curs = (lines-1) * cols;
134         }
135
136         putstr ("Uncompressing kernel...");
137         decompress_kernel ((void*) KADDR);
138         putstr ("done\n");
139         putstr ("Booting the kernel\n");
140 }