bootldr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Read flash partition table from Compaq Bootloader
  3.  *
  4.  * Copyright 2001 Compaq Computer Corporation.
  5.  *
  6.  * $Id: bootldr.c,v 1.6 2001/10/02 15:05:11 dwmw2 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.  * Maintainer: Jamey Hicks (jamey.hicks@compaq.com)
  19.  */
  20. #include <linux/kernel.h>
  21. #include <linux/slab.h>
  22. #include <linux/mtd/mtd.h>
  23. #include <linux/mtd/partitions.h>
  24. #include <asm/setup.h>
  25. #include <linux/bootmem.h>
  26. #define FLASH_PARTITION_NAMELEN 32
  27. enum LFR_FLAGS {
  28.    LFR_SIZE_PREFIX = 1, /* prefix data with 4-byte size */
  29.    LFR_PATCH_BOOTLDR = 2, /* patch bootloader's 0th instruction */
  30.    LFR_KERNEL = 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */
  31.    LFR_EXPAND = 8               /* expand partition size to fit rest of flash */
  32. };
  33. // the tags are parsed too early to malloc or alloc_bootmem so we'll fix it
  34. // for now
  35. #define MAX_NUM_PARTITIONS 8
  36. typedef struct FlashRegion {
  37.    char name[FLASH_PARTITION_NAMELEN];
  38.    unsigned long base;
  39.    unsigned long size;
  40.    enum LFR_FLAGS flags;
  41. } FlashRegion;
  42. typedef struct BootldrFlashPartitionTable {
  43.   int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */
  44.   int npartitions;
  45.   struct FlashRegion partition[8];
  46. } BootldrFlashPartitionTable;
  47. #define BOOTLDR_MAGIC      0x646c7462        /* btld: marks a valid bootldr image */
  48. #define BOOTLDR_PARTITION_MAGIC  0x646c7470  /* btlp: marks a valid bootldr partition table in params sector */
  49. #define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */
  50. #define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */
  51. #define BOOTCAP_WAKEUP (1<<0)
  52. #define BOOTCAP_PARTITIONS (1<<1) /* partition table stored in params sector */
  53. #define BOOTCAP_PARAMS_AFTER_BOOTLDR (1<<2) /* params sector right after bootldr sector(s), else in last sector */
  54. static struct BootldrFlashPartitionTable Table;
  55. static struct BootldrFlashPartitionTable *partition_table = NULL;
  56. int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts)
  57. {
  58. struct mtd_partition *parts;
  59. int ret, retlen, i;
  60. int npartitions = 0;
  61. long partition_table_offset;
  62. long bootmagic = 0;
  63. long bootcap = 0;
  64. int namelen = 0;
  65. char *names; 
  66. #if 0
  67. /* verify bootldr magic */
  68. ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic);
  69. if (ret) 
  70. goto out;
  71.         if (bootmagic != BOOTLDR_MAGIC)
  72.                 goto out;
  73. /* see if bootldr supports partition tables and where to find the partition table */
  74. ret = master->read(master, BOOTCAP_OFFSET, sizeof(long), &retlen, (void *)&bootcap);
  75. if (ret) 
  76. goto out;
  77. if (!(bootcap & BOOTCAP_PARTITIONS))
  78. goto out;
  79. if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR)
  80. partition_table_offset = master->erasesize;
  81. else
  82. partition_table_offset = master->size - master->erasesize;
  83. printk(__FUNCTION__ ": partition_table_offset=%#lxn", partition_table_offset);
  84. printk(__FUNCTION__ ": ptable_addr=%#lxn", ptable_addr);
  85. /* Read the partition table */
  86. partition_table = (struct BootldrFlashPartitionTable *)kmalloc(PAGE_SIZE, GFP_KERNEL);
  87. if (!partition_table)
  88. return -ENOMEM;
  89. ret = master->read(master, partition_table_offset,
  90.    PAGE_SIZE, &retlen, (void *)partition_table);
  91. if (ret)
  92.     goto out;
  93. #endif
  94. if (!partition_table)
  95.     return -ENOMEM;
  96. printk(__FUNCTION__ ": magic=%#xn", partition_table->magic);
  97. printk(__FUNCTION__ ": numPartitions=%#xn", partition_table->npartitions);
  98. /* check for partition table magic number */
  99. if (partition_table->magic != BOOTLDR_PARTITION_MAGIC) 
  100. goto out;
  101. npartitions = (partition_table->npartitions > MAX_NUM_PARTITIONS)?
  102.     MAX_NUM_PARTITIONS:partition_table->npartitions;
  103. printk(__FUNCTION__ ": npartitions=%#xn", npartitions);
  104. for (i = 0; i < npartitions; i++) {
  105. namelen += strlen(partition_table->partition[i].name) + 1;
  106. }
  107. parts = kmalloc(sizeof(*parts)*npartitions + namelen, GFP_KERNEL);
  108. if (!parts) {
  109. ret = -ENOMEM;
  110. goto out;
  111. }
  112. names = (char *)&parts[npartitions];
  113. memset(parts, 0, sizeof(*parts)*npartitions + namelen);
  114. // from here we use the partition table
  115. for (i = 0; i < npartitions; i++) {
  116.                 struct FlashRegion *partition = &partition_table->partition[i];
  117. const char *name = partition->name;
  118. parts[i].name = names;
  119. names += strlen(name) + 1;
  120. strcpy(parts[i].name, name);
  121.                 if (partition->flags & LFR_EXPAND)
  122.                         parts[i].size = MTDPART_SIZ_FULL;
  123.                 else
  124.                         parts[i].size = partition->size;
  125. parts[i].offset = partition->base;
  126. parts[i].mask_flags = 0;
  127. printk("        partition %s o=%x s=%xn", 
  128.        parts[i].name, parts[i].offset, parts[i].size);
  129. }
  130. ret = npartitions;
  131. *pparts = parts;
  132.  out:
  133. #if 0
  134. if (partition_table)
  135. kfree(partition_table);
  136. #endif
  137. return ret;
  138. }
  139. static 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. #ifdef CONFIG_DEBUG_LL    
  147.     sprintf(buf,"ptable: magic = = 0x%lx  npartitions= %d n",
  148.     tag->u.ptable.magic,tag->u.ptable.npartitions);
  149.     printascii(buf);
  150.     
  151.     for (i=0; i<tag->u.ptable.npartitions; i++){
  152. sprintf(buf,"ptable: partition name = %s base= 0x%lx  size= 0x%lx flags= 0x%lxn",
  153.     (char *) (&tag->u.ptable.partition[i].name[0]),
  154. tag->u.ptable.partition[i].base,
  155. tag->u.ptable.partition[i].size,
  156. tag->u.ptable.partition[i].flags);
  157. printascii(buf);
  158.     }
  159. #endif
  160.     memcpy((void *)partition_table,(void *) (&(tag->u.ptable)),sizeof(partition_table) +
  161. sizeof(struct FlashRegion)*tag->u.ptable.npartitions);
  162.     
  163.     return 0;
  164. }
  165. __tagtable(ATAG_PTABLE, parse_tag_ptable);
  166. EXPORT_SYMBOL(parse_bootldr_partitions);
  167. MODULE_LICENSE("GPL");
  168. MODULE_AUTHOR("Compaq Computer Corporation");
  169. MODULE_DESCRIPTION("Parsing code for Compaq bootldr partitions");