2 * Copyright (C) 2010 Samsung Electrnoics
3 * Kyungmin Park <kyungmin.park@samsung.com>
16 } __attribute__((packed));
18 #define SIGNATURE ((unsigned short) 0xAA55)
20 static int logical = 4;
21 static int extended_lba;
25 char disk_signature[4];
27 struct mbr_partition parts[4];
28 unsigned short signature;
31 void set_chs_value(struct mbr_partition *part, int part_num)
35 part->f_chs[0] = 0x01;
36 part->f_chs[1] = 0x01;
37 part->f_chs[2] = 0x00;
39 part->f_chs[0] = 0x03;
40 part->f_chs[1] = 0xd0;
41 part->f_chs[2] = 0xff;
43 part->l_chs[0] = 0x03;
44 part->l_chs[1] = 0xd0;
45 part->l_chs[2] = 0xff;
48 void set_mbr_table(unsigned int start_addr, int parts,
49 unsigned int *blocks, unsigned int *part_offset)
51 struct mmc *mmc = find_mmc_device(0);
53 unsigned int offset = start_addr;
55 unsigned int size = 0;
59 max = mmc->capacity / mmc->read_bl_len;
61 memset(&mbr_table, 0, sizeof(struct mbr));
63 mbr_table.signature = SIGNATURE;
65 if (blocks[parts - 1] == 0) {
67 for (i = 0; i < parts; i++)
69 blocks[parts - 1] = max - size;
73 for (i = 0; i < 3; i++) {
74 mbr_table.parts[i].partition_type = 0x83; /* Linux */
75 mbr_table.parts[i].lba = offset;
76 mbr_table.parts[i].nsectors = blocks[i];
77 part_offset[i] = offset;
80 set_chs_value(&mbr_table.parts[i], i);
84 mmc->block_dev.block_write(0, 0, 1, &mbr_table);
89 mbr_table.parts[i].partition_type = 0x05; /* Extended */
90 mbr_table.parts[i].lba = offset;
91 mbr_table.parts[i].nsectors = max - offset;
92 set_chs_value(&mbr_table.parts[i], i);
94 mmc->block_dev.block_write(0, 0, 1, &mbr_table);
96 for (; i < parts; i++) {
98 memset(&ebr_table, 0, sizeof(struct mbr));
100 ebr_table.signature = SIGNATURE;
102 for (j = 0; j < 2; j++) {
104 blocks[parts - 1] -= 0x10;
105 ebr_table.parts[j].partition_type = 0x83;
106 ebr_table.parts[j].lba = 0x10;
107 ebr_table.parts[j].nsectors = blocks[i];
108 set_chs_value(&ebr_table.parts[j], i);
110 if (parts != i + 1) {
111 ebr_table.parts[j].partition_type = 0x05;
112 ebr_table.parts[j].lba = 0x10 + blocks[i];
113 ebr_table.parts[j].nsectors = blocks[i + 1];
114 set_chs_value(&ebr_table.parts[j], i);
119 mmc->block_dev.block_write(0, offset, 1, &ebr_table);
121 offset += ebr_table.parts[0].lba;
122 part_offset[i] = offset;
123 offset += ebr_table.parts[0].nsectors;
127 static int get_ebr_table(struct mmc *mmc, struct mbr_partition *mp,
128 int ebr_next, unsigned int *part_offset, int parts)
131 struct mbr_partition *p;
132 char buf[512], msg[512];
133 int ret, i, sector, cylinder;
140 ret = mmc_read_blocks(mmc, buf, lba , 1);
142 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
145 ebr = (struct mbr *) buf;
147 if (ebr->signature != SIGNATURE) {
148 printf("Signature error 0x%x\n", ebr->signature);
152 for (i = 0; i < 2; i++) {
153 p = (struct mbr_partition *) &ebr->parts[i];
158 if (p->partition_type == 0x83) {
159 part_offset[parts] = lba;
165 if (p->lba && p->partition_type == 0x5)
166 parts = get_ebr_table(mmc, p, 1, part_offset, parts);
171 int get_mbr_table(unsigned int *part_offset)
173 struct mmc *mmc = find_mmc_device(0);
174 struct mbr_partition *mp;
182 ret = mmc_read_blocks(mmc, buf, 0, 1);
184 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
188 mbr = (struct mbr *) buf;
190 if (mbr->signature != SIGNATURE)
191 printf("Signature error 0x%x\n", mbr->signature);
195 for (i = 0; i < 4; i++) {
196 mp = (struct mbr_partition *) &mbr->parts[i];
198 if (!mp->partition_type)
201 if (mp->partition_type == 0x83) {
202 part_offset[parts] = mp->lba;
206 if (mp->lba && mp->partition_type == 0x5) {
207 extended_lba = mp->lba;
208 parts = get_ebr_table(mmc, mp, 0, part_offset, parts);
215 static inline int get_cylinder(char chs1, char chs2, int *sector)
217 *sector = chs1 & 0x3f;
219 return ((chs1 & 0xc0) << 2) | chs2;
222 static void ebr_show(struct mmc *mmc, struct mbr_partition *mp, int ebr_next)
225 struct mbr_partition *p;
226 char buf[512], msg[512];
227 int ret, i, sector, cylinder;
234 printf(">>> Read sector from 0x%08x (LBA: 0x%08x + 0x%x)\n",
235 lba, mp->lba, (lba == mp->lba) ? 0 : lba - mp->lba);
236 ret = mmc_read_blocks(mmc, buf, lba , 1);
238 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
241 ebr = (struct mbr *) buf;
243 if (ebr->signature != SIGNATURE) {
244 printf("Signature error 0x%x\n", ebr->signature);
248 for (i = 0; i < 2; i++) {
249 p = (struct mbr_partition *) &ebr->parts[i];
253 printf("Extended Part %d\n", logical);
255 printf("Extended Part next\n");
257 printf("status 0x%02x\n", p->status);
258 printf("head 0x%02x,", p->f_chs[0]);
259 cylinder = get_cylinder(p->f_chs[1], p->f_chs[2], §or);
260 printf("\tsector 0x%02x,", sector);
261 printf("\tcylinder 0x%04x\n", cylinder);
262 printf("type 0x%02x\n", p->partition_type);
263 printf("head 0x%02x,", p->l_chs[0]);
264 cylinder = get_cylinder(p->l_chs[1], p->l_chs[2], §or);
265 printf("\tsector 0x%02x,", sector);
266 printf("\tcylinder 0x%04x\n", cylinder);
267 printf("lba 0x%08x (%d), ", p->lba, p->lba);
268 printf("nsectors 0x%08x (%d)\n", p->nsectors, p->nsectors);
272 ret = mmc_read_blocks(mmc, msg, lba, 1);
274 for (i = 0; i < 8; i++)
278 if (p->lba && p->partition_type == 0x5)
283 static void mbr_show(void)
285 struct mmc *mmc = find_mmc_device(0);
286 struct mbr_partition *mp;
294 ret = mmc_read_blocks(mmc, buf, 0, 1);
296 printf("%s[%d] mmc_read_blocks %d\n", __func__, __LINE__, ret);
300 mbr = (struct mbr *) buf;
302 if (mbr->signature != SIGNATURE)
303 printf("Signature error 0x%x\n", mbr->signature);
306 printf("MBR partition info\n");
307 for (i = 0; i < 4; i++) {
308 mp = (struct mbr_partition *) &mbr->parts[i];
310 if (!mp->partition_type)
313 printf("Part %d\n", i + 1);
314 printf("status 0x%02x\n", mp->status);
315 printf("head 0x%02x,", mp->f_chs[0]);
316 printf("\tsector 0x%02x,", mp->f_chs[1] & 0x3f);
317 cylinder = (mp->f_chs[1] & 0xc0) << 2;
318 cylinder |= mp->f_chs[2];
319 printf("\tcylinder 0x%04x\n", cylinder);
320 printf("type 0x%02x\n", mp->partition_type);
321 printf("head 0x%02x,", mp->l_chs[0]);
322 printf("\tsector 0x%02x,", mp->l_chs[1] & 0x3f);
323 cylinder = (mp->l_chs[1] & 0xc0) << 2;
324 cylinder |= mp->l_chs[2];
325 printf("\tcylinder 0x%04x\n", cylinder);
326 printf("lba 0x%08x (%d), ", mp->lba, mp->lba);
327 printf("nsectors 0x%08x (%d)\n", mp->nsectors, mp->nsectors);
329 if (mp->lba && mp->partition_type == 0x5) {
330 extended_lba = mp->lba;
331 ebr_show(mmc, mp, 0);
336 static int do_mbr(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[])
340 if (strncmp(argv[1], "show", 2) == 0) {
353 mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
354 "Master Boot Record",