view loadtools/flcmplboot.c @ 414:a2df77833c21

fc-loadtool: started implementing flash erase-program-boot command
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 17 Jun 2014 05:46:21 +0000
parents bf49e348576b
children b2487cfd68fd
line wrap: on
line source

/*
 * This module contains the implementation of the flash erase-program-boot
 * hack for brickable Compal phones.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "flash.h"

extern struct flash_bank_info flash_bank_info[2];
extern struct flash_cmdset flash_cmdset_intel;

static int hack_enabled;
static uint32_t boot_sector_size;
static uint32_t ram_buffer_addr;

/* called from hwparam.c config file parser */
void
set_boot_reflash_hack(arg, filename_for_errs, lineno_for_errs)
	char *arg;
	char *filename_for_errs;
	int lineno_for_errs;
{
	char *cp, *np, *ep;

	if (hack_enabled) {
		fprintf(stderr,
			"%s line %d: duplicate boot-reflash-hack setting\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	for (cp = arg; isspace(*cp); cp++)
		;
	if (!*cp || *cp == '#') {
too_few_arg:	fprintf(stderr,
		"%s line %d: boot-reflash-hack setting: too few arguments\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (!*cp)
		goto too_few_arg;
	*cp++ = '\0';
	ram_buffer_addr = strtoul(np, &ep, 16);
	if (*ep) {
invhex:		fprintf(stderr,
			"%s line %d: syntax error (hex arguments expected)\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	while (isspace(*cp))
		cp++;
	if (!*cp || *cp == '#')
		goto too_few_arg;
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	boot_sector_size = strtoul(np, &ep, 16);
	if (*ep)
		goto invhex;
	while (isspace(*cp))
		cp++;
	if (*cp && *cp != '#') {
		fprintf(stderr,
		"%s line %d: boot-reflash-hack setting: too many arguments\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	hack_enabled = 1;
}

flashcmd_erase_program_boot(argc, argv)
	char **argv;
{
	FILE *binf;
	struct stat filestat;
	size_t len;
	char *strtoul_endp;

	if (!hack_enabled) {
		fprintf(stderr,
			"Operation not applicable to this target device\n");
		return(-1);
	}
	if (argc < 3 || argc > 4) {
inv:		fprintf(stderr, "usage: %s %s binfile [length]\n",
			argv[0], argv[1]);
		return(-1);
	}
	if (flash_get_cfi(0) < 0)
		return(-1);
	if (flash_bank_info[0].geom->regions[0].sector_size
			!= boot_sector_size) {
		fprintf(stderr,
		"error: detected flash boot sector size differs from config\n");
		return(-1);
	}
	if (flash_bank_info[0].ops != &flash_cmdset_intel) {
		fprintf(stderr,
			"error: operation implemented for Intel flash only\n");
		return(-1);
	}

	binf = fopen(argv[2], "r");
	if (!binf) {
		perror(argv[2]);
		return(-1);
	}
	fstat(fileno(binf), &filestat);
	if (!S_ISREG(filestat.st_mode)) {
		fprintf(stderr, "%s is not a regular file\n", argv[2]);
		fclose(binf);
		return(-1);
	}
	if (argc > 3) {
		len = strtoul(argv[3], &strtoul_endp, 16);
		if (*strtoul_endp) {
			fclose(binf);
			goto inv;
		}
		if (len > filestat.st_size) {
			fprintf(stderr,
			    "error: specified length exceeds file length\n");
			fclose(binf);
			return(-1);
		}
	} else
		len = filestat.st_size;
	if (len > boot_sector_size) {
		fprintf(stderr, "error: length exceeds boot sector size\n");
		fclose(binf);
		return(-1);
	}


}