[RFC] /proc/efi_memmap

Luck, Tony
2005-09-09T23:46:13Z

kexec folks asked whether I could export the EFI memory map in /proc
for use by their user level tools.

Questions:
0) Is this information already available some place I missed?
1) Is /proc/efi_memmap a good name?
2) I used mm/slab.c as my model for using seq_file ... does this look right?

-Tony

Patch against the "test" branch of my GIT tree.

---

diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -22,6 +22,8 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/efi.h>
@@ -923,3 +925,89 @@ efi_memmap_init(unsigned long *s, unsign
*s = (u64)kern_memmap;
*e = (u64)++k;
}
+
+#ifdef CONFIG_PROC_FS
+
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t n = *pos;
+ void *efi_map_start, *efi_map_end, *p;
+ u64 efi_desc_size;
+
+ if (!n)
+ seq_puts(m, "type start end attributes\n");
+
+ p = efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ while (n--) {
+ p += efi_desc_size;
+ if (p >= efi_map_end)
+ return NULL;
+ }
+
+ return p;
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ void *efi_map_start, *efi_map_end;
+ u64 efi_desc_size;
+
+ ++*pos;
+
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ return (p + efi_desc_size >= efi_map_end) ? NULL : p + efi_desc_size;
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+ efi_memory_desc_t *md = p;
+
+ seq_printf(m, "%4d %16.16lx %16.16lx %lx\n", md->type, md->phys_addr,
+ efi_md_end(md), md->attribute);
+
+ return 0;
+}
+
+static struct seq_operations efimeminfo_op = {
+ .start = s_start,
+ .next = s_next,
+ .stop = s_stop,
+ .show = s_show,
+};
+
+static int efimeminfo_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &efimeminfo_op);
+}
+
+static struct file_operations proc_efimeminfo_operations = {
+ .open = efimeminfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init
+efi_procmem(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_entry("efi_memmap", S_IRUGO, NULL);
+ if (entry)
+ entry->proc_fops = &proc_efimeminfo_operations;
+
+ return 0;
+}
+late_initcall(efi_procmem);
+
+#endif