summaryrefslogtreecommitdiff
path: root/zephyr/test/drivers/panic_output/src/panic_output_get_panic_data_write.c
blob: e1f4cda84c443ec99719c508a1cb822f810dafe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* Copyright 2022 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <zephyr/ztest.h>
#include <zephyr/ztest_assert.h>

#include "panic.h"
#include "sysjump.h"
#include "test/drivers/test_state.h"

/**
 * @brief Returns a pointer to an object (such as a struct jump_data) of type
 *        TYPE at the end of the mock_jump_data memory region, plus an optional,
 *        additional offset of OFFSET bytes. OFFSET can be used to help get the
 *        pointer after jump data has been moved by get_panic_data_write(), or
 *        left as zero to get the pre-move location.
 */
#define GET_JUMP_DATA_PTR(TYPE, OFFSET)                                    \
	((TYPE *)(mock_jump_data + sizeof(mock_jump_data) - sizeof(TYPE) + \
		  (OFFSET)))

ZTEST(panic_output_get_panic_data_write, test_existing_panic_data)
{
	struct panic_data *pdata_actual = test_get_panic_data_pointer();

	/* Pretend panic data exists by setting the magic header and setting its
	 * size.
	 */
	pdata_actual->magic = PANIC_DATA_MAGIC;
	pdata_actual->struct_size = CONFIG_PANIC_DATA_SIZE;

	/* Verify that pdata_ptr is returned */
	zassert_equal(pdata_actual, get_panic_data_write());
}

ZTEST(panic_output_get_panic_data_write, test_no_panic_data__no_jump_data)
{
	struct panic_data *pdata_actual = test_get_panic_data_pointer();
	struct panic_data pdata_expected = {
		.magic = PANIC_DATA_MAGIC,
		.struct_size = CONFIG_PANIC_DATA_SIZE,
	};

	/* Don't fill in any panic data, but add some fake data so we can ensure
	 * it gets reset to zero.
	 */
	pdata_actual->flags = 0xFF;

	/* Verify that pdata_ptr is returned */
	zassert_equal(pdata_actual, get_panic_data_write());

	/* Verify the pdata struct has correct fields filled out. */
	zassert_mem_equal(&pdata_expected, pdata_actual,
			  sizeof(struct panic_data));
}

/**
 * @brief Implements the fields of a version 1 jump_data header.
 *
 */
struct jump_data_v1 {
	/** V1 Jump data header, always goes at end. See sysjump.h for info */

	uint32_t reset_flags;
	int version;
	int magic;
};

/* Test that V1 jump data is moved correctly. */
ZTEST(panic_output_get_panic_data_write, test_no_panic_data__jump_data_v1)
{
	struct panic_data *pdata_actual = test_get_panic_data_pointer();
	struct jump_data_v1 jdata_expected = {
		.magic = JUMP_DATA_MAGIC,
		.version = 1,
		.reset_flags = 0xAABBCCDD,
	};

	/* Set up some jump data. Version 1 does not have any jump tags, only
	 * the magic, version number, and reset_flags so it is constant size.
	 */
	*GET_JUMP_DATA_PTR(struct jump_data_v1, 0) = jdata_expected;

	/* Verify that pdata_ptr is returned */
	zassert_equal(pdata_actual, get_panic_data_write());

	/* Verify that jump data has been moved to its new location */
	ssize_t expected_move_delta = -1 * sizeof(struct panic_data);
	struct jump_data_v1 *jdata_moved =
		GET_JUMP_DATA_PTR(struct jump_data_v1, expected_move_delta);

	zassert_mem_equal(&jdata_expected, jdata_moved,
			  sizeof(struct jump_data_v1));
}

/**
 * @brief Implements a V2 jump_data header plus some extra bytes in front that
 *        represent jump tag data. This reflects how they are stored in the EC's
 *        memory. The jump_tag_total field in jdata stored how many bytes of
 *        preceding jump tag data exists.
 */
