[PATCH] m68k: bitops update [3/20]
[linux-2.6/history.git] / drivers / mtd / bootldr.c
blob43fcd6bea8b89bedddd10a62403af3fdbe605ce6
1 /*
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
31 enum LFR_FLAGS {
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
39 // for now
40 #define MAX_NUM_PARTITIONS 8
41 typedef struct FlashRegion {
42 char name[FLASH_PARTITION_NAMELEN];
43 unsigned long base;
44 unsigned long size;
45 enum LFR_FLAGS flags;
46 } FlashRegion;
48 typedef struct BootldrFlashPartitionTable {
49 int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */
50 int npartitions;
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;
71 int ret, retlen, i;
72 int npartitions = 0;
73 long partition_table_offset;
74 long bootmagic = 0;
75 long bootcap = 0;
76 int namelen = 0;
78 char *names;
80 #if 0
81 /* verify bootldr magic */
82 ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic);
83 if (ret)
84 goto out;
85 if (bootmagic != BOOTLDR_MAGIC)
86 goto out;
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);
89 if (ret)
90 goto out;
92 if (!(bootcap & BOOTCAP_PARTITIONS))
93 goto out;
94 if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR)
95 partition_table_offset = master->erasesize;
96 else
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)
106 return -ENOMEM;
108 ret = master->read(master, partition_table_offset,
109 PAGE_SIZE, &retlen, (void *)partition_table);
110 if (ret)
111 goto out;
113 #endif
114 if (!partition_table)
115 return -ENOMEM;
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)
124 goto out;
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);
135 if (!parts) {
136 ret = -ENOMEM;
137 goto out;
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;
154 else
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);
164 ret = npartitions;
165 *pparts = parts;
167 out:
168 #if 0
169 if (partition_table)
170 kfree(partition_table);
171 #endif
173 return ret;
177 static int __init parse_tag_ptable(const struct tag *tag)
179 char buf[128];
180 int i;
181 int j;
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);
188 printascii(buf);
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);
196 printascii(buf);
198 #endif
200 memcpy((void *)partition_table,(void *) (&(tag->u.ptable)),sizeof(partition_table) +
201 sizeof(struct FlashRegion)*tag->u.ptable.npartitions);
204 return 0;
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");