1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <assert.h>
8 #include <zircon/compiler.h>
9 #include <stdalign.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 __BEGIN_CDECLS;
14 
15 // COAABBBB VVVVVVVV  Condition Opcode paramA paramB Value
16 
17 #define OP_ABORT  0x0 // if (cond) return no-match
18 #define OP_MATCH  0x1 // if (cond) return match
19 #define OP_GOTO   0x2 // if (cond) advance to next LABEL(paramA)
20 #define OP_SET    0x3 // if (cond) flags |= paramA
21 #define OP_CLEAR  0x4 // if (cond) flags &= (~paramA)
22 #define OP_LABEL  0x5 // no-op, labels line with paramA
23 
24 #define COND_AL   0x0 // true
25 #define COND_EQ   0x1 // bind(paramB) == Value
26 #define COND_NE   0x2 // bind(paramB) != Value
27 #define COND_GT   0x3 // bind(paramB) > Value
28 #define COND_LT   0x4 // bind(paramB) < Value
29 #define COND_GE   0x5 // bind(paramB) >= Value
30 #define COND_LE   0x6 // bind(paramB) <= Value
31 #define COND_MASK 0x7 // (bind(paramB) & Value) != 0
32 #define COND_BITS 0x8 // (bind(paramB) & Value) == Value
33 
34 // branches are forward-only
35 // branches always go to the first matching LABEL
36 // branches that cannot find a matching LABEL are treated as ABORTs
37 // there is an implied unconditional ABORT after the last instruction
38 // flags are initially zero, may be set/cleared with SET/CLEAR
39 // flags may be tested by comparison against BIND_FLAGS
40 
41 #define BINDINST(c,o,a,b,v) \
42     { (((c)&0xF)<<28)|(((o)&0xF)<<24)|(((a)&0xFF)<<16)|((b)&0xFFFF),(v) }
43 
44 #define BINDINST_CC(n) ((n) >> 28)
45 #define BINDINST_OP(n) (((n) >> 24) & 0xF)
46 #define BINDINST_PA(n) (((n) >> 16) & 0xFF)
47 #define BINDINST_PB(n) ((n) & 0xFFFF)
48 
49 #define BI_ABORT()            BINDINST(COND_AL,OP_ABORT,0,0,0)
50 #define BI_MATCH()            BINDINST(COND_AL,OP_MATCH,0,0,0)
51 #define BI_GOTO(n)            BINDINST(COND_AL,OP_GOTO,n,0,0)
52 #define BI_SET(f)             BINDINST(COND_AL,OP_SET,f,0,0)
53 #define BI_CLEAR(f)           BINDINST(COND_AL,OP_CLEAR,f,0,0)
54 #define BI_LABEL(n)           BINDINST(COND_AL,OP_LABEL,n,0,0)
55 
56 #define BI_ABORT_IF(c,b,v)    BINDINST(COND_##c,OP_ABORT,0,b,v)
57 #define BI_MATCH_IF(c,b,v)    BINDINST(COND_##c,OP_MATCH,0,b,v)
58 #define BI_GOTO_IF(c,b,v,n)   BINDINST(COND_##c,OP_GOTO,n,b,v)
59 #define BI_SET_IF(c,b,v,f)    BINDINST(COND_##c,OP_SET,f,b,v)
60 #define BI_CLEAR_IF(c,b,v,f)  BINDINST(COND_##c,OP_CLEAR,f,b,v)
61 
62 // for drivers that only want to be bound on user request
63 #define BI_ABORT_IF_AUTOBIND  BI_ABORT_IF(NE, BIND_AUTOBIND, 0)
64 
65 // global binding variables at 0x00XX
66 #define BIND_FLAGS            0x0000 // value of the flags register
67 #define BIND_PROTOCOL         0x0001 // primary protcol of the device
68 #define BIND_AUTOBIND         0x0002 // if this is an automated bind/load
69 
70 // pci binding variables at 0x01XX
71 #define BIND_PCI_VID          0x0100
72 #define BIND_PCI_DID          0x0101
73 #define BIND_PCI_CLASS        0x0102
74 #define BIND_PCI_SUBCLASS     0x0103
75 #define BIND_PCI_INTERFACE    0x0104
76 #define BIND_PCI_REVISION     0x0105
77 #define BIND_PCI_BDF_ADDR     0x0106
78 
79 // pci binding variable utils
80 #define BIND_PCI_BDF_PACK(bus, dev, func) \
81     ((((uint32_t)(bus)  & 0xFF) << 8) |   \
82      (((uint32_t)(dev)  & 0x1F) << 3) |   \
83       ((uint32_t)(func) & 0x07))
84 
85 #define BIND_PCI_BDF_UNPACK_BUS(bdf) (((uint32_t)(bdf) >> 8) & 0xFF)
86 #define BIND_PCI_BDF_UNPACK_DEV(bdf) (((uint32_t)(bdf) >> 3) & 0x1F)
87 #define BIND_PCI_BDF_UNPACK_FUNC(bdf) ((uint32_t)(bdf) & 0x07)
88 
89 // usb binding variables at 0x02XX
90 // these are used for both ZX_PROTOCOL_USB and ZX_PROTOCOL_USB_FUNCTION
91 #define BIND_USB_VID          0x0200
92 #define BIND_USB_PID          0x0201
93 #define BIND_USB_CLASS        0x0202
94 #define BIND_USB_SUBCLASS     0x0203
95 #define BIND_USB_PROTOCOL     0x0204
96 
97 // Platform bus binding variables at 0x03XX
98 #define BIND_PLATFORM_DEV_VID 0x0300
99 #define BIND_PLATFORM_DEV_PID 0x0301
100 #define BIND_PLATFORM_DEV_DID 0x0302
101 #define BIND_PLATFORM_PROTO   0x0303
102 
103 // ACPI binding variables at 0x04XX
104 // The _HID is a 7- or 8-byte string. Because a bind property is 32-bit, use 2
105 // properties to bind using the _HID. They are encoded in big endian order for
106 // human readability. In the case of 7-byte _HID's, the 8th-byte shall be 0.
107 #define BIND_ACPI_HID_0_3      0x0400 // char 0-3
108 #define BIND_ACPI_HID_4_7      0x0401 // char 4-7
109 // The _CID may be a valid HID value or a bus-specific string. The ACPI bus
110 // driver only publishes those that are valid HID values.
111 #define BIND_ACPI_CID_0_3      0x0402 // char 0-3
112 #define BIND_ACPI_CID_4_7      0x0403 // char 4-7
113 
114 // Intel HDA Codec binding variables at 0x05XX
115 #define BIND_IHDA_CODEC_VID         0x0500
116 #define BIND_IHDA_CODEC_DID         0x0501
117 #define BIND_IHDA_CODEC_MAJOR_REV   0x0502
118 #define BIND_IHDA_CODEC_MINOR_REV   0x0503
119 #define BIND_IHDA_CODEC_VENDOR_REV  0x0504
120 #define BIND_IHDA_CODEC_VENDOR_STEP 0x0505
121 
122 // Serial binding variables at 0x06XX
123 #define BIND_SERIAL_CLASS           0x0600
124 #define BIND_SERIAL_VID             0x0601
125 #define BIND_SERIAL_PID             0x0602
126 
127 // NAND binding variables at 0x07XX
128 #define BIND_NAND_CLASS             0x0700
129 
130 // Bluetooth binding variables at 0x08XX
131 #define BIND_BT_GATT_SVC_UUID16     0x0800
132 // 128-bit UUID is split across 4 32-bit unsigned ints
133 #define BIND_BT_GATT_SVC_UUID128_1     0x0801
134 #define BIND_BT_GATT_SVC_UUID128_2     0x0802
135 #define BIND_BT_GATT_SVC_UUID128_3     0x0803
136 #define BIND_BT_GATT_SVC_UUID128_4     0x0804
137 
138 // SDIO binding variables at 0x09XX
139 #define BIND_SDIO_VID             0x0900
140 #define BIND_SDIO_PID             0x0901
141 
142 // I2C binding variables at 0x0AXX
143 #define BIND_I2C_CLASS            0x0A00
144 
145 // TEMPORARY binding variables at 0xfXX
146 // I2C_ADDR is a temporary way to bind the i2c touchscreen on the Acer12. This
147 // binding will eventually be made via some sort of ACPI device enumeration.
148 #define BIND_I2C_ADDR         0x0f00
149 
150 typedef struct zx_bind_inst {
151     uint32_t op;
152     uint32_t arg;
153 } zx_bind_inst_t;
154 
155 typedef struct zx_device_prop {
156     uint16_t id;
157     uint16_t reserved;
158     uint32_t value;
159 } zx_device_prop_t;
160 
161 // simple example
162 #if 0
163 zx_bind_inst_t i915_binding[] = {
164     BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PCI),
165     BI_ABORT_IF(NE, BIND_PCI_VID, 0x8086),
166     BI_MATCH_IF(EQ, BIND_PCI_DID, 0x1616), // broadwell
167     BI_MATCH_IF(EQ, BIND_PCI_DID, 0x1916), // skylake
168     BI_ABORT(),
169 };
170 #endif
171 
172 #define ZIRCON_NOTE_NAME "Zircon"
173 #define ZIRCON_NOTE_DRIVER 0x31565244 // DRV1
174 
175 typedef struct {
176     // Elf64_Nhdr fields:
177     uint32_t namesz;
178     uint32_t descsz;
179     uint32_t type;
180     // ELF note name.  namesz is the exact size of the name (including '\0'),
181     // but the storage size is always rounded up to a multiple of 4 bytes.
182     char name[(sizeof(ZIRCON_NOTE_NAME) + 3) & -4];
183 } zircon_driver_note_header_t;
184 
185 #define ZIRCON_DRIVER_NOTE_HEADER_INIT(object) {        \
186         /* .namesz = */ sizeof(ZIRCON_NOTE_NAME),              \
187         /* .descsz = */ (sizeof(object) -                       \
188                          sizeof(zircon_driver_note_header_t)), \
189         /* .type = */ ZIRCON_NOTE_DRIVER,                      \
190         /* .name = */ ZIRCON_NOTE_NAME,                        \
191     }
192 
193 typedef struct {
194     // See flag bits below.
195     uint32_t flags;
196 
197     // Driver Metadata
198     uint32_t bindcount;
199     uint32_t reserved0;
200     char name[32];
201     char vendor[16];
202     char version[16];
203 
204     // Driver Bind Program follows
205 } zircon_driver_note_payload_t;
206 
207 // Flag bits in the driver note:
208 
209 // Driver is built with `-fsanitize=address` and can only be loaded into a
210 // devhost that supports the ASan runtime.
211 #define ZIRCON_DRIVER_NOTE_FLAG_ASAN (1u << 0)
212 
213 #define ZIRCON_DRIVER_NOTE_PAYLOAD_INIT(Driver,VendorName,Version,BindCount) \
214     {                                                               \
215         /* .flags = */ ZIRCON_DRIVER_NOTE_FLAGS,                    \
216         /* .bindcount = */ (BindCount),                             \
217         /* .reserved0 = */ 0,                                       \
218         /* .name = */ #Driver,                                      \
219         /* .vendor = */ VendorName,                                 \
220         /* .version = */ Version,                                   \
221     }
222 
223 #define ZIRCON_DRIVER_NOTE_FLAGS \
224     (__has_feature(address_sanitizer) ? ZIRCON_DRIVER_NOTE_FLAG_ASAN : 0)
225 
226 typedef struct {
227     zircon_driver_note_header_t header;
228     zircon_driver_note_payload_t payload;
229 } zircon_driver_note_t;
230 
231 static_assert(offsetof(zircon_driver_note_t, payload) ==
232               sizeof(zircon_driver_note_header_t),
233               "alignment snafu?");
234 
235 // Without this, ASan will add redzone padding after the object, which
236 // would make it invalid ELF note format.
237 #if __has_feature(address_sanitizer)
238 # define ZIRCON_DRIVER_NOTE_ASAN __attribute__((no_sanitize("address")))
239 #else
240 # define ZIRCON_DRIVER_NOTE_ASAN
241 #endif
242 
243 // GCC has a quirk about how '__attribute__((visibility("default")))'
244 // (__EXPORT here) works for const variables in C++.  The attribute has no
245 // effect when used on the definition of a const variable, and GCC gives a
246 // warning/error about that.  The attribute must appear on the "extern"
247 // declaration of the variable instead.
248 
249 // We explicitly align the note to 4 bytes.  That's its natural alignment
250 // anyway, but the compilers sometimes like to over-align as an
251 // optimization while other tools sometimes like to complain if SHT_NOTE
252 // sections are over-aligned (since this could result in padding being
253 // inserted that makes it violate the ELF note format).  Standard C11
254 // doesn't permit alignas(...) on a type but we could use __ALIGNED(4) on
255 // all the types (i.e. GNU __attribute__ syntax instead of C11 syntax).
256 // But the alignment of the types is not actually the issue: it's the
257 // compiler deciding to over-align the individual object regardless of its
258 // type's alignment, so we have to explicitly set the alignment of the
259 // object to defeat any compiler default over-alignment.
260 
261 #define ZIRCON_DRIVER_BEGIN(Driver,Ops,VendorName,Version,BindCount) \
262 zx_driver_rec_t __zircon_driver_rec__ __EXPORT = {\
263     /* .ops = */ &(Ops),\
264     /* .driver = */ NULL,\
265     /* .log_flags = */ 7, /* DDK_LOG_ERROR | DDK_LOG_WARN | DDK_LOG_INFO */\
266 };\
267 extern const struct zircon_driver_note __zircon_driver_note__ __EXPORT;\
268 alignas(4) __SECTION(".note.zircon.driver." #Driver) ZIRCON_DRIVER_NOTE_ASAN \
269 const struct zircon_driver_note {\
270     zircon_driver_note_t note;\
271     zx_bind_inst_t binding[BindCount];\
272 } __zircon_driver_note__ = {\
273     /* .note = */{\
274         ZIRCON_DRIVER_NOTE_HEADER_INIT(__zircon_driver_note__),\
275         ZIRCON_DRIVER_NOTE_PAYLOAD_INIT(Driver,VendorName,Version,BindCount),\
276     },\
277     /* .binding = */ {
278 
279 #define ZIRCON_DRIVER_END(Driver) }};
280 
281 //TODO: if we moved the Ops from the BEGIN() to END() macro we
282 //      could add a zircon_driver_note_t* to the zx_driver_rec_t,
283 //      define it in END(), and have only one symbol to dlsym()
284 //      when loading drivers
285 
286 __END_CDECLS;
287