2006-10-13 15:07:01 +00:00
|
|
|
/*
|
|
|
|
* Makes a tree bootable image for IBM Evaluation boards.
|
|
|
|
* Basically, just take a zImage, skip the ELF header, and stuff
|
|
|
|
* a 32 byte header on the front.
|
|
|
|
*
|
|
|
|
* We use htonl, which is a network macro, to make sure we're doing
|
|
|
|
* The Right Thing on an LE machine. It's non-obvious, but it should
|
|
|
|
* work on anything BSD'ish.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#ifdef __sun__
|
|
|
|
#include <inttypes.h>
|
|
|
|
#else
|
|
|
|
#include <stdint.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* This gets tacked on the front of the image. There are also a few
|
|
|
|
* bytes allocated after the _start label used by the boot rom (see
|
|
|
|
* head.S for details).
|
|
|
|
*/
|
|
|
|
typedef struct boot_block {
|
|
|
|
uint32_t bb_magic; /* 0x0052504F */
|
|
|
|
uint32_t bb_dest; /* Target address of the image */
|
|
|
|
uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
|
|
|
|
uint32_t bb_debug_flag; /* Run debugger or image after load */
|
|
|
|
uint32_t bb_entry_point; /* The image address to start */
|
|
|
|
uint32_t bb_checksum; /* 32 bit checksum including header */
|
|
|
|
uint32_t reserved[2];
|
|
|
|
} boot_block_t;
|
|
|
|
|
|
|
|
#define IMGBLK 512
|
2009-08-10 17:14:55 +00:00
|
|
|
unsigned int tmpbuf[IMGBLK / sizeof(unsigned int)];
|
2006-10-13 15:07:01 +00:00
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int in_fd, out_fd;
|
|
|
|
int nblks, i;
|
2009-04-30 18:16:44 +00:00
|
|
|
unsigned int cksum, *cp;
|
2006-10-13 15:07:01 +00:00
|
|
|
struct stat st;
|
|
|
|
boot_block_t bt;
|
|
|
|
|
2007-05-08 04:10:01 +00:00
|
|
|
if (argc < 5) {
|
|
|
|
fprintf(stderr, "usage: %s <zImage-file> <boot-image> <load address> <entry point>\n",argv[0]);
|
2006-10-13 15:07:01 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stat(argv[1], &st) < 0) {
|
|
|
|
perror("stat");
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
nblks = (st.st_size + IMGBLK) / IMGBLK;
|
|
|
|
|
|
|
|
bt.bb_magic = htonl(0x0052504F);
|
|
|
|
|
|
|
|
/* If we have the optional entry point parameter, use it */
|
2007-05-08 04:10:01 +00:00
|
|
|
bt.bb_dest = htonl(strtoul(argv[3], NULL, 0));
|
|
|
|
bt.bb_entry_point = htonl(strtoul(argv[4], NULL, 0));
|
2006-10-13 15:07:01 +00:00
|
|
|
|
|
|
|
/* We know these from the linker command.
|
|
|
|
* ...and then move it up into memory a little more so the
|
|
|
|
* relocation can happen.
|
|
|
|
*/
|
|
|
|
bt.bb_num_512blocks = htonl(nblks);
|
|
|
|
bt.bb_debug_flag = 0;
|
|
|
|
|
|
|
|
bt.bb_checksum = 0;
|
|
|
|
|
|
|
|
/* To be neat and tidy :-).
|
|
|
|
*/
|
|
|
|
bt.reserved[0] = 0;
|
|
|
|
bt.reserved[1] = 0;
|
|
|
|
|
|
|
|
if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
|
|
|
|
perror("zImage open");
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
|
|
|
|
perror("bootfile open");
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
cksum = 0;
|
|
|
|
cp = (void *)&bt;
|
2009-04-30 18:16:44 +00:00
|
|
|
for (i = 0; i < sizeof(bt) / sizeof(unsigned int); i++)
|
2006-10-13 15:07:01 +00:00
|
|
|
cksum += *cp++;
|
|
|
|
|
|
|
|
/* Assume zImage is an ELF file, and skip the 64K header.
|
|
|
|
*/
|
2009-08-10 17:14:55 +00:00
|
|
|
if (read(in_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
|
2006-10-13 15:07:01 +00:00
|
|
|
fprintf(stderr, "%s is too small to be an ELF image\n",
|
|
|
|
argv[1]);
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
|
2009-08-10 17:14:55 +00:00
|
|
|
if (tmpbuf[0] != htonl(0x7f454c46)) {
|
2006-10-13 15:07:01 +00:00
|
|
|
fprintf(stderr, "%s is not an ELF image\n", argv[1]);
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
|
|
|
|
fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
nblks -= (64 * 1024) / IMGBLK;
|
|
|
|
|
|
|
|
/* And away we go......
|
|
|
|
*/
|
|
|
|
if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
|
|
|
|
perror("boot-image write");
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (nblks-- > 0) {
|
2009-08-10 17:14:55 +00:00
|
|
|
if (read(in_fd, tmpbuf, sizeof(tmpbuf)) < 0) {
|
2006-10-13 15:07:01 +00:00
|
|
|
perror("zImage read");
|
|
|
|
exit(5);
|
|
|
|
}
|
2009-08-10 17:14:55 +00:00
|
|
|
cp = tmpbuf;
|
2009-04-30 18:16:44 +00:00
|
|
|
for (i = 0; i < sizeof(tmpbuf) / sizeof(unsigned int); i++)
|
2006-10-13 15:07:01 +00:00
|
|
|
cksum += *cp++;
|
|
|
|
if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
|
|
|
|
perror("boot-image write");
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rewrite the header with the computed checksum.
|
|
|
|
*/
|
|
|
|
bt.bb_checksum = htonl(cksum);
|
|
|
|
if (lseek(out_fd, 0, SEEK_SET) < 0) {
|
|
|
|
perror("rewrite seek");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
|
|
|
|
perror("boot-image rewrite");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|