blob: d2b2c999d1b9e84fd62dda10a8900e3e0b75064f [file] [log] [blame]
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include "load.h"
#include "palo.h"
#define B32(x) __be32_to_cpu((x))
/* compute the sum of words in an 4-byte aligned region */
int
checksum(void *p, size_t len)
{
int xsum = 0;
int *x = (int *)p;
int i;
if (0) printf("checksum(%p, %u) = ", p, len);
len /= 4;
for (i = 0; i < len; i++)
{
xsum += B32(x[i]);
}
if (0) printf("0x%08x\n", xsum);
return (xsum);
}
/* maximum allowed HP boot loader (IPL) size */
#define MAXBLSIZE (256 * 1024)
void
fix_bootloader(int out, int bootloader)
{
size_t rblsize; /* sector-rounded boot loader size */
struct loadable loadable;
int xsum1;
void *blimage;
int r;
int wide;
memset(&loadable, 0, sizeof loadable);
r = prepare_loadable(bootloader, &loadable, &wide);
if (!r)
{
fprintf(stderr, "Can't grok your bootloader executable format\n");
exit(2);
}
rblsize = loadable.size;
printf("entry 0x%08x size %d\n", loadable.entry, rblsize);
rblsize += (FW_BLOCKSIZE - 1);
rblsize &= ~(FW_BLOCKSIZE - 1);
if (loadable.entry != loadable.first)
{
fprintf(stderr, "Entry point addres 0x%08x must be the same as the lowest"
"address 0x%08x\n", loadable.entry, loadable.first);
exit(2);
}
/* IPL max size is 256k */
if (rblsize > MAXBLSIZE)
error(5, loadable.size);
/* load the boot loader into RAM */
/* WORKAROUND: since the ELF32 value of p_memsz of the iplelf binary
* is wrong, just use 5 times more memory here to avoid a segfault. */
blimage = (void *)malloc(5*MAXBLSIZE);
assert(blimage != NULL);
if (!load_loadable(blimage, bootloader, &loadable))
error(13);
/* checksum it */
xsum1 = checksum(blimage, rblsize);
/* write checksum into RAM -- see ipl/crt0.S!!! */
((int *)blimage)[1] = B32(-xsum1);
/* write it out */
seekwrite(out, blimage, rblsize, 0);
close(bootloader);
free(blimage);
}
int
main(int argc, char *argv[])
{
int bootloader = -1;
int out = -1;
switch(argc)
{
case 1:
bootloader = fileno(stdin);
out = fileno(stdout);
break;
case 2:
if ((bootloader = open(argv[1], O_RDONLY)) == -1)
{
perror(argv[1]);
return 2;
}
out = fileno(stdout);
break;
case 3:
if ((bootloader = open(argv[1], O_RDONLY)) == -1)
{
perror(argv[1]);
return 2;
}
if ((out = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1)
{
perror(argv[2]);
return 2;
}
break;
default:
fprintf(stderr, "Usage: %s [ipl [bootable_ipl]]\n", argv[0]);
return 3;
}
fix_bootloader(out, bootloader);
fsync(out);
return 0;
}