1 | /*-------------------------------------------------------------------------+ |
---|
2 | | bin2boot.c v1.1 - PC386 BSP - 1997/08/18 |
---|
3 | +--------------------------------------------------------------------------+ |
---|
4 | | This file contains the i386 binary to boot image filter. |
---|
5 | +--------------------------------------------------------------------------+ |
---|
6 | | (C) Copyright 1997 - |
---|
7 | | - NavIST Group - Real-Time Distributed Systems and Industrial Automation |
---|
8 | | |
---|
9 | | http://pandora.ist.utl.pt |
---|
10 | | |
---|
11 | | Instituto Superior Tecnico * Lisboa * PORTUGAL |
---|
12 | +--------------------------------------------------------------------------+ |
---|
13 | | Disclaimer: |
---|
14 | | |
---|
15 | | This file is provided "AS IS" without warranty of any kind, either |
---|
16 | | expressed or implied. |
---|
17 | +--------------------------------------------------------------------------*/ |
---|
18 | |
---|
19 | |
---|
20 | #include <stdio.h> |
---|
21 | #include <stdlib.h> |
---|
22 | #include <string.h> |
---|
23 | #include <unistd.h> |
---|
24 | #include "bytetype.h" |
---|
25 | #include "bootimg.h" |
---|
26 | |
---|
27 | /*-------------------------------------------------------------------------+ |
---|
28 | | Constants |
---|
29 | +--------------------------------------------------------------------------*/ |
---|
30 | #define SEG_MASK 0xffff0000 |
---|
31 | /* Mask for segment part of seg:off address. */ |
---|
32 | #define OFF_MASK 0x0000ffff |
---|
33 | /* Mask for offset part of seg:off address. */ |
---|
34 | #define DEFAULT_START_ADDR 0x10200 /* Default start address for binary. */ |
---|
35 | #define BOOTIMG_HDR_SIZE 0x0200 /* Size of output file header. */ |
---|
36 | #define BUFFER_BLOCK_SIZE 0x1000 /* Size of transfer buffer size. */ |
---|
37 | #define LAST_BLOCK_SIZE 0x0200 |
---|
38 | /* The output file must have a size multiple of this value. */ |
---|
39 | |
---|
40 | |
---|
41 | /*-------------------------------------------------------------------------+ |
---|
42 | | Macros |
---|
43 | +--------------------------------------------------------------------------*/ |
---|
44 | #define getSeg(x) (Word)((x) >> 16) |
---|
45 | /* Return seg part (Word) of a seg:off address (DWord). */ |
---|
46 | |
---|
47 | #define getOff(x) (Word)((x) & OFF_MASK) |
---|
48 | /* Return off part (Word) of a seg:off address (DWord). */ |
---|
49 | |
---|
50 | #define getSegOff(x) ((((x) & SEG_MASK) << 12) + ((x) & OFF_MASK)) |
---|
51 | /* Converts a flat address to a seg:off address. */ |
---|
52 | |
---|
53 | /*-------------------------------------------------------------------------+ |
---|
54 | | Global Variables |
---|
55 | +--------------------------------------------------------------------------*/ |
---|
56 | const char UsageMsg[] = "\ |
---|
57 | Usage: bin2boot [<infile> [<outfile>]] [-s <start_address>] [-v]\n\ |
---|
58 | \n\ |
---|
59 | <infile> : input file name\n\ |
---|
60 | <outfile> : output file name\n\ |
---|
61 | -s <outfile> : start address of binary image\n\ |
---|
62 | -m <size> : actual size (for compressed images)\n\ |
---|
63 | -v : verbose output\n"; /* Usage message. */ |
---|
64 | |
---|
65 | |
---|
66 | /*-------------------------------------------------------------------------+ |
---|
67 | | External Prototypes (for use with getopt) |
---|
68 | +--------------------------------------------------------------------------*/ |
---|
69 | extern char *optarg; |
---|
70 | |
---|
71 | int getopt(int, char *const[], const char *); |
---|
72 | |
---|
73 | |
---|
74 | /*-------------------------------------------------------------------------+ |
---|
75 | | Auxiliary Functions |
---|
76 | +--------------------------------------------------------------------------*/ |
---|
77 | static DWord |
---|
78 | getNumArg(char *arg) |
---|
79 | { |
---|
80 | char *dummy; |
---|
81 | |
---|
82 | if (arg[0] == '0') |
---|
83 | if ((arg[1] == 'x') || (arg[1] == 'X')) /* Hexadecimal */ |
---|
84 | return (DWord)strtol(arg, &dummy, 16); |
---|
85 | else /* Octal */ |
---|
86 | return (DWord)strtol(arg, &dummy, 8); |
---|
87 | else /* Decimal */ |
---|
88 | return (DWord)strtol(arg, &dummy, 10); |
---|
89 | } /* getNumArg */ |
---|
90 | |
---|
91 | |
---|
92 | /*-------------------------------------------------------------------------+ |
---|
93 | | Main |
---|
94 | +--------------------------------------------------------------------------*/ |
---|
95 | void main(int argc, char *argv[]) |
---|
96 | { |
---|
97 | FileHeader bootimgFileHdr; /* Output file header. */ |
---|
98 | LoadingInfo imageInfo; /* Section header. */ |
---|
99 | Byte auxBuf[BUFFER_BLOCK_SIZE]; /* */ |
---|
100 | DWord nRead; /* Number of bytes read. */ |
---|
101 | Word padSize; /* Size of padding at end of file. */ |
---|
102 | |
---|
103 | char *progName = argv[0]; /* Program name for errors. */ |
---|
104 | FILE *fpIn = stdin; |
---|
105 | FILE *fpOut = stdout; |
---|
106 | DWord binStart = DEFAULT_START_ADDR; /* Start address of image. */ |
---|
107 | DWord memLen = 0; /* Real length for compressed images. */ |
---|
108 | |
---|
109 | char currArg; |
---|
110 | int argCount; |
---|
111 | int flag; /* general purpose flag */ |
---|
112 | int verbose = 0; /* flag for verbose output */ |
---|
113 | |
---|
114 | while ((currArg = getopt(argc, argv, "hm:s:v")) >= 0) /* parse command line */ |
---|
115 | switch (currArg) |
---|
116 | { |
---|
117 | case 'h' : |
---|
118 | fprintf(stderr, UsageMsg); |
---|
119 | exit(0); |
---|
120 | break; |
---|
121 | case 'm' : |
---|
122 | memLen = getNumArg(optarg); |
---|
123 | break; |
---|
124 | case 's' : |
---|
125 | binStart = getNumArg(optarg); |
---|
126 | break; |
---|
127 | case 'v' : |
---|
128 | verbose = 1; |
---|
129 | break; |
---|
130 | default : |
---|
131 | fprintf(stderr, UsageMsg); |
---|
132 | exit(1); |
---|
133 | break; |
---|
134 | } /* switch */ |
---|
135 | |
---|
136 | flag = 0; |
---|
137 | |
---|
138 | for (argCount = 1; argCount < argc; argCount++) |
---|
139 | if (argv[argCount][0] == '-') |
---|
140 | { |
---|
141 | if (argv[argCount][1] == 's') |
---|
142 | argCount++; |
---|
143 | } |
---|
144 | else if (flag) /* we already have the input file => output file */ |
---|
145 | { |
---|
146 | if ((fpOut = fopen(argv[argCount], "w")) == NULL) |
---|
147 | { |
---|
148 | fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]); |
---|
149 | exit(1); |
---|
150 | } |
---|
151 | } |
---|
152 | else /* input file */ |
---|
153 | { |
---|
154 | if ((fpIn = fopen(argv[argCount], "r")) == NULL) |
---|
155 | { |
---|
156 | fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]); |
---|
157 | exit(1); |
---|
158 | } |
---|
159 | flag = 1; |
---|
160 | } |
---|
161 | |
---|
162 | /*** begin: Conversion to Bootimg */ |
---|
163 | |
---|
164 | /*** File Header */ |
---|
165 | |
---|
166 | if (verbose) |
---|
167 | fprintf(stderr, "\nBoot Image File Header:\n\n"); |
---|
168 | |
---|
169 | bootimgFileHdr.magicNum = BOOT_IMAGE_MAGIC; /* 4 bytes - magic number */ |
---|
170 | bootimgFileHdr.flagsLen = NON_VENDOR_LEN; /* 4 bytes - flags and length */ |
---|
171 | bootimgFileHdr.locAddr = getSegOff(binStart - BOOTIMG_HDR_SIZE); |
---|
172 | /* 4 bytes - location address in ds:bx format */ |
---|
173 | bootimgFileHdr.execAddr = getSegOff(binStart); |
---|
174 | /* 4 bytes - execute address in cs:ip format */ |
---|
175 | |
---|
176 | if (verbose) |
---|
177 | { |
---|
178 | fprintf(stderr, ">> location address in ds:bx format: %04x:%04x\n", |
---|
179 | getSeg(bootimgFileHdr.locAddr), getOff(bootimgFileHdr.locAddr)); |
---|
180 | fprintf(stderr, ">> execute address in cs:ip format: %04x:%04x\n", |
---|
181 | getSeg(bootimgFileHdr.execAddr), getOff(bootimgFileHdr.execAddr)); |
---|
182 | } |
---|
183 | |
---|
184 | /*** Write File Header to output file */ |
---|
185 | |
---|
186 | fwrite((void *)(& bootimgFileHdr), sizeof(FileHeader), 1, fpOut); |
---|
187 | |
---|
188 | /*** Sections */ |
---|
189 | |
---|
190 | if (verbose) |
---|
191 | fprintf(stderr, "\nCode Section:\n\n"); |
---|
192 | |
---|
193 | imageInfo.flagsTagsLens = 0x04000004; |
---|
194 | /* flags, vendor's tags, vendor and non-vendor lengths */ |
---|
195 | imageInfo.loadAddr = binStart; /* load address */ |
---|
196 | |
---|
197 | rewind(fpIn); |
---|
198 | fseek(fpIn, 0, SEEK_END); |
---|
199 | nRead = ftell(fpIn); |
---|
200 | rewind(fpIn); |
---|
201 | padSize = LAST_BLOCK_SIZE - (nRead % LAST_BLOCK_SIZE); |
---|
202 | imageInfo.imageLength = nRead + padSize; /* image length */ |
---|
203 | imageInfo.memoryLength = (memLen != 0) ? memLen : imageInfo.imageLength; |
---|
204 | /* memory length */ |
---|
205 | |
---|
206 | fwrite((void *)(&imageInfo), sizeof(LoadingInfo), 1, fpOut); |
---|
207 | |
---|
208 | if (verbose) |
---|
209 | { |
---|
210 | fprintf(stderr, ">> load address: 0x%08lx\n", imageInfo.loadAddr); |
---|
211 | fprintf(stderr, ">> image length: 0x%08lx\n", imageInfo.imageLength); |
---|
212 | fprintf(stderr, ">> memory length: 0x%08lx\n\n", imageInfo.memoryLength); |
---|
213 | } |
---|
214 | |
---|
215 | nRead = BOOTIMG_HDR_SIZE - sizeof(FileHeader) - sizeof(LoadingInfo); |
---|
216 | memset((void *)auxBuf, 0x00, nRead); |
---|
217 | fwrite((void *)auxBuf, 1, nRead, fpOut); |
---|
218 | |
---|
219 | nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn); |
---|
220 | |
---|
221 | while (!feof(fpIn)) |
---|
222 | { |
---|
223 | fwrite((void *)auxBuf, BUFFER_BLOCK_SIZE, 1, fpOut); |
---|
224 | nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn); |
---|
225 | } |
---|
226 | |
---|
227 | fwrite((void *)auxBuf, 1, nRead, fpOut); |
---|
228 | |
---|
229 | memset((void *)auxBuf, 0x00, padSize); |
---|
230 | fwrite((void *)auxBuf, 1, padSize, fpOut); |
---|
231 | |
---|
232 | fclose(fpOut); |
---|
233 | fclose(fpIn); |
---|
234 | |
---|
235 | /*** end: Conversion to Bootimg */ |
---|
236 | |
---|
237 | exit(0); |
---|
238 | |
---|
239 | } /* main */ |
---|