1/* 2 * Read flash partition table from Compaq Bootloader 3 * 4 * Copyright 2001 Compaq Computer Corporation. 5 * 6 * $Id: bootldr.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $ 7 * 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. 11 * 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. 15 * 16 */ 17 18/* 19 * Maintainer: Jamey Hicks (jamey.hicks@compaq.com) 20 */ 21 22#include <linux/kernel.h> 23#include <linux/slab.h> 24 25#include <linux/mtd/mtd.h> 26#include <linux/mtd/partitions.h> 27#include <asm/setup.h> 28#include <linux/bootmem.h> 29 30#define FLASH_PARTITION_NAMELEN 32 31enum 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 */ 36}; 37 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 41typedef struct FlashRegion { 42 char name[FLASH_PARTITION_NAMELEN]; 43 unsigned long base; 44 unsigned long size; 45 enum LFR_FLAGS flags; 46} FlashRegion; 47 48typedef struct BootldrFlashPartitionTable { 49 int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */ 50 int npartitions; 51 struct FlashRegion partition[8]; 52} BootldrFlashPartitionTable; 53 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 */ 56 57#define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */ 58#define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */ 59 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 */ 63 64static struct BootldrFlashPartitionTable Table; 65static struct BootldrFlashPartitionTable *partition_table = NULL; 66 67 68int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts) 69{ 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; 77 78 char *names; 79 80 if (!partition_table) 81 return -ENOMEM; 82 83 84 printk(__FUNCTION__ ": magic=%#x\n", partition_table->magic); 85 printk(__FUNCTION__ ": numPartitions=%#x\n", partition_table->npartitions); 86 87 88 /* check for partition table magic number */ 89 if (partition_table->magic != BOOTLDR_PARTITION_MAGIC) 90 goto out; 91 npartitions = (partition_table->npartitions > MAX_NUM_PARTITIONS)? 92 MAX_NUM_PARTITIONS:partition_table->npartitions; 93 94 printk(__FUNCTION__ ": npartitions=%#x\n", npartitions); 95 96 for (i = 0; i < npartitions; i++) { 97 namelen += strlen(partition_table->partition[i].name) + 1; 98 } 99 100 parts = kmalloc(sizeof(*parts)*npartitions + namelen, GFP_KERNEL); 101 if (!parts) { 102 ret = -ENOMEM; 103 goto out; 104 } 105 names = (char *)&parts[npartitions]; 106 memset(parts, 0, sizeof(*parts)*npartitions + namelen); 107 108 109 110 // from here we use the partition table 111 for (i = 0; i < npartitions; i++) { 112 struct FlashRegion *partition = &partition_table->partition[i]; 113 const char *name = partition->name; 114 parts[i].name = names; 115 names += strlen(name) + 1; 116 strcpy(parts[i].name, name); 117 118 if (partition->flags & LFR_EXPAND) 119 parts[i].size = MTDPART_SIZ_FULL; 120 else 121 parts[i].size = partition->size; 122 parts[i].offset = partition->base; 123 parts[i].mask_flags = 0; 124 125 printk(" partition %s o=%x s=%x\n", 126 parts[i].name, parts[i].offset, parts[i].size); 127 128 } 129 130 ret = npartitions; 131 *pparts = parts; 132 133 out: 134 135 return ret; 136} 137 138 139static int __init parse_tag_ptable(const struct tag *tag) 140{ 141 char buf[128]; 142 int i; 143 int j; 144 145 partition_table = &Table; 146 147#ifdef CONFIG_DEBUG_LL 148 sprintf(buf,"ptable: magic = = 0x%lx npartitions= %d \n", 149 tag->u.ptable.magic,tag->u.ptable.npartitions); 150 printascii(buf); 151 152 for (i=0; i<tag->u.ptable.npartitions; i++){ 153 sprintf(buf,"ptable: partition name = %s base= 0x%lx size= 0x%lx flags= 0x%lx\n", 154 (char *) (&tag->u.ptable.partition[i].name[0]), 155 tag->u.ptable.partition[i].base, 156 tag->u.ptable.partition[i].size, 157 tag->u.ptable.partition[i].flags); 158 printascii(buf); 159 } 160#endif 161 162 memcpy((void *)partition_table,(void *) (&(tag->u.ptable)),sizeof(partition_table) + 163 sizeof(struct FlashRegion)*tag->u.ptable.npartitions); 164 165 166 return 0; 167} 168 169__tagtable(ATAG_PTABLE, parse_tag_ptable); 170 171EXPORT_SYMBOL(parse_bootldr_partitions); 172 173 174MODULE_LICENSE("GPL"); 175MODULE_AUTHOR("Compaq Computer Corporation"); 176MODULE_DESCRIPTION("Parsing code for Compaq bootldr partitions"); 177