@@ -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+
6265int 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