Magellan Linux

Annotation of /trunk/linterm_tools/fw_builder/make-nk/make-nk.c

Parent Directory Parent Directory | Revision Log 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)
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     }