2 * Read flash partition table from Compaq Bootloader
4 * Copyright 2001 Compaq Computer Corporation.
6 * $Id: bootldr.c,v 1.6 2001/10/02 15:05:11 dwmw2 Exp $
8 * Use consistent with the GNU GPL is permitted,
9 * provided that this copyright notice is
10 * preserved in its entirety in all copies and derived works.
12 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
13 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
14 * FITNESS FOR ANY PARTICULAR PURPOSE.
19 * Maintainer: Jamey Hicks (jamey.hicks@compaq.com)
22 #include <linux/kernel.h>
23 #include <linux/slab.h>
25 #include <linux/mtd/mtd.h>
26 #include <linux/mtd/partitions.h>
27 #include <asm/setup.h>
28 #include <linux/bootmem.h>
30 #define FLASH_PARTITION_NAMELEN 32
32 LFR_SIZE_PREFIX
= 1, /* prefix data with 4-byte size */
33 LFR_PATCH_BOOTLDR
= 2, /* patch bootloader's 0th instruction */
34 LFR_KERNEL
= 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */
35 LFR_EXPAND
= 8 /* expand partition size to fit rest of flash */
38 // the tags are parsed too early to malloc or alloc_bootmem so we'll fix it
40 #define MAX_NUM_PARTITIONS 8
41 typedef struct FlashRegion
{
42 char name
[FLASH_PARTITION_NAMELEN
];
48 typedef struct BootldrFlashPartitionTable
{
49 int magic
; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */
51 struct FlashRegion partition
[8];
52 } BootldrFlashPartitionTable
;
54 #define BOOTLDR_MAGIC 0x646c7462 /* btld: marks a valid bootldr image */
55 #define BOOTLDR_PARTITION_MAGIC 0x646c7470 /* btlp: marks a valid bootldr partition table in params sector */
57 #define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */
58 #define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */
60 #define BOOTCAP_WAKEUP (1<<0)
61 #define BOOTCAP_PARTITIONS (1<<1) /* partition table stored in params sector */
62 #define BOOTCAP_PARAMS_AFTER_BOOTLDR (1<<2) /* params sector right after bootldr sector(s), else in last sector */
64 static struct BootldrFlashPartitionTable Table
;
65 static struct BootldrFlashPartitionTable
*partition_table
= NULL
;
68 int parse_bootldr_partitions(struct mtd_info
*master
, struct mtd_partition
**pparts
)
70 struct mtd_partition
*parts
;
73 long partition_table_offset
;
81 /* verify bootldr magic */
82 ret
= master
->read(master
, BOOTLDR_MAGIC_OFFSET
, sizeof(long), &retlen
, (void *)&bootmagic
);
85 if (bootmagic
!= BOOTLDR_MAGIC
)
87 /* see if bootldr supports partition tables and where to find the partition table */
88 ret
= master
->read(master
, BOOTCAP_OFFSET
, sizeof(long), &retlen
, (void *)&bootcap
);
92 if (!(bootcap
& BOOTCAP_PARTITIONS
))
94 if (bootcap
& BOOTCAP_PARAMS_AFTER_BOOTLDR
)
95 partition_table_offset
= master
->erasesize
;
97 partition_table_offset
= master
->size
- master
->erasesize
;
99 printk(__FUNCTION__
": partition_table_offset=%#lx\n", partition_table_offset
);
100 printk(__FUNCTION__
": ptable_addr=%#lx\n", ptable_addr
);
103 /* Read the partition table */
104 partition_table
= (struct BootldrFlashPartitionTable
*)kmalloc(PAGE_SIZE
, GFP_KERNEL
);
105 if (!partition_table
)
108 ret
= master
->read(master
, partition_table_offset
,
109 PAGE_SIZE
, &retlen
, (void *)partition_table
);
114 if (!partition_table
)
118 printk(__FUNCTION__
": magic=%#x\n", partition_table
->magic
);
119 printk(__FUNCTION__
": numPartitions=%#x\n", partition_table
->npartitions
);
122 /* check for partition table magic number */
123 if (partition_table
->magic
!= BOOTLDR_PARTITION_MAGIC
)
125 npartitions
= (partition_table
->npartitions
> MAX_NUM_PARTITIONS
)?
126 MAX_NUM_PARTITIONS
:partition_table
->npartitions
;
128 printk(__FUNCTION__
": npartitions=%#x\n", npartitions
);
130 for (i
= 0; i
< npartitions
; i
++) {
131 namelen
+= strlen(partition_table
->partition
[i
].name
) + 1;
134 parts
= kmalloc(sizeof(*parts
)*npartitions
+ namelen
, GFP_KERNEL
);
139 names
= (char *)&parts
[npartitions
];
140 memset(parts
, 0, sizeof(*parts
)*npartitions
+ namelen
);
144 // from here we use the partition table
145 for (i
= 0; i
< npartitions
; i
++) {
146 struct FlashRegion
*partition
= &partition_table
->partition
[i
];
147 const char *name
= partition
->name
;
148 parts
[i
].name
= names
;
149 names
+= strlen(name
) + 1;
150 strcpy(parts
[i
].name
, name
);
152 if (partition
->flags
& LFR_EXPAND
)
153 parts
[i
].size
= MTDPART_SIZ_FULL
;
155 parts
[i
].size
= partition
->size
;
156 parts
[i
].offset
= partition
->base
;
157 parts
[i
].mask_flags
= 0;
159 printk(" partition %s o=%x s=%x\n",
160 parts
[i
].name
, parts
[i
].offset
, parts
[i
].size
);
170 kfree(partition_table
);
177 static int __init
parse_tag_ptable(const struct tag
*tag
)
183 partition_table
= &Table
;
185 #ifdef CONFIG_DEBUG_LL
186 sprintf(buf
,"ptable: magic = = 0x%lx npartitions= %d \n",
187 tag
->u
.ptable
.magic
,tag
->u
.ptable
.npartitions
);
190 for (i
=0; i
<tag
->u
.ptable
.npartitions
; i
++){
191 sprintf(buf
,"ptable: partition name = %s base= 0x%lx size= 0x%lx flags= 0x%lx\n",
192 (char *) (&tag
->u
.ptable
.partition
[i
].name
[0]),
193 tag
->u
.ptable
.partition
[i
].base
,
194 tag
->u
.ptable
.partition
[i
].size
,
195 tag
->u
.ptable
.partition
[i
].flags
);
200 memcpy((void *)partition_table
,(void *) (&(tag
->u
.ptable
)),sizeof(partition_table
) +
201 sizeof(struct FlashRegion
)*tag
->u
.ptable
.npartitions
);
207 __tagtable(ATAG_PTABLE
, parse_tag_ptable
);
209 EXPORT_SYMBOL(parse_bootldr_partitions
);
212 MODULE_LICENSE("GPL");
213 MODULE_AUTHOR("Compaq Computer Corporation");
214 MODULE_DESCRIPTION("Parsing code for Compaq bootldr partitions");