rev |
line source |
pascal@20333
|
1 --- linux-3.16.53/drivers/firmware/efi/efi-stub-helper.c
|
pascal@20333
|
2 +++ linux-3.16.53/drivers/firmware/efi/efi-stub-helper.c
|
pascal@20333
|
3 @@ -321,6 +321,77 @@
|
pascal@20333
|
4
|
pascal@20333
|
5
|
pascal@20333
|
6 /*
|
pascal@20333
|
7 + *
|
pascal@20333
|
8 + */
|
pascal@20333
|
9 +static efi_status_t get_file_size(efi_system_table_t *sys_table_arg,
|
pascal@20333
|
10 + efi_loaded_image_t *image,
|
pascal@20333
|
11 + efi_char16_t *filename_16,
|
pascal@20333
|
12 + struct file_info *file)
|
pascal@20333
|
13 +{
|
pascal@20333
|
14 + efi_status_t status;
|
pascal@20333
|
15 + efi_file_handle_t *fh = NULL;
|
pascal@20333
|
16 +#ifdef CONFIG_X86_64
|
pascal@20333
|
17 + efi_char16_t *p, c;
|
pascal@20333
|
18 +#endif
|
pascal@20333
|
19 +
|
pascal@20333
|
20 + /* Only open the volume once. */
|
pascal@20333
|
21 + if (!fh) {
|
pascal@20333
|
22 + status = efi_open_volume(sys_table_arg, image,
|
pascal@20333
|
23 + (void **)&fh);
|
pascal@20333
|
24 + if (status != EFI_SUCCESS)
|
pascal@20333
|
25 + return status;
|
pascal@20333
|
26 + }
|
pascal@20333
|
27 +#ifdef CONFIG_X86_64
|
pascal@20333
|
28 + for (p = filename_16; *p != '\0'; p++);
|
pascal@20333
|
29 + c = p[-2];
|
pascal@20333
|
30 + while (1) {
|
pascal@20333
|
31 +#endif
|
pascal@20333
|
32 + status = efi_file_size(sys_table_arg, fh, filename_16,
|
pascal@20333
|
33 + (void **)&file->handle, &file->size);
|
pascal@20333
|
34 +#ifdef CONFIG_X86_64
|
pascal@20333
|
35 + if (status != EFI_SUCCESS && p[-2] != '\0') {
|
pascal@20333
|
36 + p[-2] = '\0';
|
pascal@20333
|
37 + continue;
|
pascal@20333
|
38 + }
|
pascal@20333
|
39 + break;
|
pascal@20333
|
40 + }
|
pascal@20333
|
41 + p[-2] = c;
|
pascal@20333
|
42 +#endif
|
pascal@20333
|
43 + return status;
|
pascal@20333
|
44 +}
|
pascal@20333
|
45 +
|
pascal@20333
|
46 +/*
|
pascal@20333
|
47 + *
|
pascal@20333
|
48 + */
|
pascal@20333
|
49 +static efi_status_t read_efi_file(efi_system_table_t *sys_table_arg,
|
pascal@20333
|
50 + struct file_info *file,
|
pascal@20333
|
51 + unsigned long addr,
|
pascal@20333
|
52 + unsigned long size)
|
pascal@20333
|
53 +{
|
pascal@20333
|
54 + efi_status_t status;
|
pascal@20333
|
55 +
|
pascal@20333
|
56 + while (size) {
|
pascal@20333
|
57 + unsigned long chunksize;
|
pascal@20333
|
58 + if (size > EFI_READ_CHUNK_SIZE)
|
pascal@20333
|
59 + chunksize = EFI_READ_CHUNK_SIZE;
|
pascal@20333
|
60 + else
|
pascal@20333
|
61 + chunksize = size;
|
pascal@20333
|
62 +
|
pascal@20333
|
63 + status = efi_file_read(file->handle,
|
pascal@20333
|
64 + &chunksize,
|
pascal@20333
|
65 + (void *)addr);
|
pascal@20333
|
66 + if (status != EFI_SUCCESS) {
|
pascal@20333
|
67 + pr_efi_err(sys_table_arg, "Failed to read file\n");
|
pascal@20333
|
68 + break;
|
pascal@20333
|
69 + }
|
pascal@20333
|
70 + addr += chunksize;
|
pascal@20333
|
71 + size -= chunksize;
|
pascal@20333
|
72 + }
|
pascal@20333
|
73 + efi_file_close(file->handle);
|
pascal@20333
|
74 + return status;
|
pascal@20333
|
75 +}
|
pascal@20333
|
76 +
|
pascal@20333
|
77 +/*
|
pascal@20333
|
78 * Check the cmdline for a LILO-style file= arguments.
|
pascal@20333
|
79 *
|
pascal@20333
|
80 * We only support loading a file from the same filesystem as
|
pascal@20333
|
81 @@ -414,18 +485,14 @@
|
pascal@20333
|
82 }
|
pascal@20333
|
83 }
|
pascal@20333
|
84
|
pascal@20333
|
85 +#ifdef CONFIG_X86_64
|
pascal@20333
|
86 + *p++ = '6';
|
pascal@20333
|
87 + *p++ = '4';
|
pascal@20333
|
88 +#endif
|
pascal@20333
|
89 *p = '\0';
|
pascal@20333
|
90
|
pascal@20333
|
91 - /* Only open the volume once. */
|
pascal@20333
|
92 - if (!i) {
|
pascal@20333
|
93 - status = efi_open_volume(sys_table_arg, image,
|
pascal@20333
|
94 - (void **)&fh);
|
pascal@20333
|
95 - if (status != EFI_SUCCESS)
|
pascal@20333
|
96 - goto free_files;
|
pascal@20333
|
97 - }
|
pascal@20333
|
98 -
|
pascal@20333
|
99 - status = efi_file_size(sys_table_arg, fh, filename_16,
|
pascal@20333
|
100 - (void **)&file->handle, &file->size);
|
pascal@20333
|
101 + status = get_file_size(sys_table_arg,image,filename_16,file);
|
pascal@20333
|
102 +
|
pascal@20333
|
103 if (status != EFI_SUCCESS)
|
pascal@20333
|
104 goto close_handles;
|
pascal@20333
|
105
|
pascal@20333
|
106 @@ -433,8 +500,6 @@
|
pascal@20333
|
107 }
|
pascal@20333
|
108
|
pascal@20333
|
109 if (file_size_total) {
|
pascal@20333
|
110 - unsigned long addr;
|
pascal@20333
|
111 -
|
pascal@20333
|
112 /*
|
pascal@20333
|
113 * Multiple files need to be at consecutive addresses in memory,
|
pascal@20333
|
114 * so allocate enough memory for all the files. This is used
|
pascal@20333
|
115 @@ -454,30 +519,10 @@
|
pascal@20333
|
116 goto free_file_total;
|
pascal@20333
|
117 }
|
pascal@20333
|
118
|
pascal@20333
|
119 - addr = file_addr;
|
pascal@20333
|
120 for (j = 0; j < nr_files; j++) {
|
pascal@20333
|
121 - unsigned long size;
|
pascal@20333
|
122 -
|
pascal@20333
|
123 - size = files[j].size;
|
pascal@20333
|
124 - while (size) {
|
pascal@20333
|
125 - unsigned long chunksize;
|
pascal@20333
|
126 - if (size > EFI_READ_CHUNK_SIZE)
|
pascal@20333
|
127 - chunksize = EFI_READ_CHUNK_SIZE;
|
pascal@20333
|
128 - else
|
pascal@20333
|
129 - chunksize = size;
|
pascal@20333
|
130 -
|
pascal@20333
|
131 - status = efi_file_read(files[j].handle,
|
pascal@20333
|
132 - &chunksize,
|
pascal@20333
|
133 - (void *)addr);
|
pascal@20333
|
134 - if (status != EFI_SUCCESS) {
|
pascal@20333
|
135 - pr_efi_err(sys_table_arg, "Failed to read file\n");
|
pascal@20333
|
136 - goto free_file_total;
|
pascal@20333
|
137 - }
|
pascal@20333
|
138 - addr += chunksize;
|
pascal@20333
|
139 - size -= chunksize;
|
pascal@20333
|
140 - }
|
pascal@20333
|
141 -
|
pascal@20333
|
142 - efi_file_close(files[j].handle);
|
pascal@20333
|
143 + status = read_efi_file(sys_table_arg, &files[j], file_addr, files[j].size);
|
pascal@20333
|
144 + if (status != EFI_SUCCESS)
|
pascal@20333
|
145 + goto free_file_total;
|
pascal@20333
|
146 }
|
pascal@20333
|
147
|
pascal@20333
|
148 }
|
pascal@20333
|
149 @@ -649,6 +694,30 @@
|
pascal@20333
|
150 }
|
pascal@20333
|
151
|
pascal@20333
|
152 if (!options_chars) {
|
pascal@20333
|
153 + /* No command line options, look for linux.cmdline */
|
pascal@20333
|
154 +#ifdef CONFIG_X86_64
|
pascal@20333
|
155 +#define cmdline_name L"EFI\\BOOT\\linux.cmdline64"
|
pascal@20333
|
156 +#else
|
pascal@20333
|
157 +#define cmdline_name L"EFI\\BOOT\\linux.cmdline"
|
pascal@20333
|
158 +#endif
|
pascal@20333
|
159 + struct file_info file;
|
pascal@20333
|
160 + efi_char16_t filename_16[sizeof(cmdline_name)];
|
pascal@20333
|
161 +
|
pascal@20333
|
162 + memcpy((void *)filename_16, (void *)cmdline_name, sizeof(cmdline_name));
|
pascal@20333
|
163 + if (get_file_size(sys_table_arg, image, filename_16, &file) != EFI_SUCCESS)
|
pascal@20333
|
164 + goto no_cmdline_file;
|
pascal@20333
|
165 +
|
pascal@20333
|
166 + options_bytes = file.size+1;
|
pascal@20333
|
167 + if (efi_low_alloc(sys_table_arg, options_bytes, 0, &cmdline_addr) != EFI_SUCCESS)
|
pascal@20333
|
168 + goto no_cmdline_file;
|
pascal@20333
|
169 +
|
pascal@20333
|
170 + *((u8 *)cmdline_addr + file.size) = '\0';
|
pascal@20333
|
171 + if (read_efi_file(sys_table_arg, &file, cmdline_addr, file.size) == EFI_SUCCESS)
|
pascal@20333
|
172 + goto return_cmdline;
|
pascal@20333
|
173 + }
|
pascal@20333
|
174 + no_cmdline_file:
|
pascal@20333
|
175 +
|
pascal@20333
|
176 + if (!options_chars) {
|
pascal@20333
|
177 /* No command line options, so return empty string*/
|
pascal@20333
|
178 options = &zero;
|
pascal@20333
|
179 }
|
pascal@20333
|
180 @@ -665,6 +734,7 @@
|
pascal@20333
|
181 s1 = efi_utf16_to_utf8(s1, s2, options_chars);
|
pascal@20333
|
182 *s1 = '\0';
|
pascal@20333
|
183
|
pascal@20333
|
184 +return_cmdline:
|
pascal@20333
|
185 *cmd_line_len = options_bytes;
|
pascal@20333
|
186 return (char *)cmdline_addr;
|
pascal@20333
|
187 }
|