1 /* $NetBSD: setbootimg.c,v 1.2 2009/03/14 15:36:15 dsl Exp $ */
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>
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 */
37 int main
PROTO((int argc
, char *argv
[]));
38 static unsigned get_uint16
PROTO((void *));
39 static unsigned get_uint32
PROTO((void *));
46 # define VA_START(a, v) va_start(a, v)
50 # define VA_START(a, v) va_start(a)
54 static void err
PROTO((int eval
, const char *fmt
, ...));
55 static void errx
PROTO((int eval
, const char *fmt
, ...));
59 err(int eval
, const char *fmt
, ...)
61 err(eval
, fmt
, va_alist
)
70 fprintf(stderr
, "setbootimg: ");
73 vfprintf(stderr
, fmt
, ap
);
75 fprintf(stderr
, ": ");
84 errx(int eval
, const char *fmt
, ...)
86 errx(eval
, fmt
, va_alist
)
94 fprintf(stderr
, "setbootimg: ");
97 vfprintf(stderr
, fmt
, ap
);
100 fprintf(stderr
, "\n");
109 unsigned char *q
= p
;
111 return q
[0] << 8 | q
[1];
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
;
138 int labelstart
, labelend
, imgstart
, imgend
;
141 fprintf(stderr
, "usage: %s image_file boot_block\n", argv
[0]);
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
);
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
);
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
)
191 imgstart
= get_uint16(boot
+ labelend
);
193 errx(1, "%s: no image support by this boot", bootfile
);
195 imgend
= get_uint16(boot
+ imgstart
);
198 if (imgend
< imgstart
|| imgend
>= size_boot
)
201 /* disklabel exists? */
202 if (get_uint32(boot
+ labelstart
) == MAGIC_DISKLABEL
)
203 labelstart
= labelend
; /* don't destroy disklabel */
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
);
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
);
234 err(1, "%s: close write", bootfile
);