1 /******************************************************************************
2 * partition_mt.c - MT6516 NAND partition managment Driver
4 * Copyright 2009-2010 MediaTek Co.,Ltd.
7 * This file provid the other drivers partition relative functions
10 * ----------------------------------------
11 * v1.0, 28 Feb 2011, mtk80134 written
12 * ----------------------------------------
13 ******************************************************************************/
15 #include <linux/slab.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/delay.h>
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/types.h>
22 #include <linux/wait.h>
23 #include <linux/spinlock.h>
24 #include <linux/mtd/nand_ecc.h>
25 #include <linux/platform_device.h>
26 #include <linux/proc_fs.h>
27 #include <linux/time.h>
28 #include <linux/miscdevice.h>
30 #include <linux/mtd/mtd.h>
31 #include <linux/mtd/nand.h>
32 #include <linux/mtd/partitions.h>
35 #include <asm/cacheflush.h>
36 #include <asm/uaccess.h>
38 #include <mach/mt_typedefs.h>
39 #include <mach/mt_clkmgr.h>
40 #include <mach/mtk_nand.h>
41 #include "board-custom.h"
43 //#include "partition.h"
44 #include <mach/board.h>
49 #if defined(MTK_MLC_NAND_SUPPORT)
50 extern bool MLC_DEVICE
;// to build pass xiaolei
53 unsigned long long partition_type_array
[PART_MAX_COUNT
];
55 pt_resident new_part
[PART_MAX_COUNT
];
56 pt_resident lastest_part
[PART_MAX_COUNT
];
57 unsigned char part_name
[PART_MAX_COUNT
][MAX_PARTITION_NAME_LEN
];
58 struct mtd_partition g_pasStatic_Partition
[PART_MAX_COUNT
];
60 //struct excel_info PartInfo[PART_MAX_COUNT];
62 #define MTD_SECFG_STR "seccnfg"
63 #define MTD_BOOTIMG_STR "boot"
64 #define MTD_ANDROID_STR "system"
65 #define MTD_SECRO_STR "secstatic"
66 #define MTD_USRDATA_STR "userdata"
71 u8 sig_buf
[PT_SIG_SIZE
];
72 //not support add new partition automatically.
74 extern struct mtd_partition g_pasStatic_Partition
[];
77 DM_PARTITION_INFO_PACKET pmtctl
;
78 struct mtd_partition g_exist_Partition
[PART_MAX_COUNT
];
81 //char page_buf[LPAGE+64];
82 //char page_readbuf[LPAGE];
87 #define PMT_READ _IOW(PMT_MAGIC, 1, int)
88 #define PMT_WRITE _IOW(PMT_MAGIC, 2, int)
89 #define PMT_VERSION _IOW(PMT_MAGIC, 3, int)
92 extern bool g_bInitDone
;
93 extern struct mtk_nand_host
*host
;
95 #if defined(MTK_SPI_NAND_SUPPORT)
96 extern snand_flashdev_info devinfo
;
98 extern flashdev_info_t devinfo
;
100 typedef u32 (*GetLowPageNumber
)(u32 pageNo
);
101 extern GetLowPageNumber functArray
[];
105 int (*read_pmt
) (char *buf
);
106 int (*write_pmt
) (char *buf
);
108 static struct pmt_config g_partition_fuc
;
110 static bool init_pmt_done
= FALSE
;
111 int new_part_tab(u8
* buf
, struct mtd_info
*mtd
);
112 int update_part_tab(struct mtd_info
*mtd
);
113 static int read_pmt(void __user
*arg
);
114 void get_part_tab_from_complier(void)
117 printk(KERN_INFO
"get_pt_from_complier \n");
119 memcpy(&g_exist_Partition
, &g_pasStatic_Partition
, sizeof(struct mtd_partition
) * PART_MAX_COUNT
);
122 while (g_pasStatic_Partition
[index
].size
!= MTDPART_SIZ_FULL
) //the last partition sizefull ==0
125 memcpy(lastest_part
[index
].name
, g_pasStatic_Partition
[index
].name
, MAX_PARTITION_NAME_LEN
);
126 lastest_part
[index
].size
= g_pasStatic_Partition
[index
].size
;
127 lastest_part
[index
].offset
= g_pasStatic_Partition
[index
].offset
;
128 lastest_part
[index
].mask_flags
= g_pasStatic_Partition
[index
].mask_flags
; //this flag in kernel should be fufilled even though in flash is 0.
129 printk(KERN_INFO
"get_ptr %s %llx \n", lastest_part
[index
].name
, lastest_part
[index
].offset
);
132 //get last partition info
133 memcpy(lastest_part
[index
].name
, g_pasStatic_Partition
[index
].name
, MAX_PARTITION_NAME_LEN
);
134 lastest_part
[index
].size
= g_pasStatic_Partition
[index
].size
;
135 lastest_part
[index
].offset
= g_pasStatic_Partition
[index
].offset
;
136 lastest_part
[index
].mask_flags
= g_pasStatic_Partition
[index
].mask_flags
; //this flag in kernel should be fufilled even though in flash is 0.
137 printk(KERN_INFO
"get_ptr %s %llx \n", lastest_part
[index
].name
, lastest_part
[index
].offset
);
141 u64
part_get_startaddress(u64 byte_address
, u32
*idx
)
144 if(TRUE
== init_pmt_done
)
146 while (index
< part_num
) {
147 //MSG(INIT, "g_exist_Partition[%d].offset %x\n",index, g_exist_Partition[index].offset);
148 if(g_exist_Partition
[index
].offset
> byte_address
)
150 //MSG(INIT, "find g_exist_Partition[%d].offset %x\n",index-1, g_exist_Partition[index-1].offset);
152 return g_exist_Partition
[index
-1].offset
;
161 bool raw_partition(u32 index
)
163 if(partition_type_array
[index
] == REGION_LOW_PAGE
)
169 int find_empty_page_from_top(u64 start_addr
, struct mtd_info
*mtd
)
171 int page_offset
;//,i;
173 #if defined(MTK_MLC_NAND_SUPPORT)
176 struct mtd_oob_ops ops_pt
;
177 struct erase_info ei
;
180 ei
.len
= mtd
->erasesize
;
185 ops_pt
.datbuf
= (uint8_t *) page_buf
;
186 ops_pt
.mode
= MTD_OPS_AUTO_OOB
;
187 ops_pt
.len
= mtd
->writesize
;
190 ops_pt
.oobretlen
= 0;
191 ops_pt
.oobbuf
= page_buf
+ page_size
;
193 memset(page_buf
, 0xFF, page_size
+ mtd
->oobsize
);
194 memset(page_readbuf
, 0xFF, page_size
);
195 //mt6577_nand_erase(start_addr); //for test
196 #if defined(MTK_MLC_NAND_SUPPORT)
197 for (page_offset
= 0,i
=0; page_offset
< (block_size
/ page_size
); page_offset
= functArray
[devinfo
.feature_set
.ptbl_idx
](i
++))
199 for (page_offset
= 0; page_offset
< (block_size
/ page_size
); page_offset
++)
202 current_add
= start_addr
+ (page_offset
* page_size
);
203 if (mtd
->_read_oob(mtd
, (loff_t
) current_add
, &ops_pt
) != 0)
205 printk(KERN_INFO
"find_emp read failed %llx \n", current_add
);
209 if (memcmp(page_readbuf
, page_buf
, page_size
) || memcmp(page_buf
+ page_size
, page_readbuf
, 32))
214 printk(KERN_INFO
"find_emp at %x \n", page_offset
);
220 printk(KERN_INFO
"find_emp find empty at %x \n", page_offset
);
223 //printk (KERN_INFO "test code %x \n",i);
224 //page_offset = 0x40;
225 if (page_offset
!= 0x40)
227 printk(KERN_INFO
"find_emp at %x\n", page_offset
);
231 printk(KERN_INFO
"find_emp no empty \n");
232 ei
.addr
= start_addr
;
233 if (mtd
->_erase(mtd
, &ei
) != 0)
234 { //no good block for used in replace pool
235 printk(KERN_INFO
"find_emp erase mirror failed %llx\n", start_addr
);
236 pi
.mirror_pt_has_space
= 0;
240 return 0; //the first page is empty
246 bool find_mirror_pt_from_bottom(u64
*start_addr
, struct mtd_info
* mtd
)
250 u64 current_start_addr
= 0;
252 struct mtd_oob_ops ops_pt
;
254 mpt_start_addr
= ((mtd
->size
) + block_size
);
255 //mpt_start_addr=MPT_LOCATION*block_size-page_size;
256 memset(page_buf
, 0xFF, page_size
+ mtd
->oobsize
);
258 ops_pt
.datbuf
= (uint8_t *) page_buf
;
259 ops_pt
.mode
= MTD_OPS_AUTO_OOB
;
260 ops_pt
.len
= mtd
->writesize
;
263 ops_pt
.oobretlen
= 0;
264 ops_pt
.oobbuf
= page_buf
+ page_size
;
266 printk(KERN_INFO
"find_mirror find begain at %llx \n", mpt_start_addr
);
268 for (mpt_locate
= ((block_size
/ page_size
) - 1),i
= ((block_size
/ page_size
) - 1); mpt_locate
>= 0; mpt_locate
--)//mpt_locate--)
270 memset(pmt_spare
, 0xFF, PT_SIG_SIZE
);
272 current_start_addr
= mpt_start_addr
+ mpt_locate
* page_size
;
273 if (mtd
->_read_oob(mtd
, (loff_t
) current_start_addr
, &ops_pt
) != 0)
275 printk(KERN_INFO
"find_mirror read failed %llx %x \n", current_start_addr
, mpt_locate
);
277 memcpy(pmt_spare
, &page_buf
[page_size
], PT_SIG_SIZE
); //auto do need skip bad block
278 //need enhance must be the larget sequnce number
282 for (i
= 0; i
< 8; i
++)
284 printk(KERN_INFO
"%x %x \n", page_buf
[i
], page_buf
[2048 + i
]);
289 if (is_valid_mpt(page_buf
) && is_valid_mpt(pmt_spare
))
291 //if no pt, pt.has space is 0;
292 pi
.sequencenumber
= page_buf
[PT_SIG_SIZE
+ page_size
];
293 printk(KERN_INFO
"find_mirror find valid pt at %llx sq %x \n", current_start_addr
, pi
.sequencenumber
);
300 if (mpt_locate
== -1)
302 printk(KERN_INFO
"no valid mirror page\n");
303 pi
.sequencenumber
= 0;
307 *start_addr
= current_start_addr
;
312 //int load_exist_part_tab(u8 *buf,struct mtd_info *mtd)
313 int load_exist_part_tab(u8
* buf
)
318 int reval
= DM_ERR_OK
;
321 //u8 pmt_spare[PT_SIG_SIZE];
322 struct mtd_oob_ops ops_pt
;
323 struct mtd_info
*mtd
;
327 block_size
= mtd
->erasesize
; // devinfo.blocksize*1024;
328 page_size
= mtd
->writesize
; // devinfo.pagesize;
329 //if(host->hw->nand_sec_shift == 10) //MLC
330 // block_size = block_size >> 1;
331 pt_start_addr
= (mtd
->size
);
332 //pt_start_addr=PT_LOCATION*block_size;
333 printk(KERN_INFO
"load_exist_part_tab %llx\n", pt_start_addr
);
334 ops_pt
.datbuf
= (uint8_t *) page_buf
;
335 ops_pt
.mode
= MTD_OPS_AUTO_OOB
;
336 ops_pt
.len
= mtd
->writesize
;
339 ops_pt
.oobretlen
= 0;
340 ops_pt
.oobbuf
= (page_buf
+ page_size
);
343 printk(KERN_INFO
"ops_pt.len %x \n", ops_pt
.len
);
344 if (mtd
->_read_oob
== NULL
)
346 printk(KERN_INFO
"shoud not happpen \n");
349 for (pt_locate
= 0,i
= 0; pt_locate
< (block_size
/ page_size
); pt_locate
++)
351 pt_cur_addr
= pt_start_addr
+ pt_locate
* page_size
;
352 //memset(pmt_spare,0xFF,PT_SIG_SIZE);
354 //printk (KERN_INFO "load_pt read pt %x \n",pt_cur_addr);
356 if (mtd
->_read_oob(mtd
, (loff_t
) pt_cur_addr
, &ops_pt
) != 0)
358 printk(KERN_INFO
"load_pt read pt failded: %llx\n", (u64
) pt_cur_addr
);
363 for (i
= 0; i
< 8; i
++)
365 printk(KERN_INFO
"%x %x \n", *(page_buf
+ i
), *(page_buf
+ 2048 + i
));
370 //memcpy(pmt_spare,&page_buf[LPAGE] ,PT_SIG_SIZE); //do not need skip bad block flag
371 if (is_valid_pt(page_buf
) && is_valid_pt(page_buf
+ mtd
->writesize
))
373 pi
.sequencenumber
= page_buf
[PT_SIG_SIZE
+ page_size
];
374 printk(KERN_INFO
"load_pt find valid pt at %llx sq %x \n", pt_start_addr
, pi
.sequencenumber
);
382 //pt_locate=(block_size/page_size);
383 if (pt_locate
== (block_size
/ page_size
))
385 //first download or download is not compelte after erase or can not download last time
386 printk(KERN_INFO
"load_pt find pt failed \n");
387 pi
.pt_has_space
= 0; //or before download pt power lost
389 if (!find_mirror_pt_from_bottom(&mirror_address
, mtd
))
391 printk(KERN_INFO
"First time download \n");
392 reval
= ERR_NO_EXIST
;
396 //used the last valid mirror pt, at lease one is valid.
397 mtd
->_read_oob(mtd
, (loff_t
) mirror_address
, &ops_pt
);
400 memcpy(&lastest_part
, &page_buf
[PT_SIG_SIZE
], sizeof(lastest_part
));
405 static int pmt_open(struct inode
*inode
, struct file
*filp
)
407 printk(KERN_INFO
"[%s]:(MAJOR)%d:(MINOR)%d\n", __func__
, MAJOR(inode
->i_rdev
), MINOR(inode
->i_rdev
));
408 //filp->private_data = (int*);
412 static int pmt_release(struct inode
*inode
, struct file
*filp
)
414 printk(KERN_INFO
"[%s]:(MAJOR)%d:(MINOR)%d\n", __func__
, MAJOR(inode
->i_rdev
), MINOR(inode
->i_rdev
));
418 static long pmt_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
420 long ret
= 0; // , i=0;
421 ulong version
= PT_SIG
;
423 void __user
*uarg
= (void __user
*)arg
;
424 printk(KERN_INFO
"PMT IOCTL: Enter\n");
427 if (false == g_bInitDone
)
429 printk(KERN_INFO
"ERROR: NAND Flash Not initialized !!\n");
437 printk(KERN_INFO
"PMT IOCTL: PMT_READ\n");
438 ret
= read_pmt(uarg
);
441 printk(KERN_INFO
"PMT IOCTL: PMT_WRITE\n");
442 if (copy_from_user(&pmtctl
, uarg
, sizeof(DM_PARTITION_INFO_PACKET
)))
447 new_part_tab((u8
*) & pmtctl
, (struct mtd_info
*)&host
->mtd
);
448 update_part_tab((struct mtd_info
*)&host
->mtd
);
452 if(copy_to_user((void __user
*)arg
,&version
,PT_SIG_SIZE
))
463 static int read_pmt(void __user
*arg
)
465 printk(KERN_ERR
"read_pmt\n");
467 if(copy_to_user(arg
,&lastest_part
,sizeof(pt_resident
)*PART_MAX_COUNT
))
472 static struct file_operations pmt_fops
= {
473 .owner
= THIS_MODULE
,
474 .unlocked_ioctl
= pmt_ioctl
,
476 .release
= pmt_release
,
479 static struct miscdevice pmt_dev
= {
480 .minor
= MISC_DYNAMIC_MINOR
,
485 static int lowercase(int c
)
487 if((c
>= 'A') && (c
<= 'Z'))
492 void construct_mtd_partition(struct mtd_info
*mtd
)
495 for(i
= 0; i
< PART_MAX_COUNT
; i
++)
497 //if((lastest_part[i].size == 0) && (strcmp(lastest_part[i].name,"BMTPOOL")))
499 if(!strcmp(lastest_part
[i
-1].name
,"BMTPOOL"))
502 for(j
=0; j
< MAX_PARTITION_NAME_LEN
; j
++)
504 if(lastest_part
[i
].name
[j
] == 0)
506 part_name
[i
][j
] = lowercase(lastest_part
[i
].name
[j
]);
508 PartInfo
[i
].name
= part_name
[i
];
509 g_exist_Partition
[i
].name
= part_name
[i
];
510 if(!strcmp(lastest_part
[i
].name
,"SECCFG"))
511 g_exist_Partition
[i
].name
= MTD_SECFG_STR
;
513 if(!strcmp(lastest_part
[i
].name
,"BOOTIMG"))
514 g_exist_Partition
[i
].name
= MTD_BOOTIMG_STR
;
516 if(!strcmp(lastest_part
[i
].name
,"SEC_RO"))
517 g_exist_Partition
[i
].name
= MTD_SECRO_STR
;
519 if(!strcmp(lastest_part
[i
].name
,"ANDROID"))
520 g_exist_Partition
[i
].name
= MTD_ANDROID_STR
;
522 if(!strcmp(lastest_part
[i
].name
,"USRDATA"))
523 g_exist_Partition
[i
].name
= MTD_USRDATA_STR
;
525 g_exist_Partition
[i
].size
= (uint64_t) lastest_part
[i
].size
;//mtd partition
526 g_exist_Partition
[i
].offset
= (uint64_t) lastest_part
[i
].offset
;
528 g_exist_Partition
[i
].mask_flags
= lastest_part
[i
].mask_flags
;
530 //PartInfo[i].name = part_name[i]; //dumchar
531 PartInfo
[i
].type
= NAND
;
532 PartInfo
[i
].start_address
= lastest_part
[i
].offset
;
533 PartInfo
[i
].size
= lastest_part
[i
].size
;
534 partition_type_array
[i
]= lastest_part
[i
].part_id
;
535 printk("partition %s %s size %llx\n", lastest_part
[i
].name
,PartInfo
[i
].name
, g_exist_Partition
[i
].offset
);
538 if(MLC_DEVICE
== TRUE
)
540 mtd
->eraseregions
[i
].offset
= lastest_part
[i
].offset
;
541 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
;
543 if(partition_type_array
[i
] == REGION_LOW_PAGE
)
545 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
/2;
548 mtd
->numeraseregions
++;
553 g_exist_Partition
[i
-1].size
= MTDPART_SIZ_FULL
;
556 void part_init_pmt(struct mtd_info
*mtd
, u8
* buf
)
558 struct mtd_partition
*part
;
563 printk(KERN_INFO
"part_init_pmt %s\n", __TIME__
);
564 page_buf
= kzalloc(mtd
->writesize
+ mtd
->oobsize
, GFP_KERNEL
);
565 page_readbuf
= kzalloc(mtd
->writesize
, GFP_KERNEL
);
567 part
= &g_pasStatic_Partition
[0];
568 lastblk
= part
->offset
+ part
->size
;
569 printk(KERN_INFO
"offset %llx part->size %llx %s\n", part
->offset
, part
->size
, part
->name
);
574 if(part
->offset
== MTDPART_OFS_APPEND
)
575 part
->offset
= lastblk
;
576 lastblk
= part
->offset
+ part
->size
;
577 printk(KERN_INFO
"mt_part_init_pmt %llx\n", part
->offset
);
578 if (part
->size
== 0) ////the last partition sizefull ==0
585 memset(&pi
, 0xFF, sizeof(pi
));
586 memset(&lastest_part
, 0, PART_MAX_COUNT
* sizeof(pt_resident
));
587 retval
= load_exist_part_tab(buf
);
589 if (retval
== ERR_NO_EXIST
) //first run preloader before dowload
591 //and valid mirror last download or first download
592 printk(KERN_INFO
"%s no pt \n", __func__
);
593 get_part_tab_from_complier(); //get from complier
594 if(MLC_DEVICE
== TRUE
)
595 mtd
->numeraseregions
= 0;
596 for (i
= 0; i
< part_num
; i
++)
599 if(MLC_DEVICE
== TRUE
)
601 mtd
->eraseregions
[i
].offset
= lastest_part
[i
].offset
;
602 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
;
603 if(partition_type_array
[i
] == REGION_LOW_PAGE
)
605 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
/2;
608 mtd
->numeraseregions
++;
614 printk(KERN_INFO
"Find pt or mpt \n");
615 if(MLC_DEVICE
== TRUE
)
616 mtd
->numeraseregions
= 0;
618 memcpy(&g_exist_Partition
, &g_pasStatic_Partition
, sizeof(struct mtd_partition
) * part_num
);
619 for (i
= 0; i
< part_num
; i
++)
621 printk(KERN_INFO
"partition %s size %llx %llx \n", lastest_part
[i
].name
, lastest_part
[i
].offset
, lastest_part
[i
].size
);
622 //still use the name in g_pasSatic_partition
623 g_exist_Partition
[i
].size
= lastest_part
[i
].size
;
624 g_exist_Partition
[i
].offset
= lastest_part
[i
].offset
;
626 if(MLC_DEVICE
== TRUE
)
628 mtd
->eraseregions
[i
].offset
= lastest_part
[i
].offset
;
629 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
;
630 #if 0//to build pass xiaolei
631 if(partition_type_array
[i
] == TYPE_RAW
)
633 mtd
->eraseregions
[i
].erasesize
= mtd
->erasesize
/2;
636 mtd
->numeraseregions
++;
639 //still use the mask flag in g_pasSatic_partition
640 if (i
== (part_num
- 1))
642 g_exist_Partition
[i
].size
= MTDPART_SIZ_FULL
;
644 printk(KERN_INFO
"partition %s size %llx\n", lastest_part
[i
].name
, g_exist_Partition
[i
].offset
);
647 construct_mtd_partition(mtd
);
649 init_pmt_done
= TRUE
;
651 printk(KERN_INFO
": register NAND PMT device ...\n");
652 #ifndef MTK_EMMC_SUPPORT
654 err
= misc_register(&pmt_dev
);
657 printk(KERN_INFO
"PMT failed to register device!\n");
663 int new_part_tab(u8
* buf
, struct mtd_info
*mtd
)
665 DM_PARTITION_INFO_PACKET
*dm_part
= (DM_PARTITION_INFO_PACKET
*) buf
;
666 int part_num
, change_index
, i
= 0;
669 u64 start_addr
= (u64
)((mtd
->size
) + block_size
);
670 u64 current_addr
= 0;
671 struct mtd_oob_ops ops_pt
;
674 pi
.tool_or_sd_update
= 2; //tool download is 1.
676 ops_pt
.mode
= MTD_OPS_AUTO_OOB
;
677 ops_pt
.len
= mtd
->writesize
;
680 ops_pt
.oobretlen
= 0;
681 ops_pt
.oobbuf
= page_buf
+ page_size
;
683 //the first image is ?
685 for (part_num
= 0; part_num
< PART_MAX_COUNT
; part_num
++)
687 memcpy(new_part
[part_num
].name
, dm_part
->part_info
[part_num
].part_name
, MAX_PARTITION_NAME_LEN
);
688 new_part
[part_num
].offset
= dm_part
->part_info
[part_num
].start_addr
;
689 new_part
[part_num
].size
= dm_part
->part_info
[part_num
].part_len
;
690 new_part
[part_num
].mask_flags
= 0;
691 //MSG (INIT, "DM_PARTITION_INFO_PACKET %s size %x %x \n",dm_part->part_info[part_num].part_name,dm_part->part_info[part_num].part_len,part_num);
692 printk(KERN_INFO
"new_pt %s size %llx \n", new_part
[part_num
].name
, new_part
[part_num
].size
);
693 if (dm_part
->part_info
[part_num
].part_len
== 0)
695 printk(KERN_INFO
"new_pt last %x \n", part_num
);
703 memcpy(&new_part
[0], &lastest_part
[0], sizeof(new_part
));
704 MSG(INIT
, "new_part %x size \n", sizeof(new_part
));
705 for (i
= 0; i
< part_num
; i
++)
707 MSG(INIT
, "npt partition %s size \n", new_part
[i
].name
);
708 //MSG (INIT, "npt %x size \n",new_part[i].offset);
709 //MSG (INIT, "npt %x size \n",lastest_part[i].offset);
710 //MSG (INIT, "npt %x size \n",new_part[i].size);
711 dm_part
->part_info
[5].part_visibility
= 1;
712 dm_part
->part_info
[5].dl_selected
= 1;
713 new_part
[5].size
= lastest_part
[5].size
+ 0x100000;
716 //------------for test
717 //Find the first changed partition, whether is visible
718 for (change_index
= 0; change_index
<= part_num
; change_index
++)
720 if ((new_part
[change_index
].size
!= lastest_part
[change_index
].size
) || (new_part
[change_index
].offset
!= lastest_part
[change_index
].offset
))
722 printk(KERN_INFO
"new_pt %x size changed from %llx to %llx\n", change_index
, lastest_part
[change_index
].size
, new_part
[change_index
].size
);
728 if (pi
.pt_changed
== 1)
730 //Is valid image update
731 for (i
= change_index
; i
<= part_num
; i
++)
734 if (dm_part
->part_info
[i
].dl_selected
== 0 && dm_part
->part_info
[i
].part_visibility
== 1)
736 printk(KERN_INFO
"Full download is need %x \n", i
);
737 retval
= DM_ERR_NO_VALID_TABLE
;
742 pageoffset
= find_empty_page_from_top(start_addr
, mtd
);
743 //download partition used the new partition
744 //write mirror at the same 2 page
745 memset(page_buf
, 0xFF, page_size
+ 64);
746 *(int *)sig_buf
= MPT_SIG
;
747 memcpy(page_buf
, &sig_buf
, PT_SIG_SIZE
);
748 memcpy(&page_buf
[PT_SIG_SIZE
], &new_part
[0], sizeof(new_part
));
749 memcpy(&page_buf
[page_size
], &sig_buf
, PT_SIG_SIZE
);
750 pi
.sequencenumber
+= 1;
751 memcpy(&page_buf
[page_size
+ PT_SIG_SIZE
], &pi
, PT_SIG_SIZE
);
753 if (pageoffset
!= 0xFFFF)
755 if ((pageoffset
% 2) != 0)
757 printk(KERN_INFO
"new_pt mirror block may destroy last time%x\n", pageoffset
);
760 for (i
= 0; i
< 2; i
++)
762 current_addr
= start_addr
+ (pageoffset
+ i
) * page_size
;
763 ops_pt
.datbuf
= (uint8_t *) page_buf
;
764 if (mtd
->_write_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0)
766 printk(KERN_INFO
"new_pt write m first page failed %llx\n", current_addr
);
769 printk(KERN_INFO
"new_pt write mirror at %llx\n", current_addr
);
770 ops_pt
.datbuf
= (uint8_t *) page_readbuf
;
772 if ((mtd
->_read_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0) || memcmp(page_buf
, page_readbuf
, page_size
))
774 printk(KERN_INFO
"new_pt read or verify first mirror page failed %llx \n", current_addr
);
775 ops_pt
.datbuf
= (uint8_t *) page_buf
;
776 memset(page_buf
, 0, PT_SIG_SIZE
);
777 if (mtd
->_read_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0)
779 printk(KERN_INFO
"new_pt mark failed %llx\n", current_addr
);
783 printk(KERN_INFO
"new_pt write mirror ok %x\n", i
);
784 //any one success set this flag?
792 printk(KERN_INFO
"new_part_tab no pt change %x\n", i
);
799 int update_part_tab(struct mtd_info
*mtd
)
804 u64 start_addr
= (u64
)(mtd
->size
); //PT_LOCATION*block_size;
805 u64 current_addr
= 0;
806 struct erase_info ei
;
807 struct mtd_oob_ops ops_pt
;
809 memset(page_buf
, 0xFF, page_size
+ 64);
812 ei
.len
= mtd
->erasesize
;
817 ops_pt
.mode
= MTD_OPS_AUTO_OOB
;
818 ops_pt
.len
= mtd
->writesize
;
821 ops_pt
.oobretlen
= 0;
822 ops_pt
.oobbuf
= page_buf
+ page_size
;
825 if ((pi
.pt_changed
== 1 || pi
.pt_has_space
== 0) && pi
.tool_or_sd_update
== 2)
827 printk(KERN_INFO
"update_pt pt changes\n");
829 ei
.addr
= start_addr
;
830 if (mtd
->_erase(mtd
, &ei
) != 0)
831 { //no good block for used in replace pool
832 printk(KERN_INFO
"update_pt erase failed %llx\n", start_addr
);
833 if (pi
.mirror_pt_dl
== 0)
834 retval
= DM_ERR_NO_SPACE_FOUND
;
838 for (retry_r
= 0; retry_r
< RETRY_TIMES
; retry_r
++)
840 for (retry_w
= 0; retry_w
< RETRY_TIMES
; retry_w
++)
842 current_addr
= start_addr
+ (retry_w
+ retry_r
* RETRY_TIMES
) * page_size
;
843 *(int *)sig_buf
= PT_SIG
;
844 memcpy(page_buf
, &sig_buf
, PT_SIG_SIZE
);
845 memcpy(&page_buf
[PT_SIG_SIZE
], &new_part
[0], sizeof(new_part
));
846 memcpy(&page_buf
[page_size
], &sig_buf
, PT_SIG_SIZE
);
847 memcpy(&page_buf
[page_size
+ PT_SIG_SIZE
], &pi
, PT_SIG_SIZE
);
849 ops_pt
.datbuf
= (uint8_t *) page_buf
;
850 if (mtd
->_write_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0)
851 { //no good block for used in replace pool . still used the original ones
852 printk(KERN_INFO
"update_pt write failed %x\n", retry_w
);
853 memset(page_buf
, 0, PT_SIG_SIZE
);
854 if (mtd
->_write_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0)
856 printk(KERN_INFO
"write error mark failed\n");
862 printk(KERN_INFO
"write pt success %llx %x \n", current_addr
, retry_w
);
863 break; // retry_w should not count.
866 if (retry_w
== RETRY_TIMES
)
868 printk(KERN_INFO
"update_pt retry w failed\n");
869 if (pi
.mirror_pt_dl
== 0) //mirror also can not write down
871 retval
= DM_ERR_NO_SPACE_FOUND
;
878 current_addr
= (start_addr
+ (((retry_w
) + retry_r
* RETRY_TIMES
) * page_size
));
879 ops_pt
.datbuf
= (uint8_t *) page_readbuf
;
880 if ((mtd
->_read_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0) || memcmp(page_buf
, page_readbuf
, page_size
))
883 printk(KERN_INFO
"v or r failed %x\n", retry_r
);
884 memset(page_buf
, 0, PT_SIG_SIZE
);
885 ops_pt
.datbuf
= (uint8_t *) page_buf
;
886 if (mtd
->_write_oob(mtd
, (loff_t
) current_addr
, &ops_pt
) != 0)
888 printk(KERN_INFO
"read error mark failed\n");
895 printk(KERN_INFO
"update_pt r&v ok%llx\n", current_addr
);
901 printk(KERN_INFO
"update_pt no change \n");
906 int get_part_num_nand()
911 EXPORT_SYMBOL(get_part_num_nand
);