~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/kernel/ksysfs.c

Version: ~ [ linux-5.2-rc4 ] ~ [ linux-5.1.9 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.50 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.125 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.181 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.181 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.68 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Architecture specific sysfs attributes in /sys/kernel
  3  *
  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>
  8  *
  9  * This file is released under the GPLv2
 10  */
 11 
 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>
 18 #include <linux/mm.h>
 19 
 20 #include <asm/io.h>
 21 #include <asm/setup.h>
 22 
 23 static ssize_t version_show(struct kobject *kobj,
 24                             struct kobj_attribute *attr, char *buf)
 25 {
 26         return sprintf(buf, "0x%04x\n", boot_params.hdr.version);
 27 }
 28 
 29 static struct kobj_attribute boot_params_version_attr = __ATTR_RO(version);
 30 
 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)
 34 {
 35         memcpy(buf, (void *)&boot_params + off, count);
 36         return count;
 37 }
 38 
 39 static struct bin_attribute boot_params_data_attr = {
 40         .attr = {
 41                 .name = "data",
 42                 .mode = S_IRUGO,
 43         },
 44         .read = boot_params_data_read,
 45         .size = sizeof(boot_params),
 46 };
 47 
 48 static struct attribute *boot_params_version_attrs[] = {
 49         &boot_params_version_attr.attr,
 50         NULL,
 51 };
 52 
 53 static struct bin_attribute *boot_params_data_attrs[] = {
 54         &boot_params_data_attr,
 55         NULL,
 56 };
 57 
 58 static struct attribute_group boot_params_attr_group = {
 59         .attrs = boot_params_version_attrs,
 60         .bin_attrs = boot_params_data_attrs,
 61 };
 62 
 63 static int kobj_to_setup_data_nr(struct kobject *kobj, int *nr)
 64 {
 65         const char *name;
 66 
 67         name = kobject_name(kobj);
 68         return kstrtoint(name, 10, nr);
 69 }
 70 
 71 static int get_setup_data_paddr(int nr, u64 *paddr)
 72 {
 73         int i = 0;
 74         struct setup_data *data;
 75         u64 pa_data = boot_params.hdr.setup_data;
 76 
 77         while (pa_data) {
 78                 if (nr == i) {
 79                         *paddr = pa_data;
 80                         return 0;
 81                 }
 82                 data = ioremap_cache(pa_data, sizeof(*data));
 83                 if (!data)
 84                         return -ENOMEM;
 85 
 86                 pa_data = data->next;
 87                 iounmap(data);
 88                 i++;
 89         }
 90         return -EINVAL;
 91 }
 92 
 93 static int __init get_setup_data_size(int nr, size_t *size)
 94 {
 95         int i = 0;
 96         struct setup_data *data;
 97         u64 pa_data = boot_params.hdr.setup_data;
 98 
 99         while (pa_data) {
100                 data = ioremap_cache(pa_data, sizeof(*data));
101                 if (!data)
102                         return -ENOMEM;
103                 if (nr == i) {
104                         *size = data->len;
105                         iounmap(data);
106                         return 0;
107                 }
108 
109                 pa_data = data->next;
110                 iounmap(data);
111                 i++;
112         }
113         return -EINVAL;
114 }
115 
116 static ssize_t type_show(struct kobject *kobj,
117                          struct kobj_attribute *attr, char *buf)
118 {
119         int nr, ret;
120         u64 paddr;
121         struct setup_data *data;
122 
123         ret = kobj_to_setup_data_nr(kobj, &nr);
124         if (ret)
125                 return ret;
126 
127         ret = get_setup_data_paddr(nr, &paddr);
128         if (ret)
129                 return ret;
130         data = ioremap_cache(paddr, sizeof(*data));
131         if (!data)
132                 return -ENOMEM;
133 
134         ret = sprintf(buf, "0x%x\n", data->type);
135         iounmap(data);
136         return ret;
137 }
138 
139 static ssize_t setup_data_data_read(struct file *fp,
140                                     struct kobject *kobj,
141                                     struct bin_attribute *bin_attr,
142                                     char *buf,
143                                     loff_t off, size_t count)
144 {
145         int nr, ret = 0;
146         u64 paddr;
147         struct setup_data *data;
148         void *p;
149 
150         ret = kobj_to_setup_data_nr(kobj, &nr);
151         if (ret)
152                 return ret;
153 
154         ret = get_setup_data_paddr(nr, &paddr);
155         if (ret)
156                 return ret;
157         data = ioremap_cache(paddr, sizeof(*data));
158         if (!data)
159                 return -ENOMEM;
160 
161         if (off > data->len) {
162                 ret = -EINVAL;
163                 goto out;
164         }
165 
166         if (count > data->len - off)
167                 count = data->len - off;
168 
169         if (!count)
170                 goto out;
171 
172         ret = count;
173         p = ioremap_cache(paddr + sizeof(*data), data->len);
174         if (!p) {
175                 ret = -ENOMEM;
176                 goto out;
177         }
178         memcpy(buf, p + off, count);
179         iounmap(p);
180 out:
181         iounmap(data);
182         return ret;
183 }
184 
185 static struct kobj_attribute type_attr = __ATTR_RO(type);
186 
187 static struct bin_attribute data_attr __ro_after_init = {
188         .attr = {
189                 .name = "data",
190                 .mode = S_IRUGO,
191         },
192         .read = setup_data_data_read,
193 };
194 
195 static struct attribute *setup_data_type_attrs[] = {
196         &type_attr.attr,
197         NULL,
198 };
199 
200 static struct bin_attribute *setup_data_data_attrs[] = {
201         &data_attr,
202         NULL,
203 };
204 
205 static struct attribute_group setup_data_attr_group = {
206         .attrs = setup_data_type_attrs,
207         .bin_attrs = setup_data_data_attrs,
208 };
209 
210 static int __init create_setup_data_node(struct kobject *parent,
211                                          struct kobject **kobjp, int nr)
212 {
213         int ret = 0;
214         size_t size;
215         struct kobject *kobj;
216         char name[16]; /* should be enough for setup_data nodes numbers */
217         snprintf(name, 16, "%d", nr);
218 
219         kobj = kobject_create_and_add(name, parent);
220         if (!kobj)
221                 return -ENOMEM;
222 
223         ret = get_setup_data_size(nr, &size);
224         if (ret)
225                 goto out_kobj;
226 
227         data_attr.size = size;
228         ret = sysfs_create_group(kobj, &setup_data_attr_group);
229         if (ret)
230                 goto out_kobj;
231         *kobjp = kobj;
232 
233         return 0;
234 out_kobj:
235         kobject_put(kobj);
236         return ret;
237 }
238 
239 static void __init cleanup_setup_data_node(struct kobject *kobj)
240 {
241         sysfs_remove_group(kobj, &setup_data_attr_group);
242         kobject_put(kobj);
243 }
244 
245 static int __init get_setup_data_total_num(u64 pa_data, int *nr)
246 {
247         int ret = 0;
248         struct setup_data *data;
249 
250         *nr = 0;
251         while (pa_data) {
252                 *nr += 1;
253                 data = ioremap_cache(pa_data, sizeof(*data));
254                 if (!data) {
255                         ret = -ENOMEM;
256                         goto out;
257                 }
258                 pa_data = data->next;
259                 iounmap(data);
260         }
261 
262 out:
263         return ret;
264 }
265 
266 static int __init create_setup_data_nodes(struct kobject *parent)
267 {
268         struct kobject *setup_data_kobj, **kobjp;
269         u64 pa_data;
270         int i, j, nr, ret = 0;
271 
272         pa_data = boot_params.hdr.setup_data;
273         if (!pa_data)
274                 return 0;
275 
276         setup_data_kobj = kobject_create_and_add("setup_data", parent);
277         if (!setup_data_kobj) {
278                 ret = -ENOMEM;
279                 goto out;
280         }
281 
282         ret = get_setup_data_total_num(pa_data, &nr);
283         if (ret)
284                 goto out_setup_data_kobj;
285 
286         kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL);
287         if (!kobjp) {
288                 ret = -ENOMEM;
289                 goto out_setup_data_kobj;
290         }
291 
292         for (i = 0; i < nr; i++) {
293                 ret = create_setup_data_node(setup_data_kobj, kobjp + i, i);
294                 if (ret)
295                         goto out_clean_nodes;
296         }
297 
298         kfree(kobjp);
299         return 0;
300 
301 out_clean_nodes:
302         for (j = i - 1; j > 0; j--)
303                 cleanup_setup_data_node(*(kobjp + j));
304         kfree(kobjp);
305 out_setup_data_kobj:
306         kobject_put(setup_data_kobj);
307 out:
308         return ret;
309 }
310 
311 static int __init boot_params_ksysfs_init(void)
312 {
313         int ret;
314         struct kobject *boot_params_kobj;
315 
316         boot_params_kobj = kobject_create_and_add("boot_params",
317                                                   kernel_kobj);
318         if (!boot_params_kobj) {
319                 ret = -ENOMEM;
320                 goto out;
321         }
322 
323         ret = sysfs_create_group(boot_params_kobj, &boot_params_attr_group);
324         if (ret)
325                 goto out_boot_params_kobj;
326 
327         ret = create_setup_data_nodes(boot_params_kobj);
328         if (ret)
329                 goto out_create_group;
330 
331         return 0;
332 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);
336 out:
337         return ret;
338 }
339 
340 arch_initcall(boot_params_ksysfs_init);
341 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp