diff options
Diffstat (limited to 'arch/i386/boot/tools/build.c')
-rw-r--r-- | arch/i386/boot/tools/build.c | 160 |
1 files changed, 71 insertions, 89 deletions
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c index 05798419a6a9..886f47d8a488 100644 --- a/arch/i386/boot/tools/build.c +++ b/arch/i386/boot/tools/build.c | |||
@@ -1,13 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
3 | * Copyright (C) 1997 Martin Mares | 3 | * Copyright (C) 1997 Martin Mares |
4 | * Copyright (C) 2007 H. Peter Anvin | ||
4 | */ | 5 | */ |
5 | 6 | ||
6 | /* | 7 | /* |
7 | * This file builds a disk-image from three different files: | 8 | * This file builds a disk-image from three different files: |
8 | * | 9 | * |
9 | * - bootsect: compatibility mbr which prints an error message if | ||
10 | * someone tries to boot the kernel directly. | ||
11 | * - setup: 8086 machine code, sets up system parm | 10 | * - setup: 8086 machine code, sets up system parm |
12 | * - system: 80386 code for actual system | 11 | * - system: 80386 code for actual system |
13 | * | 12 | * |
@@ -21,6 +20,7 @@ | |||
21 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 | 20 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 |
22 | * Cross compiling fixes by Gertjan van Wingerde, July 1996 | 21 | * Cross compiling fixes by Gertjan van Wingerde, July 1996 |
23 | * Rewritten by Martin Mares, April 1997 | 22 | * Rewritten by Martin Mares, April 1997 |
23 | * Substantially overhauled by H. Peter Anvin, April 2007 | ||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <stdio.h> | 26 | #include <stdio.h> |
@@ -32,23 +32,25 @@ | |||
32 | #include <sys/sysmacros.h> | 32 | #include <sys/sysmacros.h> |
33 | #include <unistd.h> | 33 | #include <unistd.h> |
34 | #include <fcntl.h> | 34 | #include <fcntl.h> |
35 | #include <sys/mman.h> | ||
35 | #include <asm/boot.h> | 36 | #include <asm/boot.h> |
36 | 37 | ||
37 | typedef unsigned char byte; | 38 | typedef unsigned char u8; |
38 | typedef unsigned short word; | 39 | typedef unsigned short u16; |
39 | typedef unsigned long u32; | 40 | typedef unsigned long u32; |
40 | 41 | ||
41 | #define DEFAULT_MAJOR_ROOT 0 | 42 | #define DEFAULT_MAJOR_ROOT 0 |
42 | #define DEFAULT_MINOR_ROOT 0 | 43 | #define DEFAULT_MINOR_ROOT 0 |
43 | 44 | ||
44 | /* Minimal number of setup sectors (see also bootsect.S) */ | 45 | /* Minimal number of setup sectors */ |
45 | #define SETUP_SECTS 4 | 46 | #define SETUP_SECT_MIN 5 |
47 | #define SETUP_SECT_MAX 64 | ||
46 | 48 | ||
47 | byte buf[1024]; | 49 | /* This must be large enough to hold the entire setup */ |
48 | int fd; | 50 | u8 buf[SETUP_SECT_MAX*512]; |
49 | int is_big_kernel; | 51 | int is_big_kernel; |
50 | 52 | ||
51 | void die(const char * str, ...) | 53 | static void die(const char * str, ...) |
52 | { | 54 | { |
53 | va_list args; | 55 | va_list args; |
54 | va_start(args, str); | 56 | va_start(args, str); |
@@ -57,15 +59,9 @@ void die(const char * str, ...) | |||
57 | exit(1); | 59 | exit(1); |
58 | } | 60 | } |
59 | 61 | ||
60 | void file_open(const char *name) | 62 | static void usage(void) |
61 | { | 63 | { |
62 | if ((fd = open(name, O_RDONLY, 0)) < 0) | 64 | die("Usage: build [-b] setup system [rootdev] [> image]"); |
63 | die("Unable to open `%s': %m", name); | ||
64 | } | ||
65 | |||
66 | void usage(void) | ||
67 | { | ||
68 | die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); | ||
69 | } | 65 | } |
70 | 66 | ||
71 | int main(int argc, char ** argv) | 67 | int main(int argc, char ** argv) |
@@ -73,27 +69,30 @@ int main(int argc, char ** argv) | |||
73 | unsigned int i, sz, setup_sectors; | 69 | unsigned int i, sz, setup_sectors; |
74 | int c; | 70 | int c; |
75 | u32 sys_size; | 71 | u32 sys_size; |
76 | byte major_root, minor_root; | 72 | u8 major_root, minor_root; |
77 | struct stat sb; | 73 | struct stat sb; |
74 | FILE *file; | ||
75 | int fd; | ||
76 | void *kernel; | ||
78 | 77 | ||
79 | if (argc > 2 && !strcmp(argv[1], "-b")) | 78 | if (argc > 2 && !strcmp(argv[1], "-b")) |
80 | { | 79 | { |
81 | is_big_kernel = 1; | 80 | is_big_kernel = 1; |
82 | argc--, argv++; | 81 | argc--, argv++; |
83 | } | 82 | } |
84 | if ((argc < 4) || (argc > 5)) | 83 | if ((argc < 3) || (argc > 4)) |
85 | usage(); | 84 | usage(); |
86 | if (argc > 4) { | 85 | if (argc > 3) { |
87 | if (!strcmp(argv[4], "CURRENT")) { | 86 | if (!strcmp(argv[3], "CURRENT")) { |
88 | if (stat("/", &sb)) { | 87 | if (stat("/", &sb)) { |
89 | perror("/"); | 88 | perror("/"); |
90 | die("Couldn't stat /"); | 89 | die("Couldn't stat /"); |
91 | } | 90 | } |
92 | major_root = major(sb.st_dev); | 91 | major_root = major(sb.st_dev); |
93 | minor_root = minor(sb.st_dev); | 92 | minor_root = minor(sb.st_dev); |
94 | } else if (strcmp(argv[4], "FLOPPY")) { | 93 | } else if (strcmp(argv[3], "FLOPPY")) { |
95 | if (stat(argv[4], &sb)) { | 94 | if (stat(argv[3], &sb)) { |
96 | perror(argv[4]); | 95 | perror(argv[3]); |
97 | die("Couldn't stat root device."); | 96 | die("Couldn't stat root device."); |
98 | } | 97 | } |
99 | major_root = major(sb.st_rdev); | 98 | major_root = major(sb.st_rdev); |
@@ -108,79 +107,62 @@ int main(int argc, char ** argv) | |||
108 | } | 107 | } |
109 | fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); | 108 | fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); |
110 | 109 | ||
111 | file_open(argv[1]); | 110 | /* Copy the setup code */ |
112 | i = read(fd, buf, sizeof(buf)); | 111 | file = fopen(argv[1], "r"); |
113 | fprintf(stderr,"Boot sector %d bytes.\n",i); | 112 | if (!file) |
114 | if (i != 512) | 113 | die("Unable to open `%s': %m", argv[1]); |
115 | die("Boot block must be exactly 512 bytes"); | 114 | c = fread(buf, 1, sizeof(buf), file); |
115 | if (ferror(file)) | ||
116 | die("read-error on `setup'"); | ||
117 | if (c < 1024) | ||
118 | die("The setup must be at least 1024 bytes"); | ||
116 | if (buf[510] != 0x55 || buf[511] != 0xaa) | 119 | if (buf[510] != 0x55 || buf[511] != 0xaa) |
117 | die("Boot block hasn't got boot flag (0xAA55)"); | 120 | die("Boot block hasn't got boot flag (0xAA55)"); |
121 | fclose(file); | ||
122 | |||
123 | /* Pad unused space with zeros */ | ||
124 | setup_sectors = (c + 511) / 512; | ||
125 | if (setup_sectors < SETUP_SECT_MIN) | ||
126 | setup_sectors = SETUP_SECT_MIN; | ||
127 | i = setup_sectors*512; | ||
128 | memset(buf+c, 0, i-c); | ||
129 | |||
130 | /* Set the default root device */ | ||
118 | buf[508] = minor_root; | 131 | buf[508] = minor_root; |
119 | buf[509] = major_root; | 132 | buf[509] = major_root; |
120 | if (write(1, buf, 512) != 512) | ||
121 | die("Write call failed"); | ||
122 | close (fd); | ||
123 | |||
124 | file_open(argv[2]); /* Copy the setup code */ | ||
125 | for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) | ||
126 | if (write(1, buf, c) != c) | ||
127 | die("Write call failed"); | ||
128 | if (c != 0) | ||
129 | die("read-error on `setup'"); | ||
130 | close (fd); | ||
131 | |||
132 | setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ | ||
133 | /* for compatibility with ancient versions of LILO. */ | ||
134 | if (setup_sectors < SETUP_SECTS) | ||
135 | setup_sectors = SETUP_SECTS; | ||
136 | fprintf(stderr, "Setup is %d bytes.\n", i); | ||
137 | memset(buf, 0, sizeof(buf)); | ||
138 | while (i < setup_sectors * 512) { | ||
139 | c = setup_sectors * 512 - i; | ||
140 | if (c > sizeof(buf)) | ||
141 | c = sizeof(buf); | ||
142 | if (write(1, buf, c) != c) | ||
143 | die("Write call failed"); | ||
144 | i += c; | ||
145 | } | ||
146 | 133 | ||
147 | file_open(argv[3]); | 134 | fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); |
148 | if (fstat (fd, &sb)) | 135 | |
149 | die("Unable to stat `%s': %m", argv[3]); | 136 | /* Open and stat the kernel file */ |
137 | fd = open(argv[2], O_RDONLY); | ||
138 | if (fd < 0) | ||
139 | die("Unable to open `%s': %m", argv[2]); | ||
140 | if (fstat(fd, &sb)) | ||
141 | die("Unable to stat `%s': %m", argv[2]); | ||
150 | sz = sb.st_size; | 142 | sz = sb.st_size; |
151 | fprintf (stderr, "System is %d kB\n", sz/1024); | 143 | fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); |
144 | kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); | ||
145 | if (kernel == MAP_FAILED) | ||
146 | die("Unable to mmap '%s': %m", argv[2]); | ||
152 | sys_size = (sz + 15) / 16; | 147 | sys_size = (sz + 15) / 16; |
153 | if (!is_big_kernel && sys_size > DEF_SYSSIZE) | 148 | if (!is_big_kernel && sys_size > DEF_SYSSIZE) |
154 | die("System is too big. Try using bzImage or modules."); | 149 | die("System is too big. Try using bzImage or modules."); |
155 | while (sz > 0) { | 150 | |
156 | int l, n; | 151 | /* Patch the setup code with the appropriate size parameters */ |
157 | 152 | buf[0x1f1] = setup_sectors-1; | |
158 | l = (sz > sizeof(buf)) ? sizeof(buf) : sz; | 153 | buf[0x1f4] = sys_size; |
159 | if ((n=read(fd, buf, l)) != l) { | 154 | buf[0x1f5] = sys_size >> 8; |
160 | if (n < 0) | 155 | buf[0x1f6] = sys_size >> 16; |
161 | die("Error reading %s: %m", argv[3]); | 156 | buf[0x1f7] = sys_size >> 24; |
162 | else | 157 | |
163 | die("%s: Unexpected EOF", argv[3]); | 158 | if (fwrite(buf, 1, i, stdout) != i) |
164 | } | 159 | die("Writing setup failed"); |
165 | if (write(1, buf, l) != l) | 160 | |
166 | die("Write failed"); | 161 | /* Copy the kernel code */ |
167 | sz -= l; | 162 | if (fwrite(kernel, 1, sz, stdout) != sz) |
168 | } | 163 | die("Writing kernel failed"); |
169 | close(fd); | 164 | close(fd); |
170 | 165 | ||
171 | if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ | 166 | /* Everything is OK */ |
172 | die("Output: seek failed"); | 167 | return 0; |
173 | buf[0] = setup_sectors; | ||
174 | if (write(1, buf, 1) != 1) | ||
175 | die("Write of setup sector count failed"); | ||
176 | if (lseek(1, 500, SEEK_SET) != 500) | ||
177 | die("Output: seek failed"); | ||
178 | buf[0] = (sys_size & 0xff); | ||
179 | buf[1] = ((sys_size >> 8) & 0xff); | ||
180 | buf[2] = ((sys_size >> 16) & 0xff); | ||
181 | buf[3] = ((sys_size >> 24) & 0xff); | ||
182 | if (write(1, buf, 4) != 4) | ||
183 | die("Write of image length failed"); | ||
184 | |||
185 | return 0; /* Everything is OK */ | ||
186 | } | 168 | } |