Coverage Report

Created: 2026-10-17 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/fs/pstore/platform.c
Line
Count
Source
1
/*
2
 * Persistent Storage - platform driver interface parts.
3
 *
4
 * Copyright (C) 2007-2008 Google, Inc.
5
 * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License version 2 as
9
 *  published by the Free Software Foundation.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#define pr_fmt(fmt) "pstore: " fmt
21
22
#include <linux/types.h>
23
#include <linux/pstore.h>
24
#include <linux/string.h>
25
#include <linux/kernel.h>
26
#include <linux/spinlock.h>
27
#include <linux/mutex.h>
28
#include <console.h>
29
#include <malloc.h>
30
#include <linux/printk.h>
31
#include <module.h>
32
33
#include "internal.h"
34
35
struct pstore_info *psinfo;
36
37
static char *backend;
38
39
/* How much of the console log to snapshot */
40
static unsigned long kmsg_bytes = 10240;
41
42
void pstore_set_kmsg_bytes(int bytes)
43
0
{
44
0
  kmsg_bytes = bytes;
45
0
}
46
47
static int pstore_ready;
48
49
bool pstore_is_ready(void)
50
0
{
51
0
  return pstore_ready;
52
0
}
53
EXPORT_SYMBOL(pstore_is_ready);
54
55
void pstore_log(const char *str)
56
83.2k
{
57
83.2k
  uint64_t id;
58
83.2k
  static int in_pstore;
59
60
83.2k
  if (!IS_ENABLED(CONFIG_FS_PSTORE_CONSOLE))
61
0
    return;
62
63
83.2k
  if (!pstore_ready)
64
83.2k
    return;
65
66
0
  if (in_pstore)
67
0
    return;
68
69
0
  in_pstore = 1;
70
71
0
  psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
72
0
        str, 0, strlen(str), psinfo);
73
74
0
  in_pstore = 0;
75
0
}
76
77
static void pstore_console_capture_log(void)
78
0
{
79
0
  uint64_t id;
80
0
  struct log_entry *log, *tmp;
81
82
0
  if (IS_ENABLED(CONFIG_CONSOLE_NONE))
83
0
    return;
84
85
0
  list_for_each_entry_safe(log, tmp, &barebox_logbuf, list) {
86
0
    psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
87
0
          log->msg, 0, strlen(log->msg), psinfo);
88
0
  }
89
0
}
90
91
/*
92
 * platform specific persistent storage driver registers with
93
 * us here. If pstore is already mounted, call the platform
94
 * read function right away to populate the file system. If not
95
 * then the pstore mount code will call us later to fill out
96
 * the file system.
97
 *
98
 * Register with kmsg_dump to save last part of console log on panic.
99
 */
100
int pstore_register(struct pstore_info *psi)
101
0
{
102
0
  if (backend && strcmp(backend, psi->name))
103
0
    return -EPERM;
104
105
0
  spin_lock(&pstore_lock);
106
0
  if (psinfo) {
107
0
    spin_unlock(&pstore_lock);
108
0
    return -EBUSY;
109
0
  }
110
111
0
  psinfo = psi;
112
0
  mutex_init(&psinfo->read_mutex);
113
0
  spin_unlock(&pstore_lock);
114
115
0
  pstore_get_records(0);
116
117
0
  pstore_console_capture_log();
118
0
  pstore_ready = 1;
119
120
0
  pr_info("Registered %s as persistent store backend\n", psi->name);
121
122
0
  return 0;
123
0
}
124
EXPORT_SYMBOL_GPL(pstore_register);
125
126
/*
127
 * Read all the records from the persistent store. Create
128
 * files in our filesystem.  Don't warn about -EEXIST errors
129
 * when we are re-scanning the backing store looking to add new
130
 * error records.
131
 */
132
void pstore_get_records(int quiet)
133
0
{
134
0
  struct pstore_info *psi = psinfo;
135
0
  struct pstore_record  record = { .psi = psi, };
136
0
  int     failed = 0, rc;
137
0
  int     unzipped_len = -1;
138
139
0
  if (!psi)
140
0
    return;
141
142
0
  mutex_lock(&psi->read_mutex);
143
0
  if (psi->open && psi->open(psi))
144
0
    goto out;
145
146
0
  while ((record.size = psi->read(&record)) > 0) {
147
0
    if (record.compressed &&
148
0
        record.type == PSTORE_TYPE_DMESG) {
149
0
      pr_err("barebox does not have ramoops compression support\n");
150
0
      continue;
151
0
    }
152
0
    rc = pstore_mkfile(&record);
153
0
    if (unzipped_len < 0) {
154
      /* Free buffer other than big oops */
155
0
      kfree(record.buf);
156
0
      record.buf = NULL;
157
0
    } else
158
0
      unzipped_len = -1;
159
0
    if (rc && (rc != -EEXIST || !quiet))
160
0
      failed++;
161
162
0
    memset(&record, 0, sizeof(record));
163
0
    record.psi = psi;
164
0
  }
165
0
  if (psi->close)
166
0
    psi->close(psi);
167
0
out:
168
0
  mutex_unlock(&psi->read_mutex);
169
170
0
  if (failed)
171
0
    pr_warn("failed to load %d record(s) from '%s'\n",
172
0
      failed, psi->name);
173
0
}