4 * Driver for exporting VPD content to sysfs.
6 * Copyright 2017 Google Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License v2.0 as published by
10 * the Free Software Foundation.
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.
18 #include <linux/ctype.h>
19 #include <linux/init.h>
21 #include <linux/kernel.h>
22 #include <linux/kobject.h>
23 #include <linux/list.h>
24 #include <linux/module.h>
25 #include <linux/of_address.h>
26 #include <linux/platform_device.h>
27 #include <linux/slab.h>
28 #include <linux/sysfs.h>
30 #include "coreboot_table.h"
31 #include "vpd_decode.h"
33 #define CB_TAG_VPD 0x2c
34 #define VPD_CBMEM_MAGIC 0x43524f53
36 static struct kobject
*vpd_kobj
;
49 char *raw_name
; /* the string name_raw */
50 struct kobject
*kobj
; /* vpd/name directory */
52 struct bin_attribute bin_attr
; /* vpd/name_raw bin_attribute */
53 struct list_head attribs
; /* key/value in vpd_attrib_info list */
56 struct vpd_attrib_info
{
59 struct bin_attribute bin_attr
;
60 struct list_head list
;
63 static struct vpd_section ro_vpd
;
64 static struct vpd_section rw_vpd
;
66 static ssize_t
vpd_attrib_read(struct file
*filp
, struct kobject
*kobp
,
67 struct bin_attribute
*bin_attr
, char *buf
,
68 loff_t pos
, size_t count
)
70 struct vpd_attrib_info
*info
= bin_attr
->private;
72 return memory_read_from_buffer(buf
, count
, &pos
, info
->value
,
77 * vpd_section_check_key_name()
79 * The VPD specification supports only [a-zA-Z0-9_]+ characters in key names but
80 * old firmware versions may have entries like "S/N" which are problematic when
81 * exporting them as sysfs attributes. These keys present in old firmwares are
84 * Returns VPD_OK for a valid key name, VPD_FAIL otherwise.
86 * @key: The key name to check
87 * @key_len: key name length
89 static int vpd_section_check_key_name(const u8
*key
, s32 key_len
)
93 while (key_len
-- > 0) {
96 if (!isalnum(c
) && c
!= '_')
103 static int vpd_section_attrib_add(const u8
*key
, s32 key_len
,
104 const u8
*value
, s32 value_len
,
108 struct vpd_section
*sec
= arg
;
109 struct vpd_attrib_info
*info
;
112 * Return VPD_OK immediately to decode next entry if the current key
113 * name contains invalid characters.
115 if (vpd_section_check_key_name(key
, key_len
) != VPD_OK
)
118 info
= kzalloc(sizeof(*info
), GFP_KERNEL
);
122 info
->key
= kstrndup(key
, key_len
, GFP_KERNEL
);
128 sysfs_bin_attr_init(&info
->bin_attr
);
129 info
->bin_attr
.attr
.name
= info
->key
;
130 info
->bin_attr
.attr
.mode
= 0444;
131 info
->bin_attr
.size
= value_len
;
132 info
->bin_attr
.read
= vpd_attrib_read
;
133 info
->bin_attr
.private = info
;
137 INIT_LIST_HEAD(&info
->list
);
139 ret
= sysfs_create_bin_file(sec
->kobj
, &info
->bin_attr
);
143 list_add_tail(&info
->list
, &sec
->attribs
);
154 static void vpd_section_attrib_destroy(struct vpd_section
*sec
)
156 struct vpd_attrib_info
*info
;
157 struct vpd_attrib_info
*temp
;
159 list_for_each_entry_safe(info
, temp
, &sec
->attribs
, list
) {
160 sysfs_remove_bin_file(sec
->kobj
, &info
->bin_attr
);
166 static ssize_t
vpd_section_read(struct file
*filp
, struct kobject
*kobp
,
167 struct bin_attribute
*bin_attr
, char *buf
,
168 loff_t pos
, size_t count
)
170 struct vpd_section
*sec
= bin_attr
->private;
172 return memory_read_from_buffer(buf
, count
, &pos
, sec
->baseaddr
,
176 static int vpd_section_create_attribs(struct vpd_section
*sec
)
183 ret
= vpd_decode_string(sec
->bin_attr
.size
, sec
->baseaddr
,
184 &consumed
, vpd_section_attrib_add
, sec
);
185 } while (ret
== VPD_OK
);
190 static int vpd_section_init(const char *name
, struct vpd_section
*sec
,
191 phys_addr_t physaddr
, size_t size
)
195 sec
->baseaddr
= memremap(physaddr
, size
, MEMREMAP_WB
);
201 /* We want to export the raw partion with name ${name}_raw */
202 sec
->raw_name
= kasprintf(GFP_KERNEL
, "%s_raw", name
);
203 if (!sec
->raw_name
) {
208 sysfs_bin_attr_init(&sec
->bin_attr
);
209 sec
->bin_attr
.attr
.name
= sec
->raw_name
;
210 sec
->bin_attr
.attr
.mode
= 0444;
211 sec
->bin_attr
.size
= size
;
212 sec
->bin_attr
.read
= vpd_section_read
;
213 sec
->bin_attr
.private = sec
;
215 err
= sysfs_create_bin_file(vpd_kobj
, &sec
->bin_attr
);
217 goto err_free_raw_name
;
219 sec
->kobj
= kobject_create_and_add(name
, vpd_kobj
);
222 goto err_sysfs_remove
;
225 INIT_LIST_HEAD(&sec
->attribs
);
226 vpd_section_create_attribs(sec
);
233 sysfs_remove_bin_file(vpd_kobj
, &sec
->bin_attr
);
235 kfree(sec
->raw_name
);
237 memunmap(sec
->baseaddr
);
241 static int vpd_section_destroy(struct vpd_section
*sec
)
244 vpd_section_attrib_destroy(sec
);
245 kobject_put(sec
->kobj
);
246 sysfs_remove_bin_file(vpd_kobj
, &sec
->bin_attr
);
247 kfree(sec
->raw_name
);
248 memunmap(sec
->baseaddr
);
249 sec
->enabled
= false;
255 static int vpd_sections_init(phys_addr_t physaddr
)
257 struct vpd_cbmem __iomem
*temp
;
258 struct vpd_cbmem header
;
261 temp
= memremap(physaddr
, sizeof(struct vpd_cbmem
), MEMREMAP_WB
);
265 memcpy_fromio(&header
, temp
, sizeof(struct vpd_cbmem
));
268 if (header
.magic
!= VPD_CBMEM_MAGIC
)
271 if (header
.ro_size
) {
272 ret
= vpd_section_init("ro", &ro_vpd
,
273 physaddr
+ sizeof(struct vpd_cbmem
),
279 if (header
.rw_size
) {
280 ret
= vpd_section_init("rw", &rw_vpd
,
281 physaddr
+ sizeof(struct vpd_cbmem
) +
282 header
.ro_size
, header
.rw_size
);
284 vpd_section_destroy(&ro_vpd
);
292 static int vpd_probe(struct coreboot_device
*dev
)
296 vpd_kobj
= kobject_create_and_add("vpd", firmware_kobj
);
300 ret
= vpd_sections_init(dev
->cbmem_ref
.cbmem_addr
);
302 kobject_put(vpd_kobj
);
309 static int vpd_remove(struct coreboot_device
*dev
)
311 vpd_section_destroy(&ro_vpd
);
312 vpd_section_destroy(&rw_vpd
);
314 kobject_put(vpd_kobj
);
319 static struct coreboot_driver vpd_driver
= {
321 .remove
= vpd_remove
,
328 static int __init
coreboot_vpd_init(void)
330 return coreboot_driver_register(&vpd_driver
);
333 static void __exit
coreboot_vpd_exit(void)
335 coreboot_driver_unregister(&vpd_driver
);
338 module_init(coreboot_vpd_init
);
339 module_exit(coreboot_vpd_exit
);
341 MODULE_AUTHOR("Google, Inc.");
342 MODULE_LICENSE("GPL");