From 2f8b44aae2827a7280dc0a8e5b46a9f33e5eea60 Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Fri, 2 Mar 2012 16:29:42 +0100 Subject: Add RKW firmware file format loader Change-Id: I5283fdcdb8d263fd9375a6d29396f82650aeb686 --- firmware/target/arm/rk27xx/rkw-loader.c | 149 ++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 firmware/target/arm/rk27xx/rkw-loader.c (limited to 'firmware/target/arm/rk27xx/rkw-loader.c') diff --git a/firmware/target/arm/rk27xx/rkw-loader.c b/firmware/target/arm/rk27xx/rkw-loader.c new file mode 100644 index 0000000000..328ad127d0 --- /dev/null +++ b/firmware/target/arm/rk27xx/rkw-loader.c @@ -0,0 +1,149 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2012 Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 1 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "rkw.h" +#include "crc32-rkw.h" +#include "file.h" +#include "panic.h" + +/* error strings sorted by number */ +/* error 0 is empty */ +static const char *err_str[] = { + "Loading OK", + "Can't open RKW file", + "Can't read RKW header", + "Invalid RKW magic number", + "RKW header CRC error", + "RKW file too big", + "RKW Load address mismatch", + "Bad model number", + "Error Reading File", + "RKW firmware CRC error" +}; + +const char *rkw_strerror(int8_t errno) +{ + if (-errno >= sizeof(err_str)/sizeof(err_str[0]) || errno > 0) + return "Unknown error"; + + return err_str[-errno]; +} + +/* loosely based on load_firmware() + * on success we return size loaded image + * on error we return negative value which can be deciphered by means + * of rkw_strerror() function + */ +int load_rkw(unsigned char* buf, const char* filename, int buffer_size) +{ + int fd; + int rc; + int len; + int ret; + uint32_t crc, fw_crc; + struct rkw_header_t rkw_info; + + fd = open(filename, O_RDONLY); + + if(fd < 0) + return -1; + + rc = read(fd, &rkw_info, sizeof(rkw_info)); + if (rc < (int)sizeof(rkw_info)) + { + ret = -2; + goto end; + } + + /* check if RKW is valid */ + if (rkw_info.magic_number != RKLD_MAGIC) + { + ret = -3; + goto end; + } + + /* check header crc if present */ + if (rkw_info.load_options & RKW_HEADER_CRC) + { + crc = crc32_rkw((uint8_t *)&rkw_info, sizeof(rkw_info)-sizeof(uint32_t)); + if (rkw_info.crc != crc) + { + ret = -4; + goto end; + } + } + + /* check image size */ + len = rkw_info.load_limit - rkw_info.load_address; + if (len > buffer_size) + { + ret = -5; + goto end; + } + + /* check load address - we support loading only at 0x60000000 */ + if (rkw_info.load_address != 0x60000000) + { + ret = -6; + goto end; + } + + /* rockbox extension - we use one of reserved fields to store + * model number information. This prevents from loading + * rockbox RKW for different player. + */ + if (rkw_info.reserved0 != 0 && rkw_info.reserved0 != MODEL_NUMBER) + { + ret = -7; + goto end; + } + + /* skip header */ + lseek(fd, sizeof(rkw_info), SEEK_SET); + + /* load image into buffer */ + rc = read(fd, buf, len); + + if(rc < len) + { + ret = -8; + goto end; + } + + if (rkw_info.load_options & RKW_IMAGE_CRC) + { + rc = read(fd, &fw_crc, sizeof(uint32_t)); + + crc = crc32_rkw((uint8_t *)buf, len); + + if (fw_crc != crc) + { + ret = -9; + goto end; + } + } + + ret = len; +end: + close(fd); + return ret; +} + -- cgit v1.2.3