m68k: Add support to export bootinfo in procfs
Add optional support to export the bootinfo used to boot the kernel in a "bootinfo" file in procfs. This is useful with kexec. This is based on the similar feature for ATAGS on ARM. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
This commit is contained in:
parent
7d5f5fa276
commit
7bc1e4d8d5
|
@ -104,6 +104,13 @@ config KEXEC
|
|||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config BOOTINFO_PROC
|
||||
bool "Export bootinfo in procfs"
|
||||
depends on KEXEC && M68KCLASSIC
|
||||
help
|
||||
Say Y to export the bootinfo used to boot the kernel in a
|
||||
"bootinfo" file in procfs. This is useful with kexec.
|
||||
|
||||
menu "Platform setup"
|
||||
|
||||
source arch/m68k/Kconfig.cpu
|
||||
|
|
|
@ -13,4 +13,16 @@
|
|||
|
||||
#include <uapi/asm/bootinfo.h>
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_BOOTINFO_PROC
|
||||
extern void save_bootinfo(const struct bi_record *bi);
|
||||
#else
|
||||
static inline void save_bootinfo(const struct bi_record *bi) {}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
#endif /* _M68K_BOOTINFO_H */
|
||||
|
|
|
@ -23,4 +23,5 @@ obj-$(CONFIG_PCI) += pcibios.o
|
|||
obj-$(CONFIG_HAS_DMA) += dma.o
|
||||
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Based on arch/arm/kernel/atags_proc.c
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
|
||||
static char bootinfo_tmp[1536] __initdata;
|
||||
|
||||
static void *bootinfo_copy;
|
||||
static size_t bootinfo_size;
|
||||
|
||||
static ssize_t bootinfo_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return simple_read_from_buffer(buf, count, ppos, bootinfo_copy,
|
||||
bootinfo_size);
|
||||
}
|
||||
|
||||
static const struct file_operations bootinfo_fops = {
|
||||
.read = bootinfo_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void __init save_bootinfo(const struct bi_record *bi)
|
||||
{
|
||||
const void *start = bi;
|
||||
size_t size = sizeof(bi->tag);
|
||||
|
||||
while (be16_to_cpu(bi->tag) != BI_LAST) {
|
||||
uint16_t n = be16_to_cpu(bi->size);
|
||||
size += n;
|
||||
bi = (struct bi_record *)((unsigned long)bi + n);
|
||||
}
|
||||
|
||||
if (size > sizeof(bootinfo_tmp)) {
|
||||
pr_err("Cannot save %zu bytes of bootinfo\n", size);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("Saving %zu bytes of bootinfo\n", size);
|
||||
memcpy(bootinfo_tmp, start, size);
|
||||
bootinfo_size = size;
|
||||
}
|
||||
|
||||
static int __init init_bootinfo_procfs(void)
|
||||
{
|
||||
/*
|
||||
* This cannot go into save_bootinfo() because kmalloc and proc don't
|
||||
* work yet when it is called.
|
||||
*/
|
||||
struct proc_dir_entry *pde;
|
||||
|
||||
if (!bootinfo_size)
|
||||
return -EINVAL;
|
||||
|
||||
bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
|
||||
if (!bootinfo_copy)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
|
||||
|
||||
pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
|
||||
if (!pde) {
|
||||
kfree(bootinfo_copy);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(init_bootinfo_procfs);
|
|
@ -146,6 +146,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
|
|||
{
|
||||
uint16_t tag;
|
||||
|
||||
save_bootinfo(record);
|
||||
|
||||
while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
|
||||
int unknown = 0;
|
||||
const void *data = record->data;
|
||||
|
|
Loading…
Reference in New Issue