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