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