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