summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Leech <christopher.leech@linux.intel.com>2011-03-31 17:21:15 +0000
committerSimon Horman <horms@verge.net.au>2011-04-18 15:58:41 +0800
commite467cbaa6cfea50ce2a60de645af03a3c7580e20 (patch)
treedab4162c69633642a4cc949bd3f23c6302c357ed
parente3bb6ccd50e483d06bfeaca24c9107c31f1cf5d7 (diff)
downloadkexec-tools-e467cbaa6cfea50ce2a60de645af03a3c7580e20.tar.gz
kexec, x86: fix kexec when boot_params.hardware_subarch != 0
Simon Horman <horms@...> writes: > > On Tue, Mar 29, 2011 at 09:04:53AM +0000, WANG Cong wrote: > > On Mon, 28 Mar 2011 14:50:11 -0700, Chris Leech wrote: > > > > > kexec needs to keep the subarch setting the same as the running kernel > > > in the boot parameters, or the kernel will die in early setup. I ran > > > into this with X86_SUBARCH_MRST, but it should apply to CE4100 and any > > > future subarch that uses non-default early setup code. > > > > > > This patch requires debugfs mounted at /sys/kernel/debug, as that's the > > > only way I know of to get at the running kernels boot_params. Without > > > debugfs mounted it falls back to the current behavior of assuming > > > subarch 0. > > > > > ... > > > > > > +#define BOOT_PARAMS_DBGFS "/sys/kernel/debug/boot_params/data" > > > > A minor issue here is that you are using a hard-coded debugfs path, > > debugfs can be also mounted to /debug too, so it is better that if we can > > search the path dynamically here. > > Do you think it would be better for the code to loop through > a few common alternatives for the path? > Not fully tested, but instead of looping through possible mount points maybe look through mtab in search of debugfs by fs type. Something like this? kexec, x86: search for debugfs mountpoint in /etc/mtab From: Chris Leech <christopher.leech@linux.intel.com> Signed-off-by: Chris Leech <christopher.leech@linux.intel.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/i386/x86-linux-setup.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 50b32be0..0528ceaa 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -30,6 +30,7 @@
#include <linux/fb.h>
#include <unistd.h>
#include <dirent.h>
+#include <mntent.h>
#include <x86/x86-linux.h>
#include "../../kexec.h"
#include "kexec-x86.h"
@@ -397,14 +398,44 @@ out:
real_mode->eddbuf_entries);
}
-#define BOOT_PARAMS_DBGFS "/sys/kernel/debug/boot_params/data"
+/*
+ * This really only makes sense for virtual filesystems that are only expected
+ * to be mounted once (sysfs, debugsfs, proc), as it will return the first
+ * instance listed in mtab.
+ */
+char *find_mnt_by_fsname(char *fsname)
+{
+ FILE *mtab;
+ struct mntent *mnt;
+ char *mntdir;
+
+ mtab = setmntent("/etc/mtab", "r");
+ if (!mtab)
+ return NULL;
+ for(mnt = getmntent(mtab); mnt; mnt = getmntent(mtab)) {
+ if (strcmp(mnt->mnt_fsname, fsname) == 0)
+ break;
+ }
+ mntdir = mnt ? strdup(mnt->mnt_dir) : NULL;
+ endmntent(mtab);
+ return mntdir;
+}
void setup_subarch(struct x86_linux_param_header *real_mode)
{
int data_file;
const off_t offset = offsetof(typeof(*real_mode), hardware_subarch);
+ char *debugfs_mnt;
+ char filename[PATH_MAX];
+
+ debugfs_mnt = find_mnt_by_fsname("debugfs");
+ if (!debugfs_mnt)
+ return;
+ snprintf(filename, PATH_MAX, "%s/%s", debugfs_mnt, "boot_params/data");
+ filename[PATH_MAX-1] = 0;
+ free(debugfs_mnt);
- data_file = open(BOOT_PARAMS_DBGFS, O_RDONLY);
+ data_file = open(filename, O_RDONLY);
if (data_file < 0)
return;
if (lseek(data_file, offset, SEEK_SET) < 0)