diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 4947f30695..0a1ceee2e0 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -129,6 +129,10 @@ #include "talk.h" +#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) +#include "bootdata.h" +#endif + static const char* threads_getname(int selected_item, void *data, char *buffer, size_t buffer_len) { @@ -2539,7 +2543,30 @@ static bool dbg_skin_engine(void) } #endif +#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) +static bool dbg_boot_data(void) +{ + unsigned int crc = 0; + struct simplelist_info info; + info.scroll_all = true; + simplelist_info_init(&info, "Boot data", 1, NULL); + simplelist_set_line_count(0); + simplelist_addline("Magic: %.8s", boot_data.magic); + simplelist_addline("Length: %lu", boot_data.length); + simplelist_addline("CRC: %lx", boot_data.crc); + crc = crc_32(boot_data.payload, boot_data.length, 0xffffffff); + (crc == boot_data.crc) ? simplelist_addline("CRC: OK!") : + simplelist_addline("CRC: BAD"); + for (unsigned i = 0; i < boot_data.length; i += 4) + { + simplelist_addline("%02x: %02x %02x %02x %02x", i, boot_data.payload[i], + boot_data.payload[i+1], boot_data.payload[i+2], boot_data.payload[i+3]); + } + info.hide_selection = true; + return simplelist_show_list(&info); +} +#endif /****** The menu *********/ static const struct { unsigned char *desc; /* string or ID */ @@ -2652,6 +2679,9 @@ static const struct { {"Debug scrollwheel", dbg_scrollwheel }, #endif {"Talk engine stats", dbg_talk }, +#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) + {"Boot data", dbg_boot_data }, +#endif }; static int menu_action_callback(int btn, struct gui_synclist *lists) diff --git a/firmware/common/rb-loader.c b/firmware/common/rb-loader.c index 10807f9c96..82b636d451 100644 --- a/firmware/common/rb-loader.c +++ b/firmware/common/rb-loader.c @@ -25,6 +25,54 @@ #include "rb-loader.h" #include "loader_strerror.h" +#if defined(HAVE_BOOTDATA) +#include "bootdata.h" +#include "crc32.h" + +/* Write boot data into location marked by magic header + * buffer is already loaded with the firmware image + * we just need to find the location and write + * data into the payload along with the crc + * for later verification and use. + * Returns payload len on success, + * On error returns EKEY_NOT_FOUND + */ +static int write_bootdata(unsigned char* buf, int len, unsigned int boot_volume) +{ + struct boot_data_t bl_boot_data; + struct boot_data_t *fw_boot_data = NULL; + int search_len = MIN(len, BOOT_DATA_SEARCH_SIZE) - sizeof(struct boot_data_t); + int payload_len = EKEY_NOT_FOUND; + + /* search for boot data header prior to search_len */ + for(int i = 0;i < search_len;i++) + { + fw_boot_data = (struct boot_data_t*) &buf[i]; + if (fw_boot_data->magic[0] != BOOT_DATA_MAGIC0 || + fw_boot_data->magic[1] != BOOT_DATA_MAGIC1) + continue; + /* 0 fill bootloader struct then add our data */ + memset(&bl_boot_data.payload, 0, BOOT_DATA_PAYLOAD_SIZE); + bl_boot_data.boot_volume = boot_volume; + /* 0 fill payload region in firmware */ + memset(fw_boot_data->payload, 0, fw_boot_data->length); + /* determine maximum bytes we can write to firmware + BOOT_DATA_PAYLOAD_SIZE is the size the bootloader expects */ + payload_len = MIN(BOOT_DATA_PAYLOAD_SIZE, fw_boot_data->length); + /* write payload size back to firmware struct */ + fw_boot_data->length = payload_len; + /* copy data to firmware bootdata struct */ + memcpy(fw_boot_data->payload, &bl_boot_data.payload, payload_len); + /* calculate and write the crc for the payload */ + fw_boot_data->crc = crc_32(fw_boot_data->payload, + payload_len, + 0xffffffff); + break; + + } + return payload_len; +} +#endif /* HAVE_BOOTDATA */ /* Load firmware image in a format created by add method of tools/scramble * on success we return size loaded image * on error we return negative value which can be deciphered by means @@ -105,11 +153,14 @@ int load_firmware(unsigned char* buf, const char* firmware, int buffer_size) ret = EBAD_CHKSUM; goto end; } - +#ifdef HAVE_BOOTDATA + /* 0 is the default boot volume */ + write_bootdata(buf, ret, 0); +#endif ret = len; + end: close(fd); return ret; } - diff --git a/firmware/export/bootdata.h b/firmware/export/bootdata.h new file mode 100644 index 0000000000..322d50c20d --- /dev/null +++ b/firmware/export/bootdata.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 by Amaury Pouly + * + * 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 2 + * 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. + * + ****************************************************************************/ +#ifndef __RB_BOOTDATA__ +#define __RB_BOOTDATA__ + +#ifndef __ASSEMBLER__ +#include +#endif + +/* /!\ This file can be included in assembly files /!\ */ + +/** The boot data will be filled by the bootloader with information that might + * be relevant for Rockbox. The bootloader will search for the structure using + * the magic header within the first BOOT_DATA_SEARCH_SIZE bytes of the binary. + * Typically, this structure should be as close as possible to the entry point */ + +/* Search size for the data structure after entry point */ +#define BOOT_DATA_SEARCH_SIZE 1024 + +#define BOOT_DATA_MAGIC0 ('r' | 'b' << 8 | 'm' << 16 | 'a' << 24) +#define BOOT_DATA_MAGIC1 ('g' | 'i' << 8 | 'c' << 16 | '!' << 24) + +/* maximum size of payload */ +#define BOOT_DATA_PAYLOAD_SIZE 4 + +#ifndef __ASSEMBLER__ +/* This is the C structure */ +struct boot_data_t +{ + union + { + uint32_t crc; /* crc of payload data (CRC32 with 0xffffffff for initial value) */ + uint32_t magic[2]; /* BOOT_DATA_MAGIC0/1 */ + }; + + uint32_t length; /* length of the payload */ + + /* add fields here */ + union + { + struct + { + uint8_t boot_volume; + }; + uint8_t payload[BOOT_DATA_PAYLOAD_SIZE]; + }; +} __attribute__((packed)); + +#if !defined(BOOTLOADER) +extern struct boot_data_t boot_data; +#endif +#else /* __ASSEMBLER__ */ + +/* This assembler macro implements an empty boot structure with just the magic + * string */ +.macro put_boot_data_here +.global boot_data +boot_data: + .word BOOT_DATA_MAGIC0 + .word BOOT_DATA_MAGIC1 + .word BOOT_DATA_PAYLOAD_SIZE + .space BOOT_DATA_PAYLOAD_SIZE, 0xff /* payload, initialised with value 0xff */ +.endm + +#endif + +#endif /* __RB_BOOTDATA__ */ diff --git a/firmware/export/config/creativezen.h b/firmware/export/config/creativezen.h index 3667142791..0033b7d4eb 100644 --- a/firmware/export/config/creativezen.h +++ b/firmware/export/config/creativezen.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 90 #define MODEL_NAME "Creative Zen" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/creativezenxfi2.h b/firmware/export/config/creativezenxfi2.h index 5b275b1de8..3945311e29 100644 --- a/firmware/export/config/creativezenxfi2.h +++ b/firmware/export/config/creativezenxfi2.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 82 #define MODEL_NAME "Creative Zen X-Fi2" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/creativezenxfi3.h b/firmware/export/config/creativezenxfi3.h index 0503035914..d72b41d608 100644 --- a/firmware/export/config/creativezenxfi3.h +++ b/firmware/export/config/creativezenxfi3.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 83 #define MODEL_NAME "Creative Zen X-Fi3" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/samsungypz5.h b/firmware/export/config/samsungypz5.h index 08b607741c..882acc2a6c 100644 --- a/firmware/export/config/samsungypz5.h +++ b/firmware/export/config/samsungypz5.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 84 #define MODEL_NAME "Samsung YP-Z5" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h index 03d6c00b2e..af5235a6c3 100644 --- a/firmware/export/config/sansafuzeplus.h +++ b/firmware/export/config/sansafuzeplus.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 72 #define MODEL_NAME "Sandisk Sansa Fuze+" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/sonynwze360.h b/firmware/export/config/sonynwze360.h index dc466ec797..a25e95d274 100644 --- a/firmware/export/config/sonynwze360.h +++ b/firmware/export/config/sonynwze360.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 89 #define MODEL_NAME "Sony NWZ-E360 series" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/export/config/sonynwze370.h b/firmware/export/config/sonynwze370.h index 0f88d98b58..2ed87f2f1b 100644 --- a/firmware/export/config/sonynwze370.h +++ b/firmware/export/config/sonynwze370.h @@ -8,6 +8,8 @@ /* For Rolo and boot loader */ #define MODEL_NUMBER 88 #define MODEL_NAME "Sony NWZ-E370/E380 series" +/* Define if boot data from bootloader has been enabled for the target */ +#define HAVE_BOOTDATA #define HW_SAMPR_CAPS SAMPR_CAP_ALL diff --git a/firmware/target/arm/imx233/crt0.S b/firmware/target/arm/imx233/crt0.S index 5e1720c7c9..8db8400dbf 100644 --- a/firmware/target/arm/imx233/crt0.S +++ b/firmware/target/arm/imx233/crt0.S @@ -21,6 +21,10 @@ #include "config.h" #include "cpu.h" +#if defined(HAVE_BOOTDATA) && !defined(BOOTLOADER) +#include "bootdata.h" +#endif + .section .vectors,"ax",%progbits .code 32 /* most handlers are in DRAM which is too far away for a relative jump */ @@ -165,6 +169,11 @@ remap: 1: b 1b +#if defined(HAVE_BOOTDATA) && !defined(BOOTLOADER) +/* boot data structure */ +put_boot_data_here +#endif + /* Cache-align interrupt stacks */ .balign 32 /* 256 words of IRQ stack */