diff --git a/firmware/export/config.h b/firmware/export/config.h index 87fbd97516..3ee2330879 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -352,6 +352,10 @@ Lyre prototype 1 */ #define IMX233_TQFP128 3 #define IMX233_LQFP100 4 +/* IMX233_PARTITIONS */ +#define IMX233_FREESCALE (1 << 0) /* Freescale I.MX233 nonstandard two-level MBR */ +#define IMX233_CREATIVE (1 << 1) /* Creative MBLK windowing */ + /* now go and pick yours */ #if defined(ARCHOS_PLAYER) #include "config/archosplayer.h" diff --git a/firmware/export/config/creativezenxfi3.h b/firmware/export/config/creativezenxfi3.h index de0ff8bac8..b4a328d894 100644 --- a/firmware/export/config/creativezenxfi3.h +++ b/firmware/export/config/creativezenxfi3.h @@ -3,6 +3,7 @@ */ #define IMX233_SUBTARGET 3780 #define IMX233_PACKAGE IMX233_BGA169 +#define IMX233_PARTITIONS IMX233_FREESCALE /* For Rolo and boot loader */ #define MODEL_NUMBER 83 diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h index 1c5c2e0193..e7622fa568 100644 --- a/firmware/export/config/sansafuzeplus.h +++ b/firmware/export/config/sansafuzeplus.h @@ -3,6 +3,7 @@ */ #define IMX233_SUBTARGET 3780 #define IMX233_PACKAGE IMX233_BGA169 +#define IMX233_PARTITIONS IMX233_FREESCALE /* For Rolo and boot loader */ #define MODEL_NUMBER 72 diff --git a/firmware/export/config/sonynwze360.h b/firmware/export/config/sonynwze360.h index d914c1c253..a0f05f4342 100644 --- a/firmware/export/config/sonynwze360.h +++ b/firmware/export/config/sonynwze360.h @@ -3,6 +3,7 @@ */ #define IMX233_SUBTARGET 3780 #define IMX233_PACKAGE IMX233_BGA169 +#define IMX233_PARTITIONS IMX233_FREESCALE /* For Rolo and boot loader */ #define MODEL_NUMBER 89 diff --git a/firmware/export/config/sonynwze370.h b/firmware/export/config/sonynwze370.h index 45fa289e0d..412200a4ce 100644 --- a/firmware/export/config/sonynwze370.h +++ b/firmware/export/config/sonynwze370.h @@ -3,6 +3,7 @@ */ #define IMX233_SUBTARGET 3780 #define IMX233_PACKAGE IMX233_BGA169 +#define IMX233_PARTITIONS IMX233_FREESCALE /* For Rolo and boot loader */ #define MODEL_NUMBER 88 diff --git a/firmware/target/arm/imx233/partitions-imx233.c b/firmware/target/arm/imx233/partitions-imx233.c index 06c5a48f32..ebc7b9a6e6 100644 --- a/firmware/target/arm/imx233/partitions-imx233.c +++ b/firmware/target/arm/imx233/partitions-imx233.c @@ -19,6 +19,7 @@ * ****************************************************************************/ #include "partitions-imx233.h" +#include "string.h" static bool enable_window = true; @@ -32,8 +33,79 @@ bool imx233_partitions_is_window_enabled(void) return enable_window; } -int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned *end) +#if (IMX233_PARTITIONS & IMX233_CREATIVE) +#define MBLK_MAGIC 0x4d424c4b /* MBLK */ +#define MBLK_COUNT 31 +/* MBLK is not located in the first sector ! + * Creative code uses the hard-coded *absolute* address 0x3ffe00, + * bypassing all partition related information !! + * NOTE: for some reason, the ZEN uses a different value ?! */ +#ifdef CREATIVE_ZEN +#define MBLK_ADDR 0x400000 +#else +#define MBLK_ADDR 0x3ffe00 +#endif + +struct mblk_header_t { + uint32_t magic; + uint32_t block_size; + uint64_t total_size; +} __attribute__((packed)); + +struct mblk_partition_t +{ + uint32_t size; + uint32_t start; + char name[8]; +} __attribute__((packed)); + +static const char *creative_part_name(enum imx233_part_t part) +{ + switch(part) + { + case IMX233_PART_USER: return "cfs"; + case IMX233_PART_CFS: return "cfs"; + case IMX233_PART_MINIFS: return "minifs"; + default: return ""; + } +} + +static int compute_window_creative(IF_MD(int drive,) enum imx233_part_t part, + unsigned *start, unsigned *end) +{ + uint8_t mblk[512]; + int ret = storage_read_sectors(IF_MD(drive,) MBLK_ADDR / 512, 1, mblk); + if(ret < 0) + return ret; + struct mblk_header_t *hdr = (void *)mblk; + if(hdr->magic != MBLK_MAGIC) + return -70; /* bad magic */ + struct mblk_partition_t *ent = (void *)(hdr + 1); + const char *name = creative_part_name(part); + for(int i = 0; i < MBLK_COUNT; i++) + { + if(ent[i].name[0] == 0) + continue; + if(strcmp(ent[i].name, name) == 0) + { + *start = ent[i].start * hdr->block_size / 512; + *end = *start + ent[i].size * hdr->block_size / 512; + return 0; + } + } + return -80; /* not found */ +} +#endif /* #(IMX233_PARTITIONS & IMX233_CREATIVE) */ + +#if (IMX233_PARTITIONS & IMX233_FREESCALE) +static int compute_window_freescale(IF_MD(int drive,) enum imx233_part_t part, + unsigned *start, unsigned *end) +{ + uint8_t mbr[512]; + int ret = storage_read_sectors(IF_MD(drive,) 0, 1, mbr); + if(ret < 0) + return ret; /** * Freescale uses a strange layout: is has a first MBR at sector 0 with four entries: * 1) Actual user partition @@ -54,19 +126,54 @@ int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned * it seems that it is similarly truncated. */ if(mbr[510] != 0x55 || mbr[511] != 0xAA) return -101; /* invalid MBR */ - /* sanity check that the first partition is greater than 2Gib */ - uint8_t *ent = &mbr[446]; - *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24; - /* ignore two lowest bits(see comment above) */ - *start &= ~3; - *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24); - *end &= ~3; - /* ignore two lowest bits(order is important, first truncate then add start) */ - *end += *start; - - if(ent[4] == 0x53) - return -102; /* sigmatel partition */ - if((*end - *start) < 4 * 1024 * 1024) - return -103; /* partition too small */ - return 0; + if(part == IMX233_PART_USER) + { + /* sanity check that the first partition is greater than 2Gib */ + uint8_t *ent = &mbr[446]; + *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24; + /* ignore two lowest bits(see comment above) */ + *start &= ~3; + *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24); + *end &= ~3; + /* ignore two lowest bits(order is important, first truncate then add start) */ + *end += *start; + + if(ent[4] == 0x53) + return -102; /* sigmatel partition */ + if((*end - *start) < 4 * 1024 * 1024) + return -103; /* partition too small */ + return 0; + } + else if(part == IMX233_PART_BOOT) + { + /* sanity check that the second partition is correct */ + uint8_t *ent = &mbr[462]; + if(ent[4] != 0x53) + return -104; /* wrong type */ + *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24; + *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24); + *end += *start; + + return 0; + } + else + return -50; +} +#endif /* (IMX233_PARTITIONS & IMX233_FREESCALE) */ + +int imx233_partitions_compute_window(IF_MD(int drive,) enum imx233_part_t part, + unsigned *start, unsigned *end) +{ + int ret = -1; +#if (IMX233_PARTITIONS & IMX233_CREATIVE) + ret = compute_window_creative(IF_MD(drive,) part, start, end); + if(ret >= 0) + return ret; +#endif +#if (IMX233_PARTITIONS & IMX233_FREESCALE) + ret = compute_window_freescale(IF_MD(drive,) part, start, end); + if(ret >= 0) + return ret; +#endif + return ret; } diff --git a/firmware/target/arm/imx233/partitions-imx233.h b/firmware/target/arm/imx233/partitions-imx233.h index 4490aad77f..b7ed251dee 100644 --- a/firmware/target/arm/imx233/partitions-imx233.h +++ b/firmware/target/arm/imx233/partitions-imx233.h @@ -24,10 +24,27 @@ #include "system.h" #include "storage.h" +#ifndef IMX233_PARTITIONS +#error You must define IMX233_PARTITIONS +#endif + +enum imx233_part_t +{ + IMX233_PART_USER, +#if (IMX233_PARTITIONS & IMX233_FREESCALE) + IMX233_PART_BOOT, +#endif +#if (IMX233_PARTITIONS & IMX233_CREATIVE) + IMX233_PART_CFS, + IMX233_PART_MINIFS, +#endif +}; + /* Enable/Disable window computations for internal storage following the * Freescale convention */ void imx233_partitions_enable_window(bool enable); bool imx233_partitions_is_window_enabled(void); -int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned *end); +int imx233_partitions_compute_window(IF_MD(int drive,) enum imx233_part_t part, + unsigned *start, unsigned *end); #endif /* __PARTITIONS_IMX233__ */ \ No newline at end of file diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c index a4329b1416..978e5b7247 100644 --- a/firmware/target/arm/imx233/sdmmc-imx233.c +++ b/firmware/target/arm/imx233/sdmmc-imx233.c @@ -664,12 +664,10 @@ static int init_drive(int drive) /* compute window */ if((SDMMC_FLAGS(drive) & WINDOW) && imx233_partitions_is_window_enabled()) { - uint8_t mbr[512]; - int ret = transfer_sectors(drive, 0, 1, mbr, true); - if(ret) - panicf("Cannot read MBR: %d", ret); - ret = imx233_partitions_compute_window(mbr, &window_start[drive], - &window_end[drive]); + /* NOTE: at this point the window shows the whole disk so raw disk + * accesses can be made to lookup partitions */ + ret = imx233_partitions_compute_window(IF_MD(drive,) IMX233_PART_USER, + &window_start[drive], &window_end[drive]); if(ret) panicf("cannot compute partitions window: %d", ret); SDMMC_INFO(drive).numblocks = window_end[drive] - window_start[drive];