summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/partitions-imx233.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/partitions-imx233.c')
-rw-r--r--firmware/target/arm/imx233/partitions-imx233.c139
1 files changed, 123 insertions, 16 deletions
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 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "partitions-imx233.h" 21#include "partitions-imx233.h"
22#include "string.h"
22 23
23static bool enable_window = true; 24static bool enable_window = true;
24 25
@@ -32,8 +33,79 @@ bool imx233_partitions_is_window_enabled(void)
32 return enable_window; 33 return enable_window;
33} 34}
34 35
35int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned *end) 36#if (IMX233_PARTITIONS & IMX233_CREATIVE)
37#define MBLK_MAGIC 0x4d424c4b /* MBLK */
38#define MBLK_COUNT 31
39/* MBLK is not located in the first sector !
40 * Creative code uses the hard-coded *absolute* address 0x3ffe00,
41 * bypassing all partition related information !!
42 * NOTE: for some reason, the ZEN uses a different value ?! */
43#ifdef CREATIVE_ZEN
44#define MBLK_ADDR 0x400000
45#else
46#define MBLK_ADDR 0x3ffe00
47#endif
48
49struct mblk_header_t
50{
51 uint32_t magic;
52 uint32_t block_size;
53 uint64_t total_size;
54} __attribute__((packed));
55
56struct mblk_partition_t
57{
58 uint32_t size;
59 uint32_t start;
60 char name[8];
61} __attribute__((packed));
62
63static const char *creative_part_name(enum imx233_part_t part)
64{
65 switch(part)
66 {
67 case IMX233_PART_USER: return "cfs";
68 case IMX233_PART_CFS: return "cfs";
69 case IMX233_PART_MINIFS: return "minifs";
70 default: return "";
71 }
72}
73
74static int compute_window_creative(IF_MD(int drive,) enum imx233_part_t part,
75 unsigned *start, unsigned *end)
36{ 76{
77 uint8_t mblk[512];
78 int ret = storage_read_sectors(IF_MD(drive,) MBLK_ADDR / 512, 1, mblk);
79 if(ret < 0)
80 return ret;
81 struct mblk_header_t *hdr = (void *)mblk;
82 if(hdr->magic != MBLK_MAGIC)
83 return -70; /* bad magic */
84 struct mblk_partition_t *ent = (void *)(hdr + 1);
85 const char *name = creative_part_name(part);
86 for(int i = 0; i < MBLK_COUNT; i++)
87 {
88 if(ent[i].name[0] == 0)
89 continue;
90 if(strcmp(ent[i].name, name) == 0)
91 {
92 *start = ent[i].start * hdr->block_size / 512;
93 *end = *start + ent[i].size * hdr->block_size / 512;
94 return 0;
95 }
96 }
97 return -80; /* not found */
98}
99#endif /* #(IMX233_PARTITIONS & IMX233_CREATIVE) */
100
101#if (IMX233_PARTITIONS & IMX233_FREESCALE)
102static int compute_window_freescale(IF_MD(int drive,) enum imx233_part_t part,
103 unsigned *start, unsigned *end)
104{
105 uint8_t mbr[512];
106 int ret = storage_read_sectors(IF_MD(drive,) 0, 1, mbr);
107 if(ret < 0)
108 return ret;
37 /** 109 /**
38 * Freescale uses a strange layout: is has a first MBR at sector 0 with four entries: 110 * Freescale uses a strange layout: is has a first MBR at sector 0 with four entries:
39 * 1) Actual user partition 111 * 1) Actual user partition
@@ -54,19 +126,54 @@ int imx233_partitions_compute_window(uint8_t mbr[512], unsigned *start, unsigned
54 * it seems that it is similarly truncated. */ 126 * it seems that it is similarly truncated. */
55 if(mbr[510] != 0x55 || mbr[511] != 0xAA) 127 if(mbr[510] != 0x55 || mbr[511] != 0xAA)
56 return -101; /* invalid MBR */ 128 return -101; /* invalid MBR */
57 /* sanity check that the first partition is greater than 2Gib */ 129 if(part == IMX233_PART_USER)
58 uint8_t *ent = &mbr[446]; 130 {
59 *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24; 131 /* sanity check that the first partition is greater than 2Gib */
60 /* ignore two lowest bits(see comment above) */ 132 uint8_t *ent = &mbr[446];
61 *start &= ~3; 133 *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24;
62 *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24); 134 /* ignore two lowest bits(see comment above) */
63 *end &= ~3; 135 *start &= ~3;
64 /* ignore two lowest bits(order is important, first truncate then add start) */ 136 *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24);
65 *end += *start; 137 *end &= ~3;
66 138 /* ignore two lowest bits(order is important, first truncate then add start) */
67 if(ent[4] == 0x53) 139 *end += *start;
68 return -102; /* sigmatel partition */ 140
69 if((*end - *start) < 4 * 1024 * 1024) 141 if(ent[4] == 0x53)
70 return -103; /* partition too small */ 142 return -102; /* sigmatel partition */
71 return 0; 143 if((*end - *start) < 4 * 1024 * 1024)
144 return -103; /* partition too small */
145 return 0;
146 }
147 else if(part == IMX233_PART_BOOT)
148 {
149 /* sanity check that the second partition is correct */
150 uint8_t *ent = &mbr[462];
151 if(ent[4] != 0x53)
152 return -104; /* wrong type */
153 *start = ent[8] | ent[9] << 8 | ent[10] << 16 | ent[11] << 24;
154 *end = (ent[12] | ent[13] << 8 | ent[14] << 16 | ent[15] << 24);
155 *end += *start;
156
157 return 0;
158 }
159 else
160 return -50;
161}
162#endif /* (IMX233_PARTITIONS & IMX233_FREESCALE) */
163
164int imx233_partitions_compute_window(IF_MD(int drive,) enum imx233_part_t part,
165 unsigned *start, unsigned *end)
166{
167 int ret = -1;
168#if (IMX233_PARTITIONS & IMX233_CREATIVE)
169 ret = compute_window_creative(IF_MD(drive,) part, start, end);
170 if(ret >= 0)
171 return ret;
172#endif
173#if (IMX233_PARTITIONS & IMX233_FREESCALE)
174 ret = compute_window_freescale(IF_MD(drive,) part, start, end);
175 if(ret >= 0)
176 return ret;
177#endif
178 return ret;
72} 179}