Contents of /trunk/linterm_tools/fw_builder/make-nk/make-nk.c
Parent Directory | Revision Log
Revision 658 -
(show annotations)
(download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5870 byte(s)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5870 byte(s)
initial import
1 | /* |
2 | Copyright (C) 2000 by Anders Larsen and Baumer Ident GmbH |
3 | |
4 | Slightly adapted for the winterm.gaast.project by Wilmer van der Gaast |
5 | |
6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. |
10 | |
11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with this program. If not, write to the Free Software |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ |
20 | |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
23 | #include <string.h> |
24 | #include <unistd.h> |
25 | #include <asm/types.h> |
26 | #include <sys/stat.h> |
27 | |
28 | int verbose = 0; |
29 | |
30 | u_int8_t signature[7] = "B000FF\n"; |
31 | u_int32_t start = 0x90000; |
32 | u_int32_t test = 0x17db90; |
33 | |
34 | |
35 | int usage(char *const argv0) |
36 | { |
37 | fprintf(stderr, "Puts a kernel and (optionally) initrd together in one nk.bin file.\n" |
38 | "\n" |
39 | "Read the documentation before using this tool!\n" |
40 | "\n" |
41 | "Usage: %s -k <kernel> [<other options>]\n" |
42 | "\n" |
43 | "Options:\n" |
44 | "-k <file>\tKernel file (MUST be in bzImage format)\n" |
45 | "-i <file>\tInitial ramdisk file (default: none)\n" |
46 | "-m <size>\tMemory size (dec) in KB (default: see boot.S)\n" |
47 | "-r <addr>\tOffset of RAM-disk (default: calculated from memsize)\n" |
48 | "-o <file>\tOutput file (default: nk.bin)\n" |
49 | "-v\t\tVerbose mode\n" |
50 | "-h\t\tThis information\n", argv0); |
51 | |
52 | return EXIT_FAILURE; |
53 | } |
54 | |
55 | |
56 | int copy(char const *name, u_int32_t offset, u_int32_t addr, FILE * fpo) |
57 | { |
58 | int ch; |
59 | u_int32_t cksum = 0; |
60 | u_int32_t size = 0; |
61 | FILE *fpi; |
62 | |
63 | if (!(fpi = fopen(name, "r"))) { |
64 | perror("Can't open input file"); |
65 | return EXIT_FAILURE; |
66 | } |
67 | fseek(fpo, 3 * sizeof(u_int32_t), SEEK_CUR); |
68 | if (offset) |
69 | fseek(fpi, offset, SEEK_SET); |
70 | while ((ch = getc(fpi)) != EOF) { |
71 | size++; |
72 | cksum += ch; |
73 | putc(ch, fpo); |
74 | } |
75 | fseek(fpo, -(long) (size + 3 * sizeof(u_int32_t)), SEEK_CUR); |
76 | fwrite(&addr, sizeof(addr), 1, fpo); |
77 | fwrite(&size, sizeof(size), 1, fpo); |
78 | fwrite(&cksum, sizeof(cksum), 1, fpo); |
79 | fseek(fpo, size, SEEK_CUR); |
80 | |
81 | if (verbose) |
82 | printf("%16s @ %08x, %7d bytes (checksum %08x)\n", name, |
83 | addr, size, cksum); |
84 | |
85 | fclose(fpi); |
86 | return size; |
87 | } |
88 | |
89 | |
90 | int main(int argc, char *const *argv) |
91 | { |
92 | int ch; |
93 | u_int16_t offset; |
94 | u_int32_t memsize = 0; |
95 | u_int32_t rootaddr = 0; |
96 | u_int32_t rootsize = 0; |
97 | u_int32_t linuxoff; |
98 | u_int32_t ul; |
99 | char version[41]; |
100 | FILE *fpi; |
101 | FILE *fpo; |
102 | char const *cp; |
103 | struct stat statbuf; |
104 | |
105 | char *kernel = NULL; |
106 | char *initrd = NULL; |
107 | char *output = "nk.bin"; |
108 | |
109 | while ((ch = getopt(argc, argv, "k:i:o:m:r:vh")) != EOF) |
110 | switch (ch) { |
111 | case 'k': |
112 | kernel = strdup(optarg); |
113 | break; |
114 | |
115 | case 'i': |
116 | initrd = strdup(optarg); |
117 | |
118 | if (stat(initrd, &statbuf)) { |
119 | perror("Can't stat initrd"); |
120 | return EXIT_FAILURE; |
121 | } |
122 | rootsize = statbuf.st_size; |
123 | |
124 | break; |
125 | |
126 | case 'o': |
127 | output = strdup(optarg); |
128 | break; |
129 | |
130 | case 'm': |
131 | /* Subtracting 1024 here because the kernel asks for |
132 | *extended* memory size. */ |
133 | memsize = strtol(optarg, 0, 10) - 1024; |
134 | break; |
135 | |
136 | case 'r': |
137 | rootaddr = strtol(optarg, 0, 16); |
138 | break; |
139 | |
140 | case 'v': |
141 | verbose++; |
142 | break; |
143 | |
144 | default: |
145 | return usage(argv[0]); |
146 | } |
147 | |
148 | if (kernel == NULL ) |
149 | return usage(argv[0]); |
150 | |
151 | |
152 | // extract information from kernel |
153 | if (!(fpi = fopen(kernel, "r"))) { |
154 | perror("Can't open kernel"); |
155 | return EXIT_FAILURE; |
156 | } |
157 | |
158 | fseek(fpi, 0x1f1, SEEK_SET); |
159 | fread(&linuxoff, sizeof(linuxoff), 1, fpi); |
160 | fseek(fpi, 0x20e, SEEK_SET); |
161 | fread(&offset, sizeof(offset), 1, fpi); |
162 | fseek(fpi, offset + 0x200, SEEK_SET); // SETUPSEG - INITSEG |
163 | fread(version, sizeof(version), 1, fpi); |
164 | version[sizeof(version) - 1] = 0; |
165 | fclose(fpi); |
166 | linuxoff = ((linuxoff & 0xff) + 1) * 512; |
167 | |
168 | |
169 | // update information in "boot" |
170 | if (!(fpi = fopen("boot", "r+"))) { |
171 | perror("Can't open boot"); |
172 | return EXIT_FAILURE; |
173 | } |
174 | |
175 | // copy kernel version string |
176 | if ((cp = strtok(version, " ")) != NULL) { |
177 | fseek(fpi, 0x22e, SEEK_SET); // 0x20e + Minix header |
178 | fread(&offset, sizeof(offset), 1, fpi); |
179 | fseek(fpi, offset + 0x26, SEEK_SET); // Minix header + "Linux " |
180 | fwrite(cp, strlen(cp) + 1, 1, fpi); |
181 | } |
182 | // get/set memory size |
183 | fseek(fpi, 0x200, SEEK_SET); // 0x1e0 + Minix header |
184 | if (memsize == 0) |
185 | fread(&memsize, sizeof(memsize), 1, fpi); |
186 | else |
187 | fwrite(&memsize, sizeof(memsize), 1, fpi); |
188 | |
189 | if (memsize != 0) |
190 | memsize = (memsize + 1024) * 1024; |
191 | |
192 | if (initrd) { |
193 | // write initrd info |
194 | if (rootaddr == 0) { |
195 | if (memsize != 0) |
196 | rootaddr = (memsize - rootsize) & 0xfffe0000; |
197 | else |
198 | rootaddr = 0x300000; /* Let's hope the kernel is <2MB! :-) */ |
199 | } |
200 | fseek(fpi, 0x238, SEEK_SET); |
201 | fwrite(&rootaddr, sizeof(rootaddr), 1, fpi); |
202 | fwrite(&rootsize, sizeof(rootsize), 1, fpi); |
203 | fclose(fpi); |
204 | } |
205 | |
206 | |
207 | // write NK.bin header |
208 | if (!(fpo = fopen(output, "w+"))) { |
209 | perror("Can't open output file"); |
210 | return EXIT_FAILURE; |
211 | } |
212 | fwrite(signature, sizeof(signature), 1, fpo); |
213 | fwrite(&start, sizeof(start), 1, fpo); |
214 | fwrite(&test, sizeof(test), 1, fpo); |
215 | |
216 | copy("boot", 32, 0x90000, fpo); |
217 | copy(kernel, linuxoff, 0x100000, fpo); |
218 | if (initrd) |
219 | copy(initrd, 0, rootaddr, fpo); |
220 | |
221 | // write NK.bin trailer |
222 | ul = 0; |
223 | fwrite(&ul, sizeof(ul), 1, fpo); |
224 | // this is the real entry point, start seems to be bogus, or something else? |
225 | ul = 0x91000; |
226 | fwrite(&ul, sizeof(ul), 1, fpo); |
227 | ul = 0; |
228 | fwrite(&ul, sizeof(ul), 1, fpo); |
229 | |
230 | fclose(fpo); |
231 | |
232 | return EXIT_SUCCESS; |
233 | } |