1 /* 2 * SPDX-License-Identifier: GPL-2.0+ 3 * 4 * based on: cmd_jffs2.c 5 * 6 * Add support for a CRAMFS located in RAM 7 */ 8 9 10 /* 11 * CRAMFS support 12 */ 13 #include <common.h> 14 #include <command.h> 15 #include <malloc.h> 16 #include <linux/list.h> 17 #include <linux/ctype.h> 18 #include <jffs2/jffs2.h> 19 #include <jffs2/load_kernel.h> 20 #include <cramfs/cramfs_fs.h> 21 22 /* enable/disable debugging messages */ 23 #define DEBUG_CRAMFS 24 #undef DEBUG_CRAMFS 25 26 #ifdef DEBUG_CRAMFS 27 # define DEBUGF(fmt, args...) printf(fmt ,##args) 28 #else 29 # define DEBUGF(fmt, args...) 30 #endif 31 32 #include <flash.h> 33 34 #ifndef CONFIG_MTD_NOR_FLASH 35 # define OFFSET_ADJUSTMENT 0 36 #else 37 # define OFFSET_ADJUSTMENT (flash_info[id.num].start[0]) 38 #endif 39 40 #ifndef CONFIG_CMD_JFFS2 41 #include <linux/stat.h> 42 char *mkmodestr(unsigned long mode, char *str) 43 { 44 static const char *l = "xwr"; 45 int mask = 1, i; 46 char c; 47 48 switch (mode & S_IFMT) { 49 case S_IFDIR: str[0] = 'd'; break; 50 case S_IFBLK: str[0] = 'b'; break; 51 case S_IFCHR: str[0] = 'c'; break; 52 case S_IFIFO: str[0] = 'f'; break; 53 case S_IFLNK: str[0] = 'l'; break; 54 case S_IFSOCK: str[0] = 's'; break; 55 case S_IFREG: str[0] = '-'; break; 56 default: str[0] = '?'; 57 } 58 59 for(i = 0; i < 9; i++) { 60 c = l[i%3]; 61 str[9-i] = (mode & mask)?c:'-'; 62 mask = mask<<1; 63 } 64 65 if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S'; 66 if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S'; 67 if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T'; 68 str[10] = '\0'; 69 return str; 70 } 71 #endif /* CONFIG_CMD_JFFS2 */ 72 73 extern int cramfs_check (struct part_info *info); 74 extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename); 75 extern int cramfs_ls (struct part_info *info, char *filename); 76 extern int cramfs_info (struct part_info *info); 77 78 /***************************************************/ 79 /* U-Boot commands */ 80 /***************************************************/ 81 82 /** 83 * Routine implementing fsload u-boot command. This routine tries to load 84 * a requested file from cramfs filesystem at location 'cramfsaddr'. 85 * cramfsaddr is an evironment variable. 86 * 87 * @param cmdtp command internal data 88 * @param flag command flag 89 * @param argc number of arguments supplied to the command 90 * @param argv arguments list 91 * @return 0 on success, 1 otherwise 92 */ 93 int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 94 { 95 char *filename; 96 int size; 97 ulong offset = load_addr; 98 99 struct part_info part; 100 struct mtd_device dev; 101 struct mtdids id; 102 103 ulong addr; 104 addr = simple_strtoul(getenv("cramfsaddr"), NULL, 16); 105 106 /* hack! */ 107 /* cramfs_* only supports NOR flash chips */ 108 /* fake the device type */ 109 id.type = MTD_DEV_TYPE_NOR; 110 id.num = 0; 111 dev.id = &id; 112 part.dev = &dev; 113 /* fake the address offset */ 114 part.offset = addr - OFFSET_ADJUSTMENT; 115 116 /* pre-set Boot file name */ 117 if ((filename = getenv("bootfile")) == NULL) { 118 filename = "uImage"; 119 } 120 121 if (argc == 2) { 122 filename = argv[1]; 123 } 124 if (argc == 3) { 125 offset = simple_strtoul(argv[1], NULL, 0); 126 load_addr = offset; 127 filename = argv[2]; 128 } 129 130 size = 0; 131 if (cramfs_check(&part)) 132 size = cramfs_load ((char *) offset, &part, filename); 133 134 if (size > 0) { 135 printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n", 136 size, offset); 137 setenv_hex("filesize", size); 138 } else { 139 printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename); 140 } 141 142 return !(size > 0); 143 } 144 145 /** 146 * Routine implementing u-boot ls command which lists content of a given 147 * directory at location 'cramfsaddr'. 148 * cramfsaddr is an evironment variable. 149 * 150 * @param cmdtp command internal data 151 * @param flag command flag 152 * @param argc number of arguments supplied to the command 153 * @param argv arguments list 154 * @return 0 on success, 1 otherwise 155 */ 156 int do_cramfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 157 { 158 char *filename = "/"; 159 int ret; 160 struct part_info part; 161 struct mtd_device dev; 162 struct mtdids id; 163 164 ulong addr; 165 addr = simple_strtoul(getenv("cramfsaddr"), NULL, 16); 166 167 /* hack! */ 168 /* cramfs_* only supports NOR flash chips */ 169 /* fake the device type */ 170 id.type = MTD_DEV_TYPE_NOR; 171 id.num = 0; 172 dev.id = &id; 173 part.dev = &dev; 174 /* fake the address offset */ 175 part.offset = addr - OFFSET_ADJUSTMENT; 176 177 if (argc == 2) 178 filename = argv[1]; 179 180 ret = 0; 181 if (cramfs_check(&part)) 182 ret = cramfs_ls (&part, filename); 183 184 return ret ? 0 : 1; 185 } 186 187 /* command line only */ 188 189 /***************************************************/ 190 U_BOOT_CMD( 191 cramfsload, 3, 0, do_cramfs_load, 192 "load binary file from a filesystem image", 193 "[ off ] [ filename ]\n" 194 " - load binary file from address 'cramfsaddr'\n" 195 " with offset 'off'\n" 196 ); 197 U_BOOT_CMD( 198 cramfsls, 2, 1, do_cramfs_ls, 199 "list files in a directory (default /)", 200 "[ directory ]\n" 201 " - list files in a directory.\n" 202 ); 203