0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/io.h>
0011 #include <linux/workqueue.h>
0012 #include <linux/fs.h>
0013 #include <linux/syscalls.h>
0014 #include <linux/export.h>
0015 #include <linux/ctype.h>
0016 #include <linux/memblock.h>
0017 #include <linux/of.h>
0018 #include <linux/slab.h>
0019
0020 #include "platform.h"
0021
0022 enum {
0023 OS_AREA_SEGMENT_SIZE = 0X200,
0024 };
0025
0026 enum os_area_ldr_format {
0027 HEADER_LDR_FORMAT_RAW = 0,
0028 HEADER_LDR_FORMAT_GZIP = 1,
0029 };
0030
0031 #define OS_AREA_HEADER_MAGIC_NUM "cell_ext_os_area"
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 struct os_area_header {
0049 u8 magic_num[16];
0050 u32 hdr_version;
0051 u32 db_area_offset;
0052 u32 ldr_area_offset;
0053 u32 _reserved_1;
0054 u32 ldr_format;
0055 u32 ldr_size;
0056 u32 _reserved_2[6];
0057 };
0058
0059 enum os_area_boot_flag {
0060 PARAM_BOOT_FLAG_GAME_OS = 0,
0061 PARAM_BOOT_FLAG_OTHER_OS = 1,
0062 };
0063
0064 enum os_area_ctrl_button {
0065 PARAM_CTRL_BUTTON_O_IS_YES = 0,
0066 PARAM_CTRL_BUTTON_X_IS_YES = 1,
0067 };
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 struct os_area_params {
0090 u32 boot_flag;
0091 u32 _reserved_1[3];
0092 u32 num_params;
0093 u32 _reserved_2[3];
0094
0095 s64 rtc_diff;
0096 u8 av_multi_out;
0097 u8 ctrl_button;
0098 u8 _reserved_3[6];
0099
0100 u8 static_ip_addr[4];
0101 u8 network_mask[4];
0102 u8 default_gateway[4];
0103 u8 _reserved_4[4];
0104
0105 u8 dns_primary[4];
0106 u8 dns_secondary[4];
0107 u8 _reserved_5[8];
0108 };
0109
0110 #define OS_AREA_DB_MAGIC_NUM "-db-"
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 struct os_area_db {
0129 u8 magic_num[4];
0130 u16 version;
0131 u16 _reserved_1;
0132 u16 index_64;
0133 u16 count_64;
0134 u16 index_32;
0135 u16 count_32;
0136 u16 index_16;
0137 u16 count_16;
0138 u32 _reserved_2;
0139 u8 _db_data[1000];
0140 };
0141
0142
0143
0144
0145
0146 enum os_area_db_owner {
0147 OS_AREA_DB_OWNER_ANY = -1,
0148 OS_AREA_DB_OWNER_NONE = 0,
0149 OS_AREA_DB_OWNER_PROTOTYPE = 1,
0150 OS_AREA_DB_OWNER_LINUX = 2,
0151 OS_AREA_DB_OWNER_PETITBOOT = 3,
0152 OS_AREA_DB_OWNER_MAX = 32,
0153 };
0154
0155 enum os_area_db_key {
0156 OS_AREA_DB_KEY_ANY = -1,
0157 OS_AREA_DB_KEY_NONE = 0,
0158 OS_AREA_DB_KEY_RTC_DIFF = 1,
0159 OS_AREA_DB_KEY_VIDEO_MODE = 2,
0160 OS_AREA_DB_KEY_MAX = 8,
0161 };
0162
0163 struct os_area_db_id {
0164 int owner;
0165 int key;
0166 };
0167
0168 static const struct os_area_db_id os_area_db_id_empty = {
0169 .owner = OS_AREA_DB_OWNER_NONE,
0170 .key = OS_AREA_DB_KEY_NONE
0171 };
0172
0173 static const struct os_area_db_id os_area_db_id_any = {
0174 .owner = OS_AREA_DB_OWNER_ANY,
0175 .key = OS_AREA_DB_KEY_ANY
0176 };
0177
0178 static const struct os_area_db_id os_area_db_id_rtc_diff = {
0179 .owner = OS_AREA_DB_OWNER_LINUX,
0180 .key = OS_AREA_DB_KEY_RTC_DIFF
0181 };
0182
0183 #define SECONDS_FROM_1970_TO_2000 946684800LL
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 static struct saved_params {
0195 unsigned int valid;
0196 s64 rtc_diff;
0197 unsigned int av_multi_out;
0198 } saved_params;
0199
0200 static struct property property_rtc_diff = {
0201 .name = "linux,rtc_diff",
0202 .length = sizeof(saved_params.rtc_diff),
0203 .value = &saved_params.rtc_diff,
0204 };
0205
0206 static struct property property_av_multi_out = {
0207 .name = "linux,av_multi_out",
0208 .length = sizeof(saved_params.av_multi_out),
0209 .value = &saved_params.av_multi_out,
0210 };
0211
0212
0213 static DEFINE_MUTEX(os_area_flash_mutex);
0214
0215 static const struct ps3_os_area_flash_ops *os_area_flash_ops;
0216
0217 void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops)
0218 {
0219 mutex_lock(&os_area_flash_mutex);
0220 os_area_flash_ops = ops;
0221 mutex_unlock(&os_area_flash_mutex);
0222 }
0223 EXPORT_SYMBOL_GPL(ps3_os_area_flash_register);
0224
0225 static ssize_t os_area_flash_read(void *buf, size_t count, loff_t pos)
0226 {
0227 ssize_t res = -ENODEV;
0228
0229 mutex_lock(&os_area_flash_mutex);
0230 if (os_area_flash_ops)
0231 res = os_area_flash_ops->read(buf, count, pos);
0232 mutex_unlock(&os_area_flash_mutex);
0233
0234 return res;
0235 }
0236
0237 static ssize_t os_area_flash_write(const void *buf, size_t count, loff_t pos)
0238 {
0239 ssize_t res = -ENODEV;
0240
0241 mutex_lock(&os_area_flash_mutex);
0242 if (os_area_flash_ops)
0243 res = os_area_flash_ops->write(buf, count, pos);
0244 mutex_unlock(&os_area_flash_mutex);
0245
0246 return res;
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256 static void os_area_set_property(struct device_node *node,
0257 struct property *prop)
0258 {
0259 int result;
0260 struct property *tmp = of_find_property(node, prop->name, NULL);
0261
0262 if (tmp) {
0263 pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
0264 of_remove_property(node, tmp);
0265 }
0266
0267 result = of_add_property(node, prop);
0268
0269 if (result)
0270 pr_debug("%s:%d of_set_property failed\n", __func__,
0271 __LINE__);
0272 }
0273
0274
0275
0276
0277
0278
0279 static void __init os_area_get_property(struct device_node *node,
0280 struct property *prop)
0281 {
0282 const struct property *tmp = of_find_property(node, prop->name, NULL);
0283
0284 if (tmp) {
0285 BUG_ON(prop->length != tmp->length);
0286 memcpy(prop->value, tmp->value, prop->length);
0287 } else
0288 pr_debug("%s:%d not found %s\n", __func__, __LINE__,
0289 prop->name);
0290 }
0291
0292 static void dump_field(char *s, const u8 *field, int size_of_field)
0293 {
0294 #if defined(DEBUG)
0295 int i;
0296
0297 for (i = 0; i < size_of_field; i++)
0298 s[i] = isprint(field[i]) ? field[i] : '.';
0299 s[i] = 0;
0300 #endif
0301 }
0302
0303 #define dump_header(_a) _dump_header(_a, __func__, __LINE__)
0304 static void _dump_header(const struct os_area_header *h, const char *func,
0305 int line)
0306 {
0307 char str[sizeof(h->magic_num) + 1];
0308
0309 dump_field(str, h->magic_num, sizeof(h->magic_num));
0310 pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
0311 str);
0312 pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
0313 h->hdr_version);
0314 pr_debug("%s:%d: h.db_area_offset: %u\n", func, line,
0315 h->db_area_offset);
0316 pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
0317 h->ldr_area_offset);
0318 pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
0319 h->ldr_format);
0320 pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
0321 h->ldr_size);
0322 }
0323
0324 #define dump_params(_a) _dump_params(_a, __func__, __LINE__)
0325 static void _dump_params(const struct os_area_params *p, const char *func,
0326 int line)
0327 {
0328 pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag);
0329 pr_debug("%s:%d: p.num_params: %u\n", func, line, p->num_params);
0330 pr_debug("%s:%d: p.rtc_diff %lld\n", func, line, p->rtc_diff);
0331 pr_debug("%s:%d: p.av_multi_out %u\n", func, line, p->av_multi_out);
0332 pr_debug("%s:%d: p.ctrl_button: %u\n", func, line, p->ctrl_button);
0333 pr_debug("%s:%d: p.static_ip_addr: %u.%u.%u.%u\n", func, line,
0334 p->static_ip_addr[0], p->static_ip_addr[1],
0335 p->static_ip_addr[2], p->static_ip_addr[3]);
0336 pr_debug("%s:%d: p.network_mask: %u.%u.%u.%u\n", func, line,
0337 p->network_mask[0], p->network_mask[1],
0338 p->network_mask[2], p->network_mask[3]);
0339 pr_debug("%s:%d: p.default_gateway: %u.%u.%u.%u\n", func, line,
0340 p->default_gateway[0], p->default_gateway[1],
0341 p->default_gateway[2], p->default_gateway[3]);
0342 pr_debug("%s:%d: p.dns_primary: %u.%u.%u.%u\n", func, line,
0343 p->dns_primary[0], p->dns_primary[1],
0344 p->dns_primary[2], p->dns_primary[3]);
0345 pr_debug("%s:%d: p.dns_secondary: %u.%u.%u.%u\n", func, line,
0346 p->dns_secondary[0], p->dns_secondary[1],
0347 p->dns_secondary[2], p->dns_secondary[3]);
0348 }
0349
0350 static int verify_header(const struct os_area_header *header)
0351 {
0352 if (memcmp(header->magic_num, OS_AREA_HEADER_MAGIC_NUM,
0353 sizeof(header->magic_num))) {
0354 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
0355 return -1;
0356 }
0357
0358 if (header->hdr_version < 1) {
0359 pr_debug("%s:%d hdr_version failed\n", __func__, __LINE__);
0360 return -1;
0361 }
0362
0363 if (header->db_area_offset > header->ldr_area_offset) {
0364 pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
0365 return -1;
0366 }
0367
0368 return 0;
0369 }
0370
0371 static int db_verify(const struct os_area_db *db)
0372 {
0373 if (memcmp(db->magic_num, OS_AREA_DB_MAGIC_NUM,
0374 sizeof(db->magic_num))) {
0375 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
0376 return -EINVAL;
0377 }
0378
0379 if (db->version != 1) {
0380 pr_debug("%s:%d version failed\n", __func__, __LINE__);
0381 return -EINVAL;
0382 }
0383
0384 return 0;
0385 }
0386
0387 struct db_index {
0388 uint8_t owner:5;
0389 uint8_t key:3;
0390 };
0391
0392 struct db_iterator {
0393 const struct os_area_db *db;
0394 struct os_area_db_id match_id;
0395 struct db_index *idx;
0396 struct db_index *last_idx;
0397 union {
0398 uint64_t *value_64;
0399 uint32_t *value_32;
0400 uint16_t *value_16;
0401 };
0402 };
0403
0404 static unsigned int db_align_up(unsigned int val, unsigned int size)
0405 {
0406 return (val + (size - 1)) & (~(size - 1));
0407 }
0408
0409
0410
0411
0412
0413
0414
0415
0416 static int db_for_each_64(const struct os_area_db *db,
0417 const struct os_area_db_id *match_id, struct db_iterator *i)
0418 {
0419 next:
0420 if (!i->db) {
0421 i->db = db;
0422 i->match_id = match_id ? *match_id : os_area_db_id_any;
0423 i->idx = (void *)db + db->index_64;
0424 i->last_idx = i->idx + db->count_64;
0425 i->value_64 = (void *)db + db->index_64
0426 + db_align_up(db->count_64, 8);
0427 } else {
0428 i->idx++;
0429 i->value_64++;
0430 }
0431
0432 if (i->idx >= i->last_idx) {
0433 pr_debug("%s:%d: reached end\n", __func__, __LINE__);
0434 return 0;
0435 }
0436
0437 if (i->match_id.owner != OS_AREA_DB_OWNER_ANY
0438 && i->match_id.owner != (int)i->idx->owner)
0439 goto next;
0440 if (i->match_id.key != OS_AREA_DB_KEY_ANY
0441 && i->match_id.key != (int)i->idx->key)
0442 goto next;
0443
0444 return 1;
0445 }
0446
0447 static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id)
0448 {
0449 struct db_iterator i;
0450
0451 for (i.db = NULL; db_for_each_64(db, id, &i); ) {
0452
0453 pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
0454 i.idx->owner, i.idx->key,
0455 (unsigned long long)*i.value_64);
0456
0457 i.idx->owner = 0;
0458 i.idx->key = 0;
0459 *i.value_64 = 0;
0460 }
0461 return 0;
0462 }
0463
0464 static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,
0465 uint64_t value)
0466 {
0467 struct db_iterator i;
0468
0469 pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,
0470 id->owner, id->key, (unsigned long long)value);
0471
0472 if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY
0473 || id->key == OS_AREA_DB_KEY_ANY) {
0474 pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,
0475 __LINE__, id->owner, id->key);
0476 return -1;
0477 }
0478
0479 db_delete_64(db, id);
0480
0481 i.db = NULL;
0482 if (db_for_each_64(db, &os_area_db_id_empty, &i)) {
0483
0484 pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
0485 i.idx->owner, i.idx->key,
0486 (unsigned long long)*i.value_64);
0487
0488 i.idx->owner = id->owner;
0489 i.idx->key = id->key;
0490 *i.value_64 = value;
0491
0492 pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,
0493 i.idx->owner, i.idx->key,
0494 (unsigned long long)*i.value_64);
0495 return 0;
0496 }
0497 pr_debug("%s:%d: database full.\n",
0498 __func__, __LINE__);
0499 return -1;
0500 }
0501
0502 static int __init db_get_64(const struct os_area_db *db,
0503 const struct os_area_db_id *id, uint64_t *value)
0504 {
0505 struct db_iterator i;
0506
0507 i.db = NULL;
0508 if (db_for_each_64(db, id, &i)) {
0509 *value = *i.value_64;
0510 pr_debug("%s:%d: found %lld\n", __func__, __LINE__,
0511 (long long int)*i.value_64);
0512 return 0;
0513 }
0514 pr_debug("%s:%d: not found\n", __func__, __LINE__);
0515 return -1;
0516 }
0517
0518 static int __init db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff)
0519 {
0520 return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);
0521 }
0522
0523 #define dump_db(a) _dump_db(a, __func__, __LINE__)
0524 static void _dump_db(const struct os_area_db *db, const char *func,
0525 int line)
0526 {
0527 char str[sizeof(db->magic_num) + 1];
0528
0529 dump_field(str, db->magic_num, sizeof(db->magic_num));
0530 pr_debug("%s:%d: db.magic_num: '%s'\n", func, line,
0531 str);
0532 pr_debug("%s:%d: db.version: %u\n", func, line,
0533 db->version);
0534 pr_debug("%s:%d: db.index_64: %u\n", func, line,
0535 db->index_64);
0536 pr_debug("%s:%d: db.count_64: %u\n", func, line,
0537 db->count_64);
0538 pr_debug("%s:%d: db.index_32: %u\n", func, line,
0539 db->index_32);
0540 pr_debug("%s:%d: db.count_32: %u\n", func, line,
0541 db->count_32);
0542 pr_debug("%s:%d: db.index_16: %u\n", func, line,
0543 db->index_16);
0544 pr_debug("%s:%d: db.count_16: %u\n", func, line,
0545 db->count_16);
0546 }
0547
0548 static void os_area_db_init(struct os_area_db *db)
0549 {
0550 enum {
0551 HEADER_SIZE = offsetof(struct os_area_db, _db_data),
0552 INDEX_64_COUNT = 64,
0553 VALUES_64_COUNT = 57,
0554 INDEX_32_COUNT = 64,
0555 VALUES_32_COUNT = 57,
0556 INDEX_16_COUNT = 64,
0557 VALUES_16_COUNT = 57,
0558 };
0559
0560 memset(db, 0, sizeof(struct os_area_db));
0561
0562 memcpy(db->magic_num, OS_AREA_DB_MAGIC_NUM, sizeof(db->magic_num));
0563 db->version = 1;
0564 db->index_64 = HEADER_SIZE;
0565 db->count_64 = VALUES_64_COUNT;
0566 db->index_32 = HEADER_SIZE
0567 + INDEX_64_COUNT * sizeof(struct db_index)
0568 + VALUES_64_COUNT * sizeof(u64);
0569 db->count_32 = VALUES_32_COUNT;
0570 db->index_16 = HEADER_SIZE
0571 + INDEX_64_COUNT * sizeof(struct db_index)
0572 + VALUES_64_COUNT * sizeof(u64)
0573 + INDEX_32_COUNT * sizeof(struct db_index)
0574 + VALUES_32_COUNT * sizeof(u32);
0575 db->count_16 = VALUES_16_COUNT;
0576
0577
0578
0579 BUILD_BUG_ON(sizeof(struct db_index) != 1);
0580 BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);
0581 BUILD_BUG_ON(INDEX_64_COUNT & 0x7);
0582 BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);
0583 BUILD_BUG_ON(INDEX_32_COUNT & 0x7);
0584 BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);
0585 BUILD_BUG_ON(INDEX_16_COUNT & 0x7);
0586 BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);
0587 BUILD_BUG_ON(HEADER_SIZE
0588 + INDEX_64_COUNT * sizeof(struct db_index)
0589 + VALUES_64_COUNT * sizeof(u64)
0590 + INDEX_32_COUNT * sizeof(struct db_index)
0591 + VALUES_32_COUNT * sizeof(u32)
0592 + INDEX_16_COUNT * sizeof(struct db_index)
0593 + VALUES_16_COUNT * sizeof(u16)
0594 > sizeof(struct os_area_db));
0595 }
0596
0597
0598
0599
0600
0601
0602 static int update_flash_db(void)
0603 {
0604 const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
0605 struct os_area_header *header;
0606 ssize_t count;
0607 int error;
0608 loff_t pos;
0609 struct os_area_db* db;
0610
0611
0612
0613 header = kmalloc(buf_len, GFP_KERNEL);
0614 if (!header)
0615 return -ENOMEM;
0616
0617 count = os_area_flash_read(header, buf_len, 0);
0618 if (count < 0) {
0619 pr_debug("%s: os_area_flash_read failed %zd\n", __func__,
0620 count);
0621 error = count;
0622 goto fail;
0623 }
0624
0625 pos = header->db_area_offset * OS_AREA_SEGMENT_SIZE;
0626 if (count < OS_AREA_SEGMENT_SIZE || verify_header(header) ||
0627 count < pos) {
0628 pr_debug("%s: verify_header failed\n", __func__);
0629 dump_header(header);
0630 error = -EINVAL;
0631 goto fail;
0632 }
0633
0634
0635
0636 db = (void *)header + pos;
0637
0638 error = db_verify(db);
0639 if (error) {
0640 pr_notice("%s: Verify of flash database failed, formatting.\n",
0641 __func__);
0642 dump_db(db);
0643 os_area_db_init(db);
0644 }
0645
0646
0647
0648 db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
0649
0650 count = os_area_flash_write(db, sizeof(struct os_area_db), pos);
0651 if (count < 0 || count < sizeof(struct os_area_db)) {
0652 pr_debug("%s: os_area_flash_write failed %zd\n", __func__,
0653 count);
0654 error = count < 0 ? count : -EIO;
0655 }
0656
0657 fail:
0658 kfree(header);
0659 return error;
0660 }
0661
0662
0663
0664
0665
0666
0667
0668
0669 static void os_area_queue_work_handler(struct work_struct *work)
0670 {
0671 struct device_node *node;
0672 int error;
0673
0674 pr_debug(" -> %s:%d\n", __func__, __LINE__);
0675
0676 node = of_find_node_by_path("/");
0677 if (node) {
0678 os_area_set_property(node, &property_rtc_diff);
0679 of_node_put(node);
0680 } else
0681 pr_debug("%s:%d of_find_node_by_path failed\n",
0682 __func__, __LINE__);
0683
0684 error = update_flash_db();
0685 if (error)
0686 pr_warn("%s: Could not update FLASH ROM\n", __func__);
0687
0688 pr_debug(" <- %s:%d\n", __func__, __LINE__);
0689 }
0690
0691 static void os_area_queue_work(void)
0692 {
0693 static DECLARE_WORK(q, os_area_queue_work_handler);
0694
0695 wmb();
0696 schedule_work(&q);
0697 }
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713 void __init ps3_os_area_save_params(void)
0714 {
0715 int result;
0716 u64 lpar_addr;
0717 unsigned int size;
0718 struct os_area_header *header;
0719 struct os_area_params *params;
0720 struct os_area_db *db;
0721
0722 pr_debug(" -> %s:%d\n", __func__, __LINE__);
0723
0724 result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
0725
0726 if (result) {
0727 pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
0728 __func__, __LINE__);
0729 return;
0730 }
0731
0732 header = (struct os_area_header *)__va(lpar_addr);
0733 params = (struct os_area_params *)__va(lpar_addr
0734 + OS_AREA_SEGMENT_SIZE);
0735
0736 result = verify_header(header);
0737
0738 if (result) {
0739
0740 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
0741 dump_header(header);
0742 return;
0743 }
0744
0745 db = (struct os_area_db *)__va(lpar_addr
0746 + header->db_area_offset * OS_AREA_SEGMENT_SIZE);
0747
0748 dump_header(header);
0749 dump_params(params);
0750 dump_db(db);
0751
0752 result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);
0753 if (result)
0754 saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff
0755 : SECONDS_FROM_1970_TO_2000;
0756 saved_params.av_multi_out = params->av_multi_out;
0757 saved_params.valid = 1;
0758
0759 memset(header, 0, sizeof(*header));
0760
0761 pr_debug(" <- %s:%d\n", __func__, __LINE__);
0762 }
0763
0764
0765
0766
0767
0768 void __init ps3_os_area_init(void)
0769 {
0770 struct device_node *node;
0771
0772 pr_debug(" -> %s:%d\n", __func__, __LINE__);
0773
0774 node = of_find_node_by_path("/");
0775
0776 if (!saved_params.valid && node) {
0777
0778 os_area_get_property(node, &property_rtc_diff);
0779 os_area_get_property(node, &property_av_multi_out);
0780 }
0781
0782 if(!saved_params.rtc_diff)
0783 saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
0784
0785 if (node) {
0786 os_area_set_property(node, &property_rtc_diff);
0787 os_area_set_property(node, &property_av_multi_out);
0788 of_node_put(node);
0789 } else
0790 pr_debug("%s:%d of_find_node_by_path failed\n",
0791 __func__, __LINE__);
0792
0793 pr_debug(" <- %s:%d\n", __func__, __LINE__);
0794 }
0795
0796
0797
0798
0799
0800 u64 ps3_os_area_get_rtc_diff(void)
0801 {
0802 return saved_params.rtc_diff;
0803 }
0804 EXPORT_SYMBOL_GPL(ps3_os_area_get_rtc_diff);
0805
0806
0807
0808
0809
0810
0811
0812
0813 void ps3_os_area_set_rtc_diff(u64 rtc_diff)
0814 {
0815 if (saved_params.rtc_diff != rtc_diff) {
0816 saved_params.rtc_diff = rtc_diff;
0817 os_area_queue_work();
0818 }
0819 }
0820 EXPORT_SYMBOL_GPL(ps3_os_area_set_rtc_diff);
0821
0822
0823
0824
0825
0826 enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void)
0827 {
0828 return saved_params.av_multi_out;
0829 }
0830 EXPORT_SYMBOL_GPL(ps3_os_area_get_av_multi_out);