| 1 | #ifndef FW_CFG_H |
| 2 | #define FW_CFG_H |
| 3 | |
| 4 | #include "exec/hwaddr.h" |
| 5 | #include "standard-headers/linux/qemu_fw_cfg.h" |
| 6 | #include "hw/core/sysbus.h" |
| 7 | #include "system/dma.h" |
| 8 | #include "qom/object.h" |
| 9 | |
| 10 | #define TYPE_FW_CFG "fw_cfg" |
| 11 | #define TYPE_FW_CFG_IO "fw_cfg_io" |
| 12 | #define TYPE_FW_CFG_MEM "fw_cfg_mem" |
| 13 | #define TYPE_FW_CFG_DATA_GENERATOR_INTERFACE "fw_cfg-data-generator" |
| 14 | |
| 15 | OBJECT_DECLARE_SIMPLE_TYPE(FWCfgState, FW_CFG) |
| 16 | OBJECT_DECLARE_SIMPLE_TYPE(FWCfgIoState, FW_CFG_IO) |
| 17 | OBJECT_DECLARE_SIMPLE_TYPE(FWCfgMemState, FW_CFG_MEM) |
| 18 | |
| 19 | typedef struct FWCfgDataGeneratorClass FWCfgDataGeneratorClass; |
| 20 | DECLARE_CLASS_CHECKERS(FWCfgDataGeneratorClass, FW_CFG_DATA_GENERATOR, |
| 21 | TYPE_FW_CFG_DATA_GENERATOR_INTERFACE) |
| 22 | |
| 23 | struct FWCfgDataGeneratorClass { |
| 24 | /*< private >*/ |
| 25 | InterfaceClass parent_class; |
| 26 | /*< public >*/ |
| 27 | |
| 28 | /** |
| 29 | * get_data: |
| 30 | * @obj: the object implementing this interface |
| 31 | * @errp: pointer to a NULL-initialized error object |
| 32 | * |
| 33 | * Returns: A byte array containing data to add, or NULL without |
| 34 | * @errp set if no data is required, or NULL with @errp |
| 35 | * set on failure. |
| 36 | * |
| 37 | * The caller should release the reference when no longer |
| 38 | * required. |
| 39 | */ |
| 40 | GByteArray *(*get_data)(Object *obj, Error **errp); |
| 41 | }; |
| 42 | |
| 43 | typedef struct fw_cfg_file FWCfgFile; |
| 44 | |
| 45 | typedef struct FWCfgFiles { |
| 46 | uint32_t count; |
| 47 | FWCfgFile f[]; |
| 48 | } FWCfgFiles; |
| 49 | |
| 50 | typedef struct fw_cfg_dma_access FWCfgDmaAccess; |
| 51 | |
| 52 | typedef void (*FWCfgCallback)(void *opaque); |
| 53 | typedef void (*FWCfgWriteCallback)(void *opaque, off_t start, size_t len); |
| 54 | |
| 55 | typedef struct FWCfgEntry FWCfgEntry; |
| 56 | |
| 57 | struct FWCfgState { |
| 58 | /*< private >*/ |
| 59 | SysBusDevice parent_obj; |
| 60 | /*< public >*/ |
| 61 | |
| 62 | uint16_t file_slots; |
| 63 | FWCfgEntry *entries[2]; |
| 64 | int *entry_order; |
| 65 | FWCfgFiles *files; |
| 66 | uint16_t cur_entry; |
| 67 | uint32_t cur_offset; |
| 68 | Notifier machine_ready; |
| 69 | |
| 70 | bool dma_enabled; |
| 71 | dma_addr_t dma_addr; |
| 72 | AddressSpace *dma_as; |
| 73 | MemoryRegion dma_iomem; |
| 74 | |
| 75 | /* restore during migration */ |
| 76 | bool acpi_mr_restore; |
| 77 | uint64_t table_mr_size; |
| 78 | uint64_t linker_mr_size; |
| 79 | uint64_t rsdp_mr_size; |
| 80 | }; |
| 81 | |
| 82 | struct FWCfgIoState { |
| 83 | /*< private >*/ |
| 84 | FWCfgState parent_obj; |
| 85 | /*< public >*/ |
| 86 | |
| 87 | MemoryRegion comb_iomem; |
| 88 | }; |
| 89 | |
| 90 | struct FWCfgMemState { |
| 91 | /*< private >*/ |
| 92 | FWCfgState parent_obj; |
| 93 | /*< public >*/ |
| 94 | |
| 95 | MemoryRegion ctl_iomem, data_iomem; |
| 96 | uint32_t data_width; |
| 97 | MemoryRegionOps wide_data_ops; |
| 98 | }; |
| 99 | |
| 100 | /** |
| 101 | * fw_cfg_add_bytes: |
| 102 | * @s: fw_cfg device being modified |
| 103 | * @key: selector key value for new fw_cfg item |
| 104 | * @data: pointer to start of item data |
| 105 | * @len: size of item data |
| 106 | * |
| 107 | * Add a new fw_cfg item, available by selecting the given key, as a raw |
| 108 | * "blob" of the given size. The data referenced by the starting pointer |
| 109 | * is only linked, NOT copied, into the data structure of the fw_cfg device. |
| 110 | */ |
| 111 | void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); |
| 112 | |
| 113 | /** |
| 114 | * fw_cfg_add_string: |
| 115 | * @s: fw_cfg device being modified |
| 116 | * @key: selector key value for new fw_cfg item |
| 117 | * @value: NUL-terminated ascii string |
| 118 | * |
| 119 | * Add a new fw_cfg item, available by selecting the given key. The item |
| 120 | * data will consist of a dynamically allocated copy of the provided string, |
| 121 | * including its NUL terminator. |
| 122 | */ |
| 123 | void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value); |
| 124 | |
| 125 | /** |
| 126 | * fw_cfg_modify_string: |
| 127 | * @s: fw_cfg device being modified |
| 128 | * @key: selector key value for new fw_cfg item |
| 129 | * @value: NUL-terminated ascii string |
| 130 | * |
| 131 | * Replace the fw_cfg item available by selecting the given key. The new |
| 132 | * data will consist of a dynamically allocated copy of the provided string, |
| 133 | * including its NUL terminator. The data being replaced, assumed to have |
| 134 | * been dynamically allocated during an earlier call to either |
| 135 | * fw_cfg_add_string() or fw_cfg_modify_string(), is freed before returning. |
| 136 | */ |
| 137 | void fw_cfg_modify_string(FWCfgState *s, uint16_t key, const char *value); |
| 138 | |
| 139 | /** |
| 140 | * fw_cfg_add_i16: |
| 141 | * @s: fw_cfg device being modified |
| 142 | * @key: selector key value for new fw_cfg item |
| 143 | * @value: 16-bit integer |
| 144 | * |
| 145 | * Add a new fw_cfg item, available by selecting the given key. The item |
| 146 | * data will consist of a dynamically allocated copy of the given 16-bit |
| 147 | * value, converted to little-endian representation. |
| 148 | */ |
| 149 | void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); |
| 150 | |
| 151 | /** |
| 152 | * fw_cfg_modify_i16: |
| 153 | * @s: fw_cfg device being modified |
| 154 | * @key: selector key value for new fw_cfg item |
| 155 | * @value: 16-bit integer |
| 156 | * |
| 157 | * Replace the fw_cfg item available by selecting the given key. The new |
| 158 | * data will consist of a dynamically allocated copy of the given 16-bit |
| 159 | * value, converted to little-endian representation. The data being replaced, |
| 160 | * assumed to have been dynamically allocated during an earlier call to |
| 161 | * either fw_cfg_add_i16() or fw_cfg_modify_i16(), is freed before returning. |
| 162 | */ |
| 163 | void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value); |
| 164 | |
| 165 | /** |
| 166 | * fw_cfg_add_i32: |
| 167 | * @s: fw_cfg device being modified |
| 168 | * @key: selector key value for new fw_cfg item |
| 169 | * @value: 32-bit integer |
| 170 | * |
| 171 | * Add a new fw_cfg item, available by selecting the given key. The item |
| 172 | * data will consist of a dynamically allocated copy of the given 32-bit |
| 173 | * value, converted to little-endian representation. |
| 174 | */ |
| 175 | void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); |
| 176 | |
| 177 | /** |
| 178 | * fw_cfg_modify_i32: |
| 179 | * @s: fw_cfg device being modified |
| 180 | * @key: selector key value for new fw_cfg item |
| 181 | * @value: 32-bit integer |
| 182 | * |
| 183 | * Replace the fw_cfg item available by selecting the given key. The new |
| 184 | * data will consist of a dynamically allocated copy of the given 32-bit |
| 185 | * value, converted to little-endian representation. The data being replaced, |
| 186 | * assumed to have been dynamically allocated during an earlier call to |
| 187 | * either fw_cfg_add_i32() or fw_cfg_modify_i32(), is freed before returning. |
| 188 | */ |
| 189 | void fw_cfg_modify_i32(FWCfgState *s, uint16_t key, uint32_t value); |
| 190 | |
| 191 | /** |
| 192 | * fw_cfg_add_i64: |
| 193 | * @s: fw_cfg device being modified |
| 194 | * @key: selector key value for new fw_cfg item |
| 195 | * @value: 64-bit integer |
| 196 | * |
| 197 | * Add a new fw_cfg item, available by selecting the given key. The item |
| 198 | * data will consist of a dynamically allocated copy of the given 64-bit |
| 199 | * value, converted to little-endian representation. |
| 200 | */ |
| 201 | void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); |
| 202 | |
| 203 | /** |
| 204 | * fw_cfg_modify_i64: |
| 205 | * @s: fw_cfg device being modified |
| 206 | * @key: selector key value for new fw_cfg item |
| 207 | * @value: 64-bit integer |
| 208 | * |
| 209 | * Replace the fw_cfg item available by selecting the given key. The new |
| 210 | * data will consist of a dynamically allocated copy of the given 64-bit |
| 211 | * value, converted to little-endian representation. The data being replaced, |
| 212 | * assumed to have been dynamically allocated during an earlier call to |
| 213 | * either fw_cfg_add_i64() or fw_cfg_modify_i64(), is freed before returning. |
| 214 | */ |
| 215 | void fw_cfg_modify_i64(FWCfgState *s, uint16_t key, uint64_t value); |
| 216 | |
| 217 | /** |
| 218 | * fw_cfg_add_file: |
| 219 | * @s: fw_cfg device being modified |
| 220 | * @filename: name of new fw_cfg file item |
| 221 | * @data: pointer to start of item data |
| 222 | * @len: size of item data |
| 223 | * |
| 224 | * Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data |
| 225 | * referenced by the starting pointer is only linked, NOT copied, into the |
| 226 | * data structure of the fw_cfg device. |
| 227 | * The next available (unused) selector key starting at FW_CFG_FILE_FIRST |
| 228 | * will be used; also, a new entry will be added to the file directory |
| 229 | * structure residing at key value FW_CFG_FILE_DIR, containing the item name, |
| 230 | * data size, and assigned selector key value. |
| 231 | */ |
| 232 | void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, |
| 233 | size_t len); |
| 234 | |
| 235 | /** |
| 236 | * fw_cfg_add_file_callback: |
| 237 | * @s: fw_cfg device being modified |
| 238 | * @filename: name of new fw_cfg file item |
| 239 | * @select_cb: callback function when selecting |
| 240 | * @write_cb: callback function after a write |
| 241 | * @callback_opaque: argument to be passed into callback function |
| 242 | * @data: pointer to start of item data |
| 243 | * @len: size of item data |
| 244 | * @read_only: is file read only |
| 245 | * |
| 246 | * Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data |
| 247 | * referenced by the starting pointer is only linked, NOT copied, into the |
| 248 | * data structure of the fw_cfg device. |
| 249 | * The next available (unused) selector key starting at FW_CFG_FILE_FIRST |
| 250 | * will be used; also, a new entry will be added to the file directory |
| 251 | * structure residing at key value FW_CFG_FILE_DIR, containing the item name, |
| 252 | * data size, and assigned selector key value. |
| 253 | * Additionally, set a callback function (and argument) to be called each |
| 254 | * time this item is selected (by having its selector key either written to |
| 255 | * the fw_cfg control register, or passed to QEMU in FWCfgDmaAccess.control |
| 256 | * with FW_CFG_DMA_CTL_SELECT). |
| 257 | */ |
| 258 | void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, |
| 259 | FWCfgCallback select_cb, |
| 260 | FWCfgWriteCallback write_cb, |
| 261 | void *callback_opaque, |
| 262 | void *data, size_t len, bool read_only); |
| 263 | |
| 264 | /** |
| 265 | * fw_cfg_modify_file: |
| 266 | * @s: fw_cfg device being modified |
| 267 | * @filename: name of new fw_cfg file item |
| 268 | * @data: pointer to start of item data |
| 269 | * @len: size of item data |
| 270 | * |
| 271 | * Replace a NAMED fw_cfg item. If an existing item is found, its callback |
| 272 | * information will be cleared, and a pointer to its data will be returned |
| 273 | * to the caller, so that it may be freed if necessary. If an existing item |
| 274 | * is not found, this call defaults to fw_cfg_add_file(), and NULL is |
| 275 | * returned to the caller. |
| 276 | * In either case, the new item data is only linked, NOT copied, into the |
| 277 | * data structure of the fw_cfg device. |
| 278 | * |
| 279 | * Returns: pointer to old item's data, or NULL if old item does not exist. |
| 280 | */ |
| 281 | void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, |
| 282 | size_t len); |
| 283 | |
| 284 | /** |
| 285 | * fw_cfg_add_file_from_generator: |
| 286 | * @s: fw_cfg device being modified |
| 287 | * @filename: name of new fw_cfg file item |
| 288 | * @part: name of object implementing FW_CFG_DATA_GENERATOR interface |
| 289 | * @parent: the object in which to resolve the @part |
| 290 | * @errp: pointer to a NULL initialized error object |
| 291 | * |
| 292 | * If the @part object generates content, add a new NAMED fw_cfg item with it. |
| 293 | * The data generated by the @part object is copied into the data structure of |
| 294 | * the fw_cfg device. |
| 295 | * The next available (unused) selector key starting at FW_CFG_FILE_FIRST |
| 296 | * will be used; also, a new entry will be added to the file directory |
| 297 | * structure residing at key value FW_CFG_FILE_DIR, containing the item name, |
| 298 | * data size, and assigned selector key value. |
| 299 | * |
| 300 | * If the @part object does not generate content, no fw_cfg item is added. |
| 301 | * |
| 302 | * Returns: %true on success, %false on error. |
| 303 | */ |
| 304 | bool fw_cfg_add_file_from_generator(FWCfgState *s, |
| 305 | Object *parent, const char *part, |
| 306 | const char *filename, Error **errp); |
| 307 | |
| 308 | /** |
| 309 | * fw_cfg_init_io_dma: |
| 310 | * @iobase: x86 port number which is the base of the fw_cfg port range |
| 311 | * @dma_as: the device will do DMA to/from this AddressSpace |
| 312 | * |
| 313 | * Create a fw_cfg device and map it into the specified I/O port range. |
| 314 | * |
| 315 | * This creates a device with the x86 PC standard port I/O layout: |
| 316 | * - Selector Register IOport: @iobase |
| 317 | * - Data Register IOport: @iobase + 1 |
| 318 | * - DMA Address IOport: @iobase + 4 |
| 319 | * |
| 320 | * Returns the device object. |
| 321 | */ |
| 322 | FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, AddressSpace *dma_as); |
| 323 | |
| 324 | /** |
| 325 | * fw_cfg_init_mem_nodma: |
| 326 | * |
| 327 | * @ctl_addr: address of the selector register |
| 328 | * @data_addr: address of the data address |
| 329 | * @data_width: width of the data register in bytes |
| 330 | * |
| 331 | * Create a fw_cfg device without DMA support, and map its |
| 332 | * registers at the specified addresses. |
| 333 | * |
| 334 | * Do not use this function in code for a board type that didn't |
| 335 | * already support the fw_cfg device. All new board types should |
| 336 | * include DMA support and use the standard register layout -- use |
| 337 | * fw_cfg_init_mem_dma() instead. |
| 338 | * |
| 339 | * Returns the device object. |
| 340 | */ |
| 341 | FWCfgState *fw_cfg_init_mem_nodma(hwaddr ctl_addr, hwaddr data_addr, |
| 342 | unsigned data_width); |
| 343 | /** |
| 344 | * fw_cfg_init_mem_dma: |
| 345 | * @base_addr: address to map the device at |
| 346 | * @as: the device will do DMA to/from this AddressSpace |
| 347 | * |
| 348 | * Create and map a fw_cfg device at the specified base address. |
| 349 | * |
| 350 | * This always creates a device with DMA support, and the "standard" |
| 351 | * register layout: |
| 352 | * - offset 0 : data, 64 bits |
| 353 | * - offset 8 : selector, 16 bits |
| 354 | * - offset 16 : DMA address, 64 bits |
| 355 | * |
| 356 | * The device will be created, configured and realized, and its |
| 357 | * memory regions for the registers will be mapped at the specified |
| 358 | * address. |
| 359 | * |
| 360 | * Returns the device object. |
| 361 | */ |
| 362 | FWCfgState *fw_cfg_init_mem_dma(hwaddr base_addr, AddressSpace *dma_as); |
| 363 | |
| 364 | FWCfgState *fw_cfg_find(void); |
| 365 | bool fw_cfg_dma_enabled(void *opaque); |
| 366 | |
| 367 | /** |
| 368 | * fw_cfg_arch_key_name: |
| 369 | * |
| 370 | * @key: The uint16 selector key. |
| 371 | * |
| 372 | * The key is architecture-specific (the FW_CFG_ARCH_LOCAL mask is expected |
| 373 | * to be set in the key). |
| 374 | * |
| 375 | * Returns: The stringified architecture-specific name if the selector |
| 376 | * refers to a well-known numerically defined item, or NULL on |
| 377 | * key lookup failure. |
| 378 | */ |
| 379 | const char *fw_cfg_arch_key_name(uint16_t key); |
| 380 | |
| 381 | /** |
| 382 | * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified |
| 383 | * by key. |
| 384 | * @fw_cfg: The firmware config instance to store the data in. |
| 385 | * @size_key: The firmware config key to store the size of the loaded |
| 386 | * data under, with fw_cfg_add_i32(). |
| 387 | * @data_key: The firmware config key to store the loaded data under, |
| 388 | * with fw_cfg_add_bytes(). |
| 389 | * @image_name: The name of the image file to load. If it is NULL, the |
| 390 | * function returns without doing anything. |
| 391 | * @try_decompress: Whether the image should be decompressed (gunzipped) before |
| 392 | * adding it to fw_cfg. If decompression fails, the image is |
| 393 | * loaded as-is. |
| 394 | * |
| 395 | * In case of failure, the function prints an error message to stderr and the |
| 396 | * process exits with status 1. |
| 397 | */ |
| 398 | void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key, |
| 399 | uint16_t data_key, const char *image_name, |
| 400 | bool try_decompress); |
| 401 | |
| 402 | /** |
| 403 | * load_image_to_fw_cfg_file() - Load an image file into an fw_cfg entry |
| 404 | * identified by fw_cfg file name. |
| 405 | * @fw_cfg: The firmware config instance to store the data in. |
| 406 | * @fw_cfg_name: The name of the fw_cfg (pseudo) file. |
| 407 | * @image_name: The name of the image file to load. If it is NULL, the |
| 408 | * function returns without doing anything. |
| 409 | * |
| 410 | * In case of failure, the function prints an error message to stderr and the |
| 411 | * process exits with status 1. |
| 412 | */ |
| 413 | void load_image_to_fw_cfg_file(FWCfgState *fw_cfg, |
| 414 | const char *fw_cfg_name, |
| 415 | const char *image_name); |
| 416 | |
| 417 | #endif |