Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.14 293 lines 7.1 kB view raw
1/* 2 * Makes a prep bootable image which can be dd'd onto 3 * a disk device to make a bootdisk. Will take 4 * as input a elf executable, strip off the header 5 * and write out a boot image as: 6 * 1) default - strips elf header 7 * suitable as a network boot image 8 * 2) -pbp - strips elf header and writes out prep boot partition image 9 * cat or dd onto disk for booting 10 * 3) -asm - strips elf header and writes out as asm data 11 * useful for generating data for a compressed image 12 * -- Cort 13 * 14 * Modified for x86 hosted builds by Matt Porter <porter@neta.com> 15 * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de> 16 */ 17 18#include <fcntl.h> 19#include <stdio.h> 20#include <stdlib.h> 21#include <string.h> 22#include <strings.h> 23#include <sys/stat.h> 24#include <unistd.h> 25 26#define cpu_to_le32(x) le32_to_cpu((x)) 27unsigned long le32_to_cpu(unsigned long x) 28{ 29 return (((x & 0x000000ffU) << 24) | 30 ((x & 0x0000ff00U) << 8) | 31 ((x & 0x00ff0000U) >> 8) | 32 ((x & 0xff000000U) >> 24)); 33} 34 35 36#define cpu_to_le16(x) le16_to_cpu((x)) 37unsigned short le16_to_cpu(unsigned short x) 38{ 39 return (((x & 0x00ff) << 8) | 40 ((x & 0xff00) >> 8)); 41} 42 43#define cpu_to_be32(x) (x) 44#define be32_to_cpu(x) (x) 45#define cpu_to_be16(x) (x) 46#define be16_to_cpu(x) (x) 47 48/* size of read buffer */ 49#define SIZE 0x1000 50 51 52typedef unsigned long dword_t; 53typedef unsigned short word_t; 54typedef unsigned char byte_t; 55typedef byte_t block_t[512]; 56typedef byte_t page_t[4096]; 57 58 59/* 60 * Partition table entry 61 * - from the PReP spec 62 */ 63typedef struct partition_entry { 64 byte_t boot_indicator; 65 byte_t starting_head; 66 byte_t starting_sector; 67 byte_t starting_cylinder; 68 69 byte_t system_indicator; 70 byte_t ending_head; 71 byte_t ending_sector; 72 byte_t ending_cylinder; 73 74 dword_t beginning_sector; 75 dword_t number_of_sectors; 76} partition_entry_t; 77 78#define BootActive 0x80 79#define SystemPrep 0x41 80 81void copy_image(int , int); 82void write_prep_partition(int , int ); 83void write_asm_data( int in, int out ); 84 85unsigned int elfhdr_size = 65536; 86 87int main(int argc, char *argv[]) 88{ 89 int in_fd, out_fd; 90 int argptr = 1; 91 unsigned int prep = 0; 92 unsigned int asmoutput = 0; 93 94 if ( (argc < 3) || (argc > 4) ) 95 { 96 fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]); 97 exit(-1); 98 } 99 100 /* needs to handle args more elegantly -- but this is a small/simple program */ 101 102 /* check for -pbp */ 103 if ( !strcmp( argv[argptr], "-pbp" ) ) 104 { 105 prep = 1; 106 argptr++; 107 } 108 109 /* check for -asm */ 110 if ( !strcmp( argv[argptr], "-asm" ) ) 111 { 112 asmoutput = 1; 113 argptr++; 114 } 115 116 /* input file */ 117 if ( !strcmp( argv[argptr], "-" ) ) 118 in_fd = 0; /* stdin */ 119 else 120 if ((in_fd = open( argv[argptr] , 0)) < 0) 121 exit(-1); 122 argptr++; 123 124 /* output file */ 125 if ( !strcmp( argv[argptr], "-" ) ) 126 out_fd = 1; /* stdout */ 127 else 128 if ((out_fd = creat( argv[argptr] , 0755)) < 0) 129 exit(-1); 130 argptr++; 131 132 /* skip elf header in input file */ 133 /*if ( !prep )*/ 134 lseek(in_fd, elfhdr_size, SEEK_SET); 135 136 /* write prep partition if necessary */ 137 if ( prep ) 138 write_prep_partition( in_fd, out_fd ); 139 140 /* write input image to bootimage */ 141 if ( asmoutput ) 142 write_asm_data( in_fd, out_fd ); 143 else 144 copy_image(in_fd, out_fd); 145 146 return 0; 147} 148 149void write_prep_partition(int in, int out) 150{ 151 unsigned char block[512]; 152 partition_entry_t pe; 153 dword_t *entry = (dword_t *)&block[0]; 154 dword_t *length = (dword_t *)&block[sizeof(long)]; 155 struct stat info; 156 157 if (fstat(in, &info) < 0) 158 { 159 fprintf(stderr,"info failed\n"); 160 exit(-1); 161 } 162 163 bzero( block, sizeof block ); 164 165 /* set entry point and boot image size skipping over elf header */ 166#ifdef __i386__ 167 *entry = 0x400/*+65536*/; 168 *length = info.st_size-elfhdr_size+0x400; 169#else 170 *entry = cpu_to_le32(0x400/*+65536*/); 171 *length = cpu_to_le32(info.st_size-elfhdr_size+0x400); 172#endif /* __i386__ */ 173 174 /* sets magic number for msdos partition (used by linux) */ 175 block[510] = 0x55; 176 block[511] = 0xAA; 177 178 /* 179 * Build a "PReP" partition table entry in the boot record 180 * - "PReP" may only look at the system_indicator 181 */ 182 pe.boot_indicator = BootActive; 183 pe.system_indicator = SystemPrep; 184 /* 185 * The first block of the diskette is used by this "boot record" which 186 * actually contains the partition table. (The first block of the 187 * partition contains the boot image, but I digress...) We'll set up 188 * one partition on the diskette and it shall contain the rest of the 189 * diskette. 190 */ 191 pe.starting_head = 0; /* zero-based */ 192 pe.starting_sector = 2; /* one-based */ 193 pe.starting_cylinder = 0; /* zero-based */ 194 pe.ending_head = 1; /* assumes two heads */ 195 pe.ending_sector = 18; /* assumes 18 sectors/track */ 196 pe.ending_cylinder = 79; /* assumes 80 cylinders/diskette */ 197 198 /* 199 * The "PReP" software ignores the above fields and just looks at 200 * the next two. 201 * - size of the diskette is (assumed to be) 202 * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette) 203 * - unlike the above sector numbers, the beginning sector is zero-based! 204 */ 205#if 0 206 pe.beginning_sector = cpu_to_le32(1); 207#else 208 /* This has to be 0 on the PowerStack? */ 209#ifdef __i386__ 210 pe.beginning_sector = 0; 211#else 212 pe.beginning_sector = cpu_to_le32(0); 213#endif /* __i386__ */ 214#endif 215 216#ifdef __i386__ 217 pe.number_of_sectors = 2*18*80-1; 218#else 219 pe.number_of_sectors = cpu_to_le32(2*18*80-1); 220#endif /* __i386__ */ 221 222 memcpy(&block[0x1BE], &pe, sizeof(pe)); 223 224 write( out, block, sizeof(block) ); 225 write( out, entry, sizeof(*entry) ); 226 write( out, length, sizeof(*length) ); 227 /* set file position to 2nd sector where image will be written */ 228 lseek( out, 0x400, SEEK_SET ); 229} 230 231 232 233void 234copy_image(int in, int out) 235{ 236 char buf[SIZE]; 237 int n; 238 239 while ( (n = read(in, buf, SIZE)) > 0 ) 240 write(out, buf, n); 241} 242 243 244void 245write_asm_data( int in, int out ) 246{ 247 int i, cnt, pos, len; 248 unsigned int cksum, val; 249 unsigned char *lp; 250 unsigned char buf[SIZE]; 251 unsigned char str[256]; 252 253 write( out, "\t.data\n\t.globl input_data\ninput_data:\n", 254 strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) ); 255 pos = 0; 256 cksum = 0; 257 while ((len = read(in, buf, sizeof(buf))) > 0) 258 { 259 cnt = 0; 260 lp = (unsigned char *)buf; 261 len = (len + 3) & ~3; /* Round up to longwords */ 262 for (i = 0; i < len; i += 4) 263 { 264 if (cnt == 0) 265 { 266 write( out, "\t.long\t", strlen( "\t.long\t" ) ); 267 } 268 sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]); 269 write( out, str, strlen(str) ); 270 val = *(unsigned long *)lp; 271 cksum ^= val; 272 lp += 4; 273 if (++cnt == 4) 274 { 275 cnt = 0; 276 sprintf( str, " # %x \n", pos+i-12); 277 write( out, str, strlen(str) ); 278 } else 279 { 280 write( out, ",", 1 ); 281 } 282 } 283 if (cnt) 284 { 285 write( out, "0\n", 2 ); 286 } 287 pos += len; 288 } 289 sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos); 290 write( out, str, strlen(str) ); 291 292 fprintf(stderr, "cksum = %x\n", cksum); 293}