1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <console/console.h>
4 #include <drivers/vpd/vpd.h>
5 #include <drivers/ocp/include/vpd.h>
6 #include <string.h>
7 #include <program_loading.h>
8
9 #define CMDLINE_LOGLVL_STR "loglevel="
10
overwrite_kernel_loglevel(uintptr_t start)11 static void overwrite_kernel_loglevel(uintptr_t start)
12 {
13 int val;
14 if (!vpd_get_int(KERNEL_LOG_LEVEL, VPD_RW_THEN_RO, &val)) {
15 printk(BIOS_DEBUG, "%s: not able to get VPD %s\n", __func__, KERNEL_LOG_LEVEL);
16 return;
17 }
18
19 printk(BIOS_DEBUG, "%s: VPD %s, got %d\n", __func__, KERNEL_LOG_LEVEL, val);
20 if (val < 0 || val > 7) {
21 printk(BIOS_INFO, "Invalid VPD for Linux kernel log level\n");
22 return;
23 }
24
25 int loglevel;
26 char *loc = strstr((const char *)start, CMDLINE_LOGLVL_STR);
27 if (!loc) {
28 printk(BIOS_INFO, "%s is not found from LINUX_COMMAND_LINE\n",
29 CMDLINE_LOGLVL_STR);
30 return;
31 }
32
33 char *loc_bkup;
34 loc += strlen(CMDLINE_LOGLVL_STR);
35 loc_bkup = loc;
36 loglevel = skip_atoi(&loc);
37 printk(BIOS_DEBUG, "Original kernel log level is %d\n", loglevel);
38 /* Unlikely but don't overwrite with such an unexpected case. */
39 if (loglevel < 0 || loglevel > 7) {
40 printk(BIOS_DEBUG, "Invalid kernel log level, must be from 0 to 7.\n");
41 return;
42 }
43
44 char c = '0' + val;
45 printk(BIOS_INFO, "Overwrite kernel log level with %c from VPD.\n", c);
46 memcpy(loc_bkup, &c, 1);
47 }
48
platform_segment_loaded(uintptr_t start,size_t size,int flags)49 void platform_segment_loaded(uintptr_t start, size_t size, int flags)
50 {
51 /* CONFIG_LINUX_COMMAND_LINE is in the final segment. */
52 if (flags != SEG_FINAL)
53 return;
54
55 overwrite_kernel_loglevel(start);
56 }
57