[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Flashing Ultra OBP



On Fri, Nov 01, 2002 at 08:58:50AM -0800, Brian Macy wrote:
> I just noticed the flash module. I don't see any instructions on how to 
> use it (just dd an image?) or on how to extract the image from the sun 
> supplied upgrade executable.

I can't recall where the program is to write flash (I used to have it
around), but you should be able to find it with a google search real
easy. As for extracting an OBP flash from a Sun update, use the attached
program I write awhile back to do exactly that.

This program could probably be done more easily using objdump, but I
like writing code, so here it is.

-- 
Debian     - http://www.debian.org/
Linux 1394 - http://www.linux1394.org/
Subversion - http://subversion.tigris.org/
Deqo       - http://www.deqo.com/
/* Extract an OBP flash file from a Sun stand-alone update */

/* (C) 2001 Ben Collins <bcollins@debian.org> */

/* Licensed under the GPLv2 */

/* Sun supplies OBP flash updates via their SunSolve website. These files
 * are stand-alone programs that you boot in order to install the flash.
 * I've tried booting one of these via SILO, but it doesn't work (maybe
 * SILO can be made to do that?).
 *
 * Anyway, the OBP flash consists of two segments, OBP and POST, each 512k
 * bytes long (although it does not actually use all of that). Each of
 * these segments is stored in the .text section of the Sun flash update
 * program. This program basically searches for the first occurence of the
 * flash magic (OBMD), copies 512k from that point, and starts searching
 * for the second segment after that. Pretty simple.
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>

struct obp {
	char		magic[4];       /* OBMD */
	unsigned int	size;
	unsigned int	checksum;
	unsigned int	__unknown2;
	char		name[4];        /* OBP or POST */
	unsigned int	year;
	unsigned char	mon;
	unsigned char	mday;
	unsigned char	hour;
	unsigned char	min;
	unsigned char	major;
	unsigned char	minor;
	unsigned char	patchlevel;
	unsigned char	__unknown3;
};

#define FLASH_SIZE (1024*1024)

static void print_obp_info(struct obp *obp)
{
	printf("%-4s\tVersion: %d.%d.%-3d\t%04d/%02d/%02d %02d:%02d\n",
			obp->name, obp->major, obp->minor, obp->patchlevel,
			obp->year, obp->mon, obp->mday, obp->hour, obp->min);
	printf("\tSize: %u\n\tChecksum: %04X\n", obp->size, obp->checksum);
	return;
}

int main(int argc, char *argv[])
{
	unsigned char *data;
	unsigned int size;
	int fdin, fdout, i;
	char *outfile = "flash-stripped";
	struct obp *obp;

	if (argc != 2 && argc != 3) {
		fprintf(stderr, "Usage: extract-flash <flash-update> [output file]\n");
		exit(1);
	}

	if (argc == 3) {
		outfile = argv[2];
		if (unlink(outfile)) {
			perror(outfile);
			exit(1);
		}
	}

	fdin = open(argv[1], O_RDONLY);
	if (fdin < 0) {
		perror(argv[1]);
		exit(1);
	}

	fdout = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0644);
	if (fdout < 0) {
		perror(outfile);
		exit(1);
	}

	size = lseek(fdin, 0, SEEK_END);
	if (size < 0) {
		perror(argv[1]);
		exit(1);
	}

	data = mmap(0, size, PROT_READ, MAP_SHARED, fdin, 0);
	if (data == (void *)-1) {
		perror(argv[1]);
		exit(1);
	}

	while (memcmp(data, "OBMD", 4) && size) {
		data++;
		size--;
	}

	if (!size) {
		fprintf(stderr, "Could not find OBP magic\n");
		exit(1);
	}

	obp = (struct obp *)data;
	print_obp_info(obp);

	write(fdout, data, FLASH_SIZE/2);

	data += FLASH_SIZE/2;

	while (memcmp(data, "OBMD", 4) && size) {
		data++;
		size--;
	}

	if (!size) {
		fprintf(stderr, "Could not find OBP magic\n");
		exit(1);
	}

	obp = (struct obp *)data;
	print_obp_info(obp);

	write(fdout, data, FLASH_SIZE/2);

	close(fdin);
	close(fdout);

	return 0;
}

Reply to: