PS3 platform routines
[petitboot] / ui / common / ps3.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define _GNU_SOURCE
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/ioctl.h>
27 #include <ps3-flash.h>
28 #include <ps3-av.h>
29
30 #include "log/log.h"
31 #include "pb-system.h"
32 #include "ps3.h"
33
34 static const char flash_dev[] = "/dev/ps3flash";
35 static const char fb_dev[] = "/dev/fb0";
36
37 static const struct os_area_db_id id_default_item =
38 {
39         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
40         .key = 1,
41 };
42 static const struct os_area_db_id id_video_mode =
43 {
44         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
45         .key = OS_AREA_DB_KEY_VIDEO_MODE,    /* 2 */
46 };
47 static const struct os_area_db_id id_flags =
48 {
49         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
50         .key = 3,
51 };
52
53 struct ps3_flash_ctx {
54         FILE *dev;
55         struct os_area_header header;
56         struct os_area_params params;
57         struct os_area_db db;
58 };
59
60 static void ps3_flash_close(struct ps3_flash_ctx *fc)
61 {
62         fclose(fc->dev);
63         fc->dev = NULL;
64 }
65
66 static int ps3_flash_open(struct ps3_flash_ctx *fc, const char *mode)
67 {
68         int result;
69
70         fc->dev = fopen(flash_dev, mode);
71
72         if (!fc->dev) {
73                 pb_log("%s: fopen failed: %s: %s\n", __func__, strerror(errno),
74                         flash_dev);
75                 return -1;
76         }
77
78         os_area_set_log_stream(pb_log_get_stream());
79
80         result = os_area_fixed_read(&fc->header, &fc->params, fc->dev);
81
82         if (result) {
83                 pb_log("%s: os_area_fixed_read failed: %s\n", __func__);
84                 goto fail;
85         }
86
87         return 0;
88
89 fail:
90         ps3_flash_close(fc);
91         return -1;
92 }
93
94 /**
95  * ps3_flash_get_values - Read values from the PS3 flash memory database.
96  *
97  * Returns zero on success.
98  */
99
100 int ps3_flash_get_values(struct ps3_flash_values *values)
101 {
102         int result;
103         int sum;
104         struct ps3_flash_ctx fc;
105         uint64_t tmp;
106
107         memset(values, 0, sizeof(*values));
108
109         result = ps3_flash_open(&fc, "r");
110
111         if (result)
112                 return -1;
113
114         result = os_area_db_read(&fc.db, &fc.header, fc.dev);
115
116         if (result) {
117                 pb_log("%s: os_area_db_read failed: %s\n", __func__,
118                         strerror(errno));
119                 goto fail;
120         }
121
122         sum = result = os_area_db_get(&fc.db, &id_default_item, &tmp);
123
124         if (!result)
125                 values->default_item = (uint32_t)tmp;
126
127         sum += result = os_area_db_get(&fc.db, &id_video_mode, &tmp);
128
129         if (!result)
130                 values->video_mode = (uint16_t)tmp;
131
132
133         pb_log("%s: default_item: %u\n", __func__, values->default_item);
134         pb_log("%s: video_mode:   %u\n", __func__, values->video_mode);
135
136         ps3_flash_close(&fc);
137         return !!sum;
138
139 fail:
140         ps3_flash_close(&fc);
141         return -1;
142 }
143
144 /**
145  * ps3_flash_set_values - Writes values from the PS3 flash memory database.
146  *
147  * Formats the flash database before writing if a valid database if not found.
148  * Returns zero on success.
149  */
150
151 int ps3_flash_set_values(const struct ps3_flash_values *values)
152 {
153         int result;
154         struct ps3_flash_ctx fc;
155
156         pb_log("%s: default_item: %u\n", __func__, values->default_item);
157         pb_log("%s: video_mode:   %u\n", __func__, values->video_mode);
158
159         result = ps3_flash_open(&fc, "r+");
160
161         if (result)
162                 return result;
163
164         result = os_area_db_read(&fc.db, &fc.header, fc.dev);
165
166         if (result) {
167                 pb_log("%s: os_area_db_read failed: %s\n", __func__,
168                         strerror(errno));
169                 pb_log("%s: formating db\n", __func__);
170
171                 result = os_area_db_format(&fc.db, &fc.header, fc.dev);
172
173                 if (result) {
174                         pb_log("%s: db_format failed: %s\n", __func__,
175                                 strerror(errno));
176                         goto fail;
177                 }
178         }
179
180         result = os_area_db_set_32(&fc.db, &id_default_item,
181                 values->default_item);
182         result += os_area_db_set_16(&fc.db, &id_video_mode,
183                 values->video_mode);
184
185         result += os_area_db_write(&fc.db, &fc.header, fc.dev);
186
187         ps3_flash_close(&fc);
188         return result;
189
190 fail:
191         ps3_flash_close(&fc);
192         return -1;
193 }
194
195 /**
196  * ps3_video_ioctl - Low level ioctl helper.
197  *
198  * Use ps3_get_video_mode or ps3_set_video_mode().
199  */
200
201 static int ps3_video_ioctl(int request, unsigned int *mode_id)
202 {
203         int result;
204         int fd;
205
206         fd = open(fb_dev, O_RDWR);
207
208         if (fd < 0) {
209                 pb_log("%s: open failed: %s: %s\n", __func__, strerror(errno),
210                         fb_dev);
211                 return -1;
212         }
213
214         result = ioctl(fd, request, (unsigned long)mode_id);
215
216         close(fd);
217
218         if (result < 0) {
219                 pb_log("%s: ioctl failed: %s: %s\n", __func__, strerror(errno),
220                         fb_dev);
221                 return -1;
222         }
223
224         return 0;
225 }
226
227 /**
228  * ps3_set_video_mode - Set the PS3 video mode.
229  * @mode_id: The PS3 video mode_id as documented in the ps3-video-mode man page.
230  *
231  * Returns zero on success.
232  */
233
234 int ps3_set_video_mode(unsigned int mode_id)
235 {
236         pb_log("%s: %u\n", __func__, mode_id);
237         return ps3_video_ioctl(PS3FB_IOCTL_SETMODE, &mode_id);
238 }
239
240 /**
241  * ps3_set_video_mode - Get the current PS3 video mode.
242  * @mode_id: The PS3 video mode_id as documented in the ps3-video-mode man page.
243  *
244  * Returns zero on success.
245  */
246
247 int ps3_get_video_mode(unsigned int *mode_id)
248 {
249         int result;
250
251         *mode_id = 0;
252
253         result =  ps3_video_ioctl(PS3FB_IOCTL_GETMODE, mode_id);
254
255         pb_log("%s: %u\n", __func__, *mode_id);
256         return result;
257 }