1 /*
2 * Copyright (C) 2018-2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 * Copyright (C) 2018-2022 Intel Corporation.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <malloc.h>
27 #include "fsutils.h"
28 #include "startupreason.h"
29 #include "log_sys.h"
30
31 #define CURRENT_KERNEL_CMDLINE "/proc/cmdline"
32
get_cmdline_bootreason(char * bootreason,const size_t limit)33 static int get_cmdline_bootreason(char *bootreason, const size_t limit)
34 {
35 int res;
36 unsigned long size;
37 char *start, *p1, *p2, *end;
38 char *cmdline;
39 const char *key = "ABL.reset=";
40
41 res = read_file(CURRENT_KERNEL_CMDLINE, &size, (void *)&cmdline);
42 if (res < 0) {
43 LOGE("failed to read file %s - %s\n",
44 CURRENT_KERNEL_CMDLINE, strerror(errno));
45 return -1;
46 }
47 if (!size) {
48 LOGW("empty file (%s)\n", CURRENT_KERNEL_CMDLINE);
49 return 0;
50 }
51
52 start = strstr(cmdline, key);
53 if (!start) {
54 LOGW("can't find reboot reason with key (%s) in cmdline\n",
55 key);
56 free(cmdline);
57 return 0;
58 }
59
60 /* if the string contains ' ' or '\n', break it by '\0' */
61 start += strlen(key);
62 p1 = strchr(start, ' ');
63 p2 = strchr(start, '\n');
64 if (p2 && p1)
65 end = MIN(p1, p2);
66 else
67 end = MAX(p1, p2);
68
69 if (!end)
70 end = cmdline + size;
71
72 const size_t len = MIN((size_t)(end - start), (size_t)(limit - 1));
73
74 if (len > 0) {
75 memcpy(bootreason, start, len);
76 *(bootreason + len) = 0;
77 }
78
79 free(cmdline);
80 return len;
81 }
82
get_default_bootreason(char * bootreason,const size_t limit)83 static int get_default_bootreason(char *bootreason, const size_t limit)
84 {
85 int len;
86 int i;
87
88 len = get_cmdline_bootreason(bootreason, limit);
89 if (len <= 0)
90 return len;
91
92 for (i = 0; i < len; i++)
93 bootreason[i] = toupper(bootreason[i]);
94
95 return len;
96
97 }
98
read_startupreason(char * startupreason,const size_t limit)99 void read_startupreason(char *startupreason, const size_t limit)
100 {
101 int res;
102 static char reboot_reason_cache[REBOOT_REASON_SIZE];
103
104 if (!startupreason || !limit)
105 return;
106
107 if (!reboot_reason_cache[0]) {
108 /* fill cache */
109 res = get_default_bootreason(reboot_reason_cache,
110 sizeof(reboot_reason_cache));
111 if (res <= 0)
112 strncpy(reboot_reason_cache, "UNKNOWN",
113 sizeof(reboot_reason_cache));
114 }
115
116 const size_t len = MIN(strnlen(reboot_reason_cache, REBOOT_REASON_SIZE),
117 limit - 1);
118
119 memcpy(startupreason, reboot_reason_cache, len);
120 *(startupreason + len) = 0;
121 return;
122 }
123