CHROMIUM: chromeos platform: ramoops OF fix
[cascardo/linux.git] / drivers / platform / chromeos.c
1 /*
2  *  ChromeOS platform support code. Glue layer between higher level functions
3  *  and per-platform firmware interfaces.
4  *
5  *  Copyright (C) 2010 The Chromium OS Authors
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * This module isolates ChromeOS platform specific behavior.  In particular,
22  * it uses calls from chromeos_acpi.c to control the boot flow, and exports some
23  * helper functions for kernel-side consumers of platform configuration, such
24  * as nvram flags.
25  */
26
27 #include <linux/types.h>
28 #include <linux/chromeos_platform.h>
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <linux/ramoops.h>
32 #include "chromeos.h"
33
34 static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size);
35 static int chromeos_write_nvram_byte(unsigned offset, u8 value);
36
37 /* the following defines are copied from
38  * vboot_reference:firmware/lib/vboot_nvstorage.c.
39  */
40 #define RECOVERY_OFFSET              2
41 #define VBNV_RECOVERY_RW_INVALID_OS  0x43
42
43 int chromeos_set_need_recovery(void)
44 {
45         if (!chromeos_legacy_set_need_recovery())
46                 return 0;
47
48         return chromeos_write_nvram_byte(RECOVERY_OFFSET,
49                                          VBNV_RECOVERY_RW_INVALID_OS);
50 }
51
52 /*
53  * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted.
54  *
55  * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
56  * algorithm would be faster, but for only 15 bytes isn't worth the code size.
57  */
58 static u8 crc8(const u8 *data, int len)
59 {
60         unsigned crc = 0;
61         int i, j;
62
63         for (j = len; j; j--, data++) {
64                 crc ^= (*data << 8);
65                 for (i = 8; i; i--) {
66                         if (crc & 0x8000)
67                                 crc ^= (0x1070 << 3);
68                         crc <<= 1;
69                 }
70         }
71         return (u8)(crc >> 8);
72 }
73
74 static int chromeos_write_nvram_byte(unsigned offset, u8 value)
75 {
76         u8 nvram_buffer[MAX_NVRAM_BUFFER_SIZE];
77
78         int size = chromeos_read_nvram(nvram_buffer, sizeof(nvram_buffer));
79
80         if (size <= 0)
81                 return -EINVAL;
82
83         if (offset >= (size - 1))
84                 return -EINVAL;
85
86         if (nvram_buffer[offset] == value)
87                 return 0;
88
89         nvram_buffer[offset] = value;
90         nvram_buffer[size - 1] = crc8(nvram_buffer, size - 1);
91
92         return chromeos_platform_write_nvram(nvram_buffer, size);
93 }
94
95 /*
96  * Read nvram buffer contents and verify it. Return 0 on success and -1 on
97  * failure (uninitialized subsystem, corrupted crc8 value, not enough room in
98  * the buffer, etc.).
99  *
100  * If everything checks out - return number of bytes in the NVRAM buffer, -1
101  * on any error.
102  */
103 static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size)
104 {
105         int size = chromeos_platform_read_nvram(nvram_buffer, buf_size);
106
107         if (size <= 0)
108                 return -1;
109
110         if (nvram_buffer[size - 1] != crc8(nvram_buffer, size - 1)) {
111                 pr_err("%s: NVRAM contents corrupted\n", __func__);
112                 return -1;
113         }
114         return size;
115 }
116
117 #ifndef CONFIG_USE_OF
118
119 /* Set the platform dependent parameters using kernel config parameters */
120 static struct ramoops_platform_data chromeos_ramoops_data = {
121         .mem_size               = CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE,
122         .mem_address            = CONFIG_CHROMEOS_RAMOOPS_RAM_START,
123         .record_size            = CONFIG_CHROMEOS_RAMOOPS_RECORD_SIZE,
124         .dump_oops              = CONFIG_CHROMEOS_RAMOOPS_DUMP_OOPS,
125 };
126
127 static struct platform_device chromeos_ramoops = {
128         .name = "ramoops",
129         .dev = {
130                 .platform_data = &chromeos_ramoops_data,
131         },
132 };
133
134 /*
135  * If you don't set the ramoops module parameters then ramoops needs a
136  * platform device in order to run. So a platform device is registered
137  * which sets the needed parameters.
138  */
139 static int __init chromeos_ramoops_init(void)
140 {
141         int ret;
142
143         ret = platform_device_register(&chromeos_ramoops);
144         if (ret) {
145                 printk(KERN_ERR "unable to register platform device\n");
146                 return ret;
147         }
148
149         return 0;
150 }
151
152 subsys_initcall(chromeos_ramoops_init);
153 #endif