summaryrefslogtreecommitdiffstats
path: root/kexec/arch/hppa/kexec-hppa.c
blob: 77c973922ffffeb6b27758c78e08d163c107ce78 (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
/*
 * kexec-hppa.c - kexec for hppa
 *
 * Copyright (C) 2019 Sven Schnelle <svens@stackframe.org>
 *
 * This source code is licensed under the GNU General Public License,
 * Version 2.  See the file COPYING for more details.
 */

#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include "../../kexec.h"
#include "../../kexec-syscall.h"
#include "kexec-hppa.h"
#include <arch/options.h>

#define SYSTEM_RAM "System RAM\n"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

static struct memory_range memory_range[MAX_MEMORY_RANGES];
unsigned long phys_offset;

/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
		unsigned long UNUSED(kexec_flags))
{
	const char *iomem = proc_iomem();
	int memory_ranges = 0;
	char line[512];
	FILE *fp;

	fp = fopen(iomem, "r");

	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}

	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long long start, end;
		char *str;
		int type;
		int consumed;
		int count;


		count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);

		if (count != 2)
			continue;

		str = line + consumed;

		if (memcmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
			type = RANGE_RAM;
		} else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		} else {
			continue;
		}

		memory_range[memory_ranges].start = start;
		memory_range[memory_ranges].end = end;
		memory_range[memory_ranges].type = type;
		if (++memory_ranges >= MAX_MEMORY_RANGES)
			break;
	}
	fclose(fp);
	*range = memory_range;
	*ranges = memory_ranges;

	dbgprint_mem_range("MEMORY RANGES", *range, *ranges);
	return 0;
}

struct file_type file_type[] = {
	{"elf-hppa", elf_hppa_probe, elf_hppa_load, elf_hppa_usage},
};
int file_types = ARRAY_SIZE(file_type);

void arch_usage(void)
{
}

int arch_process_options(int argc, char **argv)
{
	static const struct option options[] = {
		KEXEC_ALL_OPTIONS
		{ 0,			0, NULL, 0 },
	};
	static const char short_options[] = KEXEC_ALL_OPT_STR;
	int opt;

	opterr = 0; /* Don't complain about unrecognized options here */
	while ((opt = getopt_long(argc, argv, short_options, options, 0)) !=
		-1) {
		switch (opt) {
		default:
			break;
		}
	}
	/* Reset getopt for the next pass; called in other source modules */
	opterr = 1;
	optind = 1;
	return 0;
}

const struct arch_map_entry arches[] = {
	{ "parisc64", KEXEC_ARCH_HPPA },
	{ "parisc", KEXEC_ARCH_HPPA },
	{ NULL, 0 },
};

int arch_compat_trampoline(struct kexec_info *UNUSED(info))
{
	return 0;
}

void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}

int is_crashkernel_mem_reserved(void)
{
	return 0;
}

int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
{
	/* Crash kernel region size is not exposed by the system */
	return -1;
}

void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
	unsigned long base, size_t memsz)
{
	add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
}

unsigned long virt_to_phys(unsigned long addr)
{
	return addr - phys_offset;
}