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