Exemple #1
0
char *bootloader_env_get(const char *name)
{
	int lock;
	char *value = NULL;
	char *var;

	lock = lock_uboot_env();
	if (lock < 0)
		return NULL;

	if (fw_env_open (fw_env_opts)) {
		ERROR("Error: environment not initialized, %s", strerror(errno));
		unlock_uboot_env(lock);
		return NULL;
	}

	var = fw_getenv((char *)name);
	if (var)
		value = strdup(var);

	fw_env_close (fw_env_opts);

	unlock_uboot_env(lock);

	return value;
}
Exemple #2
0
static uint32_t get_memsize_from_env(void)
{
	int memsize = 0;
	char *p;

	p = fw_getenv("memsize");
	if (p)
		memsize = memparse(p, NULL);

	return memsize;
}
Exemple #3
0
static void activate_context(struct modemdata *data, const char *objpath)
{
	GError *err = NULL;
	data->context = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
			G_DBUS_PROXY_FLAGS_NONE,
			NULL,
			OFONO_SERVICE,
			objpath, /* FIXME */
			OFONO_CONTEXT_INTERFACE,
			NULL, &err);
	if (err) {
		g_warning("no proxy for context: %s\n", err->message);
		g_error_free(err);
		return;
	}
	strcpy(ipv4.gateway, "0.0.0.0");
	g_signal_connect(data->context, "g-signal", G_CALLBACK(context_signal_cb), data);
	get_process_props(data->context, data, check_context_prop);
	if (!data->context_active) {
		char *apn = fw_getenv("pongo_apn");
		char *apn_user = fw_getenv("pongo_apn_user");
		char *apn_passwd = fw_getenv("pongo_apn_pw");
		if (!apn)
			apn = "internet";
		if (strlen(apn) < 2) {
			g_free(apn);
			apn = "internet";
		}
		set_proxy_property(data->context, "AccessPointName", g_variant_new_string(apn));
		if (apn_user)
			set_proxy_property(data->context, "Username", g_variant_new_string(apn_user));
		if (apn_passwd)
			set_proxy_property(data->context, "Password", g_variant_new_string(apn_passwd));
		set_proxy_property(data->context, "Active", g_variant_new_boolean(TRUE));
	}
}
Exemple #4
0
unsigned long fw_getenvl(char *envname)
{
	unsigned long envl = 0UL;
	char *str;
	int tmp;

	str = fw_getenv(envname);
	if (str) {
		tmp = kstrtoul(str, 0, &envl);
		if (tmp)
			envl = 0;
	}

	return envl;
}
Exemple #5
0
static void __init console_config(void)
{
	char console_string[40];
	int baud = 0;
	char parity = '\0', bits = '\0', flow = '\0';
	char *s;

	s = fw_getenv("modetty0");
	if (s) {
		while (*s >= '0' && *s <= '9')
			baud = baud*10 + *s++ - '0';
		if (*s == ',')
			s++;
		if (*s)
			parity = *s++;
		if (*s == ',')
			s++;
		if (*s)
			bits = *s++;
		if (*s == ',')
			s++;
		if (*s == 'h')
			flow = 'r';
	}
	if (baud == 0)
		baud = 38400;
	if (parity != 'n' && parity != 'o' && parity != 'e')
		parity = 'n';
	if (bits != '7' && bits != '8')
		bits = '8';
	if (flow == '\0')
		flow = 'r';

	if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
		sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
			parity, bits);
		setup_early_serial8250_console(console_string);
	}

	if ((strstr(fw_getcmdline(), "console=")) == NULL) {
		sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
			parity, bits, flow);
		strcat(fw_getcmdline(), console_string);
		pr_info("Config serial console:%s\n", console_string);
	}
}
Exemple #6
0
fw_memblock_t * __init fw_getmdesc(void)
{
	char *memsize_str, *ptr;
	unsigned int memsize;
	static char cmdline[COMMAND_LINE_SIZE] __initdata;
	long val;
	int tmp;

	/* otherwise look in the environment */
	memsize_str = fw_getenv("memsize");
	if (!memsize_str) {
		pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
		physical_memsize = 0x02000000;
	} else {
		tmp = kstrtol(memsize_str, 0, &val);
		physical_memsize = (unsigned long)val;
	}

#ifdef CONFIG_CPU_BIG_ENDIAN
	/* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
	   word of physical memory */
	physical_memsize -= PAGE_SIZE;
#endif

	/* Check the command line for a memsize directive that overrides
	   the physical/default amount */
	strcpy(cmdline, arcs_cmdline);
	ptr = strstr(cmdline, "memsize=");
	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
		ptr = strstr(ptr, " memsize=");

	if (ptr)
		memsize = memparse(ptr + 8, &ptr);
	else
		memsize = physical_memsize;

	memset(mdesc, 0, sizeof(mdesc));

	mdesc[0].type = fw_dontuse;
	mdesc[0].base = 0x00000000;
	mdesc[0].size = 0x00001000;

	mdesc[1].type = fw_code;
	mdesc[1].base = 0x00001000;
	mdesc[1].size = 0x000ef000;

	/*
	 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
	 * south bridge and PCI access always forwarded to the ISA Bus and
	 * BIOSCS# is always generated.
	 * This mean that this area can't be used as DMA memory for PCI
	 * devices.
	 */
	mdesc[2].type = fw_dontuse;
	mdesc[2].base = 0x000f0000;
	mdesc[2].size = 0x00010000;

	mdesc[3].type = fw_dontuse;
	mdesc[3].base = 0x00100000;
	mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
		mdesc[3].base;

	mdesc[4].type = fw_free;
	mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
	mdesc[4].size = memsize - mdesc[4].base;

	return &mdesc[0];
}
// command line args come from, in decreasing precedence:
//   - the actual command line
//   - the bootloader control block (one per line, after "recovery")
//   - the contents of COMMAND_FILE (one per line)
static void
get_args(int *argc, char ***argv) {
    struct bootloader_message boot;
    memset(&boot, 0, sizeof(boot));
    get_bootloader_message(&boot);  // this may fail, leaving a zeroed structure

    if (boot.command[0] != 0 && boot.command[0] != 255) {
        LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command);
    }

    if (boot.status[0] != 0 && boot.status[0] != 255) {
        LOGI("Boot status: %.*s\n", sizeof(boot.status), boot.status);
    }

    // --- if arguments weren't supplied, look in the bootloader control block
    if (*argc <= 1) {
        boot.recovery[sizeof(boot.recovery) - 1] = '\0';  // Ensure termination
        const char *arg = strtok(boot.recovery, "\n");
        if (arg != NULL && !strcmp(arg, "recovery")) {
            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
            (*argv)[0] = strdup(arg);
            for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
                if ((arg = strtok(NULL, "\n")) == NULL) break;
                (*argv)[*argc] = strdup(arg);
            }
            LOGI("Got arguments from boot message\n");
        } else if (boot.recovery[0] != 0 && boot.recovery[0] != 255) {
            LOGE("Bad boot message\n\"%.20s\"\n", boot.recovery);
        }
    }

	// --- if that doesn't work, try the command file form bootloader:recovery_command
	if (*argc <= 1) {
    char *parg = NULL;
		char *recovery_command = fw_getenv ("recovery_command");
        if (recovery_command != NULL && strcmp(recovery_command, "")) {
            char *argv0 = (*argv)[0];
            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
            (*argv)[0] = argv0;  // use the same program name

            char buf[MAX_ARG_LENGTH];
			strcpy(buf, recovery_command);
			
			if((parg = strtok(buf, "#")) == NULL){
				LOGE("Bad bootloader arguments\n\"%.20s\"\n", recovery_command);
			}else{
				(*argv)[1] = strdup(parg);  // Strip newline.
				for (*argc = 2; *argc < MAX_ARGS; ++*argc) {
					if((parg = strtok(NULL, "#")) == NULL){
						break;
					}else{
						(*argv)[*argc] = strdup(parg);  // Strip newline.
					}
            	}
            	LOGI("Got arguments from bootloader\n");
			}
            
        } else {
            LOGE("Bad bootloader arguments\n\"%.20s\"\n", recovery_command);
        }
    }
	
    // --- if that doesn't work, try the command file
    char * temp_args =NULL;
    if (*argc <= 1) {
        FILE *fp = fopen_path(COMMAND_FILE, "r");
        if (fp != NULL) {
            char *argv0 = (*argv)[0];
            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
            (*argv)[0] = argv0;  // use the same program name

            char buf[MAX_ARG_LENGTH];
            for (*argc = 1; *argc < MAX_ARGS; ) {
                if (!fgets(buf, sizeof(buf), fp)) break;
			temp_args = strtok(buf, "\r\n");
			if(temp_args == NULL)  continue;
	       		(*argv)[*argc]  = strdup(temp_args);   // Strip newline.      
                		++*argc;
            }

            check_and_fclose(fp, COMMAND_FILE);
            LOGI("Got arguments from %s\n", COMMAND_FILE);
        }
    }

    // -- sleep 1 second to ensure SD card initialization complete
    usleep(1000000);

    // --- if that doesn't work, try the sdcard command file
    if (*argc <= 1) {
        FILE *fp = fopen_path(SDCARD_COMMAND_FILE, "r");
        if (fp != NULL) {
            char *argv0 = (*argv)[0];
            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
            (*argv)[0] = argv0;  // use the same program name

            char buf[MAX_ARG_LENGTH];
            for (*argc = 1; *argc < MAX_ARGS; ) {
                if (!fgets(buf, sizeof(buf), fp)) break;
			temp_args = strtok(buf, "\r\n");
			if(temp_args == NULL)  continue;
	       		(*argv)[*argc]  = strdup(temp_args);   // Strip newline.      
                		++*argc;
            }

            check_and_fclose(fp, SDCARD_COMMAND_FILE);
            LOGI("Got arguments from %s\n", SDCARD_COMMAND_FILE);
        }
    }

    // --- if that doesn't work, try the udisk command file
    if (*argc <= 1) {
        FILE *fp = fopen_path(UDISK_COMMAND_FILE, "r");
        if (fp != NULL) {
            char *argv0 = (*argv)[0];
            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
            (*argv)[0] = argv0;  // use the same program name

            char buf[MAX_ARG_LENGTH];
            for (*argc = 1; *argc < MAX_ARGS; ) {
                if (!fgets(buf, sizeof(buf), fp)) break;
			temp_args = strtok(buf, "\r\n");
			if(temp_args == NULL)  continue;
	       		(*argv)[*argc]  = strdup(temp_args);   // Strip newline.      
                		++*argc;
            }

            check_and_fclose(fp, UDISK_COMMAND_FILE);
            LOGI("Got arguments from %s\n", UDISK_COMMAND_FILE);
        }
    }

    // --- if no argument, then force show_text
    if (*argc <= 1) {
        char *argv0 = (*argv)[0];
        *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
        (*argv)[0] = argv0;  // use the same program name
        (*argv)[1] = "--show_text";
        *argc = 2;
    }

    // --> write the arguments we have back into the bootloader control block
    // always boot into recovery after this (until finish_recovery() is called)
    strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
    strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
    int i;
    for (i = 1; i < *argc; ++i) {
        strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery));
        strlcat(boot.recovery, "\n", sizeof(boot.recovery));
    }
    set_bootloader_message(&boot);
}
Exemple #8
0
static void __init append_memory(void *fdt, int root_off)
{
	__be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
	unsigned long memsize;
	unsigned mem_entries;
	int i, err, mem_off;
	enum mem_map mem_map;
	u32 config;
	char *var, param_name[10], *var_names[] = {
		"ememsize", "memsize",
	};

	/* if a memory node already exists, leave it alone */
	mem_off = fdt_path_offset(fdt, "/memory");
	if (mem_off >= 0)
		return;

	/* find memory size from the bootloader environment */
	for (i = 0; i < ARRAY_SIZE(var_names); i++) {
		var = fw_getenv(var_names[i]);
		if (!var)
			continue;

		err = kstrtoul(var, 0, &physical_memsize);
		if (!err)
			break;

		pr_warn("Failed to read the '%s' env variable '%s'\n",
			var_names[i], var);
	}

	if (!physical_memsize) {
		pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
		physical_memsize = 32 << 20;
	}

	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
		/*
		 * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
		 * the last word of physical memory.
		 */
		physical_memsize -= PAGE_SIZE;
	}

	/* default to using all available RAM */
	memsize = physical_memsize;

	/* allow the user to override the usable memory */
	for (i = 0; i < ARRAY_SIZE(var_names); i++) {
		snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
		var = strstr(arcs_cmdline, param_name);
		if (!var)
			continue;

		memsize = memparse(var + strlen(param_name), NULL);
	}

	/* if the user says there's more RAM than we thought, believe them */
	physical_memsize = max_t(unsigned long, physical_memsize, memsize);

	/* detect the memory map in use */
	if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
		/* ROCit has a register indicating the memory map in use */
		config = readl((void __iomem *)CKSEG1ADDR(ROCIT_CONFIG_GEN1));
		mem_map = config & ROCIT_CONFIG_GEN1_MEMMAP_MASK;
		mem_map >>= ROCIT_CONFIG_GEN1_MEMMAP_SHIFT;
	} else {
Exemple #9
0
fw_memblock_t * __init fw_getmdesc(int eva)
{
	char *memsize_str, *ememsize_str = NULL, *ptr;
	unsigned long memsize = 0, ememsize = 0;
	static char cmdline[COMMAND_LINE_SIZE] __initdata;
	int tmp;

	/* otherwise look in the environment */

	memsize_str = fw_getenv("memsize");
	if (memsize_str)
		tmp = kstrtol(memsize_str, 0, &memsize);
	if (eva) {
	/* Look for ememsize for EVA */
		ememsize_str = fw_getenv("ememsize");
		if (ememsize_str)
			tmp = kstrtol(ememsize_str, 0, &ememsize);
	}
	if (!memsize && !ememsize) {
		pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
		physical_memsize = 0x02000000;
	} else {
		/* If ememsize is set, then set physical_memsize to that */
		physical_memsize = ememsize ? : memsize;
	}

#ifdef CONFIG_CPU_BIG_ENDIAN
	/* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
	   word of physical memory */
	physical_memsize -= PAGE_SIZE;
#endif

	/* Check the command line for a memsize directive that overrides
	   the physical/default amount */
	strcpy(cmdline, arcs_cmdline);
	ptr = strstr(cmdline, "memsize=");
	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
		ptr = strstr(ptr, " memsize=");
	/* And now look for ememsize */
	if (eva) {
		ptr = strstr(cmdline, "ememsize=");
		if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
			ptr = strstr(ptr, " ememsize=");
	}

	if (ptr)
		memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
	else
		memsize = physical_memsize;

	/* Last 64K for HIGHMEM arithmetics */
	if (memsize > 0x7fff0000)
		memsize = 0x7fff0000;

	memset(mdesc, 0, sizeof(mdesc));

	mdesc[0].type = fw_dontuse;
	mdesc[0].base = PHYS_OFFSET;
	mdesc[0].size = 0x00001000;

	mdesc[1].type = fw_code;
	mdesc[1].base = mdesc[0].base + 0x00001000UL;
	mdesc[1].size = 0x000ef000;

	/*
	 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
	 * south bridge and PCI access always forwarded to the ISA Bus and
	 * BIOSCS# is always generated.
	 * This mean that this area can't be used as DMA memory for PCI
	 * devices.
	 */
	mdesc[2].type = fw_dontuse;
	mdesc[2].base = mdesc[0].base + 0x000f0000UL;
	mdesc[2].size = 0x00010000;

	mdesc[3].type = fw_dontuse;
	mdesc[3].base = mdesc[0].base + 0x00100000UL;
	mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
		0x00100000UL;

	mdesc[4].type = fw_free;
	mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
	mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);

	return &mdesc[0];
}
Exemple #10
0
static int switch_to_sd_bootargs(void)
{
    char startName[32];
    char sizeName[32];
    char c;
    char bootcmd[1024];
    char bootargs[1024];
    char bootcmdName[16];
    char bootargsName[16];
    
    strncpy(startName, "kernel_start",31);
    strncpy(sizeName, "kernel_size",31);
    if (fw_getenv(startName) && fw_getenv(sizeName)) {
        strncpy(startName,"rootfs_start",31);
        strncpy(sizeName,"rootfs_size",31);
        if (fw_getenv(startName) && fw_getenv(sizeName)) {
            c = 0;
        } else {
            c = 1;
        }
    } else {
        strncpy(startName,"rootfs_start",31);
        strncpy(sizeName,"rootfs_size",31);
        if (fw_getenv(startName) && fw_getenv(sizeName)) {
            c = 2;
        } else {
            ERROR("No uboot vars for backup firmware booting");
            return -1;
        }
    }
    
    if (fw_env_open()) {
        ERROR("Failed calling fw_env_open");
        return -1;
    }
    
    switch (c) {
        case 0:
            strncpy(bootcmd,sdbootcmd,1023);
            strncpy(bootargs,sdbootargs,1023);
            break;
        case 1:
            strncpy(bootcmd,sdbootcmdkernel,1023);
            strncpy(bootargs,sdbootargskernel,1023);
            break;
        case 2:
            strncpy(bootcmd,sdbootcmdrootfs,1023);
            strncpy(bootargs,sdbootargsrootfs,1023);
            break;
        default:
            return -1;
    }
    
    strncpy(bootcmdName,"bootcmd",15);
    strncpy(bootargsName,"bootargs",15);
    
    if (fw_env_write(bootcmdName,bootcmd) || fw_env_write(bootargsName,bootargs)) {
        ERROR("Error writing sd backup boot vars to uboot");
        return -1;
    }
    
    if(fw_env_close()) {
        ERROR("Error calling fw_env_close");
        return -1;
    }
    
    return 0;
    
}
Exemple #11
0
static int sd_write_image(int mtdnum, struct img_type *img)
{
    char startName[32];
    char sizeName[32];
    char *value;
    int fdout = -1;
    FILE* fp = NULL;
    char line[512]; //size of a block
    long long startBlock, sizeInBlocks, kernelStartBlock, kernelBlocks;
    ssize_t bytesWritten,bytesRead, totalBytesWritten;
    int blocksWritten;
    int ret = 0;
    unsigned long offs;
    off_t pos;
    struct flash_description *flash = get_flash_info();
    struct mtd_dev_info *mtd1, *mtd2;
    mtd2 = &flash->mtd_info[2].mtd;
    mtd1 = &flash->mtd_info[1].mtd;
    
    if (1 == mtdnum) {
        strncpy(sizeName,"kernel_size",31);
    } else if (2 == mtdnum) { //rootfs
        strncpy(sizeName,"rootfs_size",31);
    } else {
        return 0;
    }
    
    pos = lseek(img->fdin,0,SEEK_CUR);
    if (pos < 0) {
        ERROR( "%s: %s: %s", __func__, "lseek failed\n", strerror(errno));
        return -1;
    }
    
    //attempt to write firmware to backup sd partition, if it doesn't have backup fw already
    value = fw_getenv(sizeName);
    if (!value) {
        if ((fdout = open("/dev/mmcblk0p2", O_WRONLY)) < 0) {
            ERROR( "%s: %s: %s", __func__, "/dev/mmcblk0p2", strerror(errno));
            ret = -1;
            goto err;
        }
        
        fp = popen("fdisk -ul /dev/mmcblk0 | grep /dev/mmcblk0p2 | awk '{print $2}'","r");
        if (fp == NULL) {
            ERROR( "%s: %s: %s", __func__, "popen", strerror(errno));
            ret = -1;
            goto err;
        }
        if (NULL == fgets(line,511,fp)) {
            ERROR( "%s: %s: %s", __func__, "fgets from popen'd file pointer", strerror(errno));
            ret = -1;
            goto err;
        }
        kernelStartBlock = strtoll(line,NULL,10);
        if (kernelStartBlock == 0) {
            ERROR( "%s: %s: %s", __func__, "kernel start block is 0\n", strerror(errno));
            ret = -1;
            goto err;
        }
        
        kernelBlocks = ((mtd1->size) % 512 == 0) ? (mtd1->size)/512 : (mtd1->size)/512 + 1;
        
        if (1 == mtdnum) {
            startBlock = kernelStartBlock;
            sizeInBlocks = kernelBlocks;
            strncpy(startName,"kernel_start",31);
            offs = 0;
        } else {
            startBlock = kernelStartBlock + kernelBlocks;
            sizeInBlocks = ((mtd2->size) % 512 == 0) ? (mtd2->size)/512 : (mtd2->size)/512 + 1;
            strncpy(startName,"rootfs_start",31);
            offs = kernelBlocks * 512;
        }
        
        if (lseek(fdout,offs,SEEK_SET) < 0) {
            ERROR( "%s: %s: %s", __func__, "lseek error", strerror(errno));
            ret = -1;
            goto err;
        }
        
        TRACE("Copying %s to backup SD partition.",img->fname);
    
        totalBytesWritten = 0;
        blocksWritten = 0;
        while ((bytesRead = read(img->fdin,line,512)) > 0) {
            memset(line + bytesRead,0,512-bytesRead);
            bytesWritten = write(fdout,line,512);
            if (bytesWritten != 512) {
                ERROR("Did not write a complete block to SD\n");
                ret = -1;
                goto err;
            }
            totalBytesWritten += bytesWritten;
            blocksWritten++;
        }
        
        if (0 == ret) {
            if (fw_env_open()) {
                ERROR("Failure calling fw_env_open");
                ret = -1;
                goto err;
            }
            
            snprintf(line,511,"0x%llx",startBlock);
            if (fw_env_write(startName,line)) {
                ERROR("Failure calling fw_env_write");
                ret = -1;
                goto err;
            }
            
            snprintf(line,511,"0x%llx",sizeInBlocks);
            if (fw_env_write(sizeName,line)) {
                ERROR("Failure calling fw_env_write");
                ret = -1;
                goto err;
            }
            
            if (fw_env_close()) {
                ERROR("Failure calling fw_env_close");
                ret = -1;
                goto err;
            }
        }
            
        
        TRACE("kernelStartBlock: %lld, kernelBlocks: %lld, startblock: %lld, blocks: %lld, ret: %d, totalBytesWritten: %zd, blocksWritten: %d\n",kernelStartBlock,kernelBlocks,startBlock,sizeInBlocks,ret,totalBytesWritten,blocksWritten);

    }
    
err:
    //restore img->fdin. If we fail here, we give a special error code because we absolutely cannot proceed in this error case (will probably result in corrupt serial flash firmware)
    if (lseek(img->fdin,pos,SEEK_SET) < 0) {
        ERROR( "%s: %s: %s", __func__, "lseek error", strerror(errno));
        ret = -2;
    }

    if (fdout >= 0) {close(fdout);}
    if (fp) {pclose(fp);}
    
    return ret;
}