Wed Mar 8 17:06:35 2017 UTC ()
Avoid tripping on opposite-endian sysconfig/fex blobs.


(jakllsch)
diff -r1.2 -r1.3 src/sys/arch/evbarm/awin/awin_sysconfig.c

cvs diff -r1.2 -r1.3 src/sys/arch/evbarm/awin/Attic/awin_sysconfig.c (switch to unified diff)

--- src/sys/arch/evbarm/awin/Attic/awin_sysconfig.c 2015/10/25 20:46:46 1.2
+++ src/sys/arch/evbarm/awin/Attic/awin_sysconfig.c 2017/03/08 17:06:35 1.3
@@ -1,199 +1,208 @@ @@ -1,199 +1,208 @@
1/* $NetBSD: awin_sysconfig.c,v 1.2 2015/10/25 20:46:46 bouyer Exp $ */ 1/* $NetBSD: awin_sysconfig.c,v 1.3 2017/03/08 17:06:35 jakllsch Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_allwinner.h" 29#include "opt_allwinner.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: awin_sysconfig.c,v 1.2 2015/10/25 20:46:46 bouyer Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: awin_sysconfig.c,v 1.3 2017/03/08 17:06:35 jakllsch Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/intr.h> 37#include <sys/intr.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40 40
41#include <machine/bootconfig.h> 41#include <machine/bootconfig.h>
42 42
43#include <arm/allwinner/awin_reg.h> 43#include <arm/allwinner/awin_reg.h>
44#include <arm/allwinner/awin_var.h> 44#include <arm/allwinner/awin_var.h>
45 45
46#include <evbarm/awin/awin_sysconfig.h> 46#include <evbarm/awin/awin_sysconfig.h>
47 47
48static paddr_t awin_sysconfig_base = 0; 48static paddr_t awin_sysconfig_base = 0;
49#define AWIN_SYSCONFIG_SIZE 0x10000 49#define AWIN_SYSCONFIG_SIZE 0x10000
50 50
51#define AWIN_SYSCONFIG_TYPE_UNKNOWN 0 51#define AWIN_SYSCONFIG_TYPE_UNKNOWN 0
52#define AWIN_SYSCONFIG_TYPE_SINGLE_WORD 1 52#define AWIN_SYSCONFIG_TYPE_SINGLE_WORD 1
53#define AWIN_SYSCONFIG_TYPE_STRING 2 53#define AWIN_SYSCONFIG_TYPE_STRING 2
54#define AWIN_SYSCONFIG_TYPE_MULTI_WORD 3 54#define AWIN_SYSCONFIG_TYPE_MULTI_WORD 3
55#define AWIN_SYSCONFIG_TYPE_GPIO 4 55#define AWIN_SYSCONFIG_TYPE_GPIO 4
56 56
57static uint8_t awin_sysconfig[AWIN_SYSCONFIG_SIZE]; 57static uint8_t awin_sysconfig[AWIN_SYSCONFIG_SIZE];
58 58
59struct awin_sysconfig_head { 59struct awin_sysconfig_head {
60 uint32_t count; 60 uint32_t count;
61 uint32_t version[3]; 61 uint32_t version[3];
62} __packed; 62} __packed;
63 63
64struct awin_sysconfig_main_key { 64struct awin_sysconfig_main_key {
65 char name[32]; 65 char name[32];
66 uint32_t count; 66 uint32_t count;
67 uint32_t offset; 67 uint32_t offset;
68} __packed; 68} __packed;
69 69
70struct awin_sysconfig_sub_key { 70struct awin_sysconfig_sub_key {
71 char name[32]; 71 char name[32];
72 uint32_t offset; 72 uint32_t offset;
73 uint16_t count; 73 uint16_t count;
74 uint16_t type; 74 uint16_t type;
75} __packed; 75} __packed;
76 76
77struct awin_sysconfig_gpio { 77struct awin_sysconfig_gpio {
78 char name[32]; 78 char name[32];
79 uint32_t port; 79 uint32_t port;
80 uint32_t port_num; 80 uint32_t port_num;
81 int32_t mul_sel; 81 int32_t mul_sel;
82 int32_t pull; 82 int32_t pull;
83 int32_t drv_level; 83 int32_t drv_level;
84 int32_t data; 84 int32_t data;
85} __packed; 85} __packed;
86 86
87static bool awin_sysconfig_parse(const char *, const char *, 87static bool awin_sysconfig_parse(const char *, const char *,
88 struct awin_sysconfig_sub_key *); 88 struct awin_sysconfig_sub_key *);
89 89
90bool 90bool
91awin_sysconfig_init(void) 91awin_sysconfig_init(void)
92{ 92{
 93 struct awin_sysconfig_head head;
 94
93 if (get_bootconf_option(boot_args, "sysconfig", 95 if (get_bootconf_option(boot_args, "sysconfig",
94 BOOTOPT_TYPE_HEXINT, &awin_sysconfig_base) == 0) { 96 BOOTOPT_TYPE_HEXINT, &awin_sysconfig_base) == 0) {
95 return false; 97 return false;
96 } 98 }
97 if (awin_sysconfig_base == 0) { 99 if (awin_sysconfig_base == 0) {
98 return false; 100 return false;
99 } 101 }
100 102
101 const uint8_t * const sysconfig = (const uint8_t *) 103 const uint8_t * const sysconfig = (const uint8_t *)
102 (awin_sysconfig_base + KERNEL_BASE_VOFFSET); 104 (awin_sysconfig_base + KERNEL_BASE_VOFFSET);
103 memcpy(awin_sysconfig, sysconfig, AWIN_SYSCONFIG_SIZE); 105 memcpy(awin_sysconfig, sysconfig, AWIN_SYSCONFIG_SIZE);
104 106
 107 memcpy(&head, &awin_sysconfig[0], sizeof(head));
 108 if (head.count >= 0x01000000) {
 109 printf("%s(): 0x%x entries in sysconfig, ignoring.\n",
 110 __func__, head.count);
 111 return false;
 112 }
 113
105 return true; 114 return true;
106} 115}
107 116
108static bool 117static bool
109awin_sysconfig_parse(const char *key, const char *subkey, 118awin_sysconfig_parse(const char *key, const char *subkey,
110 struct awin_sysconfig_sub_key *value) 119 struct awin_sysconfig_sub_key *value)
111{ 120{
112 struct awin_sysconfig_head head; 121 struct awin_sysconfig_head head;
113 struct awin_sysconfig_main_key main_key; 122 struct awin_sysconfig_main_key main_key;
114 struct awin_sysconfig_sub_key sub_key; 123 struct awin_sysconfig_sub_key sub_key;
115 unsigned int off, n; 124 unsigned int off, n;
116 125
117 KASSERT(awin_sysconfig_base != 0); 126 KASSERT(awin_sysconfig_base != 0);
118 127
119 memcpy(&head, &awin_sysconfig[0], sizeof(head)); 128 memcpy(&head, &awin_sysconfig[0], sizeof(head));
120 129
121 for (n = 0, off = sizeof(head); n < head.count; 130 for (n = 0, off = sizeof(head); n < head.count;
122 n++, off += sizeof(main_key)) { 131 n++, off += sizeof(main_key)) {
123 memcpy(&main_key, &awin_sysconfig[off], sizeof(main_key)); 132 memcpy(&main_key, &awin_sysconfig[off], sizeof(main_key));
124 if (strcmp(key, main_key.name) == 0) { 133 if (strcmp(key, main_key.name) == 0) {
125 break; 134 break;
126 } 135 }
127 } 136 }
128 if (n == head.count) { 137 if (n == head.count) {
129 return false; 138 return false;
130 } 139 }
131 140
132 for (n = 0, off = main_key.offset << 2; n < main_key.count; 141 for (n = 0, off = main_key.offset << 2; n < main_key.count;
133 n++, off += sizeof(sub_key)) { 142 n++, off += sizeof(sub_key)) {
134 memcpy(&sub_key, &awin_sysconfig[off], sizeof(sub_key)); 143 memcpy(&sub_key, &awin_sysconfig[off], sizeof(sub_key));
135 if (strcmp(subkey, sub_key.name) == 0) { 144 if (strcmp(subkey, sub_key.name) == 0) {
136 break; 145 break;
137 } 146 }
138 } 147 }
139 if (n == main_key.count) { 148 if (n == main_key.count) {
140 return false; 149 return false;
141 } 150 }
142 151
143 memcpy(value, &sub_key, sizeof(*value)); 152 memcpy(value, &sub_key, sizeof(*value));
144 153
145 return true; 154 return true;
146} 155}
147 156
148int 157int
149awin_sysconfig_get_int(const char *key, const char *subkey) 158awin_sysconfig_get_int(const char *key, const char *subkey)
150{ 159{
151 struct awin_sysconfig_sub_key value; 160 struct awin_sysconfig_sub_key value;
152 int ret; 161 int ret;
153 162
154 if (awin_sysconfig_parse(key, subkey, &value) == false) 163 if (awin_sysconfig_parse(key, subkey, &value) == false)
155 return -1; 164 return -1;
156 165
157 if (value.type != AWIN_SYSCONFIG_TYPE_SINGLE_WORD) 166 if (value.type != AWIN_SYSCONFIG_TYPE_SINGLE_WORD)
158 return -1; 167 return -1;
159 168
160 memcpy(&ret, &awin_sysconfig[value.offset << 2], sizeof(ret)); 169 memcpy(&ret, &awin_sysconfig[value.offset << 2], sizeof(ret));
161 170
162 return ret; 171 return ret;
163} 172}
164 173
165const char * 174const char *
166awin_sysconfig_get_string(const char *key, const char *subkey) 175awin_sysconfig_get_string(const char *key, const char *subkey)
167{ 176{
168 struct awin_sysconfig_sub_key value; 177 struct awin_sysconfig_sub_key value;
169 178
170 if (awin_sysconfig_parse(key, subkey, &value) == false) 179 if (awin_sysconfig_parse(key, subkey, &value) == false)
171 return NULL; 180 return NULL;
172 181
173 if (value.type != AWIN_SYSCONFIG_TYPE_STRING) 182 if (value.type != AWIN_SYSCONFIG_TYPE_STRING)
174 return NULL; 183 return NULL;
175 184
176 return &awin_sysconfig[value.offset << 2]; 185 return &awin_sysconfig[value.offset << 2];
177} 186}
178 187
179const char * 188const char *
180awin_sysconfig_get_gpio(const char *key, const char *subkey) 189awin_sysconfig_get_gpio(const char *key, const char *subkey)
181{ 190{
182 static char gpio_str[6]; 191 static char gpio_str[6];
183 struct awin_sysconfig_sub_key value; 192 struct awin_sysconfig_sub_key value;
184 struct awin_sysconfig_gpio gpio; 193 struct awin_sysconfig_gpio gpio;
185 194
186 if (awin_sysconfig_parse(key, subkey, &value) == false) 195 if (awin_sysconfig_parse(key, subkey, &value) == false)
187 return NULL; 196 return NULL;
188 197
189 if (value.type != AWIN_SYSCONFIG_TYPE_GPIO) 198 if (value.type != AWIN_SYSCONFIG_TYPE_GPIO)
190 return NULL; 199 return NULL;
191  200
192 memcpy(&gpio, &awin_sysconfig[(value.offset << 2) - 32], sizeof(gpio)); 201 memcpy(&gpio, &awin_sysconfig[(value.offset << 2) - 32], sizeof(gpio));
193 202
194 snprintf(gpio_str, sizeof(gpio_str), "%cP%c%d", 203 snprintf(gpio_str, sizeof(gpio_str), "%cP%c%d",
195 gpio.mul_sel == 0 ? '<' : '>', 204 gpio.mul_sel == 0 ? '<' : '>',
196 (gpio.port - 1) + 'A', gpio.port_num); 205 (gpio.port - 1) + 'A', gpio.port_num);
197 206
198 return gpio_str; 207 return gpio_str;
199} 208}