1 --- a/drivers/char/Makefile 2012-02-08 19:49:18.736981163 +0100
2 +++ b/drivers/char/Makefile 2012-02-10 18:43:23.927197754 +0100
4 obj-$(CONFIG_TILE_SROM) += tile-srom.o
6 obj-$(CONFIG_PS3_PHYSMEM) += ps3physmem.o
7 +obj-$(CONFIG_PS3_STRGMNGR) += ps3strgmngr.o
8 --- a/arch/powerpc/platforms/ps3/Kconfig 2012-02-08 19:49:18.736981163 +0100
9 +++ b/arch/powerpc/platforms/ps3/Kconfig 2012-02-10 18:46:54.907113221 +0100
12 This driver allows you direct access to the PS3 physical memory.
15 + tristate "PS3 Storage Manager Driver"
18 + This driver allows you to create/delete/modify regions
19 + on PS3 storage devices.
22 bool "PS3 udbg output via UDP broadcasts on Ethernet"
24 --- a/arch/powerpc/include/uapi/asm/Kbuild 2012-12-11 10:00:27.000000000 -0900
25 +++ b/arch/powerpc/include/uapi/asm/Kbuild 2012-12-11 10:00:46.000000000 -0900
28 header-y += ucontext.h
30 +header-y += ps3strgmngr.h
31 --- /dev/null 2012-02-10 17:03:27.997801619 +0100
32 +++ b/arch/powerpc/include/asm/ps3strgmngr.h 2012-02-10 18:49:42.806463666 +0100
35 + * PS3 Storage Manager Driver
37 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>
38 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
39 + * All rights reserved.
41 + * This program is free software; you can redistribute it and/or modify it
42 + * under the terms of the GNU General Public License as published
43 + * by the Free Software Foundation; version 2 of the License.
45 + * This program is distributed in the hope that it will be useful, but
46 + * WITHOUT ANY WARRANTY; without even the implied warranty of
47 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48 + * General Public License for more details.
50 + * You should have received a copy of the GNU General Public License along
51 + * with this program; if not, write to the Free Software Foundation, Inc.,
52 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
55 +#ifndef _PS3STRGMNGR_H
56 +#define _PS3STRGMNGR_H
58 +#include <linux/types.h>
59 +#include <linux/ioctl.h>
61 +#define PS3STRGMNGR_MAX_ACL_ENTRIES 8
62 +#define PS3STRGMNGR_MAX_REGIONS 8
63 +#define PS3STRGMNGR_MAX_DEVICES 8
65 +#define PS3STRGMNGR_CTL_GET_DEVICES _IOR('s', 0, int)
66 +#define PS3STRGMNGR_CTL_CREATE_REGION _IOWR('s', 1, int)
67 +#define PS3STRGMNGR_CTL_DELETE_REGION _IOW('s', 2, int)
68 +#define PS3STRGMNGR_CTL_SET_REGION_ACL_ENTRY _IOW('s', 3, int)
70 +enum ps3strgmngr_devtype {
71 + PS3STRGMNGR_DEVTYPE_DISK = 0,
72 + PS3STRGMNGR_DEVTYPE_CDROM,
73 + PS3STRGMNGR_DEVTYPE_FLASH,
74 + PS3STRGMNGR_DEVTYPE_NOR_FLASH,
77 +enum ps3strgmngr_region_access_rights {
78 + PS3STRGMNGR_REGION_READ = (1ull << 0),
79 + PS3STRGMNGR_REGION_WRITE = (1ull << 1),
82 +struct ps3strgmngr_acl_entry {
84 + __u64 access_rights; /* enum ps3strgmngr_region_access_rights */
87 +struct ps3strgmngr_region {
91 + __u64 nr_acl_entries;
92 + struct ps3strgmngr_acl_entry acl_entry[PS3STRGMNGR_MAX_ACL_ENTRIES];
95 +struct ps3strgmngr_device {
96 + __u64 type; /* enum ps3strgmngr_devtype */
101 + struct ps3strgmngr_region region[PS3STRGMNGR_MAX_REGIONS];
104 +struct ps3strgmngr_ctl_get_devices {
107 + struct ps3strgmngr_device device[PS3STRGMNGR_MAX_DEVICES];
110 +struct ps3strgmngr_ctl_create_region {
120 +struct ps3strgmngr_ctl_delete_region {
126 +struct ps3strgmngr_ctl_set_region_acl_entry {
131 + __u64 access_rights;
134 +#endif /* _PS3STRGMNGR_H */
135 --- /dev/null 2012-02-10 17:03:27.997801619 +0100
136 +++ b/drivers/char/ps3strgmngr.c 2012-02-10 23:29:41.429492084 +0100
139 + * PS3 Storage Manager Driver
141 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>
142 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
143 + * All rights reserved.
145 + * This program is free software; you can redistribute it and/or modify it
146 + * under the terms of the GNU General Public License as published
147 + * by the Free Software Foundation; version 2 of the License.
149 + * This program is distributed in the hope that it will be useful, but
150 + * WITHOUT ANY WARRANTY; without even the implied warranty of
151 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
152 + * General Public License for more details.
154 + * You should have received a copy of the GNU General Public License along
155 + * with this program; if not, write to the Free Software Foundation, Inc.,
156 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
159 +#include <linux/module.h>
160 +#include <linux/kernel.h>
161 +#include <linux/init.h>
162 +#include <linux/slab.h>
163 +#include <linux/fs.h>
164 +#include <linux/uaccess.h>
165 +#include <linux/compat.h>
166 +#include <linux/miscdevice.h>
168 +#include <asm/ps3.h>
169 +#include <asm/lv1call.h>
170 +#include <asm/ps3strgmngr.h>
172 +#define STORAGE_BUS_TYPE 5
174 +#define STORAGE_DEV_TYPE_DISK 0
175 +#define STORAGE_DEV_TYPE_CDROM 5
176 +#define STORAGE_DEV_TYPE_FLASH 14
177 +#define STORAGE_DEV_TYPE_NOR_FLASH 254
179 +static int ps3strgmngr_read_acl(u64 dev_id, struct ps3strgmngr_region *rgn)
181 + struct ps3strgmngr_acl_entry *acl_entry;
182 + unsigned int acl_entry_index;
185 + rgn->nr_acl_entries = 0;
186 + acl_entry = rgn->acl_entry;
188 + for (acl_entry_index = 0; acl_entry_index < PS3STRGMNGR_MAX_ACL_ENTRIES; acl_entry_index++) {
189 + res = lv1_storage_get_region_acl(dev_id, rgn->id, acl_entry_index,
190 + &acl_entry->laid, &acl_entry->access_rights);
194 + rgn->nr_acl_entries++;
201 +static int ps3strgmngr_read_region(u64 bus_index, u64 dev_index, u64 dev_id, u64 dev_type,
202 + u64 rgn_index, struct ps3strgmngr_region *rgn)
204 + u64 flash_ext_flag, junk;
207 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
208 + 0x6465760000000000ul | dev_index /* dev */,
209 + 0x726567696f6e0000ul | rgn_index /* region */,
210 + 0x6964000000000000ul /* id */,
215 + if (dev_type == STORAGE_DEV_TYPE_DISK) {
216 + res = lv1_read_repository_node(1, 0x0000000073797300ul /* sys */,
217 + 0x666c617368000000ul /* flash */,
218 + 0x6578740000000000ul /* ext */,
219 + 0, &flash_ext_flag, &junk);
223 + if (!(flash_ext_flag & 0x1) && (rgn->id > 0))
227 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
228 + 0x6465760000000000ul | dev_index /* dev */,
229 + 0x726567696f6e0000ul | rgn_index /* region */,
230 + 0x7374617274000000ul /* start */,
231 + &rgn->start_block, &junk);
235 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
236 + 0x6465760000000000ul | dev_index /* dev */,
237 + 0x726567696f6e0000ul | rgn_index /* region */,
238 + 0x73697a6500000000ul /* size */,
239 + &rgn->nr_blocks, &junk);
243 + res = ps3strgmngr_read_acl(dev_id, rgn);
250 +static int ps3strgmngr_read_device(u64 bus_index, u64 dev_index,
251 + struct ps3strgmngr_device *dev)
253 + struct ps3strgmngr_region *rgn;
254 + u64 type, nr_regions, junk;
255 + unsigned int rgn_index;
258 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
259 + 0x6465760000000000ul | dev_index /* dev */,
260 + 0x7479706500000000ul /* type */,
266 + case STORAGE_DEV_TYPE_DISK:
267 + dev->type = PS3STRGMNGR_DEVTYPE_DISK;
269 + case STORAGE_DEV_TYPE_CDROM:
270 + dev->type = PS3STRGMNGR_DEVTYPE_CDROM;
272 + case STORAGE_DEV_TYPE_FLASH:
273 + dev->type = PS3STRGMNGR_DEVTYPE_FLASH;
275 + case STORAGE_DEV_TYPE_NOR_FLASH:
276 + dev->type = PS3STRGMNGR_DEVTYPE_NOR_FLASH;
279 + return (-ENOTSUPP);
283 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
284 + 0x6465760000000000ul | dev_index /* dev */,
285 + 0x6964000000000000ul /* id */,
286 + 0, &dev->id, &junk);
290 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
291 + 0x6465760000000000ul | dev_index /* dev */,
292 + 0x626c6b5f73697a65ul /* blk_size */,
293 + 0, &dev->block_size, &junk);
297 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
298 + 0x6465760000000000ul | dev_index /* dev */,
299 + 0x6e5f626c6f636b73ul /* n_blocks */,
300 + 0, &dev->nr_blocks, &junk);
304 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
305 + 0x6465760000000000ul | dev_index /* dev */,
306 + 0x6e5f726567730000ul /* n_regs */,
307 + 0, &nr_regions, &junk);
313 + for (rgn_index = 0; rgn_index < nr_regions; rgn_index++) {
314 + res = ps3strgmngr_read_region(bus_index, dev_index, dev->id, type,
326 +static int ps3strgmngr_ctl_get_devices(struct ps3strgmngr_ctl_get_devices *get_devices)
328 + struct ps3strgmngr_device *dev;
329 + unsigned int bus_index, dev_index;
330 + u64 bus_type, bus_id, nr_devices, junk;
333 + get_devices->nr_devices = 0;
334 + dev = get_devices->device;
336 + for (bus_index = 0; bus_index < 10; bus_index++) {
337 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
338 + 0x7479706500000000ul /* type */,
339 + 0, 0, &bus_type, &junk);
343 + if (bus_type == STORAGE_BUS_TYPE)
347 + if (bus_index >= 10)
350 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
351 + 0x6964000000000000ul /* id */,
352 + 0, 0, &bus_id, &junk);
356 + res = lv1_read_repository_node(1, 0x0000000062757300ul | bus_index /* bus */,
357 + 0x6e756d5f64657600ul /* num_dev */,
358 + 0, 0, &nr_devices, &junk);
362 + for (dev_index = 0; dev_index < nr_devices; dev_index++) {
363 + res = ps3strgmngr_read_device(bus_index, dev_index, dev);
367 + get_devices->nr_devices++;
374 +static int ps3strgmngr_ctl_create_region(struct ps3strgmngr_ctl_create_region *create_region)
379 + res = lv1_storage_create_region(create_region->device_id, create_region->start_block,
380 + create_region->nr_blocks, 0, create_region->laid, &create_region->region_id, &tag);
387 +static int ps3strgmngr_ctl_delete_region(struct ps3strgmngr_ctl_delete_region *delete_region)
392 + res = lv1_storage_delete_region(delete_region->device_id, delete_region->region_id, &tag);
399 +static int ps3strgmngr_ctl_set_region_acl_entry(struct ps3strgmngr_ctl_set_region_acl_entry *set_region_acl_entry)
404 + res = lv1_storage_set_region_acl(set_region_acl_entry->device_id, set_region_acl_entry->region_id,
405 + set_region_acl_entry->laid, set_region_acl_entry->access_rights,
413 +static long ps3strgmngr_ioctl(struct file *file, unsigned int cmd,
416 + void __user *argp = (void __user *) arg;
417 + struct ps3strgmngr_ctl_get_devices *get_devices;
418 + struct ps3strgmngr_ctl_create_region *create_region;
419 + struct ps3strgmngr_ctl_delete_region *delete_region;
420 + struct ps3strgmngr_ctl_set_region_acl_entry *set_region_acl_entry;
423 + if (is_compat_task())
424 + argp = compat_ptr(arg);
426 + argp = (void __user *) arg;
429 + case PS3STRGMNGR_CTL_GET_DEVICES:
430 + get_devices = kmalloc(sizeof(*get_devices), GFP_KERNEL);
434 + if (copy_from_user(get_devices, argp, sizeof(*get_devices))) {
435 + kfree(get_devices);
439 + res = ps3strgmngr_ctl_get_devices(get_devices);
441 + kfree(get_devices);
445 + if (copy_to_user(argp, get_devices, sizeof(*get_devices))) {
446 + kfree(get_devices);
450 + kfree(get_devices);
452 + case PS3STRGMNGR_CTL_CREATE_REGION:
453 + create_region = kmalloc(sizeof(*create_region), GFP_KERNEL);
454 + if (!create_region)
457 + if (copy_from_user(create_region, argp, sizeof(*create_region))) {
458 + kfree(create_region);
462 + res = ps3strgmngr_ctl_create_region(create_region);
464 + kfree(create_region);
468 + if (copy_to_user(argp, create_region, sizeof(*create_region))) {
469 + kfree(create_region);
473 + kfree(create_region);
475 + case PS3STRGMNGR_CTL_DELETE_REGION:
476 + delete_region = kmalloc(sizeof(*delete_region), GFP_KERNEL);
477 + if (!delete_region)
480 + if (copy_from_user(delete_region, argp, sizeof(*delete_region))) {
481 + kfree(delete_region);
485 + res = ps3strgmngr_ctl_delete_region(delete_region);
487 + kfree(delete_region);
491 + if (copy_to_user(argp, delete_region, sizeof(*delete_region))) {
492 + kfree(delete_region);
496 + kfree(delete_region);
498 + case PS3STRGMNGR_CTL_SET_REGION_ACL_ENTRY:
499 + set_region_acl_entry = kmalloc(sizeof(*set_region_acl_entry), GFP_KERNEL);
500 + if (!set_region_acl_entry)
503 + if (copy_from_user(set_region_acl_entry, argp, sizeof(*set_region_acl_entry))) {
504 + kfree(set_region_acl_entry);
508 + res = ps3strgmngr_ctl_set_region_acl_entry(set_region_acl_entry);
510 + kfree(set_region_acl_entry);
514 + if (copy_to_user(argp, set_region_acl_entry, sizeof(*set_region_acl_entry))) {
515 + kfree(set_region_acl_entry);
519 + kfree(set_region_acl_entry);
522 + return (-ENOIOCTLCMD);
529 +static const struct file_operations ps3strgmngr_fops = {
530 + .owner = THIS_MODULE,
531 + .unlocked_ioctl = ps3strgmngr_ioctl,
532 + .compat_ioctl = ps3strgmngr_ioctl,
535 +static struct miscdevice ps3strgmngr_misc = {
536 + .minor = MISC_DYNAMIC_MINOR,
537 + .name = "ps3strgmngr",
538 + .fops = &ps3strgmngr_fops,
541 +static int __init ps3strgmngr_init(void)
545 + res = misc_register(&ps3strgmngr_misc);
547 + pr_info("%s:%u: misc_register failed %d\n",
548 + __func__, __LINE__, res);
555 +static void __exit ps3strgmngr_exit(void)
557 + misc_deregister(&ps3strgmngr_misc);
560 +module_init(ps3strgmngr_init);
561 +module_exit(ps3strgmngr_exit);
563 +MODULE_AUTHOR("glevand");
564 +MODULE_DESCRIPTION("PS3 Storage Manager Driver");
565 +MODULE_LICENSE("GPL");