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_SCM_VERSION "0.0.1"
29 #define PS3DM_SCM_LAID 0x1070000002000001ull
30 #define PS3DM_SCM_PAID 0x10700003ff000001ull
41 static struct option long_opts
[] = {
42 { "help", no_argument
, NULL
, 'h' },
43 { "verbose", no_argument
, NULL
, 'v' },
44 { "version", no_argument
, NULL
, 'V' },
51 static void usage(void) {
53 "Usage: ps3dm_scm [OPTIONS] DEVICE COMMAND [ARGS]\n"
56 " -h, --help Show this message and exit\n"
57 " -v, --verbose Increase verbosity\n"
58 " -V, --version Show version information and exit\n"
60 " get_region_data ID Reads region data\n"
61 " get_time TID Returns RTC time\n"
62 " read_eprom OFFSET SIZE Reads EPROM data\n"
63 " get_sc_status Returns SYSCON status\n"
65 "Simple example: Get SYSCON status:\n"
66 " ps3dm_scm /dev/ps3dmproxy get_sc_status\n");
72 static void version(void)
75 "ps3dm_scm " PS3DM_SCM_VERSION
"\n"
76 "Copyright (C) 2011 graf_chokolo <grafchokolo@googlemail.com>\n"
77 "This is free software. You may redistribute copies of it "
78 "under the terms of\n"
79 "the GNU General Public License 2 "
80 "<http://www.gnu.org/licenses/gpl2.html>.\n"
81 "There is NO WARRANTY, to the extent permitted by law.\n");
87 static int process_opts(int argc
, char **argv
, struct opts
*opts
)
91 while ((c
= getopt_long(argc
, argv
, "hvV", long_opts
, NULL
)) != -1) {
103 opts
->do_version
= 1;
107 fprintf(stderr
, "Invalid command option: %c\n", c
);
112 if (optind
>= argc
) {
113 fprintf(stderr
, "No device specified\n");
117 opts
->device_name
= argv
[optind
];
120 if (optind
>= argc
) {
121 fprintf(stderr
, "No command specified\n");
125 opts
->cmd
= argv
[optind
];
132 * cmd_get_region_data
134 static int cmd_get_region_data(int fd
, struct opts
*opts
, int argc
, char **argv
)
139 struct ps3dm_hdr
*dm_hdr
;
140 struct ps3ss_hdr
*ss_hdr
;
141 struct ps3ss_scm_get_region_data
*ss_scm_get_region_data
;
144 if (optind
>= argc
) {
145 fprintf(stderr
, "No id specified\n");
149 id
= strtoul(argv
[optind
], &endptr
, 0);
150 if (*endptr
!= '\0') {
151 fprintf(stderr
, "Invalid id specified: %s\n", argv
[optind
]);
157 memset(buf
, 0, sizeof(buf
));
158 dm_hdr
= (struct ps3dm_hdr
*) buf
;
159 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
160 ss_scm_get_region_data
= (struct ps3ss_scm_get_region_data
*)(ss_hdr
+ 1);
162 dm_hdr
->request_id
= 1;
163 dm_hdr
->function_id
= PS3SS_FID_SCM
;
164 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_region_data
) + 0x30;
165 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_region_data
) + 0x30;
167 ss_hdr
->packet_id
= PS3SS_PID_SCM_GET_REGION_DATA
;
168 ss_hdr
->function_id
= PS3SS_FID_SCM
;
169 ss_hdr
->laid
= PS3DM_SCM_LAID
;
170 ss_hdr
->paid
= PS3DM_SCM_PAID
;
172 ss_scm_get_region_data
->id
= id
;
173 ss_scm_get_region_data
->data_size
= 0x30;
175 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
176 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
179 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
180 } else if (ss_hdr
->retval
) {
181 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
184 for (i
= 0; i
< ss_scm_get_region_data
->data_size
; i
++)
185 fprintf(stdout
, "0x%02x ", ss_scm_get_region_data
->data
[i
]);
187 fprintf(stdout
, "\n");
196 static int cmd_get_time(int fd
, struct opts
*opts
, int argc
, char **argv
)
201 struct ps3dm_hdr
*dm_hdr
;
202 struct ps3ss_hdr
*ss_hdr
;
203 struct ps3ss_scm_get_time
*ss_scm_get_time
;
206 if (optind
>= argc
) {
207 fprintf(stderr
, "No TID specified\n");
211 tid
= strtoul(argv
[optind
], &endptr
, 0);
212 if (*endptr
!= '\0') {
213 fprintf(stderr
, "Invalid TID specified: %s\n", argv
[optind
]);
219 memset(buf
, 0, sizeof(buf
));
220 dm_hdr
= (struct ps3dm_hdr
*) buf
;
221 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
222 ss_scm_get_time
= (struct ps3ss_scm_get_time
*)(ss_hdr
+ 1);
224 dm_hdr
->request_id
= 1;
225 dm_hdr
->function_id
= PS3SS_FID_SCM
;
226 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_time
);
227 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_time
);
229 ss_hdr
->packet_id
= PS3SS_PID_SCM_GET_TIME
;
230 ss_hdr
->function_id
= PS3SS_FID_SCM
;
231 ss_hdr
->laid
= PS3DM_SCM_LAID
;
232 ss_hdr
->paid
= PS3DM_SCM_PAID
;
234 ss_scm_get_time
->tid
= tid
;
236 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
237 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
240 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
241 } else if (ss_hdr
->retval
!= 0) {
242 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
245 fprintf(stdout
, "0x%016lx 0x%016lx\n", ss_scm_get_time
->field8
,
246 ss_scm_get_time
->field10
);
248 fprintf(stdout
, "\n");
257 static int cmd_read_eprom(int fd
, struct opts
*opts
, int argc
, char **argv
)
259 uint32_t eprom_offset
;
263 struct ps3dm_hdr
*dm_hdr
;
264 struct ps3ss_hdr
*ss_hdr
;
265 struct ps3ss_scm_read_eprom
*ss_scm_read_eprom
;
268 if (optind
>= argc
) {
269 fprintf(stderr
, "No EPROM offset specified\n");
273 eprom_offset
= strtoul(argv
[optind
], &endptr
, 0);
274 if (*endptr
!= '\0') {
275 fprintf(stderr
, "Invalid EPROM offset specified: %s\n", argv
[optind
]);
281 if (optind
>= argc
) {
282 fprintf(stderr
, "No size specified\n");
286 size
= strtoull(argv
[optind
], &endptr
, 0);
287 if ((*endptr
!= '\0') || (size
> 0x100)) {
288 fprintf(stderr
, "Invalid size specified: %s\n", argv
[optind
]);
294 memset(buf
, 0, sizeof(buf
));
295 dm_hdr
= (struct ps3dm_hdr
*) buf
;
296 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
297 ss_scm_read_eprom
= (struct ps3ss_scm_read_eprom
*)(ss_hdr
+ 1);
299 dm_hdr
->request_id
= 1;
300 dm_hdr
->function_id
= PS3SS_FID_SCM
;
301 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_read_eprom
) + size
;
302 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_read_eprom
) + size
;
304 ss_hdr
->packet_id
= PS3SS_PID_SCM_READ_EPROM
;
305 ss_hdr
->function_id
= PS3SS_FID_SCM
;
306 ss_hdr
->laid
= PS3DM_SCM_LAID
;
307 ss_hdr
->paid
= PS3DM_SCM_PAID
;
309 ss_scm_read_eprom
->offset
= eprom_offset
;
310 ss_scm_read_eprom
->nread
= size
;
311 ss_scm_read_eprom
->buf_size
= size
;
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
);
322 for (i
= 0; i
< ss_scm_read_eprom
->nread
; i
++)
323 fprintf(stdout
, "0x%02x ", ss_scm_read_eprom
->buf
[i
]);
325 fprintf(stdout
, "\n");
334 static int cmd_get_sc_status(int fd
, struct opts
*opts
, int argc
, char **argv
)
337 struct ps3dm_hdr
*dm_hdr
;
338 struct ps3ss_hdr
*ss_hdr
;
339 struct ps3ss_scm_get_sc_status
*ss_scm_get_sc_status
;
342 memset(buf
, 0, sizeof(buf
));
343 dm_hdr
= (struct ps3dm_hdr
*) buf
;
344 ss_hdr
= (struct ps3ss_hdr
*)(dm_hdr
+ 1);
345 ss_scm_get_sc_status
= (struct ps3ss_scm_get_sc_status
*)(ss_hdr
+ 1);
347 dm_hdr
->request_id
= 1;
348 dm_hdr
->function_id
= PS3SS_FID_SCM
;
349 dm_hdr
->request_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_sc_status
);
350 dm_hdr
->response_size
= PS3SS_HDR_SIZE
+ sizeof(struct ps3ss_scm_get_sc_status
);
352 ss_hdr
->packet_id
= PS3SS_PID_SCM_GET_SC_STATUS
;
353 ss_hdr
->function_id
= PS3SS_FID_SCM
;
354 ss_hdr
->laid
= PS3DM_SCM_LAID
;
355 ss_hdr
->paid
= PS3DM_SCM_PAID
;
357 error
= ps3dm_proxy_do_request(fd
, dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->request_size
,
358 dm_hdr
, PS3DM_HDR_SIZE
+ dm_hdr
->response_size
);
361 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
362 } else if (ss_hdr
->retval
) {
363 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
366 fprintf(stdout
, "0x%08x 0x%08x\n", ss_scm_get_sc_status
->version
,
367 ss_scm_get_sc_status
->mode
);
376 int main(int argc
, char **argv
)
379 int fd
= 0, error
= 0;
381 memset(&opts
, 0, sizeof(opts
));
383 if (process_opts(argc
, argv
, &opts
)) {
392 } else if (opts
.do_version
) {
397 fd
= ps3dm_proxy_open(opts
.device_name
);
399 fprintf(stderr
, "%s: %s\n", opts
.device_name
, strerror(errno
));
404 if (!strcmp(opts
.cmd
, "get_region_data")) {
405 error
= cmd_get_region_data(fd
, &opts
, argc
, argv
);
406 } else if (!strcmp(opts
.cmd
, "get_time")) {
407 error
= cmd_get_time(fd
, &opts
, argc
, argv
);
408 } else if (!strcmp(opts
.cmd
, "read_eprom")) {
409 error
= cmd_read_eprom(fd
, &opts
, argc
, argv
);
410 } else if (!strcmp(opts
.cmd
, "get_sc_status")) {
411 error
= cmd_get_sc_status(fd
, &opts
, argc
, argv
);
424 ps3dm_proxy_close(fd
);