cmd: cat: add new command
[platform/kernel/u-boot.git] / cmd / read.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  *
6  * Alternatively, this software may be distributed under the terms of the
7  * GNU General Public License ("GPL") version 2 as published by the Free
8  * Software Foundation.
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <mapmem.h>
14 #include <part.h>
15
16 int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
17 {
18         char *ep;
19         struct blk_desc *dev_desc = NULL;
20         int dev;
21         int part = 0;
22         struct disk_partition part_info;
23         ulong offset = 0u;
24         ulong limit = 0u;
25         void *addr;
26         uint blk;
27         uint cnt;
28
29         if (argc != 6) {
30                 cmd_usage(cmdtp);
31                 return 1;
32         }
33
34         dev = (int)hextoul(argv[2], &ep);
35         if (*ep) {
36                 if (*ep != ':') {
37                         printf("Invalid block device %s\n", argv[2]);
38                         return 1;
39                 }
40                 part = (int)hextoul(++ep, NULL);
41         }
42
43         dev_desc = blk_get_dev(argv[1], dev);
44         if (dev_desc == NULL) {
45                 printf("Block device %s %d not supported\n", argv[1], dev);
46                 return 1;
47         }
48
49         addr = map_sysmem(hextoul(argv[3], NULL), 0);
50         blk = hextoul(argv[4], NULL);
51         cnt = hextoul(argv[5], NULL);
52
53         if (part != 0) {
54                 if (part_get_info(dev_desc, part, &part_info)) {
55                         printf("Cannot find partition %d\n", part);
56                         return 1;
57                 }
58                 offset = part_info.start;
59                 limit = part_info.size;
60         } else {
61                 /* Largest address not available in struct blk_desc. */
62                 limit = ~0;
63         }
64
65         if (cnt + blk > limit) {
66                 printf("Read out of range\n");
67                 return 1;
68         }
69
70         if (blk_dread(dev_desc, offset + blk, cnt, addr) != cnt) {
71                 printf("Error reading blocks\n");
72                 return 1;
73         }
74
75         return 0;
76 }
77
78 U_BOOT_CMD(
79         read,   6,      0,      do_read,
80         "Load binary data from a partition",
81         "<interface> <dev[:part]> addr blk# cnt"
82 );