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