summaryrefslogtreecommitdiffstats
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/imx233/mmc-imx233.c44
-rw-r--r--firmware/target/arm/imx233/partitions-imx233.c72
-rw-r--r--firmware/target/arm/imx233/partitions-imx233.h33
3 files changed, 119 insertions, 30 deletions
diff --git a/firmware/target/arm/imx233/mmc-imx233.c b/firmware/target/arm/imx233/mmc-imx233.c
index f4dab30bcc..b2b18c871e 100644
--- a/firmware/target/arm/imx233/mmc-imx233.c
+++ b/firmware/target/arm/imx233/mmc-imx233.c
@@ -25,6 +25,7 @@
#include "storage.h"
#include "ssp-imx233.h"
#include "pinctrl-imx233.h"
+#include "partitions-imx233.h"
/**
* This code assumes a single eMMC internal flash
@@ -39,12 +40,13 @@
#define MMC_RCA 1
/** When set, this values restrict the windows of the read and writes */
-static unsigned mmc_window_start = 0;
-static unsigned mmc_window_end = INT_MAX;
+static unsigned mmc_window_start;
+static unsigned mmc_window_end;
static bool mmc_window_enable = true;
static long mmc_last_activity = -1;
static bool mmc_is_active = false;
static unsigned mmc_size = 0;
+static int mmc_first_drive = 0;
static struct mutex mmc_mutex;
@@ -142,37 +144,19 @@ int mmc_init(void)
mmc_size = *sec_count;
}
+ mmc_window_start = 0;
+ mmc_window_end = INT_MAX;
#ifdef SANSA_FUZEPLUS
- if(mmc_window_enable)
+ if(imx233_partitions_is_window_enabled())
{
- /**
- * The Fuze+ uses a strange layout: is has a first MBR at sector 0 with four entries:
- * 1) Actual user partition
- * 2) Sigmatel boot partition
- * 3)4) Other (certificate related ?) partitions
- * The partition 1) has type 1 but it's actually a type 5 (logical partition) with
- * a second partition table with usually one entry which is the FAT32 one.
- * The first table uses 512-byte sector size and the second one usually uses
- * 2048-byte logical sector size.
- *
- * We restrict mmc window to the user partition */
+ /* WARNING: mmc_first_drive is not set yet at this point */
uint8_t mbr[512];
- mmc_window_start = 0;
- mmc_window_end = INT_MAX;
ret = mmc_read_sectors(IF_MD2(0,) 0, 1, mbr);
- if(ret != 0)
- return -100;
- 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];
- mmc_window_start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24;
- mmc_window_end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24) +
- mmc_window_start;
- if(ent[4] == 0x53)
- return -102; /* sigmatel partition */
- if((mmc_window_end - mmc_window_start) < 4 * 1024 * 1024)
- return -103; /* partition too small */
+ if(ret)
+ panicf("cannot read MBR: %d", ret);
+ ret = imx233_partitions_compute_window(mbr, &mmc_window_start, &mmc_window_end);
+ if(ret)
+ panicf("cannot compute partitions window: %d", ret);
mmc_size = mmc_window_end - mmc_window_start;
}
#endif
@@ -182,7 +166,7 @@ int mmc_init(void)
int mmc_num_drives(int first_drive)
{
- (void) first_drive;
+ mmc_first_drive = first_drive;
return 1;
}
diff --git a/firmware/target/arm/imx233/partitions-imx233.c b/firmware/target/arm/imx233/partitions-imx233.c
new file mode 100644
index 0000000000..06c5a48f32
--- /dev/null
+++ b/firmware/target/arm/imx233/partitions-imx233.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2012 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.
+ *
+ ****************************************************************************/
+#include "partitions-imx233.h"
+
+static bool enable_window = true;
+
+void imx233_partitions_enable_window(bool enable)
+{
+ enable_window = enable;
+}
+
+bool imx233_partitions_is_window_enabled(void)
+{
+ return enable_window;
+}
+
+int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned *end)
+{
+ /**
+ * Freescale uses a strange layout: is has a first MBR at sector 0 with four entries:
+ * 1) Actual user partition
+ * 2) Sigmatel boot partition
+ * 3)4) Other (certificate related ?) partitions
+ * The partition 1) has type 1 but it's actually a type 5 (logical partition) with
+ * a second partition table with usually one entry which is the FAT32 one.
+ * The first table uses 512-byte sector size and the second one usually uses
+ * 2048-byte logical sector size.
+ *
+ * We restrict the window to the user partition
+ *
+ * WARNING HACK FIXME BUG
+ * Reverse engineering and experiments suggests that the OF ignores the lowest 2 bits
+ * of the LBAs in the partition table. There is at least one example
+ * (the Creative Zen X-Fi3) where this is important because the LBA of the user partition
+ * is not a multiple of 4. The behaviour of the size field is less clear but
+ * 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;
+}
diff --git a/firmware/target/arm/imx233/partitions-imx233.h b/firmware/target/arm/imx233/partitions-imx233.h
new file mode 100644
index 0000000000..4490aad77f
--- /dev/null
+++ b/firmware/target/arm/imx233/partitions-imx233.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2012 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 __PARTITIONS_IMX233__
+#define __PARTITIONS_IMX233__
+
+#include "system.h"
+#include "storage.h"
+
+/* 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);
+
+#endif /* __PARTITIONS_IMX233__ */ \ No newline at end of file