Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | /*
* Makes a Motorola PPCBUG ROM bootable image which can be flashed
* into one of the FLASH banks on a Motorola PowerPlus board.
*
* Author: Matt Porter <mporter@mvista.com>
*
* 2001 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#define ELF_HEADER_SIZE 65536
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#ifdef __sun__
#include <inttypes.h>
#else
#include <stdint.h>
#endif
/* size of read buffer */
#define SIZE 0x1000
/* PPCBUG ROM boot header */
typedef struct bug_boot_header {
uint8_t magic_word[4]; /* "BOOT" */
uint32_t entry_offset; /* Offset from top of header to code */
uint32_t routine_length; /* Length of code */
uint8_t routine_name[8]; /* Name of the boot code */
} bug_boot_header_t;
#define HEADER_SIZE sizeof(bug_boot_header_t)
void update_checksum(void *buf, size_t size, uint16_t *sum)
{
uint32_t csum = *sum;
while (size) {
csum += *(uint16_t *)buf;
if (csum > 0xffff)
csum -= 0xffff;
buf = (uint16_t *)buf + 1;
size -= 2;
}
*sum = csum;
}
uint32_t copy_image(int in_fd, int out_fd, uint16_t *sum)
{
uint8_t buf[SIZE];
int offset = 0;
int n;
uint32_t image_size = 0;
lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET);
/* Copy an image while recording its size */
while ( (n = read(in_fd, buf + offset, SIZE - offset)) > 0 ) {
n += offset;
offset = n & 1;
n -= offset;
image_size = image_size + n;
/* who's going to deal with short writes? */
write(out_fd, buf, n);
update_checksum(buf, n, sum);
if (offset)
buf[0] = buf[n];
}
/* BUG romboot requires that our size is divisible by 2 */
/* align image to 2 byte boundary */
if (offset) {
image_size += 2;
buf[1] = '\0';
write(out_fd, buf, 2);
update_checksum(buf, 2, sum);
}
return image_size;
}
void write_bugboot_header(int out_fd, uint32_t boot_size, uint16_t *sum)
{
static bug_boot_header_t bbh = {
.magic_word = "BOOT",
.routine_name = "LINUXROM"
};
/* Fill in the PPCBUG ROM boot header */
bbh.entry_offset = htonl(HEADER_SIZE); /* Entry address */
bbh.routine_length= htonl(HEADER_SIZE+boot_size+2); /* Routine length */
/* Output the header and bootloader to the file */
write(out_fd, &bbh, sizeof(bug_boot_header_t));
update_checksum(&bbh, sizeof(bug_boot_header_t), sum);
}
int main(int argc, char *argv[])
{
int image_fd, bugboot_fd;
uint32_t kernel_size = 0;
uint16_t checksum = 0;
if (argc != 3) {
fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]);
exit(-1);
}
/* Get file args */
/* kernel image file */
if ((image_fd = open(argv[1] , 0)) < 0)
exit(-1);
/* bugboot file */
if (!strcmp(argv[2], "-"))
bugboot_fd = 1; /* stdout */
else if ((bugboot_fd = creat(argv[2] , 0755)) < 0)
exit(-1);
/* Set file position after ROM header block where zImage will be written */
lseek(bugboot_fd, HEADER_SIZE, SEEK_SET);
/* Copy kernel image into bugboot image */
kernel_size = copy_image(image_fd, bugboot_fd, &checksum);
/* Set file position to beginning where header/romboot will be written */
lseek(bugboot_fd, 0, SEEK_SET);
/* Write out BUG header/romboot */
write_bugboot_header(bugboot_fd, kernel_size, &checksum);
/* Write out the calculated checksum */
lseek(bugboot_fd, 0, SEEK_END);
write(bugboot_fd, &checksum, 2);
/* Close bugboot file */
close(bugboot_fd);
return 0;
}
|