squashfs和cramfs作为根文件系统时让MTD支持跳过坏块

概述

Squashfs一般存放于nor flash中,但是也可以使用Nand flash存储squashfs文件系统,但是需要绕过坏块。

 

算法描述

在bootloader中烧写squashfs分区时,顺序的将squashfs烧到Nand flash中,如果碰上坏块,则顺序写入下一个好块。例如:#2是坏块,则数据写到#1, #3, #4,…上面。

引导linux后,在mtd相应的squashfs分区上面建立一个逻辑块与物理块的映射表。逻辑块表示squashfs要访问的块地址,而物理块表示实际存储的物理块地址。

同上例,#2是坏块,则逻辑块与物理块的映射关系建立如下:

logic[0] = phys[0],

logic[1]=phys[1],

logic[2]=phys[3],

logic[3]=phys[4],

建立映射关系后,就知道squash访问的地址对应的物理地址了。

 

程序实现:

 

声明结构:

struct part_map{

    struct mtd_info *part_mtd;  /* Mapping partition mtd */

    unsigned *map_table;        /* Mapping from logic block to phys block */

    unsigned nBlock;            /* Logic block number */

};

 

修改nandpart.c即可实现。

1. 声明一个partition mapping表。

2. 在add_mtd_partitions()函数中,当mtd分驱创建成功后,创建partition mapping表。

3. 在part_read ()函数中时,如果匹配到partition mapping的part_mtd,则先通过map_table获取到物理地址后,再调用part->master->read_ecc读取nand flash中的数据。

4. 在del_mtd_partitions()函数中,匹配到partition mapping分区,则删除之.

 

原码补丁如下:

