Coverage Report

Created: 2026-10-13 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/common/restart.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
 * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
4
 */
5
#define pr_fmt(fmt) "restart: " fmt
6
7
#include <common.h>
8
#include <restart.h>
9
#include <malloc.h>
10
#include <asm/sections.h>
11
#include <efi/types.h>
12
#include <of.h>
13
14
static LIST_HEAD(restart_handler_list);
15
static unsigned resetidx;
16
17
static __efi_runtime_data void (*rt_restart)(unsigned long flags);
18
static int rt_restart_prio = INT_MIN;
19
static __efi_runtime_data void (*rt_restart_warm)(unsigned long flags);
20
static int rt_restart_warm_prio = INT_MIN;
21
22
static void rt_restart_handler_register(struct restart_handler *handler)
23
78
{
24
78
  if (!IS_ENABLED(CONFIG_EFI_RUNTIME))
25
78
    return;
26
0
  if (!handler->rt_restart)
27
0
    return;
28
0
  if (!in_barebox_efi_runtime((ulong)handler->rt_restart)) {
29
    /* Check if __efi_runtime attribute is missing */
30
0
    pr_warn("handler outside EFI runtime section\n");
31
0
    return;
32
0
  }
33
34
0
  if (handler->priority > rt_restart_prio) {
35
0
    rt_restart = handler->rt_restart;
36
0
    rt_restart_prio = handler->priority;
37
0
  }
38
39
0
  if (handler->priority > rt_restart_warm_prio &&
40
0
      handler->flags & RESTART_WARM) {
41
0
    rt_restart_warm = handler->rt_restart;
42
0
    rt_restart_warm_prio = handler->priority;
43
0
  }
44
0
}
45
46
/**
47
 * restart_handler_register() - register a handler for restarting the system
48
 * @rst:  The handler struct
49
 *
50
 * This adds @rst to the list of registered restart handlers.
51
 *
52
 * return: 0 for success or negative error code
53
 */
54
int restart_handler_register(struct restart_handler *rst)
55
78
{
56
78
  if (!rst->name)
57
0
    rst->name = basprintf("reset%u", resetidx);
58
78
  if (!rst->priority)
59
26
    rst->priority = RESTART_DEFAULT_PRIORITY;
60
61
78
  if (rst->of_node) {
62
0
    of_property_read_u32(rst->of_node, "restart-priority",
63
0
             &rst->priority);
64
0
    if (of_property_read_bool(rst->of_node,
65
0
            "barebox,restart-warm-bootrom"))
66
0
      rst->flags |= RESTART_WARM;
67
0
  }
68
69
78
  rt_restart_handler_register(rst);
70
71
78
  list_add_tail(&rst->list, &restart_handler_list);
72
73
78
  pr_debug("registering restart handler \"%s\" with priority %d\n",
74
78
      rst->name, rst->priority);
75
76
78
  resetidx++;
77
78
  return 0;
78
78
}
79
80
/**
81
 * restart_handler_register_fn() - register a handler function
82
 * @name: restart method name or NULL if name should be auto-generated
83
 * @restart_fn: The restart function
84
 *
85
 * convenience wrapper for restart_handler_register() to register a handler
86
 * with given function and default values otherwise.
87
 *
88
 * return: 0 for success or negative error code
89
 */
90
int restart_handler_register_fn(const char *name,
91
        void (*restart_fn)(struct restart_handler *,
92
               unsigned long flags))
93
0
{
94
0
  struct restart_handler *rst;
95
0
  int ret;
96
97
0
  rst = xzalloc(sizeof(*rst));
98
99
0
  rst->name = xstrdup_const(name);
100
0
  rst->restart = restart_fn;
101
102
0
  ret = restart_handler_register(rst);
103
104
0
  if (ret)
105
0
    free(rst);
106
107
0
  return ret;
108
0
}
109
110
/**
111
 * restart_handler_get_by_name() - get highest priority `name'
112
 */
113
struct restart_handler *restart_handler_get_by_name(const char *name, int flags)
114
0
{
115
0
  struct restart_handler *rst = NULL, *tmp;
116
0
  unsigned int priority = 0;
117
118
0
  list_for_each_entry(tmp, &restart_handler_list, list) {
119
0
    if (name) {
120
0
      bool found = false;
121
122
0
      if (tmp->name && !strcmp(name, tmp->name))
123
0
        found = true;
124
0
      if (tmp->dev && !strcmp(name, dev_name(tmp->dev)))
125
0
        found = true;
126
0
      if (!found)
127
0
        continue;
128
0
    }
129
130
0
    if (flags && (tmp->flags & flags) != flags)
131
0
      continue;
132
0
    if (tmp->priority > priority) {
133
0
      priority = tmp->priority;
134
0
      rst = tmp;
135
0
    }
136
0
  }
137
138
0
  return rst;
139
0
}
140
141
/**
142
 * rt_restart_machine() - reset the machine from a runtime service
143
 */
144
void __noreturn __efi_runtime rt_restart_machine(unsigned long flags)
145
0
{
146
0
  if ((flags & RESTART_WARM) && rt_restart_warm)
147
0
    rt_restart_warm(flags);
148
0
  if (rt_restart)
149
0
    rt_restart(flags);
150
151
0
  __hang();
152
0
}
153
154
/**
155
 * restart_machine() - reset the whole system
156
 */
157
void __noreturn restart_machine(unsigned long flags)
158
0
{
159
0
  struct restart_handler *rst;
160
161
0
  rst = restart_handler_get_by_name(NULL, 0);
162
0
  if (rst) {
163
0
    pr_debug("%s: using restart handler %s\n", __func__, rst->name);
164
0
    console_flush();
165
0
    rst->restart(rst, flags);
166
0
  }
167
168
0
  hang();
169
0
}
170
171
/*
172
 * restart_handlers_print - print informations about all restart handlers
173
 */
174
void restart_handlers_print(void)
175
0
{
176
0
  struct restart_handler *tmp;
177
178
0
  list_for_each_entry(tmp, &restart_handler_list, list) {
179
0
    printf("%-20s %-20s %6d ",
180
0
           tmp->name, tmp->dev ? dev_name(tmp->dev) : "", tmp->priority);
181
0
    if (tmp->flags & RESTART_WARM)
182
0
      putchar('W');
183
0
    putchar('\n');
184
0
  }
185
186
0
  printf("\nW: Warm restart capable\n");
187
0
}