2 * Architecture specific sysfs attributes in /sys/kernel
4 * Copyright (C) 2007, Intel Corp.
5 * Huang Ying <ying.huang@intel.com>
6 * Copyright (C) 2013, 2013 Red Hat, Inc.
7 * Dave Young <dyoung@redhat.com>
9 * This file is released under the GPLv2
12 #include <linux/kobject.h>
13 #include <linux/string.h>
14 #include <linux/sysfs.h>
15 #include <linux/init.h>
16 #include <linux/stat.h>
17 #include <linux/slab.h>
21 #include <asm/setup.h>
23 static ssize_t
version_show(struct kobject
*kobj
,
24 struct kobj_attribute
*attr
, char *buf
)
26 return sprintf(buf
, "0x%04x\n", boot_params
.hdr
.version
);
29 static struct kobj_attribute boot_params_version_attr
= __ATTR_RO(version
);
31 static ssize_t
boot_params_data_read(struct file
*fp
, struct kobject
*kobj
,
32 struct bin_attribute
*bin_attr
,
33 char *buf
, loff_t off
, size_t count
)
35 memcpy(buf
, (void *)&boot_params
+ off
, count
);
39 static struct bin_attribute boot_params_data_attr
= {
44 .read
= boot_params_data_read
,
45 .size
= sizeof(boot_params
),
48 static struct attribute
*boot_params_version_attrs
[] = {
49 &boot_params_version_attr
.attr
,
53 static struct bin_attribute
*boot_params_data_attrs
[] = {
54 &boot_params_data_attr
,
58 static const struct attribute_group boot_params_attr_group
= {
59 .attrs
= boot_params_version_attrs
,
60 .bin_attrs
= boot_params_data_attrs
,
63 static int kobj_to_setup_data_nr(struct kobject
*kobj
, int *nr
)
67 name
= kobject_name(kobj
);
68 return kstrtoint(name
, 10, nr
);
71 static int get_setup_data_paddr(int nr
, u64
*paddr
)
74 struct setup_data
*data
;
75 u64 pa_data
= boot_params
.hdr
.setup_data
;
82 data
= memremap(pa_data
, sizeof(*data
), MEMREMAP_WB
);
93 static int __init
get_setup_data_size(int nr
, size_t *size
)
96 struct setup_data
*data
;
97 u64 pa_data
= boot_params
.hdr
.setup_data
;
100 data
= memremap(pa_data
, sizeof(*data
), MEMREMAP_WB
);
109 pa_data
= data
->next
;
116 static ssize_t
type_show(struct kobject
*kobj
,
117 struct kobj_attribute
*attr
, char *buf
)
121 struct setup_data
*data
;
123 ret
= kobj_to_setup_data_nr(kobj
, &nr
);
127 ret
= get_setup_data_paddr(nr
, &paddr
);
130 data
= memremap(paddr
, sizeof(*data
), MEMREMAP_WB
);
134 ret
= sprintf(buf
, "0x%x\n", data
->type
);
139 static ssize_t
setup_data_data_read(struct file
*fp
,
140 struct kobject
*kobj
,
141 struct bin_attribute
*bin_attr
,
143 loff_t off
, size_t count
)
147 struct setup_data
*data
;
150 ret
= kobj_to_setup_data_nr(kobj
, &nr
);
154 ret
= get_setup_data_paddr(nr
, &paddr
);
157 data
= memremap(paddr
, sizeof(*data
), MEMREMAP_WB
);
161 if (off
> data
->len
) {
166 if (count
> data
->len
- off
)
167 count
= data
->len
- off
;
173 p
= memremap(paddr
+ sizeof(*data
), data
->len
, MEMREMAP_WB
);
178 memcpy(buf
, p
+ off
, count
);
185 static struct kobj_attribute type_attr
= __ATTR_RO(type
);
187 static struct bin_attribute data_attr __ro_after_init
= {
192 .read
= setup_data_data_read
,
195 static struct attribute
*setup_data_type_attrs
[] = {
200 static struct bin_attribute
*setup_data_data_attrs
[] = {
205 static const struct attribute_group setup_data_attr_group
= {
206 .attrs
= setup_data_type_attrs
,
207 .bin_attrs
= setup_data_data_attrs
,
210 static int __init
create_setup_data_node(struct kobject
*parent
,
211 struct kobject
**kobjp
, int nr
)
215 struct kobject
*kobj
;
216 char name
[16]; /* should be enough for setup_data nodes numbers */
217 snprintf(name
, 16, "%d", nr
);
219 kobj
= kobject_create_and_add(name
, parent
);
223 ret
= get_setup_data_size(nr
, &size
);
227 data_attr
.size
= size
;
228 ret
= sysfs_create_group(kobj
, &setup_data_attr_group
);
239 static void __init
cleanup_setup_data_node(struct kobject
*kobj
)
241 sysfs_remove_group(kobj
, &setup_data_attr_group
);
245 static int __init
get_setup_data_total_num(u64 pa_data
, int *nr
)
248 struct setup_data
*data
;
253 data
= memremap(pa_data
, sizeof(*data
), MEMREMAP_WB
);
258 pa_data
= data
->next
;
266 static int __init
create_setup_data_nodes(struct kobject
*parent
)
268 struct kobject
*setup_data_kobj
, **kobjp
;
270 int i
, j
, nr
, ret
= 0;
272 pa_data
= boot_params
.hdr
.setup_data
;
276 setup_data_kobj
= kobject_create_and_add("setup_data", parent
);
277 if (!setup_data_kobj
) {
282 ret
= get_setup_data_total_num(pa_data
, &nr
);
284 goto out_setup_data_kobj
;
286 kobjp
= kmalloc_array(nr
, sizeof(*kobjp
), GFP_KERNEL
);
289 goto out_setup_data_kobj
;
292 for (i
= 0; i
< nr
; i
++) {
293 ret
= create_setup_data_node(setup_data_kobj
, kobjp
+ i
, i
);
295 goto out_clean_nodes
;
302 for (j
= i
- 1; j
>= 0; j
--)
303 cleanup_setup_data_node(*(kobjp
+ j
));
306 kobject_put(setup_data_kobj
);
311 static int __init
boot_params_ksysfs_init(void)
314 struct kobject
*boot_params_kobj
;
316 boot_params_kobj
= kobject_create_and_add("boot_params",
318 if (!boot_params_kobj
) {
323 ret
= sysfs_create_group(boot_params_kobj
, &boot_params_attr_group
);
325 goto out_boot_params_kobj
;
327 ret
= create_setup_data_nodes(boot_params_kobj
);
329 goto out_create_group
;
333 sysfs_remove_group(boot_params_kobj
, &boot_params_attr_group
);
334 out_boot_params_kobj
:
335 kobject_put(boot_params_kobj
);
340 arch_initcall(boot_params_ksysfs_init
);