fdt: remove unaligned access in fdt_fixup_ethernet()
[kernel/u-boot.git] / common / cmd_disk.c
1 /*
2  * (C) Copyright 2000-2011
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  */
24 #include <common.h>
25 #include <command.h>
26 #include <part.h>
27
28 #if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \
29         defined(CONFIG_USB_STORAGE)
30 int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
31                     char *const argv[])
32 {
33         int dev, part;
34         ulong addr = CONFIG_SYS_LOAD_ADDR;
35         ulong cnt;
36         disk_partition_t info;
37         image_header_t *hdr;
38         block_dev_desc_t *dev_desc;
39
40 #if defined(CONFIG_FIT)
41         const void *fit_hdr = NULL;
42 #endif
43
44         bootstage_mark(BOOTSTAGE_ID_IDE_START);
45         if (argc > 3) {
46                 bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
47                 return CMD_RET_USAGE;
48         }
49         bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
50
51         if (argc > 1)
52                 addr = simple_strtoul(argv[1], NULL, 16);
53
54         bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
55
56         part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL,
57                                         &dev_desc, &info, 1);
58         if (part < 0) {
59                 bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
60                 return 1;
61         }
62
63         dev = dev_desc->dev;
64         bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
65
66         printf("\nLoading from %s device %d, partition %d: "
67                "Name: %.32s  Type: %.32s\n", intf, dev, part, info.name,
68                info.type);
69
70         debug("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
71               info.start, info.size, info.blksz);
72
73         if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) {
74                 printf("** Read error on %d:%d\n", dev, part);
75                 bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
76                 return 1;
77         }
78         bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
79
80         switch (genimg_get_format((void *) addr)) {
81         case IMAGE_FORMAT_LEGACY:
82                 hdr = (image_header_t *) addr;
83
84                 bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
85
86                 if (!image_check_hcrc(hdr)) {
87                         puts("\n** Bad Header Checksum **\n");
88                         bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
89                         return 1;
90                 }
91                 bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
92
93                 image_print_contents(hdr);
94
95                 cnt = image_get_image_size(hdr);
96                 break;
97 #if defined(CONFIG_FIT)
98         case IMAGE_FORMAT_FIT:
99                 fit_hdr = (const void *) addr;
100                 puts("Fit image detected...\n");
101
102                 cnt = fit_get_size(fit_hdr);
103                 break;
104 #endif
105         default:
106                 bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
107                 puts("** Unknown image type\n");
108                 return 1;
109         }
110
111         cnt += info.blksz - 1;
112         cnt /= info.blksz;
113         cnt -= 1;
114
115         if (dev_desc->block_read(dev, info.start + 1, cnt,
116                                          (ulong *)(addr + info.blksz)) != cnt) {
117                 printf("** Read error on %d:%d\n", dev, part);
118                 bootstage_error(BOOTSTAGE_ID_IDE_READ);
119                 return 1;
120         }
121         bootstage_mark(BOOTSTAGE_ID_IDE_READ);
122
123 #if defined(CONFIG_FIT)
124         /* This cannot be done earlier,
125          * we need complete FIT image in RAM first */
126         if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
127                 if (!fit_check_format(fit_hdr)) {
128                         bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
129                         puts("** Bad FIT image format\n");
130                         return 1;
131                 }
132                 bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
133                 fit_print_contents(fit_hdr);
134         }
135 #endif
136
137         flush_cache(addr, (cnt+1)*info.blksz);
138
139         /* Loading ok, update default load address */
140         load_addr = addr;
141
142         return bootm_maybe_autostart(cmdtp, argv[0]);
143 }
144 #endif