struct jump_data_v2_plus_tags {
	/** Arbitrary amount of jump tag data. */
	uint8_t tag_data[8];
	/** V2 Jump data header, always goes at end. See sysjump.h for info */
	struct {
		int jump_tag_total;
		uint32_t reset_flags;
		int version;
		int magic;
	} jdata;
};

/* Test that V2 jump data is moved correctly. */
ZTEST(panic_output_get_panic_data_write, test_no_panic_data__jump_data_v2)
{
	struct panic_data *pdata_actual = test_get_panic_data_pointer();
	struct jump_data_v2_plus_tags jdata_expected = {
		/* Arbitrary jump tag data */
		.tag_data = {1, 2, 3, 4, 5, 6, 7, 8},
		.jdata = {
			.magic = JUMP_DATA_MAGIC,
			.version = 2,
			.reset_flags = 0xAABBCCDD,
			.jump_tag_total = sizeof(jdata_expected.tag_data),
		},
	};

	/* Set up some jump data and preceding tags */
	*GET_JUMP_DATA_PTR(struct jump_data_v2_plus_tags, 0) = jdata_expected;

	/* Verify that pdata_ptr is returned */
	zassert_equal(pdata_actual, get_panic_data_write());

	/* Verify that jump data and tags moved to their new location */
	ssize_t expected_move_delta = -1 * sizeof(struct panic_data);
	struct jump_data_v2_plus_tags *jdata_moved = GET_JUMP_DATA_PTR(
		struct jump_data_v2_plus_tags, expected_move_delta);

	zassert_mem_equal(&jdata_expected, jdata_moved,
			  sizeof(struct jump_data_v2_plus_tags));
}

/**
 * @brief Implements a V3 jump_data header with space in front for jump tag data
 */
struct jump_data_v3_plus_tags {
	/** Arbitrary amount of jump tag data. */
	uint8_t tag_data[8];
	/** V3 Jump data header, always goes at end. See sysjump.h for info */
	struct {
		uint8_t reserved0;
		int struct_size;
		int jump_tag_total;
		uint32_t reset_flags;
		int version;
		int magic;
	} jdata;
};

/* Test that V3 jump data is moved correctly. */
ZTEST(panic_output_get_panic_data_write, test_no_panic_data__jump_data_v3)
{
	struct panic_data *pdata_actual = test_get_panic_data_pointer();
	struct jump_data_v3_plus_tags jdata_expected = {
		/* Arbitrary jump tag data */
		.tag_data = {1, 2, 3, 4, 5, 6, 7, 8},
		.jdata = {
			.magic = JUMP_DATA_MAGIC,
			.version = 3,
			.reset_flags = 0xAABBCCDD,
			.jump_tag_total = sizeof(jdata_expected.tag_data),
			.struct_size = sizeof(jdata_expected.jdata),
			.reserved0 = 0xFF,
		},
	};

	/* Set up some jump data and preceding tags */
	*GET_JUMP_DATA_PTR(struct jump_data_v3_plus_tags, 0) = jdata_expected;

	/* Verify that pdata_ptr is returned */
	zassert_equal(pdata_actual, get_panic_data_write());

	/* Verify that jump data and tags moved to their new location */
	ssize_t expected_move_delta = -1 * sizeof(struct panic_data);
	struct jump_data_v3_plus_tags *jdata_moved = GET_JUMP_DATA_PTR(
		struct jump_data_v3_plus_tags, expected_move_delta);

	zassert_mem_equal(&jdata_expected, jdata_moved,
			  sizeof(struct jump_data_v3_plus_tags));
}

static void reset(void *data)
{
	ARG_UNUSED(data);

	struct panic_data *pdata = test_get_panic_data_pointer();

	memset(pdata, 0, sizeof(struct panic_data));
	memset(mock_jump_data, 0, sizeof(mock_jump_data));
}

ZTEST_SUITE(panic_output_get_panic_data_write, drivers_predicate_post_main,
	    NULL, reset, reset, NULL);