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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: redboot.c,v 1.6 2001/10/25 09:16:06 dwmw2 Exp $
  3.  *
  4.  * Parse RedBoot-style Flash Image System (FIS) tables and
  5.  * produce a Linux partition array to match.
  6.  */
  7. #include <linux/kernel.h>
  8. #include <linux/slab.h>
  9. #include <linux/mtd/mtd.h>
  10. #include <linux/mtd/partitions.h>
  11. struct fis_image_desc {
  12.     unsigned char name[16];      // Null terminated name
  13.     unsigned long flash_base;    // Address within FLASH of image
  14.     unsigned long mem_base;      // Address in memory where it executes
  15.     unsigned long size;          // Length of image
  16.     unsigned long entry_point;   // Execution entry point
  17.     unsigned long data_length;   // Length of actual data
  18.     unsigned char _pad[256-(16+7*sizeof(unsigned long))];
  19.     unsigned long desc_cksum;    // Checksum over image descriptor
  20.     unsigned long file_cksum;    // Checksum over image data
  21. };
  22. struct fis_list {
  23. struct fis_image_desc *img;
  24. struct fis_list *next;
  25. };
  26. static inline int redboot_checksum(struct fis_image_desc *img)
  27. {
  28. /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
  29. return 1;
  30. }
  31. int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts)
  32. {
  33. int nrparts = 0;
  34. struct fis_image_desc *buf;
  35. struct mtd_partition *parts;
  36. struct fis_list *fl = NULL, *tmp_fl;
  37. int ret, i;
  38. size_t retlen;
  39. char *names;
  40. int namelen = 0;
  41. buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  42. if (!buf)
  43. return -ENOMEM;
  44. /* Read the start of the last erase block */
  45. ret = master->read(master, master->size - master->erasesize,
  46.    PAGE_SIZE, &retlen, (void *)buf);
  47. if (ret)
  48. goto out;
  49. if (retlen != PAGE_SIZE) {
  50. ret = -EIO;
  51. goto out;
  52. }
  53. /* RedBoot image could appear in any of the first three slots */
  54. for (i = 0; i < 3; i++) {
  55. if (!memcmp(buf[i].name, "RedBoot", 8))
  56. break;
  57. }
  58. if (i == 3) {
  59. /* Didn't find it */
  60. printk(KERN_NOTICE "No RedBoot partition table detected in %sn",
  61.        master->name);
  62. ret = 0;
  63. goto out;
  64. }
  65. for (i = 0; i < PAGE_SIZE / sizeof(struct fis_image_desc); i++) {
  66. struct fis_list *new_fl, **prev;
  67. if (buf[i].name[0] == 0xff)
  68. break;
  69. if (!redboot_checksum(&buf[i]))
  70. break;
  71. new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL);
  72. namelen += strlen(buf[i].name)+1;
  73. if (!new_fl) {
  74. ret = -ENOMEM;
  75. goto out;
  76. }
  77. new_fl->img = &buf[i];
  78. buf[i].flash_base &= master->size-1;
  79. /* I'm sure the JFFS2 code has done me permanent damage.
  80.  * I now think the following is _normal_
  81.  */
  82. prev = &fl;
  83. while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base)
  84. prev = &(*prev)->next;
  85. new_fl->next = *prev;
  86. *prev = new_fl;
  87. nrparts++;
  88. }
  89. if (fl->img->flash_base)
  90. nrparts++;
  91. for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
  92. if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base)
  93. nrparts++;
  94. }
  95. parts = kmalloc(sizeof(*parts)*nrparts + namelen, GFP_KERNEL);
  96. if (!parts) {
  97. ret = -ENOMEM;
  98. goto out;
  99. }
  100. names = (char *)&parts[nrparts];
  101. memset(parts, 0, sizeof(*parts)*nrparts + namelen);
  102. i=0;
  103. if (fl->img->flash_base) {
  104.        parts[0].name = "unallocated space";
  105.        parts[0].size = fl->img->flash_base;
  106.        parts[0].offset = 0;
  107. }
  108. for ( ; i<nrparts; i++) {
  109. parts[i].size = fl->img->size;
  110. parts[i].offset = fl->img->flash_base;
  111. parts[i].name = names;
  112. strcpy(names, fl->img->name);
  113. names += strlen(names)+1;
  114. if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) {
  115. i++;
  116. parts[i].offset = parts[i-1].size + parts[i-1].offset;
  117. parts[i].size = fl->next->img->flash_base - parts[i].offset;
  118. parts[i].name = "unallocated space";
  119. }
  120. tmp_fl = fl;
  121. fl = fl->next;
  122. kfree(tmp_fl);
  123. }
  124. ret = nrparts;
  125. *pparts = parts;
  126.  out:
  127. while (fl) {
  128. struct fis_list *old = fl;
  129. fl = fl->next;
  130. kfree(old);
  131. }
  132. kfree(buf);
  133. return ret;
  134. }
  135. EXPORT_SYMBOL(parse_redboot_partitions);
  136. MODULE_LICENSE("GPL");
  137. MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
  138. MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables");