1 // SPDX-License-Identifier: GPL-2.0-only 2 /* inode.c: /proc/openprom handling routines 3 * 4 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com) 5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 6 */ 7 8 #include <linux/module.h> 9 #include <linux/types.h> 10 #include <linux/string.h> 11 #include <linux/fs.h> 12 #include <linux/fs_context.h> 13 #include <linux/init.h> 14 #include <linux/slab.h> 15 #include <linux/seq_file.h> 16 #include <linux/magic.h> 17 18 #include <asm/openprom.h> 19 #include <asm/oplib.h> 20 #include <asm/prom.h> 21 #include <linux/uaccess.h> 22 23 static DEFINE_MUTEX(op_mutex); 24 25 #define OPENPROM_ROOT_INO 0 26 27 enum op_inode_type { 28 op_inode_node, 29 op_inode_prop, 30 }; 31 32 union op_inode_data { 33 struct device_node *node; 34 struct property *prop; 35 }; 36 37 struct op_inode_info { 38 struct inode vfs_inode; 39 enum op_inode_type type; 40 union op_inode_data u; 41 }; 42 43 static struct inode *openprom_iget(struct super_block *sb, ino_t ino); 44 45 static inline struct op_inode_info *OP_I(struct inode *inode) 46 { 47 return container_of(inode, struct op_inode_info, vfs_inode); 48 } 49 50 static int is_string(unsigned char *p, int len) 51 { 52 int i; 53 54 for (i = 0; i < len; i++) { 55 unsigned char val = p[i]; 56 57 if ((i && !val) || 58 (val >= ' ' && val <= '~')) 59 continue; 60 61 return 0; 62 } 63 64 return 1; 65 } 66 67 static int property_show(struct seq_file *f, void *v) 68 { 69 struct property *prop = f->private; 70 void *pval; 71 int len; 72 73 len = prop->length; 74 pval = prop->value; 75 76 if (is_string(pval, len)) { 77 while (len > 0) { 78 int n = strlen(pval); 79 80 seq_printf(f, "%s", (char *) pval); 81 82 /* Skip over the NULL byte too. */ 83 pval += n + 1; 84 len -= n + 1; 85 86 if (len > 0) 87 seq_printf(f, " + "); 88 } 89 } else { 90 if (len & 3) { 91 while (len) { 92 len--; 93 if (len) 94 seq_printf(f, "%02x.", 95 *(unsigned char *) pval); 96 else 97 seq_printf(f, "%02x", 98 *(unsigned char *) pval); 99 pval++; 100 } 101 } else { 102 while (len >= 4) { 103 len -= 4; 104 105 if (len) 106 seq_printf(f, "%08x.", 107 *(unsigned int *) pval); 108 else 109 seq_printf(f, "%08x", 110 *(unsigned int *) pval); 111 pval += 4; 112 } 113 } 114 } 115 seq_printf(f, "\n"); 116 117 return 0; 118 } 119 120 static void *property_start(struct seq_file *f, loff_t *pos) 121 { 122 if (*pos == 0) 123 return pos; 124 return NULL; 125 } 126 127 static void *property_next(struct seq_file *f, void *v, loff_t *pos) 128 { 129 (*pos)++; 130 return NULL; 131 } 132 133 static void property_stop(struct seq_file *f, void *v) 134 { 135 /* Nothing to do */ 136 } 137 138 static const struct seq_operations property_op = { 139 .start = property_start, 140 .next = property_next, 141 .stop = property_stop, 142 .show = property_show 143 }; 144 145 static int property_open(struct inode *inode, struct file *file) 146 { 147 struct op_inode_info *oi = OP_I(inode); 148 int ret; 149 150 BUG_ON(oi->type != op_inode_prop); 151 152 ret = seq_open(file, &property_op); 153 if (!ret) { 154 struct seq_file *m = file->private_data; 155 m->private = oi->u.prop; 156 } 157 return ret; 158 } 159 160 static const struct file_operations openpromfs_prop_ops = { 161 .open = property_open, 162 .read = seq_read, 163 .llseek = seq_lseek, 164 .release = seq_release, 165 }; 166 167 static int openpromfs_readdir(struct file *, struct dir_context *); 168 169 static const struct file_operations openprom_operations = { 170 .read = generic_read_dir, 171 .iterate_shared = openpromfs_readdir, 172 .llseek = generic_file_llseek, 173 }; 174 175 static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int); 176 177 static const struct inode_operations openprom_inode_operations = { 178 .lookup = openpromfs_lookup, 179 }; 180 181 static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 182 { 183 struct op_inode_info *ent_oi, *oi = OP_I(dir); 184 struct device_node *dp, *child; 185 struct property *prop; 186 enum op_inode_type ent_type; 187 union op_inode_data ent_data; 188 const char *name; 189 struct inode *inode; 190 unsigned int ino; 191 int len; 192 193 BUG_ON(oi->type != op_inode_node); 194 195 dp = oi->u.node; 196 197 name = dentry->d_name.name; 198 len = dentry->d_name.len; 199 200 mutex_lock(&op_mutex); 201 202 child = dp->child; 203 while (child) { 204 const char *node_name = kbasename(child->full_name); 205 int n = strlen(node_name); 206 207 if (len == n && 208 !strncmp(node_name, name, len)) { 209 ent_type = op_inode_node; 210 ent_data.node = child; 211 ino = child->unique_id; 212 goto found; 213 } 214 child = child->sibling; 215 } 216 217 prop = dp->properties; 218 while (prop) { 219 int n = strlen(prop->name); 220 221 if (len == n && !strncmp(prop->name, name, len)) { 222 ent_type = op_inode_prop; 223 ent_data.prop = prop; 224 ino = prop->unique_id; 225 goto found; 226 } 227 228 prop = prop->next; 229 } 230 231 mutex_unlock(&op_mutex); 232 return ERR_PTR(-ENOENT); 233 234 found: 235 inode = openprom_iget(dir->i_sb, ino); 236 mutex_unlock(&op_mutex); 237 if (IS_ERR(inode)) 238 return ERR_CAST(inode); 239 ent_oi = OP_I(inode); 240 ent_oi->type = ent_type; 241 ent_oi->u = ent_data; 242 243 switch (ent_type) { 244 case op_inode_node: 245 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; 246 inode->i_op = &openprom_inode_operations; 247 inode->i_fop = &openprom_operations; 248 set_nlink(inode, 2); 249 break; 250 case op_inode_prop: 251 if (of_node_name_eq(dp, "options") && (len == 17) && 252 !strncmp (name, "security-password", 17)) 253 inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; 254 else 255 inode->i_mode = S_IFREG | S_IRUGO; 256 inode->i_fop = &openpromfs_prop_ops; 257 set_nlink(inode, 1); 258 inode->i_size = ent_oi->u.prop->length; 259 break; 260 } 261 262 return d_splice_alias(inode, dentry); 263 } 264 265 static int openpromfs_readdir(struct file *file, struct dir_context *ctx) 266 { 267 struct inode *inode = file_inode(file); 268 struct op_inode_info *oi = OP_I(inode); 269 struct device_node *dp = oi->u.node; 270 struct device_node *child; 271 struct property *prop; 272 int i; 273 274 mutex_lock(&op_mutex); 275 276 if (ctx->pos == 0) { 277 if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR)) 278 goto out; 279 ctx->pos = 1; 280 } 281 if (ctx->pos == 1) { 282 if (!dir_emit(ctx, "..", 2, 283 (dp->parent == NULL ? 284 OPENPROM_ROOT_INO : 285 dp->parent->unique_id), DT_DIR)) 286 goto out; 287 ctx->pos = 2; 288 } 289 i = ctx->pos - 2; 290 291 /* First, the children nodes as directories. */ 292 child = dp->child; 293 while (i && child) { 294 child = child->sibling; 295 i--; 296 } 297 while (child) { 298 if (!dir_emit(ctx, 299 kbasename(child->full_name), 300 strlen(kbasename(child->full_name)), 301 child->unique_id, DT_DIR)) 302 goto out; 303 304 ctx->pos++; 305 child = child->sibling; 306 } 307 308 /* Next, the properties as files. */ 309 prop = dp->properties; 310 while (i && prop) { 311 prop = prop->next; 312 i--; 313 } 314 while (prop) { 315 if (!dir_emit(ctx, prop->name, strlen(prop->name), 316 prop->unique_id, DT_REG)) 317 goto out; 318 319 ctx->pos++; 320 prop = prop->next; 321 } 322 323 out: 324 mutex_unlock(&op_mutex); 325 return 0; 326 } 327 328 static struct kmem_cache *op_inode_cachep; 329 330 static struct inode *openprom_alloc_inode(struct super_block *sb) 331 { 332 struct op_inode_info *oi; 333 334 oi = kmem_cache_alloc(op_inode_cachep, GFP_KERNEL); 335 if (!oi) 336 return NULL; 337 338 return &oi->vfs_inode; 339 } 340 341 static void openprom_free_inode(struct inode *inode) 342 { 343 kmem_cache_free(op_inode_cachep, OP_I(inode)); 344 } 345 346 static struct inode *openprom_iget(struct super_block *sb, ino_t ino) 347 { 348 struct inode *inode; 349 350 inode = iget_locked(sb, ino); 351 if (!inode) 352 return ERR_PTR(-ENOMEM); 353 if (inode->i_state & I_NEW) { 354 inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); 355 if (inode->i_ino == OPENPROM_ROOT_INO) { 356 inode->i_op = &openprom_inode_operations; 357 inode->i_fop = &openprom_operations; 358 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; 359 } 360 unlock_new_inode(inode); 361 } 362 return inode; 363 } 364 365 static int openprom_remount(struct super_block *sb, int *flags, char *data) 366 { 367 sync_filesystem(sb); 368 *flags |= SB_NOATIME; 369 return 0; 370 } 371 372 static const struct super_operations openprom_sops = { 373 .alloc_inode = openprom_alloc_inode, 374 .free_inode = openprom_free_inode, 375 .statfs = simple_statfs, 376 .remount_fs = openprom_remount, 377 }; 378 379 static int openprom_fill_super(struct super_block *s, struct fs_context *fc) 380 { 381 struct inode *root_inode; 382 struct op_inode_info *oi; 383 int ret; 384 385 s->s_flags |= SB_NOATIME; 386 s->s_blocksize = 1024; 387 s->s_blocksize_bits = 10; 388 s->s_magic = OPENPROM_SUPER_MAGIC; 389 s->s_op = &openprom_sops; 390 s->s_time_gran = 1; 391 root_inode = openprom_iget(s, OPENPROM_ROOT_INO); 392 if (IS_ERR(root_inode)) { 393 ret = PTR_ERR(root_inode); 394 goto out_no_root; 395 } 396 397 oi = OP_I(root_inode); 398 oi->type = op_inode_node; 399 oi->u.node = of_find_node_by_path("/"); 400 401 s->s_root = d_make_root(root_inode); 402 if (!s->s_root) 403 goto out_no_root_dentry; 404 return 0; 405 406 out_no_root_dentry: 407 ret = -ENOMEM; 408 out_no_root: 409 printk("openprom_fill_super: get root inode failed\n"); 410 return ret; 411 } 412 413 static int openpromfs_get_tree(struct fs_context *fc) 414 { 415 return get_tree_single(fc, openprom_fill_super); 416 } 417 418 static const struct fs_context_operations openpromfs_context_ops = { 419 .get_tree = openpromfs_get_tree, 420 }; 421 422 static int openpromfs_init_fs_context(struct fs_context *fc) 423 { 424 fc->ops = &openpromfs_context_ops; 425 return 0; 426 } 427 428 static struct file_system_type openprom_fs_type = { 429 .owner = THIS_MODULE, 430 .name = "openpromfs", 431 .init_fs_context = openpromfs_init_fs_context, 432 .kill_sb = kill_anon_super, 433 }; 434 MODULE_ALIAS_FS("openpromfs"); 435 436 static void op_inode_init_once(void *data) 437 { 438 struct op_inode_info *oi = (struct op_inode_info *) data; 439 440 inode_init_once(&oi->vfs_inode); 441 } 442 443 static int __init init_openprom_fs(void) 444 { 445 int err; 446 447 op_inode_cachep = kmem_cache_create("op_inode_cache", 448 sizeof(struct op_inode_info), 449 0, 450 (SLAB_RECLAIM_ACCOUNT | 451 SLAB_MEM_SPREAD | SLAB_ACCOUNT), 452 op_inode_init_once); 453 if (!op_inode_cachep) 454 return -ENOMEM; 455 456 err = register_filesystem(&openprom_fs_type); 457 if (err) 458 kmem_cache_destroy(op_inode_cachep); 459 460 return err; 461 } 462 463 static void __exit exit_openprom_fs(void) 464 { 465 unregister_filesystem(&openprom_fs_type); 466 /* 467 * Make sure all delayed rcu free inodes are flushed before we 468 * destroy cache. 469 */ 470 rcu_barrier(); 471 kmem_cache_destroy(op_inode_cachep); 472 } 473 474 module_init(init_openprom_fs) 475 module_exit(exit_openprom_fs) 476 MODULE_LICENSE("GPL"); 477