[U-Boot-Users] Reading out version_string from a binary

Fredrik Roubert fredrik.roubert at barco.com
Tue Nov 21 14:02:36 CET 2006


Hi!

I use U-Boot (1.1.4) on a custom PowerPC (MPC8347) based board, and from
my application I need to read out the value of version_string from the
U-Boot binary, for logging. I've written some code that does this (see
attached sample program), but would like some comments if someone has
suggestions on how to do it more robust.

On MPC83XX, version_string is stored at the beginning of .rodata, so if
only the offset for .rodata is found, reading out version_string is
quite straightforward.

The offset of .rodata changes, however, when code is added or removed
from U-Boot. I've found that an offset is being written at the end of
start.o, from which it is possible to calculate the offset of .rodata,
and even though this works for my current needs, it's hardly what one
would call a robust solutions.

Does anyone have ideas about a better way to do this?

Cheers // Fredrik Roubert

-- 
Barco Medical Imaging          |  +32 56 233549
http://www.barco.com/medical/  |  fredrik.roubert at barco.com
-------------- next part --------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <errno.h>


static char *
ubootver(const char *path)
{
	/* This code assumes big-endian U-Boot binaries. */

	enum /* Magic constants to find the .reloc segment. */
	{
		START = 0x3748,
		MAGIC = 0x7ea8,
	};

	static char buf[128]; /* Must be large enough. */

	int fd, err;
	uint32_t tmp, offset, base;

	if (path == NULL)
	{
		errno = EINVAL;
		return NULL;
	}

	if ((fd = open(path, O_RDONLY)) == -1)
		return NULL;

	/* Get offset for .reloc segment. */

	if
	(
		lseek(fd, START, SEEK_SET) != START ||
		read(fd, &tmp, sizeof tmp) != sizeof tmp
	)
		goto error;

	offset = ntohl(tmp) - MAGIC;

	/* Get base for address space. */

	if
	(
		lseek(fd, offset, SEEK_SET) != offset ||
		read(fd, &tmp, sizeof tmp) != sizeof tmp
	)
		goto error;

	base = ntohl(tmp) - offset;

	/* Get offset for version_string. */

	if (read(fd, &tmp, sizeof tmp) != sizeof tmp)
		goto error;

	offset = ntohl(tmp) - base;

	/* Read version_string. */

	if
	(
		lseek(fd, offset, SEEK_SET) != offset ||
		read(fd, buf, sizeof buf) != sizeof buf
	)
		goto error;

	if (close(fd) == -1)
		return NULL;

	return buf;

error:
	err = errno;
	close(fd);
	errno = err;
	return NULL;
}


int
main(int argc, char *argv[])
{
	char *ver;

	if (argc != 2)
	{
		fprintf(stderr, "Usage: %s [PATH]\n", argv[0]);
		return EXIT_FAILURE;
	}

	if ((ver = ubootver(argv[1])) == NULL)
	{
		perror("ubootver()");
		return EXIT_FAILURE;
	}

	printf("\"%s\"\n", ver);

	return EXIT_SUCCESS;
}



More information about the U-Boot mailing list