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
|
#include "config.h"
#include "libopenbios/bindings.h"
#include "libc/byteorder.h"
#include "libopenbios/ofmem.h"
#define NO_QEMU_PROTOS
#include "arch/common/fw_cfg.h"
#if !defined(CONFIG_SPARC64)
static volatile uint16_t *fw_cfg_cmd;
static volatile uint8_t *fw_cfg_data;
static void
fw_cfg_read_bytes(char *buf, unsigned int nbytes)
{
unsigned int i;
for (i = 0; i < nbytes; i++)
buf[i] = *fw_cfg_data;
}
void
fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes)
{
*fw_cfg_cmd = cmd;
fw_cfg_read_bytes(buf, nbytes);
}
#else
// XXX depends on PCI bus location, should be removed
static void
fw_cfg_read_bytes(char *buf, unsigned int nbytes)
{
unsigned int i;
for (i = 0; i < nbytes; i++)
buf[i] = inb(CONFIG_FW_CFG_ADDR + 1);
}
void
fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes)
{
outw(cmd, CONFIG_FW_CFG_ADDR);
fw_cfg_read_bytes(buf, nbytes);
}
#endif
uint64_t
fw_cfg_read_i64(uint16_t cmd)
{
uint64_t buf;
fw_cfg_read(cmd, (char *)&buf, sizeof(uint64_t));
return __le64_to_cpu(buf);
}
uint32_t
fw_cfg_read_i32(uint16_t cmd)
{
uint32_t buf;
fw_cfg_read(cmd, (char *)&buf, sizeof(uint32_t));
return __le32_to_cpu(buf);
}
uint16_t
fw_cfg_read_i16(uint16_t cmd)
{
uint16_t buf;
fw_cfg_read(cmd, (char *)&buf, sizeof(uint16_t));
return __le16_to_cpu(buf);
}
uint32_t
fw_cfg_find_file(const char *filename, uint16_t *select, uint32_t *size)
{
FWCfgFile f;
unsigned int i;
uint32_t buf, count;
/* Unusually all FW_CFG_FILE_DIR fields are BE */
fw_cfg_read(FW_CFG_FILE_DIR, (char *)&buf, sizeof(uint32_t));
count = __be32_to_cpu(buf);
for (i = 0; i < count; i++) {
fw_cfg_read_bytes((char *)&f, sizeof(f));
if (!strcmp(f.name, filename)) {
*select = __be16_to_cpu(f.select);
*size = __be32_to_cpu(f.size);
return -1;
}
}
return 0;
}
char *
fw_cfg_read_file(const char *filename, uint32_t *size)
{
uint16_t cmd;
uint32_t nbytes;
char *buf;
if (fw_cfg_find_file(filename, &cmd, &nbytes)) {
buf = malloc(nbytes);
fw_cfg_read(cmd, buf, nbytes);
*size = nbytes;
return buf;
}
return NULL;
}
//
// ( fname fnamelen -- buf buflen -1 | 0 )
//
void
forth_fw_cfg_read_file(void)
{
char *filename = pop_fstr_copy();
char *buffer;
uint32_t size;
buffer = fw_cfg_read_file(filename, &size);
if (buffer) {
PUSH(pointer2cell(buffer));
PUSH(size);
PUSH(-1);
return;
}
PUSH(0);
}
void
fw_cfg_init(void)
{
#if defined(CONFIG_SPARC32)
fw_cfg_cmd = (void *)ofmem_map_io(CONFIG_FW_CFG_ADDR, 2);
fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2;
#elif defined(CONFIG_SPARC64)
// Nothing for the port version
#elif defined(CONFIG_PPC)
fw_cfg_cmd = (void *)CONFIG_FW_CFG_ADDR;
fw_cfg_data = (void *)(CONFIG_FW_CFG_ADDR + 2);
#endif
}
|