From 07138ba2ba08ce586486baab081aa455eb021fea Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sat, 19 May 2012 13:33:45 +0200 Subject: [PATCH] imx233: move the freescale partition handling to its own file The freescale firmware partitions has a lots of quirks that need to be dealt with, so do it the proper way. Change-Id: I8a5bd3fb462a4df143bc6c931057f3ffedd4b3d3 --- bootloader/imx233.c | 19 +++-- firmware/SOURCES | 1 + firmware/target/arm/imx233/mmc-imx233.c | 44 ++++-------- .../target/arm/imx233/partitions-imx233.c | 72 +++++++++++++++++++ .../target/arm/imx233/partitions-imx233.h | 33 +++++++++ 5 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 firmware/target/arm/imx233/partitions-imx233.c create mode 100644 firmware/target/arm/imx233/partitions-imx233.h diff --git a/bootloader/imx233.c b/bootloader/imx233.c index 6d356b9cce..c1ab4893c3 100644 --- a/bootloader/imx233.c +++ b/bootloader/imx233.c @@ -40,6 +40,8 @@ #include "fmradio_i2c.h" #include "version.h" #include "powermgmt.h" +#include "partitions-imx233.h" +#include "adc-imx233.h" #include "usb.h" @@ -84,6 +86,7 @@ static void usb_mode(int connect_timeout) printf("Bootloader USB mode"); /* Enable power management to charge */ powermgmt_init(); + adc_init(); usb_acknowledge(SYS_USB_CONNECTED_ACK); @@ -101,6 +104,14 @@ static void usb_mode(int connect_timeout) info.state == TOPOFF ? "topoff" : info.state == CHARGING ? "charging" : ""); lcd_putsf(0, 8, "Battery: %d%%", battery_level()); + lcd_putsf(0, 9, "Die temp: %d°C [%d, %d]", + adc_read(ADC_DIE_TEMP), IMX233_DIE_TEMP_HIGH, + IMX233_DIE_TEMP_LOW); + #ifdef ADC_BATT_TEMP + lcd_putsf(0, 10, "Batt temp: %d [%d, %d]", + adc_read(ADC_BATT_TEMP), IMX233_BATT_TEMP_HIGH, + IMX233_BATT_TEMP_LOW); + #endif lcd_update(); } } @@ -137,19 +148,15 @@ void main(uint32_t arg, uint32_t addr) button_init(); - //button_debug_screen(); printf("Boot version: %s", RBVERSION); printf("arg=%x addr=%x", arg, addr); printf("power up source: %x", __XTRACT(HW_POWER_STS, PWRUP_SOURCE)); -#ifdef SANSA_FUZEPLUS - extern void imx233_mmc_disable_window(void); if(arg == 0xfee1dead) { - printf("Disable MMC window."); - imx233_mmc_disable_window(); + printf("Disable partitions window."); + imx233_partitions_enable_window(false); } -#endif ret = storage_init(); if(ret < 0) diff --git a/firmware/SOURCES b/firmware/SOURCES index 61b437779b..81f7d87c3c 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -506,6 +506,7 @@ target/arm/imx233/timrot-imx233.c target/arm/imx233/kernel-imx233.c target/arm/imx233/sd-imx233.c target/arm/imx233/mmc-imx233.c +target/arm/imx233/partitions-imx233.c target/arm/imx233/ssp-imx233.c target/arm/imx233/dma-imx233.c target/arm/imx233/icoll-imx233.c 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