Annotation of /trunk/linterm_tools/fw_builder/make-nk/make-nk.c
Parent Directory | Revision Log
Revision 658 -
(hide annotations)
(download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 3 months ago) by niro
File MIME type: text/plain
File size: 5870 byte(s)
Mon Jan 14 16:57:24 2008 UTC (16 years, 3 months ago) by niro
File MIME type: text/plain
File size: 5870 byte(s)
initial import
1 | niro | 658 | /* |
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 | } |