Skip to content

Commit 9a0bd93

Browse files
Youling TangMingcongBai
authored andcommitted
LoongArch: kexec: Add compatibility with old interfaces
LoongArch inclusion category: feature -------------------------------- Old interface: a0 = argc, a1 = argv, a2 = bootparam New interface: a0 = efi flag, a1 = cmdline, a2 = systemtab The following interfaces are not supported: a0 = efi flag, a1 = fdt pointer, a2 = 0 Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
1 parent 98ee572 commit 9a0bd93

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

arch/loongarch/kernel/machine_kexec.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ static void kexec_image_info(const struct kimage *kimage)
5959
}
6060
}
6161

62+
#define MAX_ARGS 64
63+
#define KEXEC_CMDLINE_SIZE (COMMAND_LINE_SIZE * 2)
64+
6265
int machine_kexec_prepare(struct kimage *kimage)
6366
{
6467
int i;
@@ -70,11 +73,49 @@ int machine_kexec_prepare(struct kimage *kimage)
7073
kimage->arch.efi_boot = fw_arg0;
7174
kimage->arch.systable_ptr = fw_arg2;
7275

76+
if (!fw_arg2)
77+
pr_err("Small fdt mode is not supported!\n");
78+
7379
/* Find the command line */
7480
for (i = 0; i < kimage->nr_segments; i++) {
7581
if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
76-
if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
77-
kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
82+
if (fw_arg0 < 2) {
83+
/* New firmware */
84+
if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
85+
kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
86+
} else {
87+
/* Old firmware */
88+
int argc = 0;
89+
long offt;
90+
char *ptr, *str;
91+
unsigned long *argv;
92+
93+
/*
94+
* convert command line string to array
95+
* of parameters (as bootloader does).
96+
*/
97+
argv = (unsigned long *)kmalloc(KEXEC_CMDLINE_SIZE, GFP_KERNEL);
98+
argv[argc++] = (unsigned long)(KEXEC_CMDLINE_ADDR + KEXEC_CMDLINE_SIZE/2);
99+
str = (char *)argv + KEXEC_CMDLINE_SIZE/2;
100+
101+
if (copy_from_user(str, kimage->segment[i].buf, KEXEC_CMDLINE_SIZE/2))
102+
return -EINVAL;
103+
104+
ptr = strchr(str, ' ');
105+
106+
while (ptr && (argc < MAX_ARGS)) {
107+
*ptr = '\0';
108+
if (ptr[1] != ' ') {
109+
offt = (long)(ptr - str + 1);
110+
argv[argc++] = (unsigned long)argv + KEXEC_CMDLINE_SIZE/2 + offt;
111+
}
112+
ptr = strchr(ptr + 1, ' ');
113+
}
114+
115+
kimage->arch.efi_boot = argc;
116+
kimage->arch.cmdline_ptr = (unsigned long)argv;
117+
break;
118+
}
78119
break;
79120
}
80121
}

0 commit comments

Comments
 (0)