3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; version 2 of the License.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "ps3dm_proxy.h"
27 #define PS3DM_SM_VERSION "0.0.1"
29 #define PS3DM_SM_LAID 0x1070000002000001ull
30 #define PS3DM_SM_GET_RND_NUMBER_PAID 0x1070000031000001ull
31 #define PS3DM_SM_PAID 0x10700003ff000001ull
42 static struct option long_opts
[] = {
43 { "help", no_argument
, NULL
, 'h' },
44 { "verbose", no_argument
, NULL
, 'v' },
45 { "version", no_argument
, NULL
, 'V' },
52 static void usage(void) {
54 "Usage: ps3dm_sm [OPTIONS] DEVICE COMMAND [ARGS]\n"
57 " -h, --help Show this message and exit\n"
58 " -v, --verbose Increase verbosity\n"
59 " -V, --version Show version information and exit\n"
61 " set_encdec_key KEY KEYSIZE Sets ENCDEC/ATA key\n"
62 " set_del_encdec_key PARAM Sets/Deletes ENCDEC/ATA key\n"
64 " 0xC-0xF Deletes ENCDEC/ATA key\n"
65 " 0x10[0-F] Sets default ENCDEC/ATA key\n"
66 " 0x11[0-F] Deletes default ENCDEC/ATA key\n"
67 " get_rnd_number Returns random number\n"
68 " drive_auth PARAM Authenticates BD drive\n"
70 " 0x29 Authenticates BD drive\n"
71 " 0x46 Resets BD drive\n"
72 " ps2_disc_auth PARAM Authenticates PS2 disc\n"
73 " get_version Returns version\n"
74 " drive_ctrl PARAM Controls BD drive\n"
76 "Simple example: Get random number:\n"
77 " ps3dm_sm /dev/ps3dmproxy get_rnd_number\n");
83 static void version(void)
86 "ps3dm_sm " PS3DM_SM_VERSION
"\n"
87 "Copyright (C) 2011 graf_chokolo <grafchokolo@googlemail.com>\n"
88 "This is free software. You may redistribute copies of it "
89 "under the terms of\n"
90 "the GNU General Public License 2 "
91 "<http://www.gnu.org/licenses/gpl2.html>.\n"
92 "There is NO WARRANTY, to the extent permitted by law.\n");
98 static int process_opts(int argc
, char **argv
, struct opts
*opts
)
102 while ((c
= getopt_long(argc
, argv
, "hvV", long_opts
, NULL
)) != -1) {
114 opts
->do_version
= 1;
118 fprintf(stderr
, "Invalid command option: %c\n", c
);
123 if (optind
>= argc
) {
124 fprintf(stderr
, "No device specified\n");
128 opts
->device_name
= argv
[optind
];
131 if (optind
>= argc
) {
132 fprintf(stderr
, "No command specified\n");
136 opts
->cmd
= argv
[optind
];
145 static int cmd_set_encdec_key(int fd
, struct opts
*opts
, int argc
, char **argv
)
152 struct ps3dm_hdr
*dm_hdr
;
153 struct ps3ss_hdr
*ss_hdr
;
154 struct ps3ss_sm_set_encdec_key
*ss_sm_set_encdec_key
;
157 if (optind
>= argc
) {
158 fprintf(stderr
, "No key specified\n");
164 while (optind
< argc
) {
165 val
= strtoul(argv
[optind
], &endptr
, 0);
166 if ((*endptr
!= '\0') || (val
> 0xff)) {
167 fprintf(stderr
, "Invalid key specified: %s\n", argv
[optind
]);
173 key
[key_size
++] = val
;
180 fprintf(stderr
, "Key should be of size 24 bytes\n");
184 if (optind
>= argc
) {
185 fprintf(stderr
, "No key length specified\n");
189 key_size
= strtoull(argv
[optind
], &endptr
, 0);
190 if (*endptr
!= '\0') {
191 fprintf(stderr
, "Invalid key length specified: %s\n", argv
[optind
]);
197 memset(buf
, 0, sizeof(buf
));
198 dm_hdr
= (struct ps3dm_hdr
*) buf
;
199 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
200 ss_sm_set_encdec_key
= (struct ps3ss_sm_set_encdec_key
*)(ss_hdr
+ 1);
202 dm_hdr
->request_id
= 1;
203 dm_hdr
->function_id
= PS3SS_FID_SM
;
204 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_set_encdec_key
);
205 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_set_encdec_key
);
207 ss_hdr
->packet_id
= PS3SS_PID_SM_SET_ENCDEC_KEY
;
208 ss_hdr
->function_id
= PS3SS_FID_SM
;
209 ss_hdr
->laid
= PS3DM_SM_LAID
;
210 ss_hdr
->paid
= PS3DM_SM_PAID
;
212 memcpy(ss_sm_set_encdec_key
->key
, key
, sizeof(key
));
213 ss_sm_set_encdec_key
->key_size
= key_size
;
215 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
216 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
219 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
221 } else if (ss_hdr
->retval
) {
222 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
225 fprintf(stdout
, "0x%016lx\n", ss_sm_set_encdec_key
->param
);
232 * cmd_set_del_encdec_key
234 static int cmd_set_del_encdec_key(int fd
, struct opts
*opts
, int argc
, char **argv
)
239 struct ps3dm_hdr
*dm_hdr
;
240 struct ps3ss_hdr
*ss_hdr
;
241 struct ps3ss_sm_set_del_encdec_key
*ss_sm_set_del_encdec_key
;
244 if (optind
>= argc
) {
245 fprintf(stderr
, "No parameter specified\n");
249 param
= strtoull(argv
[optind
], &endptr
, 0);
250 if (*endptr
!= '\0') {
251 fprintf(stderr
, "Invalid parameter specified: %s\n", argv
[optind
]);
257 memset(buf
, 0, sizeof(buf
));
258 dm_hdr
= (struct ps3dm_hdr
*) buf
;
259 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
260 ss_sm_set_del_encdec_key
= (struct ps3ss_sm_set_del_encdec_key
*)(ss_hdr
+ 1);
262 dm_hdr
->request_id
= 1;
263 dm_hdr
->function_id
= PS3SS_FID_SM
;
264 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_set_del_encdec_key
);
265 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_set_del_encdec_key
);
267 ss_hdr
->packet_id
= PS3SS_PID_SM_SET_DEL_ENCDEC_KEY
;
268 ss_hdr
->function_id
= PS3SS_FID_SM
;
269 ss_hdr
->laid
= PS3DM_SM_LAID
;
270 ss_hdr
->paid
= PS3DM_SM_PAID
;
272 ss_sm_set_del_encdec_key
->param
= param
;
274 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
275 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
278 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
282 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
290 static int cmd_get_rnd_number(int fd
, struct opts
*opts
, int argc
, char **argv
)
293 struct ps3dm_hdr
*dm_hdr
;
294 struct ps3ss_hdr
*ss_hdr
;
295 struct ps3ss_sm_get_rnd_number
*ss_sm_get_rnd_number
;
298 memset(buf
, 0, sizeof(buf
));
299 dm_hdr
= (struct ps3dm_hdr
*) buf
;
300 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
301 ss_sm_get_rnd_number
= (struct ps3ss_sm_get_rnd_number
*)(ss_hdr
+ 1);
303 dm_hdr
->request_id
= 1;
304 dm_hdr
->function_id
= PS3SS_FID_SM
;
305 dm_hdr
->request_size
= PS3SS_HDR_SIZE
;
306 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_get_rnd_number
);
308 ss_hdr
->packet_id
= PS3SS_PID_SM_GET_RND_NUMBER
;
309 ss_hdr
->function_id
= PS3SS_FID_SM
;
310 ss_hdr
->laid
= PS3DM_SM_LAID
;
311 ss_hdr
->paid
= PS3DM_SM_GET_RND_NUMBER_PAID
;
313 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
314 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
317 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
318 } else if (ss_hdr
->retval
) {
319 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
321 for (i
= 0; i
< sizeof(ss_sm_get_rnd_number
->field0
); i
++)
322 fprintf(stdout
, "0x%02x ", ss_sm_get_rnd_number
->field0
[i
]);
324 fprintf(stdout
, "\n");
333 static int cmd_drive_auth(int fd
, struct opts
*opts
, int argc
, char **argv
)
338 struct ps3dm_hdr
*dm_hdr
;
339 struct ps3ss_hdr
*ss_hdr
;
340 struct ps3ss_sm_drive_auth
*ss_sm_drive_auth
;
343 if (optind
>= argc
) {
344 fprintf(stderr
, "No parameter specified\n");
348 param
= strtoull(argv
[optind
], &endptr
, 0);
349 if (*endptr
!= '\0') {
350 fprintf(stderr
, "Invalid parameter specified: %s\n", argv
[optind
]);
356 memset(buf
, 0, sizeof(buf
));
357 dm_hdr
= (struct ps3dm_hdr
*) buf
;
358 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
359 ss_sm_drive_auth
= (struct ps3ss_sm_drive_auth
*)(ss_hdr
+ 1);
361 dm_hdr
->request_id
= 1;
362 dm_hdr
->function_id
= PS3SS_FID_SM
;
363 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_drive_auth
);
364 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_drive_auth
);
366 ss_hdr
->packet_id
= PS3SS_PID_SM_DRIVE_AUTH
;
367 ss_hdr
->function_id
= PS3SS_FID_SM
;
368 ss_hdr
->laid
= PS3DM_SM_LAID
;
369 ss_hdr
->paid
= PS3DM_SM_PAID
;
371 ss_sm_drive_auth
->param
= param
;
373 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
374 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
377 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
381 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
389 static int cmd_ps2_disc_auth(int fd
, struct opts
*opts
, int argc
, char **argv
)
392 struct ps3dm_hdr
*dm_hdr
;
393 struct ps3ss_hdr
*ss_hdr
;
394 struct ps3ss_sm_ps2_disc_auth
*ss_sm_ps2_disc_auth
;
397 memset(buf
, 0, sizeof(buf
));
398 dm_hdr
= (struct ps3dm_hdr
*) buf
;
399 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
400 ss_sm_ps2_disc_auth
= (struct ps3ss_sm_ps2_disc_auth
*)(ss_hdr
+ 1);
402 dm_hdr
->request_id
= 1;
403 dm_hdr
->function_id
= PS3SS_FID_SM
;
404 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_ps2_disc_auth
);
405 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_ps2_disc_auth
);
407 ss_hdr
->packet_id
= PS3SS_PID_SM_PS2_DISC_AUTH
;
408 ss_hdr
->function_id
= PS3SS_FID_SM
;
409 ss_hdr
->laid
= PS3DM_SM_LAID
;
410 ss_hdr
->paid
= PS3DM_SM_PAID
;
412 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
413 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
416 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
417 } else if (ss_hdr
->retval
) {
418 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
421 for (i
= 0; i
< sizeof(ss_sm_ps2_disc_auth
->field0
); i
++)
422 fprintf(stdout
, "0x%02x ", ss_sm_ps2_disc_auth
->field0
[i
]);
424 fprintf(stdout
, "\n");
433 static int cmd_get_version(int fd
, struct opts
*opts
, int argc
, char **argv
)
436 struct ps3dm_hdr
*dm_hdr
;
437 struct ps3ss_hdr
*ss_hdr
;
438 struct ps3ss_sm_get_version
*ss_sm_get_version
;
441 memset(buf
, 0, sizeof(buf
));
442 dm_hdr
= (struct ps3dm_hdr
*) buf
;
443 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
444 ss_sm_get_version
= (struct ps3ss_sm_get_version
*)(ss_hdr
+ 1);
446 dm_hdr
->request_id
= 1;
447 dm_hdr
->function_id
= PS3SS_FID_SM
;
448 dm_hdr
->request_size
= PS3SS_HDR_SIZE
;
449 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_get_version
);
451 ss_hdr
->packet_id
= PS3SS_PID_SM_GET_VERSION
;
452 ss_hdr
->function_id
= PS3SS_FID_SM
;
453 ss_hdr
->laid
= PS3DM_SM_LAID
;
454 ss_hdr
->paid
= PS3DM_SM_PAID
;
456 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
457 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
460 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
461 } else if (ss_hdr
->retval
) {
462 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
464 for (i
= 0; i
< sizeof(ss_sm_get_version
->field0
); i
++)
465 fprintf(stdout
, "0x%02x ", ss_sm_get_version
->field0
[i
]);
467 fprintf(stdout
, "\n");
476 static int cmd_drive_ctrl(int fd
, struct opts
*opts
, int argc
, char **argv
)
481 struct ps3dm_hdr
*dm_hdr
;
482 struct ps3ss_hdr
*ss_hdr
;
483 struct ps3ss_sm_drive_ctrl
*ss_sm_drive_ctrl
;
486 if (optind
>= argc
) {
487 fprintf(stderr
, "No parameter specified\n");
491 param
= strtoull(argv
[optind
], &endptr
, 0);
492 if (*endptr
!= '\0') {
493 fprintf(stderr
, "Invalid parameter specified: %s\n", argv
[optind
]);
499 memset(buf
, 0, sizeof(buf
));
500 dm_hdr
= (struct ps3dm_hdr
*) buf
;
501 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
502 ss_sm_drive_ctrl
= (struct ps3ss_sm_drive_ctrl
*)(ss_hdr
+ 1);
504 dm_hdr
->request_id
= 1;
505 dm_hdr
->function_id
= PS3SS_FID_SM
;
506 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_drive_ctrl
);
507 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_sm_drive_ctrl
);
509 ss_hdr
->packet_id
= PS3SS_PID_SM_DRIVE_CTRL
;
510 ss_hdr
->function_id
= PS3SS_FID_SM
;
511 ss_hdr
->laid
= PS3DM_SM_LAID
;
512 ss_hdr
->paid
= PS3DM_SM_PAID
;
514 ss_sm_drive_ctrl
->param
= param
;
516 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
517 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
520 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
521 } else if (ss_hdr
->retval
) {
522 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
525 for (i
= 0; i
< sizeof(ss_sm_drive_ctrl
->field8
); i
++)
526 fprintf(stdout
, "0x%02x ", ss_sm_drive_ctrl
->field8
[i
]);
528 fprintf(stdout
, "\n");
537 int main(int argc
, char **argv
)
540 int fd
= 0, error
= 0;
542 memset(&opts
, 0, sizeof(opts
));
544 if (process_opts(argc
, argv
, &opts
)) {
553 } else if (opts
.do_version
) {
558 fd
= ps3dm_proxy_open(opts
.device_name
);
560 fprintf(stderr
, "%s: %s\n", opts
.device_name
, strerror(errno
));
565 if (!strcmp(opts
.cmd
, "set_encdec_key")) {
566 error
= cmd_set_encdec_key(fd
, &opts
, argc
, argv
);
567 } else if (!strcmp(opts
.cmd
, "set_del_encdec_key")) {
568 error
= cmd_set_del_encdec_key(fd
, &opts
, argc
, argv
);
569 } else if (!strcmp(opts
.cmd
, "get_rnd_number")) {
570 error
= cmd_get_rnd_number(fd
, &opts
, argc
, argv
);
571 } else if (!strcmp(opts
.cmd
, "drive_auth")) {
572 error
= cmd_drive_auth(fd
, &opts
, argc
, argv
);
573 } else if (!strcmp(opts
.cmd
, "ps2_disc_auth")) {
574 error
= cmd_ps2_disc_auth(fd
, &opts
, argc
, argv
);
575 } else if (!strcmp(opts
.cmd
, "get_version")) {
576 error
= cmd_get_version(fd
, &opts
, argc
, argv
);
577 } else if (!strcmp(opts
.cmd
, "drive_ctrl")) {
578 error
= cmd_drive_ctrl(fd
, &opts
, argc
, argv
);
591 ps3dm_proxy_close(fd
);