tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / property / normal_nand_mode.c
1 #include "normal_mode.h"
2
3 #ifdef CONFIG_OF_LIBFDT
4 #include "dev_tree.h"
5 #endif
6
7 #define KERNL_PAGE_SIZE 2048
8
9 #ifdef CONFIG_SUPPORT_TD
10 static vol_image_required_t s_boot_image_TD_table[]={
11         {"tdfixnv1","tdfixnv2",FIXNV_SIZE,TDFIXNV_ADR,IMG_RAW},
12         {"tdruntimenv1","tdruntimenv2",RUNTIMENV_SIZE,TDRUNTIMENV_ADR,IMG_RAW},
13         {"tdmodem",NULL,TDMODEM_SIZE,TDMODEM_ADR,IMG_RAW},
14         {"tddsp",NULL,TDDSP_SIZE,TDDSP_ADR,IMG_RAW},
15         {NULL,NULL,0,0,IMG_MAX}
16 };
17 #endif
18
19 #ifdef CONFIG_SUPPORT_W
20 static vol_image_required_t s_boot_image_W_table[]={
21         {"wfixnv1","wfixnv2",FIXNV_SIZE,WFIXNV_ADR,IMG_RAW},
22         {"wruntimenv1","wruntimenv2",RUNTIMENV_SIZE,WRUNTIMENV_ADR,IMG_RAW},
23         {"wdsp",NULL,WDSP_SIZE,WDSP_ADR,IMG_RAW},
24         {"wmodem",NULL,WMODEM_SIZE,WMODEM_ADR,IMG_RAW},
25         {NULL,NULL,0,0,IMG_MAX}
26 };
27 #endif
28
29 #ifdef CONFIG_SUPPORT_WIFI
30 static vol_image_required_t s_boot_image_WIFI_table[]={
31         {"wcnfixnv1","wcnfixnv2",FIXNV_SIZE,WCNFIXNV_ADR,IMG_RAW},
32         {"wcnruntimenv1","wcnruntimenv2",RUNTIMENV_SIZE,WCNRUNTIMENV_ADR,IMG_RAW},
33         {"wcnmodem",NULL,WCNMODEM_SIZE,WCNMODEM_ADR,IMG_RAW},
34         {NULL,NULL,0,0,IMG_MAX}
35 };
36 #endif
37
38 static vol_image_required_t* s_boot_image_table[]={
39 #ifdef CONFIG_SUPPORT_TD
40         s_boot_image_TD_table,
41 #endif
42
43 #ifdef CONFIG_SUPPORT_W
44         s_boot_image_W_table,
45 #endif
46
47 #ifdef CONFIG_SUPPORT_WIFI
48         s_boot_image_WIFI_table,
49 #endif
50         0
51 };
52
53
54
55 long long load_image_time = 0;
56
57 int read_logoimg(char *bmp_img,size_t size)
58 {
59         //TODO
60         return 0;
61 }
62
63 int read_spldata()
64 {
65     struct mtd_device *dev;
66     struct part_info *part;
67     u8 pnum;
68     loff_t off = 0;
69     struct mtd_info *nand;
70     int size = CONFIG_SPL_LOAD_LEN;
71
72     int ret = find_dev_and_part(SPL_PART, &dev, &pnum, &part);
73     if (ret) {
74         printf("No partition named %s\n", SPL_PART);
75         return -1;
76     } else if (dev->id->type != MTD_DEV_TYPE_NAND) {
77         printf("Partition %s not a NAND device\n", SPL_PART);
78         return -1;
79     }
80     off = part->offset;
81     nand = &nand_info[dev->id->num];
82
83     ret = nand_read_offset_ret(nand, off, &size, (void*)spl_data, &off);
84     if(ret != 0) {
85         printf("spl nand read error %d\n", ret);
86         return -1;
87     }
88     return 0;
89 }
90
91
92 int uboot_ubi_read(struct ubi_volume_desc *desc, char *buf,
93                            int offset, int size)
94 {
95         int err, lnum, off, len, tbuf_size, i = 0;
96         size_t count_save = size;
97         void *tbuf;
98         unsigned long long tmp;
99         struct ubi_volume *vol = NULL;
100         struct ubi_device *ubi = NULL;
101         loff_t offp = offset;
102
103         vol = desc->vol;
104         ubi = desc->vol->ubi;
105
106         printf("read %i bytes from volume %d to %x(buf address)\n",
107                (int) size, vol->vol_id, (unsigned)buf);
108
109         if (vol->updating) {
110                 printf("updating");
111                 return -EBUSY;
112         }
113         if (vol->upd_marker) {
114                 printf("damaged volume, update marker is set");
115                 return -EBADF;
116         }
117         if (offp == vol->used_bytes)
118                 return 0;
119
120         if (size == 0) {
121                 printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes);
122                 size = vol->used_bytes;
123         }
124
125         if (vol->corrupted)
126                 printf("read from corrupted volume %d", vol->vol_id);
127         if (offp + size > vol->used_bytes)
128                 count_save = size = vol->used_bytes - offp;
129
130         tbuf_size = vol->usable_leb_size;
131         if (size < tbuf_size)
132                 tbuf_size = ALIGN(size, ubi->min_io_size);
133         tbuf = malloc(tbuf_size);
134         if (!tbuf) {
135                 printf("NO MEM\n");
136                 return -ENOMEM;
137         }
138         len = size > tbuf_size ? tbuf_size : size;
139
140         tmp = offp;
141         off = do_div(tmp, vol->usable_leb_size);
142         lnum = tmp;
143         do {
144                 if (off + len >= vol->usable_leb_size)
145                         len = vol->usable_leb_size - off;
146
147                 err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
148                 if (err) {
149                         printf("read err %x\n", err);
150                         break;
151                 }
152                 off += len;
153                 if (off == vol->usable_leb_size) {
154                         lnum += 1;
155                         off -= vol->usable_leb_size;
156                 }
157
158                 size -= len;
159                 offp += len;
160
161                 memcpy(buf, tbuf, len);
162
163                 buf += len;
164                 len = size > tbuf_size ? tbuf_size : size;
165         } while (size);
166
167         free(tbuf);
168         return err ? err : count_save - size;
169 }
170
171 /**
172         attach ubi device to given mtdpart, and return the new
173         ubi device num.
174 */
175 static int _boot_ubi_attach_mtd(const char *mtdpart)
176 {
177         struct mtd_device *dev;
178         struct part_info *part;
179         struct mtd_info *mtd;
180         struct mtd_partition mtd_part;
181         char mtd_dev[16];
182         u8 pnum;
183         int ret;
184
185         ret = find_dev_and_part(mtdpart, &dev, &pnum, &part);
186         if(ret){
187                 printf("--->main partition %s miss<---\n",mtdpart);
188                 return -1;
189         }
190         if(dev->id->type != MTD_DEV_TYPE_NAND){
191                 printf("mtd dev %s not a nand device!\n",mtdpart);
192                 return -1;
193         }
194         sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num);
195         mtd = get_mtd_device_nm(mtd_dev);
196
197         memset(&mtd_part, 0, sizeof(mtd_part));
198         mtd_part.name = mtdpart;
199         mtd_part.size = part->size;
200         mtd_part.offset = part->offset;
201         add_mtd_partitions(mtd, &mtd_part, 1);
202         mtd = get_mtd_device_nm(mtdpart);
203
204         ret = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0);
205         if(ret<0){
206                 printf("--->ubi attach mtd %s failed<---\n",mtdpart);
207         }
208         return ret;
209 }
210
211 /**
212         Function for displaying logo.
213 */
214 static void _boot_display_logo(int ubidev, char *part, int backlight_set)
215 {
216         size_t size;
217         struct ubi_volume_desc *vol;
218
219 #ifdef CONFIG_LCD_720P
220         size = 1<<20;
221 #else
222         size = 1<<19;
223 #endif
224         unsigned char * bmp_img = malloc(size);
225         if(!bmp_img){
226             printf("%s: malloc for splash image failed!\n",__FUNCTION__);
227             return;
228         }
229         vol = ubi_open_volume_nm(ubidev, part, UBI_READONLY);
230         if (IS_ERR(vol)) {
231                 printf("cannot open \"%s\", error %d",
232                           part, (int)PTR_ERR(vol));
233                 goto end;
234         }
235
236         if(size != uboot_ubi_read(vol, bmp_img, 0, size)) {
237                 uint32_t nr;
238                 uint32_t writesize = vol->vol->ubi->mtd->writesize;
239                 printf("%s: read logo partition failed, retry page by page.\n",__FUNCTION__);
240                 for(nr = 0; nr < size; nr += writesize) {
241                         uboot_ubi_read(vol, bmp_img + nr, nr, MIN(writesize,size - nr));
242                 }
243         }
244
245         ubi_close_volume(vol);
246
247         lcd_display_logo(backlight_set,(ulong)bmp_img,size);
248 end:
249         free(bmp_img);
250         return;
251 }
252
253 static void _boot_check_and_load_nv(int ubidev, char*vol, char *bakvol, char *addr, int size)
254 {
255         char *buf, *bakbuf;
256         char status=0;
257         nv_header_t *header;
258         int len = size + NV_HEAD_LEN;
259         struct ubi_volume_desc *vol_desc;
260         struct ubi_volume_desc *bakvol_desc;
261
262         buf = malloc(len);
263         if(!buf) {
264                 printf("%s malloc buf failed.\n",__func__);
265                 return;
266         }
267         bakbuf = malloc(len);
268         if(!bakbuf) {
269                 printf("%s malloc bakbuf failed.\n",__func__);
270                 return;
271         }
272
273         vol_desc = ubi_open_volume_nm(ubidev, vol, UBI_READWRITE);
274         if (IS_ERR(vol_desc)){
275                 printf("cannot open \"%s\", error %d\n",vol, (int)PTR_ERR(vol_desc));
276                 goto bak;
277         }
278         if(len == uboot_ubi_read(vol_desc, buf, 0, len)) {
279                 header = (nv_header_t *)buf;
280                 if(NV_HEAD_MAGIC == header->magic){
281                         if(_chkNVEcc(buf+NV_HEAD_LEN, header->len,header->checksum))
282                                 status += 1;
283                 }
284         }else {
285                 printf("%s: ubi vol %s read failed!\n",__func__,vol);
286         }
287 bak:
288         bakvol_desc = ubi_open_volume_nm(ubidev, bakvol, UBI_READWRITE);
289         if (IS_ERR(bakvol_desc)){
290                 printf("cannot open \"%s\", error %d\n",bakvol, (int)PTR_ERR(bakvol_desc));
291                 goto end;
292         }
293         if(len == uboot_ubi_read(bakvol_desc, bakbuf, 0, len)) {
294                 header = (nv_header_t *)bakbuf;
295                 if(NV_HEAD_MAGIC == header->magic){
296                         if(_chkNVEcc(bakbuf+NV_HEAD_LEN, header->len,header->checksum))
297                                 status += 1<<1;
298                 }
299         }else {
300                 printf("%s: ubi vol %s read failed!\n",__func__,bakvol);
301         }
302 end:
303         if (!IS_ERR(vol_desc))
304                 ubi_close_volume(vol_desc);
305         if (!IS_ERR(vol_desc))
306                 ubi_close_volume(bakvol_desc);
307
308         switch(status){
309                 case 0:
310                         printf("vol %s:both org and bak are damaged!\n",vol);
311                         memset(addr, 0, size);
312                         break;
313                 case 1:
314                         printf("vol %s:bak is damaged!\n",vol);
315                         memcpy(addr,buf+NV_HEAD_LEN,size);
316                         do_raw_data_write(bakvol, len, len, 0, buf);
317                         break;
318                 case 2:
319                         printf("vol %s:org is damaged!\n",vol);
320                         memcpy(addr,bakbuf+NV_HEAD_LEN,size);
321                         do_raw_data_write(vol, len, len, 0, bakbuf);
322                         break;
323                 case 3:
324                         printf("vol %s:both org and bak are ok!\n",vol);
325                         memcpy(addr,buf+NV_HEAD_LEN,size);
326                         break;
327                 default:
328                         printf("%s status error!\n",__func__);
329                         break;
330         }
331
332         free(buf);
333         free(bakbuf);
334
335         return;
336 }
337
338 static void _boot_load_required_image(int ubidev, vol_image_required_t info)
339 {
340         struct ubi_volume_desc *vol;
341         if(IMG_RAW == info.fs_type){
342                 if(NULL != info.bak_vol){
343                         _boot_check_and_load_nv(ubidev, info.vol, info.bak_vol, info.mem_addr, info.size);
344                 }else{
345                         vol = ubi_open_volume_nm(ubidev, info.vol, UBI_READWRITE);
346                         if (IS_ERR(vol)){
347                                 printf("cannot open \"%s\", error %d",
348                                           info.vol, (int)PTR_ERR(vol));
349                                 return;
350                         }
351                         if(info.size != uboot_ubi_read(vol, info.mem_addr, 0, info.size)){
352                                 uint32_t nr;
353                                 uint32_t writesize = vol->vol->ubi->mtd->writesize;
354                                 printf("%s: ubi vol %s read failed,retry page by page.\n",__FUNCTION__,info.vol);
355                                 for(nr = 0; nr < info.size; nr += writesize) {
356                                         uboot_ubi_read(vol, info.mem_addr + nr, nr, MIN(writesize,info.size - nr));
357                                 }
358                         }
359                         ubi_close_volume(vol);
360                 }
361         }
362         else{
363                 TODO:
364                 printf("image type not support now,,,do it later\n");
365         }
366         return;
367 }
368
369 static int _boot_load_kernel_ramdisk_image(int ubidev, char *part, void *header, void *kaddr, void *rdaddr)
370 {
371         boot_img_hdr *hdr = (boot_img_hdr*)header;
372         struct ubi_volume_desc *vol;
373         unsigned int size,remain;
374         int lnum,offset;
375         int ret=0;
376         unsigned int dt_img_adr;
377
378         vol = ubi_open_volume_nm(ubidev, part, UBI_READONLY);
379         if (IS_ERR(vol)){
380                 printf("cannot open \"%s\", error %d",
381                           part, (int)PTR_ERR(vol));
382                 return 0;
383         }
384         
385         //image header read and check
386         lnum = 0;
387         offset = 0;
388         size = vol->vol->ubi->mtd->writesize;
389         ret = uboot_ubi_read(vol, (char*)hdr, offset, MIN(size,8192));
390         if(ret != MIN(size,8192)){
391                 printf("%s: ubi vol %s read failed,error %d.give up boot!\n",__FUNCTION__,part,ret);
392                 return 0;
393         }
394         if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)){
395                 char *n;
396                 n=hdr->magic;
397                 printf("bad boot image header, give up boot!!!!\n");
398                 return 0;
399         }
400         if(size<hdr->page_size){
401                 printf("size<hdr->page_size,read hdr again!\n");
402                 //hdr buf len is 8192, so can't read more than it
403                 ret = uboot_ubi_read(vol, (char*)hdr, offset, MIN(hdr->page_size,8192));
404                 if(ret != MIN(hdr->page_size,8192)){
405                         printf("%s: ubi vol %s read all hdr failed,error %d.give up boot!\n",__FUNCTION__,part,ret);
406                         return 0;
407                 }
408         }
409
410 #ifdef CONFIG_OF_LIBFDT
411         //load kernel image to certain addr
412         offset = hdr->page_size;
413         size = hdr->kernel_size;
414         ret = uboot_ubi_read(vol, (char*)kaddr, offset, size);
415         if(ret != size){
416                 printf("%s: kernel image read failed,error %d.give up boot!\n",__FUNCTION__,ret);
417                 return 0;
418         }
419
420         //load radmdisk image
421         offset = (offset +size+hdr->page_size-1)&~(hdr->page_size-1);
422         size = hdr->ramdisk_size;
423         ret = uboot_ubi_read(vol, (char*)rdaddr, offset, size);
424         if(ret != size){
425                 printf("%s: ramdisk image read failed,error %d.give up boot!\n",__FUNCTION__,ret);
426                 return 0;
427         }
428
429         //read dt image
430         offset = (offset +size+hdr->page_size-1)&~(hdr->page_size-1);
431         size = hdr->dt_size;
432         dt_img_adr = RAMDISK_ADR - size - hdr->page_size;
433         if(size<0){
434                 printf("dt size error\n");
435                 return 0;
436         }
437         ret = uboot_ubi_read(vol, (char*)dt_img_adr, offset, size);
438         if(ret != size) 
439         {
440                 printf("%s:dt read error! offset:0x%x,size:0x%x,dt_img_adr:0x%x\n",__FUNCTION__,offset,size,dt_img_adr);
441                 return 0;
442         }
443         if (load_dtb((int)DT_ADR,(void*)dt_img_adr)){
444                 printf("%s:dt load error!\n",__FUNCTION__);
445                 return 0;
446         }
447 #else
448         //load kernel image to certain addr
449         offset = hdr->page_size;
450         size = hdr->kernel_size;
451         ret = uboot_ubi_read(vol, (char*)kaddr, offset, size);
452         if(ret != size){
453                 printf("%s: kernel image read failed,error %d.give up boot!\n",__FUNCTION__,ret);
454                 return 0;
455         }
456
457         //load radmdisk image
458         offset = (offset +size+hdr->page_size-1)&~(hdr->page_size-1);
459         size = hdr->ramdisk_size;
460         ret = uboot_ubi_read(vol, (char*)rdaddr, offset, size);
461         if(ret != size){
462                 printf("%s: ramdisk image read failed,error %d.give up boot!\n",__FUNCTION__,ret);
463                 return 0;
464         }
465 #endif
466 #ifdef CONFIG_SDRAMDISK
467         {
468         int sd_ramdisk_size = 0;
469 #ifdef WDSP_ADR
470         size = WDSP_ADR - RAMDISK_ADR;
471 #else
472         size = TDDSP_ADR - RAMDISK_ADR;
473 #endif
474         if (size >0)
475                 sd_ramdisk_size = load_sd_ramdisk((uint8*)RAMDISK_ADR,size);
476         if (sd_ramdisk_size >0)
477                 hdr->ramdisk_size = sd_ramdisk_size;
478         }
479 #endif
480         ubi_close_volume(vol);
481         return 1;
482 }
483
484 int nand_ubi_dev_init(void)
485 {
486         int ret;
487         static int initialized=0;
488         static int dev_num=-1;
489
490         if(!initialized){
491                 //init mtd & ubi devices
492                 ret = mtdparts_init();
493                 if(ret){
494                         printf("mtdparts init error...\n");
495                         return -1;
496                 }
497                 ret = ubi_init();
498                 if(ret){
499                         printf("ubi init error...\n");
500                         return -1;
501                 }
502                 //ubi attach mtd dev, and get the new ubi dev num
503                 dev_num = _boot_ubi_attach_mtd(UBIPAC_PART);
504                 initialized = 1;
505         }
506
507         return dev_num;
508 }
509
510 void vlx_nand_boot(char * kernel_pname, char * cmdline, int backlight_set)
511 {
512         struct ubi_volume_desc *vol;
513         boot_img_hdr *hdr = (void *)raw_header;
514         int ubi_dev_num;
515         int ret;
516         int i,j;
517         long long start = get_ticks();
518
519
520         //init mtd ubi module and attach mtd dev
521         ubi_dev_num = nand_ubi_dev_init();
522         if(ubi_dev_num < 0){
523                 //dev num can't be a negative
524                 printf("boot failed...\n");
525                 return;
526         }
527         //display logo
528 #ifdef CONFIG_SPLASH_SCREEN
529         _boot_display_logo(ubi_dev_num, LOGO_PART, backlight_set);
530         performance_debug("7:");
531 #endif
532         set_vibrator(0);
533
534         //load required image which config in table
535         i = 0;
536         while(s_boot_image_table[i]){
537                 j =0;
538                 while(s_boot_image_table[i][j].vol){
539                         _boot_load_required_image(ubi_dev_num, s_boot_image_table[i][j]);
540                         j++;
541                 }
542                 i++;
543         }
544         performance_debug("8:");
545
546         ret = _boot_load_kernel_ramdisk_image(ubi_dev_num, kernel_pname, hdr, KERNEL_ADR, RAMDISK_ADR);
547         performance_debug("9:");
548         if(!ret){
549                 printf("boot: load kernel error!\n");
550                 return;
551         }
552
553         load_image_time = get_ticks() - start;
554         if(creat_cmdline(cmdline,hdr)){
555             debugf("creat_cmdline failed\n");
556             return;
557         }
558         performance_debug("10:");
559 #if BOOT_NATIVE_LINUX_MODEM
560         //sipc addr clear
561         sipc_addr_reset();
562 #endif
563         vlx_entry();
564         return;
565 }