Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / x68k / stand / bootlogo / setbootimg.c
blobc5d12effad5df168386a421801d273744ba2ef9f
1 /* $NetBSD: setbootimg.c,v 1.2 2009/03/14 15:36:15 dsl Exp $ */
3 /*
4 * set boot title image (converted by xpm2bootimg)
5 * to boot file or installed boot block
7 * use with care, not to destroy the existent boot or the disklabel
9 * written by Yasha (ITOH Yasufumi), public domain
12 #include <sys/types.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <string.h>
17 #ifdef __NetBSD__
18 #include <err.h>
19 #endif
22 * define here for cross env
24 #define SIZE_BOOTBLK 8192 /* <ufs/ffs/fs.h> BBSIZE */
25 #define MAGIC_DISKLABEL 0x82564557 /* <sys/disklabel.h> DISKMAGIC */
26 #define X68K_LABELOFF 64 /* <x68k/disklabel.h> LABELOFFSET */
28 #ifdef __STDC__
29 # define PROTO(x) x
30 #else
31 # define PROTO(x) ()
32 # ifndef const
33 # define const
34 # endif
35 #endif
37 int main PROTO((int argc, char *argv[]));
38 static unsigned get_uint16 PROTO((void *));
39 static unsigned get_uint32 PROTO((void *));
41 #ifndef __NetBSD__
42 /* for cross env */
44 #ifdef __STDC__
45 # include <stdarg.h>
46 # define VA_START(a, v) va_start(a, v)
47 # include <errno.h>
48 #else
49 # include <varargs.h>
50 # define VA_START(a, v) va_start(a)
51 extern int errno;
52 #endif
54 static void err PROTO((int eval, const char *fmt, ...));
55 static void errx PROTO((int eval, const char *fmt, ...));
57 static void
58 #ifdef __STDC__
59 err(int eval, const char *fmt, ...)
60 #else
61 err(eval, fmt, va_alist)
62 int eval;
63 const char *fmt;
64 va_dcl
65 #endif
67 int e = errno;
68 va_list ap;
70 fprintf(stderr, "setbootimg: ");
71 if (fmt) {
72 VA_START(ap, fmt);
73 vfprintf(stderr, fmt, ap);
74 va_end(ap);
75 fprintf(stderr, ": ");
77 errno = e;
78 perror((char *) 0);
79 exit(eval);
82 static void
83 #ifdef __STDC__
84 errx(int eval, const char *fmt, ...)
85 #else
86 errx(eval, fmt, va_alist)
87 int eval;
88 const char *fmt;
89 va_dcl
90 #endif
92 va_list ap;
94 fprintf(stderr, "setbootimg: ");
95 if (fmt) {
96 VA_START(ap, fmt);
97 vfprintf(stderr, fmt, ap);
98 va_end(ap);
100 fprintf(stderr, "\n");
101 exit(eval);
104 #endif
106 static unsigned
107 get_uint16(void *p)
109 unsigned char *q = p;
111 return q[0] << 8 | q[1];
114 static unsigned
115 get_uint32(void *p)
117 unsigned char *q = p;
119 return q[0] << 24 | q[1] << 16 | q[2] << 8 | q[3];
123 static const char boottop[] = {
124 0x60, 0x24, 0x53, 0x48, 0x41, 0x52, 0x50, 0x2F,
125 0x58, 0x36, 0x38, 0x30, 0x78, 0x30, 0x81, 0x99,
126 0x94, 0xE6, 0x82, 0xEA, 0x82, 0xBD, 0x8E, 0x9E,
127 0x82, 0xC9, 0x82, 0xCD, 0x8C, 0xBB, 0x8E, 0xC0,
128 0x93, 0xA6, 0x94, 0xF0, 0x81, 0x49
132 main(int argc, char *argv[])
134 char *imgfile, *bootfile;
135 char img[SIZE_BOOTBLK], boot[SIZE_BOOTBLK];
136 int size_img, size_boot;
137 int fd;
138 int labelstart, labelend, imgstart, imgend;
140 if (argc != 3) {
141 fprintf(stderr, "usage: %s image_file boot_block\n", argv[0]);
142 return 1;
145 imgfile = argv[1];
146 bootfile = argv[2];
149 * read image
151 if ((fd = open(imgfile, O_RDONLY)) < 0)
152 err(1, "%s", imgfile);
154 if ((size_img = read(fd, img, sizeof img)) < 0)
155 err(1, "%s", imgfile);
157 if (size_img >= (int) sizeof img)
158 errx(1, "%s: file too large", imgfile);
160 (void) close(fd);
163 * read boot block
165 if ((fd = open(bootfile, O_RDWR)) < 0)
166 err(1, "%s", bootfile);
168 if ((size_boot = read(fd, boot, sizeof boot)) < 0)
169 err(1, "%s", bootfile);
171 if (lseek(fd, (off_t) 0, SEEK_SET))
172 err(1, "%s: lseek", bootfile);
174 if (size_boot < 4096) /* XXX */
175 errx(1, "%s: too short", bootfile);
178 * check boot block
180 if (memcmp(boot, boottop, sizeof boottop))
181 errx(1, "%s: not a boot", bootfile);
183 labelstart = X68K_LABELOFF;
184 if (get_uint16(boot + labelstart - 4) != 0x6000) /* bra */
185 badboot: errx(1, "%s: wrong boot block", bootfile);
187 labelend = labelstart + get_uint16(boot + labelstart - 2) - 4;
188 if (labelend >= size_boot)
189 goto badboot;
191 imgstart = get_uint16(boot + labelend);
192 if (imgstart == 0)
193 errx(1, "%s: no image support by this boot", bootfile);
195 imgend = get_uint16(boot + imgstart);
196 imgstart += 2;
198 if (imgend < imgstart || imgend >= size_boot)
199 goto badboot;
201 /* disklabel exists? */
202 if (get_uint32(boot + labelstart) == MAGIC_DISKLABEL)
203 labelstart = labelend; /* don't destroy disklabel */
204 else
205 labelstart += 2;
208 * the image fits this boot?
210 if (size_img > (imgend - imgstart) + (labelend - labelstart))
211 errx(1, "%s: image doesn't fit (max %d bytes)",
212 imgfile, (imgend - imgstart) + (labelend - labelstart));
215 * put image into boot
217 if (size_img <= (imgend - imgstart)) {
218 memcpy(boot + imgstart, img, size_img);
219 } else {
220 memcpy(boot + imgstart, img, imgend - imgstart);
221 boot[labelstart - 2] = 'i';
222 boot[labelstart - 1] = 'm';
223 memcpy(boot + labelstart, img + (imgend - imgstart),
224 size_img - (imgend - imgstart));
228 * write back boot block
230 if (write(fd, boot, size_boot) != size_boot)
231 err(1, "%s: write back", bootfile);
233 if (close(fd))
234 err(1, "%s: close write", bootfile);
236 return 0;