2 * Copyright (C) 2010 Samsung Electrnoics
3 * Kyungmin Park <kyungmin.park@samsung.com>
10 #define SIGNATURE ((unsigned short) 0xAA55)
12 unsigned int mbr_offset[16];
13 unsigned int mbr_parts = 0;
15 static int logical = 4;
16 static int extended_lba;
18 static inline void set_chs_value(struct mbr_partition *part, int part_num)
22 part->f_chs[0] = 0x01;
23 part->f_chs[1] = 0x01;
24 part->f_chs[2] = 0x00;
26 part->f_chs[0] = 0x03;
27 part->f_chs[1] = 0xd0;
28 part->f_chs[2] = 0xff;
30 part->l_chs[0] = 0x03;
31 part->l_chs[1] = 0xd0;
32 part->l_chs[2] = 0xff;
35 void set_mbr_table(unsigned int start_addr, int parts,
36 unsigned int *blocks, unsigned int *part_offset)
38 struct mmc *mmc = find_mmc_device(0);
40 unsigned int offset = start_addr;
42 unsigned int size = 0;
46 max = mmc->capacity / mmc->read_bl_len;
48 memset(&mbr_table, 0, sizeof(struct mbr));
50 mbr_table.signature = SIGNATURE;
52 if (blocks[parts - 1] == 0) {
54 for (i = 0; i < parts; i++)
56 blocks[parts - 1] = max - size;
60 for (i = 0; i < 3; i++) {
61 mbr_table.parts[i].partition_type = 0x83; /* Linux */
62 mbr_table.parts[i].lba = offset;
63 mbr_table.parts[i].nsectors = blocks[i];
64 part_offset[i] = offset;
67 set_chs_value(&mbr_table.parts[i], i);
71 mmc->block_dev.block_write(0, 0, 1, &mbr_table);
76 mbr_table.parts[i].partition_type = 0x05; /* Extended */
77 mbr_table.parts[i].lba = offset;
78 mbr_table.parts[i].nsectors = max - offset;
79 set_chs_value(&mbr_table.parts[i], i);
81 mmc->block_dev.block_write(0, 0, 1, &mbr_table);
83 for (; i < parts; i++) {
85 memset(&ebr_table, 0, sizeof(struct mbr));
87 ebr_table.signature = SIGNATURE;
89 for (j = 0; j < 2; j++) {
91 blocks[parts - 1] -= 0x10;
92 ebr_table.parts[j].partition_type = 0x83;
93 ebr_table.parts[j].lba = 0x10;
94 ebr_table.parts[j].nsectors = blocks[i];
95 set_chs_value(&ebr_table.parts[j], i);
98 ebr_table.parts[j].partition_type = 0x05;
99 ebr_table.parts[j].lba = 0x10 + blocks[i];
100 ebr_table.parts[j].nsectors = blocks[i + 1];
101 set_chs_value(&ebr_table.parts[j], i);
106 mmc->block_dev.block_write(0, offset, 1, &ebr_table);
108 offset += ebr_table.parts[0].lba;
109 part_offset[i] = offset;
110 offset += ebr_table.parts[0].nsectors;
114 static int get_ebr_table(struct mmc *mmc, struct mbr_partition *mp,
115 int ebr_next, unsigned int *part_offset, int parts)
118 struct mbr_partition *p;
127 ret = mmc->block_dev.block_read(0, lba, 1, buf);
129 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
132 ebr = (struct mbr *) buf;
134 if (ebr->signature != SIGNATURE) {
135 printf("Signature error 0x%x\n", ebr->signature);
139 for (i = 0; i < 2; i++) {
140 p = (struct mbr_partition *) &ebr->parts[i];
145 if (p->partition_type == 0x83) {
146 part_offset[parts] = lba;
152 if (p->lba && p->partition_type == 0x5)
153 parts = get_ebr_table(mmc, p, 1, part_offset, parts);
158 int get_mbr_table(unsigned int *part_offset)
160 struct mmc *mmc = find_mmc_device(0);
161 struct mbr_partition *mp;
169 ret = mmc->block_dev.block_read(0, 0, 1, buf);
171 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
175 mbr = (struct mbr *) buf;
177 if (mbr->signature != SIGNATURE)
178 printf("Signature error 0x%x\n", mbr->signature);
182 for (i = 0; i < 4; i++) {
183 mp = (struct mbr_partition *) &mbr->parts[i];
185 if (!mp->partition_type)
188 if (mp->partition_type == 0x83) {
189 part_offset[parts] = mp->lba;
193 if (mp->lba && mp->partition_type == 0x5) {
194 extended_lba = mp->lba;
195 parts = get_ebr_table(mmc, mp, 0, part_offset, parts);
202 static inline int get_cylinder(char chs1, char chs2, int *sector)
204 *sector = chs1 & 0x3f;
206 return ((chs1 & 0xc0) << 2) | chs2;
209 static void ebr_show(struct mmc *mmc, struct mbr_partition *mp, int ebr_next)
212 struct mbr_partition *p;
214 int ret, i, sector, cylinder;
221 printf(">>> Read sector from 0x%08x (LBA: 0x%08x + 0x%x)\n",
222 lba, mp->lba, (lba == mp->lba) ? 0 : lba - mp->lba);
224 ret = mmc->block_dev.block_read(0, lba, 1, buf);
226 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
229 ebr = (struct mbr *) buf;
231 if (ebr->signature != SIGNATURE) {
232 printf("Signature error 0x%x\n", ebr->signature);
236 for (i = 0; i < 2; i++) {
237 p = (struct mbr_partition *) &ebr->parts[i];
242 printf("Extended Part %d\n", logical);
244 printf("Extended Part next\n");
246 printf("status 0x%02x\n", p->status);
247 printf("head 0x%02x,", p->f_chs[0]);
248 cylinder = get_cylinder(p->f_chs[1], p->f_chs[2], §or);
249 printf("\tsector 0x%02x,", sector);
250 printf("\tcylinder 0x%04x\n", cylinder);
251 printf("type 0x%02x\n", p->partition_type);
252 printf("head 0x%02x,", p->l_chs[0]);
253 cylinder = get_cylinder(p->l_chs[1], p->l_chs[2], §or);
254 printf("\tsector 0x%02x,", sector);
255 printf("\tcylinder 0x%04x\n", cylinder);
256 printf("lba 0x%08x (%d), ", p->lba, p->lba);
257 printf("nsectors 0x%08x (%d)\n", p->nsectors, p->nsectors);
260 if (p->lba && p->partition_type == 0x5)
264 static void mbr_show(void)
266 struct mmc *mmc = find_mmc_device(0);
267 struct mbr_partition *mp;
275 ret = mmc->block_dev.block_read(0, 0, 1, buf);
277 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
281 mbr = (struct mbr *) buf;
283 if (mbr->signature != SIGNATURE)
284 printf("Signature error 0x%x\n", mbr->signature);
287 printf("MBR partition info\n");
288 for (i = 0; i < 4; i++) {
289 mp = (struct mbr_partition *) &mbr->parts[i];
291 if (!mp->partition_type)
294 printf("Part %d\n", i + 1);
295 printf("status 0x%02x\n", mp->status);
296 printf("head 0x%02x,", mp->f_chs[0]);
297 printf("\tsector 0x%02x,", mp->f_chs[1] & 0x3f);
298 cylinder = (mp->f_chs[1] & 0xc0) << 2;
299 cylinder |= mp->f_chs[2];
300 printf("\tcylinder 0x%04x\n", cylinder);
301 printf("type 0x%02x\n", mp->partition_type);
302 printf("head 0x%02x,", mp->l_chs[0]);
303 printf("\tsector 0x%02x,", mp->l_chs[1] & 0x3f);
304 cylinder = (mp->l_chs[1] & 0xc0) << 2;
305 cylinder |= mp->l_chs[2];
306 printf("\tcylinder 0x%04x\n", cylinder);
307 printf("lba 0x%08x (%d), ", mp->lba, mp->lba);
308 printf("nsectors 0x%08x (%d)\n", mp->nsectors, mp->nsectors);
310 if (mp->lba && mp->partition_type == 0x5) {
311 extended_lba = mp->lba;
312 ebr_show(mmc, mp, 0);
317 static unsigned long memsize_parse (const char *const ptr, const char **retptr)
319 unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
339 void set_mbr_info(char *ramaddr, unsigned int len)
345 unsigned int size[16];
348 strncpy(mbr_str, ramaddr, len);
351 for (i = 0; ; i++, p = NULL) {
352 tok = strtok(p, ",");
355 strcpy(save[i], tok);
356 printf("part%d: %s\n", i, save[i]);
360 printf("find %d partitions\n", mbr_parts);
362 for (i = 0; i < mbr_parts; i++) {
364 size[i] = memsize_parse(p, (const char **)&p) / 512;
367 puts("save the MBR Table...\n");
368 set_mbr_table(0x800, mbr_parts, size, mbr_offset);
371 static void mbr_default(void)
375 puts("using default MBR\n");
377 mbrparts = getenv("mbrparts");
378 set_mbr_info(mbrparts, strlen(mbrparts));
381 static int do_mbr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
385 if (strncmp(argv[1], "show", 2) == 0)
387 else if (strncmp(argv[1], "default", 3) == 0)
399 mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
400 "Master Boot Record",
402 "mbr default - reset MBR partition to defaults\n"