blob: 2fe528418e9cf8b9e28e16f9c148007948ce0057 [file] [log] [blame]
Lorenz Brun0bcaaee2019-11-06 12:42:39 +01001From 73025c3f822aa19077abe4ece53b03b211faaf52 Mon Sep 17 00:00:00 2001
2From: Matthew Garrett <mjg59@coreos.com>
3Date: Thu, 9 Apr 2015 13:25:00 -0700
4Subject: [PATCH 1/2] x86: Allow built-in command line to work in early kernel
5 init
6
7The kernel supports having a command line built into it. Unfortunately this
8doesn't work in all cases - the built-in command line is only appended
9after we've jumped to the kernel proper, but various parts of the early
10boot process also pay attention to the command line.
11
12This patch moves the command line override code from the kernel itself to
13the early init code. Unfortunately the kernel can be executed by jumping
14to the 16-bit entry point, the UEFI entry point, directly to the 32-bit
15entry point or even to the entry point of the uncompressed image, and
16there is no guarantee that any of these will have access to data held in
17the others. As a result, four copies of the command line will be embedded
18in the kernel.
19
20This patch also defines a new field in boot_params in order to allow the
21earlier entry points to inform the generic setup code that the command line
22has already been appended and so shouldn't be added once more.
23
24Updated for Linux 4.19 by Lorenz Brun <lorenz@nexantic.com>
Leopold Schabelf1d34d32020-01-07 14:15:44 +010025Updated for Linux 5.4 by Leopold Schabel <leo@nexantic.com>
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010026
27Signed-off-by: Matthew Garrett <mjg59@coreos.com>
28---
Leopold Schabelf1d34d32020-01-07 14:15:44 +010029 Documentation/x86/zero-page.rst | 1 +
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010030 arch/x86/boot/boot.h | 10 ++++
31 arch/x86/boot/cmdline.c | 37 ++++++++++++++
Leopold Schabelf1d34d32020-01-07 14:15:44 +010032 arch/x86/boot/compressed/cmdline.c | 10 ++++
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010033 arch/x86/boot/compressed/eboot.c | 3 ++
34 arch/x86/boot/compressed/misc.c | 2 +
Leopold Schabelf1d34d32020-01-07 14:15:44 +010035 arch/x86/boot/compressed/misc.h | 1 +
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010036 arch/x86/boot/main.c | 3 ++
37 arch/x86/include/uapi/asm/bootparam.h | 5 +-
38 arch/x86/kernel/setup.c | 16 +++---
39 .../firmware/efi/libstub/efi-stub-helper.c | 50 +++++++++++++++++--
Leopold Schabelf1d34d32020-01-07 14:15:44 +010040 11 files changed, 127 insertions(+), 11 deletions(-)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010041
Leopold Schabelf1d34d32020-01-07 14:15:44 +010042diff --git a/Documentation/x86/zero-page.rst b/Documentation/x86/zero-page.rst
43index f088f5881666..3f84244dd573 100644
44--- a/Documentation/x86/zero-page.rst
45+++ b/Documentation/x86/zero-page.rst
46@@ -16,6 +16,7 @@ Offset/Size Proto Name Meaning
47 000/040 ALL screen_info Text mode or frame buffer information
48 (struct screen_info)
49 040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
50+054/004 ALL setup_flags Flags passed from early kernel setup
51 058/008 ALL tboot_addr Physical address of tboot shared page
52 060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
53 (struct ist_info)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010054diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +010055index ca866f1cca2e..a97502baba73 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010056--- a/arch/x86/boot/boot.h
57+++ b/arch/x86/boot/boot.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +010058@@ -269,6 +269,7 @@ void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010059 /* cmdline.c */
60 int __cmdline_find_option(unsigned long cmdline_ptr, const char *option, char *buffer, int bufsize);
61 int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option);
62+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params);
63 static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
64 {
65 unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
Leopold Schabelf1d34d32020-01-07 14:15:44 +010066@@ -289,6 +290,15 @@ static inline int cmdline_find_option_bool(const char *option)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010067 return __cmdline_find_option_bool(cmd_line_ptr, option);
68 }
Leopold Schabelf1d34d32020-01-07 14:15:44 +010069
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010070+static inline int cmdline_init(void)
71+{
72+ unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
73+
74+ if (cmd_line_ptr >= 0x100000)
75+ return -1; /* inaccessible */
76+
77+ return __cmdline_init(cmd_line_ptr, &boot_params);
78+}
79 /* cpu.c, cpucheck.c */
80 int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
81 int check_knl_erratum(void);
82diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +010083index 4ff01176c1cc..b5dfbe0b3209 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010084--- a/arch/x86/boot/cmdline.c
85+++ b/arch/x86/boot/cmdline.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +010086@@ -12,6 +12,10 @@
87
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010088 #include "boot.h"
Leopold Schabelf1d34d32020-01-07 14:15:44 +010089
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010090+#ifdef CONFIG_CMDLINE_BOOL
91+static char builtin_cmdline[] = CONFIG_CMDLINE;
92+#endif
93+
94 static inline int myisspace(u8 c)
95 {
96 return c <= ' '; /* Close enough approximation */
Leopold Schabelf1d34d32020-01-07 14:15:44 +010097@@ -154,3 +158,36 @@ int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option)
98
Lorenz Brun0bcaaee2019-11-06 12:42:39 +010099 return 0; /* Buffer overrun */
100 }
101+
102+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params)
103+{
104+#ifdef CONFIG_CMDLINE_BOOL
105+ addr_t cptr;
106+ int i = 0;
107+
108+ if (!cmdline_ptr)
109+ return -1; /* No command line */
110+
111+ set_fs(cmdline_ptr >> 4);
112+ cptr = cmdline_ptr & 0xf;
113+
114+#ifndef CONFIG_CMDLINE_OVERRIDE
115+ while (cptr < 0x10000) {
116+ char c = rdfs8(cptr);
117+ if (!c) {
118+ wrfs8(' ', cptr++);
119+ break;
120+ }
121+ cptr++;
122+ }
123+#endif /* !CONFIG_CMDLINE_OVERRIDE */
124+ while (builtin_cmdline[i] && cptr < 0xffff)
125+ wrfs8(builtin_cmdline[i++], cptr++);
126+
127+ wrfs8('\0', cptr);
128+
129+ params->setup_flags |= SETUP_CMDLINE_APPENDED;
130+#endif /* CONFIG_CMDLINE_BOOL */
131+
132+ return 0;
133+}
134diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100135index f1add5d85da9..c69b27a5e76d 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100136--- a/arch/x86/boot/compressed/cmdline.c
137+++ b/arch/x86/boot/compressed/cmdline.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100138@@ -11,6 +11,10 @@ static inline char rdfs8(addr_t addr)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100139 {
140 return *((char *)(fs + addr));
141 }
142+static inline void wrfs8(u8 v, addr_t addr)
143+{
144+ *((char *)(fs + addr)) = v;
145+}
146 #include "../cmdline.c"
147 unsigned long get_cmd_line_ptr(void)
148 {
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100149@@ -28,3 +32,9 @@ int cmdline_find_option_bool(const char *option)
150 {
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100151 return __cmdline_find_option_bool(get_cmd_line_ptr(), option);
152 }
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100153+int cmdline_init(void)
154+{
155+ if (!(boot_params->setup_flags & SETUP_CMDLINE_APPENDED))
156+ return __cmdline_init(get_cmd_line_ptr(), boot_params);
157+ return 0;
158+}
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100159diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100160index 82bc60c8acb2..a325c5dd2700 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100161--- a/arch/x86/boot/compressed/eboot.c
162+++ b/arch/x86/boot/compressed/eboot.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100163@@ -447,6 +447,9 @@ struct boot_params *make_boot_params(struct efi_config *c)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100164 /* Fill in upper bits of command line address, NOP on 32 bit */
165 boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100166
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100167+#ifdef CONFIG_CMDLINE_BOOL
168+ boot_params->setup_flags |= SETUP_CMDLINE_APPENDED;
169+#endif
170 hdr->ramdisk_image = 0;
171 hdr->ramdisk_size = 0;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100172
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100173diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100174index 9652d5c2afda..05fd4372b630 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100175--- a/arch/x86/boot/compressed/misc.c
176+++ b/arch/x86/boot/compressed/misc.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100177@@ -366,6 +366,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100178 lines = boot_params->screen_info.orig_video_lines;
179 cols = boot_params->screen_info.orig_video_cols;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100180
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100181+ cmdline_init();
182+
183 console_init();
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100184
185 /*
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100186diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100187index c8181392f70d..e2f962e7c0d4 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100188--- a/arch/x86/boot/compressed/misc.h
189+++ b/arch/x86/boot/compressed/misc.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100190@@ -68,6 +68,7 @@ static inline void debug_puthex(const char *s)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100191 /* cmdline.c */
192 int cmdline_find_option(const char *option, char *buffer, int bufsize);
193 int cmdline_find_option_bool(const char *option);
194+int cmdline_init(void);
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100195
196 struct mem_vector {
197 unsigned long long start;
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100198diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100199index e3add857c2c9..e20e81253a7d 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100200--- a/arch/x86/boot/main.c
201+++ b/arch/x86/boot/main.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100202@@ -136,6 +136,9 @@ void main(void)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100203 /* First, copy the boot header into the "zeropage" */
204 copy_boot_params();
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100205
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100206+ /* Handle built-in command line */
207+ cmdline_init();
208+
209 /* Initialize the early-boot console */
210 console_init();
211 if (cmdline_find_option_bool("debug"))
212diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100213index c895df5482c5..bb3c2073a63a 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100214--- a/arch/x86/include/uapi/asm/bootparam.h
215+++ b/arch/x86/include/uapi/asm/bootparam.h
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100216@@ -32,6 +32,9 @@
217 #define XLF_5LEVEL (1<<5)
218 #define XLF_5LEVEL_ENABLED (1<<6)
219
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100220+/* setup_flags */
221+#define SETUP_CMDLINE_APPENDED (1<<0)
222+
223 #ifndef __ASSEMBLY__
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100224
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100225 #include <linux/types.h>
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100226@@ -154,7 +157,7 @@ struct jailhouse_setup_data {
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100227 struct boot_params {
228 struct screen_info screen_info; /* 0x000 */
229 struct apm_bios_info apm_bios_info; /* 0x040 */
230- __u8 _pad2[4]; /* 0x054 */
231+ __u32 setup_flags; /* 0x054 */
232 __u64 tboot_addr; /* 0x058 */
233 struct ist_info ist_info; /* 0x060 */
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100234 __u64 acpi_rsdp_addr; /* 0x070 */
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100235diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100236index 77ea96b794bd..7985d13f8e5b 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100237--- a/arch/x86/kernel/setup.c
238+++ b/arch/x86/kernel/setup.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100239@@ -957,16 +957,18 @@ void __init setup_arch(char **cmdline_p)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100240 bss_resource.end = __pa_symbol(__bss_stop)-1;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100241
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100242 #ifdef CONFIG_CMDLINE_BOOL
243+ if (!(boot_params.setup_flags & SETUP_CMDLINE_APPENDED)) {
244 #ifdef CONFIG_CMDLINE_OVERRIDE
245- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
246-#else
247- if (builtin_cmdline[0]) {
248- /* append boot loader cmdline to builtin */
249- strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
250- strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
251 strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
252- }
253+#else
254+ if (builtin_cmdline[0]) {
255+ /* append boot loader cmdline to builtin */
256+ strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
257+ strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
258+ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
259+ }
260 #endif
261+ }
262 #endif
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100263
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100264 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
265diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100266index 35dbc2791c97..87d1e390fb49 100644
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100267--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
268+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100269@@ -9,9 +9,14 @@
270
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100271 #include <linux/efi.h>
272 #include <asm/efi.h>
273+#include <asm/setup.h>
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100274
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100275 #include "efistub.h"
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100276
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100277+#ifdef CONFIG_CMDLINE_BOOL
278+static char builtin_cmdline[] = CONFIG_CMDLINE;
279+#endif
280+
281 /*
282 * Some firmware implementations have problems reading files in one go.
283 * A read chunk size of 1MB seems to work for most platforms.
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100284@@ -799,6 +804,20 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100285 #ifndef MAX_CMDLINE_ADDRESS
286 #define MAX_CMDLINE_ADDRESS ULONG_MAX
287 #endif
288+static size_t efi_strlcat(char *dest, const char *src, size_t count)
289+{
290+ size_t dsize = strlen(dest);
291+ size_t len = strlen(src);
292+ size_t res = dsize + len;
293+
294+ dest += dsize;
295+ count -= dsize;
296+ if (len >= count)
297+ len = count-1;
298+ memcpy(dest, src, len);
299+ dest[len] = 0;
300+ return res;
301+}
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100302
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100303 /*
304 * Convert the unicode UEFI command line to ASCII to pass to kernel.
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100305@@ -809,14 +828,16 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100306 efi_loaded_image_t *image,
307 int *cmd_line_len)
308 {
309+ unsigned long cmdline_addr = 0;
310+ int i;
311+ efi_status_t status;
312+#ifndef CONFIG_CMDLINE_OVERRIDE
313 const u16 *s2;
314 u8 *s1 = NULL;
315- unsigned long cmdline_addr = 0;
316 int load_options_chars = image->load_options_size / 2; /* UTF-16 */
317 const u16 *options = image->load_options;
318 int options_bytes = 0; /* UTF-8 bytes */
319 int options_chars = 0; /* UTF-16 chars */
320- efi_status_t status;
321 u16 zero = 0;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100322
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100323 if (options) {
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100324@@ -835,8 +856,14 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
325
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100326 options_bytes++; /* NUL termination */
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100327
328+
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100329+#ifdef CONFIG_CMDLINE_BOOL
330+ /* Add length of the built-in command line, plus a space */
331+ options_bytes += strlen(builtin_cmdline);
332+ options_bytes++;
333+#endif
334 status = efi_high_alloc(sys_table_arg, options_bytes, 0,
335- &cmdline_addr, MAX_CMDLINE_ADDRESS);
336+ &cmdline_addr, MAX_CMDLINE_ADDRESS);
337 if (status != EFI_SUCCESS)
338 return NULL;
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100339
340@@ -846,7 +873,24 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100341 s1 = efi_utf16_to_utf8(s1, s2, options_chars);
342 *s1 = '\0';
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100343
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100344+#ifdef CONFIG_CMDLINE_BOOL
345+ efi_strlcat((char *)cmdline_addr, " ", COMMAND_LINE_SIZE);
346+ efi_strlcat((char *)cmdline_addr, builtin_cmdline, COMMAND_LINE_SIZE);
347+#endif
348 *cmd_line_len = options_bytes;
349+#else /* CONFIG_CMDLINE_OVERRIDE */
350+ status = efi_high_alloc(sys_table_arg, strlen(builtin_cmdline), 0,
351+ &cmdline_addr, MAX_CMDLINE_ADDRESS);
352+ if (status != EFI_SUCCESS)
353+ return NULL;
354+ while (builtin_cmdline[i] && i < COMMAND_LINE_SIZE) {
355+ ((char *)cmdline_addr)[i] = builtin_cmdline[i];
356+ i++;
357+ }
358+ ((char *)cmdline_addr)[i] = '\0';
359+ *cmd_line_len = strlen(builtin_cmdline);
360+#endif /* CONFIG_CMDLINE_OVERRIDE */
361+
362 return (char *)cmdline_addr;
363 }
Lorenz Brun0bcaaee2019-11-06 12:42:39 +0100364
Leopold Schabelf1d34d32020-01-07 14:15:44 +0100365--
3662.24.1