10517cc98SCorey Minyard /* 20517cc98SCorey Minyard * SMBIOS Support 30517cc98SCorey Minyard * 40517cc98SCorey Minyard * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. 50517cc98SCorey Minyard * Copyright (C) 2013 Red Hat, Inc. 65aca89d1SPhilippe Mathieu-Daudé * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC 70517cc98SCorey Minyard * 80517cc98SCorey Minyard * Authors: 90517cc98SCorey Minyard * Alex Williamson <alex.williamson@hp.com> 100517cc98SCorey Minyard * Markus Armbruster <armbru@redhat.com> 110517cc98SCorey Minyard * 120517cc98SCorey Minyard * This work is licensed under the terms of the GNU GPL, version 2. See 130517cc98SCorey Minyard * the COPYING file in the top-level directory. 140517cc98SCorey Minyard * 150517cc98SCorey Minyard * Contributions after 2012-01-13 are licensed under the terms of the 160517cc98SCorey Minyard * GNU GPL, version 2 or (at your option) any later version. 170517cc98SCorey Minyard */ 180517cc98SCorey Minyard 190517cc98SCorey Minyard #ifndef QEMU_SMBIOS_BUILD_H 200517cc98SCorey Minyard #define QEMU_SMBIOS_BUILD_H 210517cc98SCorey Minyard 220517cc98SCorey Minyard bool smbios_skip_table(uint8_t type, bool required_table); 230517cc98SCorey Minyard 240517cc98SCorey Minyard extern uint8_t *smbios_tables; 250517cc98SCorey Minyard extern size_t smbios_tables_len; 260517cc98SCorey Minyard extern unsigned smbios_table_max; 270517cc98SCorey Minyard extern unsigned smbios_table_cnt; 280517cc98SCorey Minyard 290517cc98SCorey Minyard #define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \ 30*05e27d74SJulia Suvorova SMBIOS_BUILD_TABLE_PRE_SIZE(tbl_type, tbl_handle, tbl_required, \ 31*05e27d74SJulia Suvorova sizeof(struct smbios_type_##tbl_type))\ 32*05e27d74SJulia Suvorova 33*05e27d74SJulia Suvorova #define SMBIOS_BUILD_TABLE_PRE_SIZE(tbl_type, tbl_handle, \ 34*05e27d74SJulia Suvorova tbl_required, tbl_len) \ 350517cc98SCorey Minyard struct smbios_type_##tbl_type *t; \ 360517cc98SCorey Minyard size_t t_off; /* table offset into smbios_tables */ \ 370517cc98SCorey Minyard int str_index = 0; \ 380517cc98SCorey Minyard do { \ 390517cc98SCorey Minyard /* should we skip building this table ? */ \ 400517cc98SCorey Minyard if (smbios_skip_table(tbl_type, tbl_required)) { \ 410517cc98SCorey Minyard return; \ 420517cc98SCorey Minyard } \ 430517cc98SCorey Minyard \ 440517cc98SCorey Minyard /* use offset of table t within smbios_tables */ \ 450517cc98SCorey Minyard /* (pointer must be updated after each realloc) */ \ 460517cc98SCorey Minyard t_off = smbios_tables_len; \ 47*05e27d74SJulia Suvorova smbios_tables_len += tbl_len; \ 480517cc98SCorey Minyard smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \ 490517cc98SCorey Minyard t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \ 500517cc98SCorey Minyard \ 510517cc98SCorey Minyard t->header.type = tbl_type; \ 52*05e27d74SJulia Suvorova t->header.length = tbl_len; \ 530517cc98SCorey Minyard t->header.handle = cpu_to_le16(tbl_handle); \ 540517cc98SCorey Minyard } while (0) 550517cc98SCorey Minyard 560517cc98SCorey Minyard #define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \ 570517cc98SCorey Minyard do { \ 580517cc98SCorey Minyard int len = (value != NULL) ? strlen(value) + 1 : 0; \ 590517cc98SCorey Minyard if (len > 1) { \ 600517cc98SCorey Minyard smbios_tables = g_realloc(smbios_tables, \ 610517cc98SCorey Minyard smbios_tables_len + len); \ 620517cc98SCorey Minyard memcpy(smbios_tables + smbios_tables_len, value, len); \ 630517cc98SCorey Minyard smbios_tables_len += len; \ 640517cc98SCorey Minyard /* update pointer post-realloc */ \ 650517cc98SCorey Minyard t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \ 660517cc98SCorey Minyard t->field = ++str_index; \ 670517cc98SCorey Minyard } else { \ 680517cc98SCorey Minyard t->field = 0; \ 690517cc98SCorey Minyard } \ 700517cc98SCorey Minyard } while (0) 710517cc98SCorey Minyard 722d6dcbf9SDaniel P. Berrange #define SMBIOS_TABLE_SET_STR_LIST(tbl_type, value) \ 732d6dcbf9SDaniel P. Berrange do { \ 742d6dcbf9SDaniel P. Berrange int len = (value != NULL) ? strlen(value) + 1 : 0; \ 752d6dcbf9SDaniel P. Berrange if (len > 1) { \ 762d6dcbf9SDaniel P. Berrange smbios_tables = g_realloc(smbios_tables, \ 772d6dcbf9SDaniel P. Berrange smbios_tables_len + len); \ 782d6dcbf9SDaniel P. Berrange memcpy(smbios_tables + smbios_tables_len, value, len); \ 792d6dcbf9SDaniel P. Berrange smbios_tables_len += len; \ 802d6dcbf9SDaniel P. Berrange ++str_index; \ 812d6dcbf9SDaniel P. Berrange } \ 822d6dcbf9SDaniel P. Berrange } while (0) 832d6dcbf9SDaniel P. Berrange 840517cc98SCorey Minyard #define SMBIOS_BUILD_TABLE_POST \ 850517cc98SCorey Minyard do { \ 860517cc98SCorey Minyard size_t term_cnt, t_size; \ 870517cc98SCorey Minyard \ 880517cc98SCorey Minyard /* add '\0' terminator (add two if no strings defined) */ \ 890517cc98SCorey Minyard term_cnt = (str_index == 0) ? 2 : 1; \ 900517cc98SCorey Minyard smbios_tables = g_realloc(smbios_tables, \ 910517cc98SCorey Minyard smbios_tables_len + term_cnt); \ 920517cc98SCorey Minyard memset(smbios_tables + smbios_tables_len, 0, term_cnt); \ 930517cc98SCorey Minyard smbios_tables_len += term_cnt; \ 940517cc98SCorey Minyard \ 950517cc98SCorey Minyard /* update smbios max. element size */ \ 960517cc98SCorey Minyard t_size = smbios_tables_len - t_off; \ 970517cc98SCorey Minyard if (t_size > smbios_table_max) { \ 980517cc98SCorey Minyard smbios_table_max = t_size; \ 990517cc98SCorey Minyard } \ 1000517cc98SCorey Minyard \ 1010517cc98SCorey Minyard /* update smbios element count */ \ 1020517cc98SCorey Minyard smbios_table_cnt++; \ 1030517cc98SCorey Minyard } while (0) 1040517cc98SCorey Minyard 1055aca89d1SPhilippe Mathieu-Daudé /* IPMI SMBIOS firmware handling */ 1065aca89d1SPhilippe Mathieu-Daudé void smbios_build_type_38_table(void); 1075aca89d1SPhilippe Mathieu-Daudé 1080517cc98SCorey Minyard #endif /* QEMU_SMBIOS_BUILD_H */ 109