1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> 4 * Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de> 5 * 6 * Usage: 7 * 8 * one commend line parameter per device, each in the form: 9 * phram=<name>,<start>,<len>[,<erasesize>] 10 * <name> may be up to 63 characters. 11 * <start>, <len>, and <erasesize> can be octal, decimal or hexadecimal. If followed 12 * by "ki", "Mi" or "Gi", the numbers will be interpreted as kilo, mega or 13 * gigabytes. <erasesize> is optional and defaults to PAGE_SIZE. 14 * 15 * Example: 16 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi,64Ki 17 */ 18 19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20 21 #include <linux/io.h> 22 #include <linux/init.h> 23 #include <linux/kernel.h> 24 #include <linux/list.h> 25 #include <linux/module.h> 26 #include <linux/moduleparam.h> 27 #include <linux/slab.h> 28 #include <linux/mtd/mtd.h> 29 #include <asm/div64.h> 30 #include <linux/platform_device.h> 31 #include <linux/of_address.h> 32 #include <linux/of.h> 33 #include <linux/security.h> 34 35 struct phram_mtd_list { 36 struct mtd_info mtd; 37 struct list_head list; 38 bool cached; 39 }; 40 41 static LIST_HEAD(phram_list); 42 43 static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) 44 { 45 u_char *start = mtd->priv; 46 47 memset(start + instr->addr, 0xff, instr->len); 48 49 return 0; 50 } 51 52 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, 53 size_t *retlen, void **virt, resource_size_t *phys) 54 { 55 *virt = mtd->priv + from; 56 *retlen = len; 57 return 0; 58 } 59 60 static int phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 61 { 62 return 0; 63 } 64 65 static int phram_read(struct mtd_info *mtd, loff_t from, size_t len, 66 size_t *retlen, u_char *buf) 67 { 68 u_char *start = mtd->priv; 69 70 memcpy(buf, start + from, len); 71 *retlen = len; 72 return 0; 73 } 74 75 static int phram_write(struct mtd_info *mtd, loff_t to, size_t len, 76 size_t *retlen, const u_char *buf) 77 { 78 u_char *start = mtd->priv; 79 80 memcpy(start + to, buf, len); 81 *retlen = len; 82 return 0; 83 } 84 85 static int phram_map(struct phram_mtd_list *phram, phys_addr_t start, size_t len) 86 { 87 void *addr = NULL; 88 89 if (phram->cached) 90 addr = memremap(start, len, MEMREMAP_WB); 91 else 92 addr = (void __force *)ioremap(start, len); 93 if (!addr) 94 return -EIO; 95 96 phram->mtd.priv = addr; 97 98 return 0; 99 } 100 101 static void phram_unmap(struct phram_mtd_list *phram) 102 { 103 void *addr = phram->mtd.priv; 104 105 if (phram->cached) { 106 memunmap(addr); 107 return; 108 } 109 110 iounmap((void __iomem *)addr); 111 } 112 113 static void unregister_devices(void) 114 { 115 struct phram_mtd_list *this, *safe; 116 117 list_for_each_entry_safe(this, safe, &phram_list, list) { 118 mtd_device_unregister(&this->mtd); 119 phram_unmap(this); 120 kfree(this->mtd.name); 121 kfree(this); 122 } 123 } 124 125 static int register_device(struct platform_device *pdev, const char *name, 126 phys_addr_t start, size_t len, uint32_t erasesize) 127 { 128 struct device_node *np = pdev ? pdev->dev.of_node : NULL; 129 bool cached = np ? !of_property_read_bool(np, "no-map") : false; 130 struct phram_mtd_list *new; 131 int ret = -ENOMEM; 132 133 new = kzalloc(sizeof(*new), GFP_KERNEL); 134 if (!new) 135 goto out0; 136 137 new->cached = cached; 138 139 ret = phram_map(new, start, len); 140 if (ret) { 141 pr_err("ioremap failed\n"); 142 goto out1; 143 } 144 145 146 new->mtd.name = name; 147 new->mtd.size = len; 148 new->mtd.flags = MTD_CAP_RAM; 149 new->mtd._erase = phram_erase; 150 new->mtd._point = phram_point; 151 new->mtd._unpoint = phram_unpoint; 152 new->mtd._read = phram_read; 153 new->mtd._write = phram_write; 154 new->mtd.owner = THIS_MODULE; 155 new->mtd.type = MTD_RAM; 156 new->mtd.erasesize = erasesize; 157 new->mtd.writesize = 1; 158 159 mtd_set_of_node(&new->mtd, np); 160 161 ret = -EAGAIN; 162 if (mtd_device_register(&new->mtd, NULL, 0)) { 163 pr_err("Failed to register new device\n"); 164 goto out2; 165 } 166 167 if (pdev) 168 platform_set_drvdata(pdev, new); 169 else 170 list_add_tail(&new->list, &phram_list); 171 172 return 0; 173 174 out2: 175 phram_unmap(new); 176 out1: 177 kfree(new); 178 out0: 179 return ret; 180 } 181 182 static int parse_num64(uint64_t *num64, char *token) 183 { 184 size_t len; 185 int shift = 0; 186 int ret; 187 188 len = strlen(token); 189 /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */ 190 if (len > 2) { 191 if (token[len - 1] == 'i') { 192 switch (token[len - 2]) { 193 case 'G': 194 shift += 10; 195 fallthrough; 196 case 'M': 197 shift += 10; 198 fallthrough; 199 case 'k': 200 shift += 10; 201 token[len - 2] = 0; 202 break; 203 default: 204 return -EINVAL; 205 } 206 } 207 } 208 209 ret = kstrtou64(token, 0, num64); 210 *num64 <<= shift; 211 212 return ret; 213 } 214 215 static int parse_name(char **pname, const char *token) 216 { 217 size_t len; 218 char *name; 219 220 len = strlen(token) + 1; 221 if (len > 64) 222 return -ENOSPC; 223 224 name = kstrdup(token, GFP_KERNEL); 225 if (!name) 226 return -ENOMEM; 227 228 *pname = name; 229 return 0; 230 } 231 232 233 static inline void kill_final_newline(char *str) 234 { 235 char *newline = strrchr(str, '\n'); 236 237 if (newline && !newline[1]) 238 *newline = 0; 239 } 240 241 242 #define parse_err(fmt, args...) do { \ 243 pr_err(fmt , ## args); \ 244 return 1; \ 245 } while (0) 246 247 #ifndef MODULE 248 static int phram_init_called; 249 /* 250 * This shall contain the module parameter if any. It is of the form: 251 * - phram=<device>,<address>,<size>[,<erasesize>] for module case 252 * - phram.phram=<device>,<address>,<size>[,<erasesize>] for built-in case 253 * We leave 64 bytes for the device name, 20 for the address , 20 for the 254 * size and 20 for the erasesize. 255 * Example: phram.phram=rootfs,0xa0000000,512Mi,65536 256 */ 257 static char phram_paramline[64 + 20 + 20 + 20]; 258 #endif 259 260 static int phram_setup(const char *val) 261 { 262 char buf[64 + 20 + 20 + 20], *str = buf; 263 char *token[4]; 264 char *name; 265 uint64_t start; 266 uint64_t len; 267 uint64_t erasesize = PAGE_SIZE; 268 uint32_t rem; 269 int i, ret; 270 271 if (strnlen(val, sizeof(buf)) >= sizeof(buf)) 272 parse_err("parameter too long\n"); 273 274 strcpy(str, val); 275 kill_final_newline(str); 276 277 for (i = 0; i < 4; i++) 278 token[i] = strsep(&str, ","); 279 280 if (str) 281 parse_err("too many arguments\n"); 282 283 if (!token[2]) 284 parse_err("not enough arguments\n"); 285 286 ret = parse_name(&name, token[0]); 287 if (ret) 288 return ret; 289 290 ret = parse_num64(&start, token[1]); 291 if (ret) { 292 parse_err("illegal start address\n"); 293 goto error; 294 } 295 296 ret = parse_num64(&len, token[2]); 297 if (ret) { 298 parse_err("illegal device length\n"); 299 goto error; 300 } 301 302 if (token[3]) { 303 ret = parse_num64(&erasesize, token[3]); 304 if (ret) { 305 parse_err("illegal erasesize\n"); 306 goto error; 307 } 308 } 309 310 if (len == 0 || erasesize == 0 || erasesize > len 311 || erasesize > UINT_MAX) { 312 parse_err("illegal erasesize or len\n"); 313 ret = -EINVAL; 314 goto error; 315 } 316 317 div_u64_rem(len, (uint32_t)erasesize, &rem); 318 if (rem) { 319 parse_err("len is not multiple of erasesize\n"); 320 ret = -EINVAL; 321 goto error; 322 } 323 324 ret = register_device(NULL, name, start, len, (uint32_t)erasesize); 325 if (ret) 326 goto error; 327 328 pr_info("%s device: %#llx at %#llx for erasesize %#llx\n", name, len, start, erasesize); 329 return 0; 330 331 error: 332 kfree(name); 333 return ret; 334 } 335 336 static int phram_param_call(const char *val, const struct kernel_param *kp) 337 { 338 #ifdef MODULE 339 return phram_setup(val); 340 #else 341 /* 342 * If more parameters are later passed in via 343 * /sys/module/phram/parameters/phram 344 * and init_phram() has already been called, 345 * we can parse the argument now. 346 */ 347 348 if (phram_init_called) 349 return phram_setup(val); 350 351 /* 352 * During early boot stage, we only save the parameters 353 * here. We must parse them later: if the param passed 354 * from kernel boot command line, phram_param_call() is 355 * called so early that it is not possible to resolve 356 * the device (even kmalloc() fails). Defer that work to 357 * phram_setup(). 358 */ 359 360 if (strlen(val) >= sizeof(phram_paramline)) 361 return -ENOSPC; 362 strcpy(phram_paramline, val); 363 364 return 0; 365 #endif 366 } 367 368 module_param_call(phram, phram_param_call, NULL, NULL, 0200); 369 MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\""); 370 371 #ifdef CONFIG_OF 372 static const struct of_device_id phram_of_match[] = { 373 { .compatible = "phram" }, 374 {} 375 }; 376 MODULE_DEVICE_TABLE(of, phram_of_match); 377 #endif 378 379 static int phram_probe(struct platform_device *pdev) 380 { 381 struct resource *res; 382 383 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 384 if (!res) 385 return -ENOMEM; 386 387 /* mtd_set_of_node() reads name from "label" */ 388 return register_device(pdev, NULL, res->start, resource_size(res), 389 PAGE_SIZE); 390 } 391 392 static void phram_remove(struct platform_device *pdev) 393 { 394 struct phram_mtd_list *phram = platform_get_drvdata(pdev); 395 396 mtd_device_unregister(&phram->mtd); 397 phram_unmap(phram); 398 kfree(phram); 399 } 400 401 static struct platform_driver phram_driver = { 402 .probe = phram_probe, 403 .remove = phram_remove, 404 .driver = { 405 .name = "phram", 406 .of_match_table = of_match_ptr(phram_of_match), 407 }, 408 }; 409 410 static int __init init_phram(void) 411 { 412 int ret; 413 414 ret = security_locked_down(LOCKDOWN_DEV_MEM); 415 if (ret) 416 return ret; 417 418 ret = platform_driver_register(&phram_driver); 419 if (ret) 420 return ret; 421 422 #ifndef MODULE 423 if (phram_paramline[0]) { 424 ret = phram_setup(phram_paramline); 425 if (ret) 426 platform_driver_unregister(&phram_driver); 427 } 428 phram_init_called = 1; 429 #endif 430 431 return ret; 432 } 433 434 static void __exit cleanup_phram(void) 435 { 436 unregister_devices(); 437 platform_driver_unregister(&phram_driver); 438 } 439 440 module_init(init_phram); 441 module_exit(cleanup_phram); 442 443 MODULE_LICENSE("GPL"); 444 MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>"); 445 MODULE_DESCRIPTION("MTD driver for physical RAM"); 446