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; }