OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [fw.c] - Rev 4

Compare with Previous | Blame | View Log

/***************************************************************************
 *
 * (C) Copyright 2017 DFC Design, s.r.o., Brno, Czech Republic
 * Author: Marek Kvas (m.kvas@dspfpga.com)
 *
 ***************************************************************************
 *
 * This file is part of Xenia Ethernet Example project.
 * 
 * Xenia Ethernet Example project is free software: you can 
 * redistribute it and/or modify it under the terms of 
 * the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Xenia Ethernet Example project is distributed in the hope that 
 * it will be useful, but WITHOUT ANY WARRANTY; without even 
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with Xenia Ethernet Example project.  If not, 
 * see <http://www.gnu.org/licenses/>.
 *
 ***************************************************************************
 */
 
#include <stdio.h>
#include <stdlib.h>
#include "uprintf.h"
#include "fw.h"
 
/* Min/max defs */
#define MIN(A, B) (((A) > (B))?(B):(A))
#define MAX(A, B) (((A) > (B))?(A):(B))
 
/*
 * Free dynamically allocated fw_hdr_ext
 * structure.
 *
 * Function always succeeds.
 */
void fw_free_hdr_ext_ptr(struct fw_hdr_ext **s)
{
	if(*s == NULL)
		return;
	if((*s)->fw_meta_ptr != NULL)
		free((*s)->fw_meta_ptr);
	if((*s)->fw_data_ptr != NULL)
		free((*s)->fw_data_ptr);
 
	free(*s);
	*s = NULL;
}
 
/*
 * Check for presence of FW in flash and
 * dynamically allocate structure describing it.
 * FW is recognized by magic on the beginning of
 * header.
 *
 * On success, zero is returned. On error,
 * negative number is returned.
 */
 
int fw_find_in_flash(struct spansion_flash *sf, uint32_t fw_hdr_flash_offset, struct fw_hdr_ext **fw_hdr_ext_ptr)
{
	int i;
	int res;
	int ret = 0;
	uint8_t rd_buf[SPANSION_FLASH_PAGE_SIZE + SPANSION_FLASH_BUF_OVERHEAD +1];
	struct fw_hdr_ext *fhe;
	uint8_t *dst;
	int byte_count;
	uint32_t flash_addr;
 
	/* Allocate space for structure */
	fhe = malloc(sizeof(*fhe));
	if(fhe == NULL) {
		ret = -1; goto err;
	}
	fhe->fw_hdr_flash_off = fw_hdr_flash_offset;
 
	/* Read FW header */
	res = spansion_flash_quad_io_read(sf, fhe->fw_hdr_flash_off,
			rd_buf, sizeof(fhe->fw_hdr));
	if(res != XST_SUCCESS) {
		ret = -3; goto err;
	}
	/* Copy header from buffer */
	memcpy(&fhe->fw_hdr, rd_buf+SPANSION_FLASH_BUF_OVERHEAD, sizeof(fhe->fw_hdr)); /* be careful about offset */
	/* Check magic */
	if(strncmp("MVFW", fhe->fw_hdr.magic, 4)) {
		ret = -4; goto err;
	}
 
	/* Read metadata from header (allocate memory for it)*/
	i = fhe->fw_hdr.fw_offset - sizeof(struct fw_hdr);
 
	fhe->fw_meta_ptr = malloc(i + 1);
	if(fhe->fw_meta_ptr == NULL) {
		ret = -5; goto err;
	}
	dst = fhe->fw_meta_ptr;
	flash_addr = fhe->fw_hdr_flash_off;
 
	while (i > 0) {
		byte_count = MIN(i, SPANSION_FLASH_PAGE_SIZE);
		res = spansion_flash_quad_io_read(sf, flash_addr, rd_buf, byte_count);
		if(res != XST_SUCCESS) {
			ret = -6; goto err;
		}
		memcpy(dst, rd_buf + SPANSION_FLASH_BUF_OVERHEAD, byte_count);
		dst += byte_count;
		flash_addr += byte_count;
		i-= byte_count;
	}
	*dst = '\0';
 
	*fw_hdr_ext_ptr = fhe;
	return ret;
err:
	fw_free_hdr_ext_ptr(&fhe);
	return ret;
}
 
void fw_print_info(struct fw_hdr_ext *fhe)
{
	uprintf("FW header at: 0x%08x\r\n", fhe->fw_hdr_flash_off);
	uprintf("FW at: 0x%08x (offset 0x%08x)\r\n", fhe->fw_hdr_flash_off + fhe->fw_hdr.fw_offset,
			fhe->fw_hdr.fw_offset);
	uprintf("FW length: %u B\r\n", fhe->fw_hdr.fw_length);
}
 
/*
 * Read FW described by fw_hdr_ext_ptr.
 * Buffer for FW is dynamically allocated.
 *
 * On success, zero is returned. On error,
 * negative number is returned.
 */
int fw_read_from_flash(struct spansion_flash *sf, struct fw_hdr_ext *fw_hdr_ext_ptr)
{
	int i;
	int res;
	uint8_t rd_buf[SPANSION_FLASH_PAGE_SIZE + SPANSION_FLASH_BUF_OVERHEAD +1];
	u8 *dst;
	int byte_count;
	uint32_t flash_addr;
 
	/* Allocate memory for buffer */
	fw_hdr_ext_ptr->fw_data_ptr = malloc(fw_hdr_ext_ptr->fw_hdr.fw_length);
	if(fw_hdr_ext_ptr->fw_data_ptr == NULL)
		return -1;
 
	/* Read whole fw */
	i = fw_hdr_ext_ptr->fw_hdr.fw_length;
	dst = fw_hdr_ext_ptr->fw_data_ptr;
	flash_addr = fw_hdr_ext_ptr->fw_hdr_flash_off + fw_hdr_ext_ptr->fw_hdr.fw_offset;
	byte_count = 0;
	while (i > 0) {
		byte_count = MIN(i, SPANSION_FLASH_PAGE_SIZE);
		res = spansion_flash_quad_io_read(sf, flash_addr, rd_buf, byte_count);
		if(res != XST_SUCCESS) {
			return -2;
		}
		memcpy(dst, rd_buf + SPANSION_FLASH_BUF_OVERHEAD, byte_count);
		dst += byte_count;
		flash_addr += byte_count;
		i-= byte_count;
	}
 
	return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.