[cpp]  view plain copy
  1. --- linux-2.6.10/drivers/mtd/mtdpart.c  2005-01-13 05:59:48.000000000 +0800  
  2. +++ linux-2.6.10-mips-dev/drivers/mtd/mtdpart.c 2009-03-12 18:50:44.000000000 +0800  
  3. @@ -22,6 +22,22 @@  
  4.  #include <linux/mtd/partitions.h>  
  5.  #include <linux/mtd/compatmac.h>  
  6.    
  7. +/* Walson: definicate two mapping table for squashfs 
  8. + * partition, because squashfs do not know bad block. 
  9. + * So the we have do the valid mapping between logic block 
  10. + * and phys block 
  11. + */   
  12. +#include <linux/mtd/nand.h>  
  13. +#define MAX_PARTITION_MAPPING   2  
  14. +struct part_map{  
  15. +    struct mtd_info *part_mtd;  /* Mapping partition mtd */  
  16. +    unsigned *map_table;        /* Mapping from logic block to phys block */  
  17. +    unsigned nBlock;            /* Logic block number */  
  18. +};  
  19. +  
  20. +static struct part_map *part_mapping[MAX_PARTITION_MAPPING];  
  21. +static int part_mapping_count = -1;  
  22. +  
  23.  /* Our partition linked list */  
  24.  static LIST_HEAD(mtd_partitions);  
  25.    
  26. @@ -51,6 +67,35 @@  
  27.             size_t *retlen, u_char *buf)  
  28.  {  
  29.     struct mtd_part *part = PART(mtd);  
  30. +  
  31. +    /* Walson: calucate physical address */  
  32. +    struct nand_chip *this = part->master->priv;      
  33. +    unsigned logic_b, phys_b;  
  34. +    unsigned i;  
  35. +  
  36. +    if ( part_mapping_count > 0 )  
  37. +    {  
  38. +        for ( i=0; i<MAX_PARTITION_MAPPING; i++ )  
  39. +        {  
  40. +            if ( part_mapping[i] && part_mapping[i]->part_mtd==mtd )  
  41. +            {  
  42. +                /* remap from logic block to physical block */  
  43. +                logic_b = from >> this->bbt_erase_shift;  
  44. +                if ( logic_b < part_mapping[i]->nBlock )  
  45. +                {  
  46. +                    phys_b = part_mapping[i]->map_table[logic_b];  
  47. +                    from = phys_b << this->bbt_erase_shift | (from&(mtd->erasesize-1));  
  48. +                }  
  49. +                else  
  50. +                {  
  51. +                    /* the offset is bigger than good block range, don't read data */  
  52. +                    *retlen = 0;  
  53. +                    return -EINVAL;  
  54. +                }  
  55. +            }  
  56. +        }  
  57. +    }  
  58. +      
  59.     if (from >= mtd->size)  
  60.         len = 0;  
  61.     else if (from + len > mtd->size)  
  62. @@ -201,6 +246,35 @@  
  63.              unsigned long count, loff_t from, size_t *retlen)  
  64.  {  
  65.     struct mtd_part *part = PART(mtd);  
  66. +  
  67. +    /* Walson: calucate physical address */  
  68. +    struct nand_chip *this = part->master->priv;      
  69. +    unsigned logic_b, phys_b;  
  70. +    unsigned i;  
  71. +      
  72. +    if ( part_mapping_count > 0 )  
  73. +    {  
  74. +        for ( i=0; i<MAX_PARTITION_MAPPING; i++ )  
  75. +        {  
  76. +            if ( part_mapping[i] && part_mapping[i]->part_mtd==mtd )  
  77. +            {  
  78. +                /* remap from logic block to physical block */  
  79. +                logic_b = from >> this->bbt_erase_shift;  
  80. +                if ( logic_b < part_mapping[i]->nBlock )  
  81. +                {  
  82. +                    phys_b = part_mapping[i]->map_table[logic_b];  
  83. +                    from = phys_b << this->bbt_erase_shift | (from&(mtd->erasesize-1));  
  84. +                }  
  85. +                else  
  86. +                {  
  87. +                    /* the offset is bigger than good block range, don't read data */  
  88. +                    *retlen = 0;  
  89. +                    return -EINVAL;  
  90. +                }  
  91. +            }  
  92. +        }  
  93. +    }  
  94. +      
  95.     if (part->master->readv_ecc == NULL)    
  96.         return part->master->readv (part->master, vecs, count,  
  97.                     from + part->offset, retlen);  
  98. @@ -317,6 +391,107 @@  
  99.     return part->master->block_markbad(part->master, ofs);  
  100.  }  
  101.    
  102. +  
  103. +/* Walson: 
  104. + * This function create a partition mapping  
  105. + */  
  106. +static int part_create_partition_mapping ( struct mtd_info *part_mtd )  
  107. +{  
  108. +    struct mtd_part *part = PART(part_mtd);  
  109. +    struct nand_chip *this = part->master->priv;      
  110. +    struct part_map *map_part;      
  111. +    int index;  
  112. +    unsigned offset;  
  113. +    int logical_b, phys_b;  
  114. +  
  115. +    if ( !part_mtd || !this )  
  116. +    {  
  117. +        printk("null mtd or it is no nand chip!");  
  118. +        return -1;  
  119. +    }      
  120. +      
  121. +    if ( part_mapping_count < 0 )  
  122. +    {  
  123. +        /* Init the part mapping table when this function called first time */  
  124. +        memset(part_mapping, 0, sizeof(struct part_map *)*MAX_PARTITION_MAPPING);  
  125. +        part_mapping_count = 0;  
  126. +    }  
  127. +  
  128. +    for ( index=0; index<MAX_PARTITION_MAPPING; index++ )  
  129. +    {  
  130. +        if ( part_mapping[index] == NULL )  
  131. +            break;  
  132. +    }  
  133. +  
  134. +    if ( index >= MAX_PARTITION_MAPPING )  
  135. +    {  
  136. +        printk("partition mapping is full!");  
  137. +        return -1;  
  138. +    }  
  139. +  
  140. +    map_part = kmalloc(sizeof(struct part_map), GFP_KERNEL);  
  141. +    if ( !map_part )  
  142. +    {  
  143. +        printk ("memory allocation error while creating partitions mapping for %s/n",  
  144. +                part_mtd->name);       
  145. +        return -1;  
  146. +    }  
  147. +  
  148. +    map_part->map_table = kmalloc(sizeof(unsigned)*(part_mtd->size>>this->bbt_erase_shift),  
  149. +                                  GFP_KERNEL);  
  150. +    if ( !map_part->map_table )  
  151. +    {  
  152. +        printk ("memory allocation error while creating partitions mapping for %s/n",  
  153. +                part_mtd->name);  
  154. +        kfree(map_part);  
  155. +        return -1;  
  156. +    }  
  157. +    memset(map_part->map_table, 0xFF, sizeof(unsigned)*(part_mtd->size>>this->bbt_erase_shift));  
  158. +  
  159. +    /* Create partition mapping table */  
  160. +    logical_b = 0;  
  161. +    for ( offset=0; offset<part_mtd->size; offset+=part_mtd->erasesize )  
  162. +    {  
  163. +        if ( part_mtd->block_isbad &&  
  164. +             part_mtd->block_isbad(part_mtd, offset) )  
  165. +             continue;          
  166. +  
  167. +        phys_b = offset >> this->bbt_erase_shift;  
  168. +        map_part->map_table[logical_b] = phys_b;  
  169. +        printk("part[%s]: logic[%u]=phys[%u]/n",   
  170. +              part_mtd->name, logical_b, phys_b);              
  171. +        logical_b++;  
  172. +    }  
  173. +    map_part->nBlock = logical_b;  
  174. +    map_part->part_mtd = part_mtd;  
  175. +      
  176. +    part_mapping[index] = map_part;  
  177. +    part_mapping_count++;  
  178. +    return 0;  
  179. +}  
  180. +  
  181. +static void part_del_partition_mapping( struct mtd_info *part_mtd )  
  182. +{  
  183. +    int index;  
  184. +    struct part_map *map_part;      
  185. +  
  186. +    if ( part_mapping_count > 0 )  
  187. +    {  
  188. +        for ( index=0; index<MAX_PARTITION_MAPPING; index++ )  
  189. +        {  
  190. +            map_part = part_mapping[index];          
  191. +            if ( map_part && map_part->part_mtd==part_mtd )  
  192. +            {  
  193. +                kfree(map_part->map_table);  
  194. +                kfree(map_part);  
  195. +                part_mapping[index] = NULL;                     
  196. +                part_mapping_count--;  
  197. +            }  
  198. +        }  
  199. +    }  
  200. +}  
  201. +  
  202. +  
  203.  /*  
  204.   * This function unregisters and destroy all slave MTD objects which are  
  205.   * attached to the given master MTD object. 
  206. @@ -333,6 +508,9 @@ 
  207.         slave = list_entry(node, struct mtd_part, list); 
  208.         if (slave->master == master) { 
  209.             struct list_head *prev = node->prev; 
  210. +             
  211. +           /* walson: Free partition mapping if created */  
  212. +           part_del_partition_mapping(&slave->mtd);  
  213.             __list_del(prev, node->next);  
  214.             if(slave->registered)  
  215.                 del_mtd_device(&slave->mtd);  
  216. @@ -513,6 +691,19 @@  
  217.         {  
  218.             /* register our partition */  
  219.             add_mtd_device(&slave->mtd);  
  220. +  
  221. +           /* Walson: Build partition mapping for squashfs */              
  222. +           if ( slave->mtd.name && 0==strcmp(slave->mtd.name, "base") )  
  223. +           {                                  
  224. +               part_create_partition_mapping(&slave->mtd);  
  225. +           }  
  226. +           else if ( slave->mtd.name && 0==strcmp(slave->mtd.name, "prog") )  
  227. +           {  
  228. +               part_create_partition_mapping(&slave->mtd);                  
  229. +           }  
  230. +           else  
  231. +           {  
  232. +           }  
  233.             slave->registered = 1;  
  234.         }  
  235.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值