@@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
52
52
g_array_append_val (array , val );
53
53
}
54
54
55
+ static void build_append_padded_str (GArray * array , const char * str ,
56
+ size_t maxlen , char pad )
57
+ {
58
+ size_t i ;
59
+ size_t len = strlen (str );
60
+
61
+ g_assert (len <= maxlen );
62
+ g_array_append_vals (array , str , len );
63
+ for (i = maxlen - len ; i > 0 ; i -- ) {
64
+ g_array_append_val (array , pad );
65
+ }
66
+ }
67
+
55
68
static void build_append_array (GArray * array , GArray * val )
56
69
{
57
70
g_array_append_vals (array , val -> data , val -> len );
@@ -1692,27 +1705,53 @@ Aml *aml_object_type(Aml *object)
1692
1705
return var ;
1693
1706
}
1694
1707
1695
- void
1696
- build_header (BIOSLinker * linker , GArray * table_data ,
1697
- AcpiTableHeader * h , const char * sig , int len , uint8_t rev ,
1698
- const char * oem_id , const char * oem_table_id )
1699
- {
1700
- unsigned tbl_offset = (char * )h - table_data -> data ;
1701
- unsigned checksum_offset = (char * )& h -> checksum - table_data -> data ;
1702
- memcpy (& h -> signature , sig , 4 );
1703
- h -> length = cpu_to_le32 (len );
1704
- h -> revision = rev ;
1705
-
1706
- strpadcpy ((char * )h -> oem_id , sizeof h -> oem_id , oem_id , ' ' );
1707
- strpadcpy ((char * )h -> oem_table_id , sizeof h -> oem_table_id ,
1708
- oem_table_id , ' ' );
1709
-
1710
- h -> oem_revision = cpu_to_le32 (1 );
1711
- memcpy (h -> asl_compiler_id , ACPI_BUILD_APPNAME8 , 4 );
1712
- h -> asl_compiler_revision = cpu_to_le32 (1 );
1713
- /* Checksum to be filled in by Guest linker */
1708
+ void acpi_table_begin (AcpiTable * desc , GArray * array )
1709
+ {
1710
+
1711
+ desc -> array = array ;
1712
+ desc -> table_offset = array -> len ;
1713
+
1714
+ /*
1715
+ * ACPI spec 1.0b
1716
+ * 5.2.3 System Description Table Header
1717
+ */
1718
+ g_assert (strlen (desc -> sig ) == 4 );
1719
+ g_array_append_vals (array , desc -> sig , 4 ); /* Signature */
1720
+ /*
1721
+ * reserve space for Length field, which will be patched by
1722
+ * acpi_table_end() when the table creation is finished.
1723
+ */
1724
+ build_append_int_noprefix (array , 0 , 4 ); /* Length */
1725
+ build_append_int_noprefix (array , desc -> rev , 1 ); /* Revision */
1726
+ build_append_int_noprefix (array , 0 , 1 ); /* Checksum */
1727
+ build_append_padded_str (array , desc -> oem_id , 6 , ' ' ); /* OEMID */
1728
+ /* OEM Table ID */
1729
+ build_append_padded_str (array , desc -> oem_table_id , 8 , ' ' );
1730
+ build_append_int_noprefix (array , 1 , 4 ); /* OEM Revision */
1731
+ g_array_append_vals (array , ACPI_BUILD_APPNAME8 , 4 ); /* Creator ID */
1732
+ build_append_int_noprefix (array , 1 , 4 ); /* Creator Revision */
1733
+ }
1734
+
1735
+ void acpi_table_end (BIOSLinker * linker , AcpiTable * desc )
1736
+ {
1737
+ /*
1738
+ * ACPI spec 1.0b
1739
+ * 5.2.3 System Description Table Header
1740
+ * Table 5-2 DESCRIPTION_HEADER Fields
1741
+ */
1742
+ const unsigned checksum_offset = 9 ;
1743
+ uint32_t table_len = desc -> array -> len - desc -> table_offset ;
1744
+ uint32_t table_len_le = cpu_to_le32 (table_len );
1745
+ gchar * len_ptr = & desc -> array -> data [desc -> table_offset + 4 ];
1746
+
1747
+ /* patch "Length" field that has been reserved by acpi_table_begin()
1748
+ * to the actual length, i.e. accumulated table length from
1749
+ * acpi_table_begin() till acpi_table_end()
1750
+ */
1751
+ memcpy (len_ptr , & table_len_le , sizeof table_len_le );
1752
+
1714
1753
bios_linker_loader_add_checksum (linker , ACPI_BUILD_TABLE_FILE ,
1715
- tbl_offset , len , checksum_offset );
1754
+ desc -> table_offset , table_len , desc -> table_offset + checksum_offset );
1716
1755
}
1717
1756
1718
1757
void * acpi_data_push (GArray * table_data , unsigned size )
@@ -1822,73 +1861,81 @@ build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data)
1822
1861
32 );
1823
1862
}
1824
1863
1825
- /* Build rsdt table */
1864
+ /*
1865
+ * ACPI 1.0 Root System Description Table (RSDT)
1866
+ */
1826
1867
void
1827
1868
build_rsdt (GArray * table_data , BIOSLinker * linker , GArray * table_offsets ,
1828
1869
const char * oem_id , const char * oem_table_id )
1829
1870
{
1830
1871
int i ;
1831
- unsigned rsdt_entries_offset ;
1832
- AcpiRsdtDescriptorRev1 * rsdt ;
1833
- int rsdt_start = table_data -> len ;
1834
- const unsigned table_data_len = (sizeof (uint32_t ) * table_offsets -> len );
1835
- const unsigned rsdt_entry_size = sizeof (rsdt -> table_offset_entry [0 ]);
1836
- const size_t rsdt_len = sizeof (* rsdt ) + table_data_len ;
1837
-
1838
- rsdt = acpi_data_push (table_data , rsdt_len );
1839
- rsdt_entries_offset = (char * )rsdt -> table_offset_entry - table_data -> data ;
1872
+ AcpiTable table = { .sig = "RSDT" , .rev = 1 ,
1873
+ .oem_id = oem_id , .oem_table_id = oem_table_id };
1874
+
1875
+ acpi_table_begin (& table , table_data );
1840
1876
for (i = 0 ; i < table_offsets -> len ; ++ i ) {
1841
1877
uint32_t ref_tbl_offset = g_array_index (table_offsets , uint32_t , i );
1842
- uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i ;
1878
+ uint32_t rsdt_entry_offset = table . array -> len ;
1843
1879
1844
- /* rsdt->table_offset_entry to be filled by Guest linker */
1880
+ /* reserve space for entry */
1881
+ build_append_int_noprefix (table .array , 0 , 4 );
1882
+
1883
+ /* mark position of RSDT entry to be filled by Guest linker */
1845
1884
bios_linker_loader_add_pointer (linker ,
1846
- ACPI_BUILD_TABLE_FILE , rsdt_entry_offset , rsdt_entry_size ,
1885
+ ACPI_BUILD_TABLE_FILE , rsdt_entry_offset , 4 ,
1847
1886
ACPI_BUILD_TABLE_FILE , ref_tbl_offset );
1887
+
1848
1888
}
1849
- build_header (linker , table_data ,
1850
- (void * )(table_data -> data + rsdt_start ),
1851
- "RSDT" , rsdt_len , 1 , oem_id , oem_table_id );
1889
+ acpi_table_end (linker , & table );
1852
1890
}
1853
1891
1854
- /* Build xsdt table */
1892
+ /*
1893
+ * ACPI 2.0 eXtended System Description Table (XSDT)
1894
+ */
1855
1895
void
1856
1896
build_xsdt (GArray * table_data , BIOSLinker * linker , GArray * table_offsets ,
1857
1897
const char * oem_id , const char * oem_table_id )
1858
1898
{
1859
1899
int i ;
1860
- unsigned xsdt_entries_offset ;
1861
- AcpiXsdtDescriptorRev2 * xsdt ;
1862
- int xsdt_start = table_data -> len ;
1863
- const unsigned table_data_len = (sizeof (uint64_t ) * table_offsets -> len );
1864
- const unsigned xsdt_entry_size = sizeof (xsdt -> table_offset_entry [0 ]);
1865
- const size_t xsdt_len = sizeof (* xsdt ) + table_data_len ;
1866
-
1867
- xsdt = acpi_data_push (table_data , xsdt_len );
1868
- xsdt_entries_offset = (char * )xsdt -> table_offset_entry - table_data -> data ;
1900
+ AcpiTable table = { .sig = "XSDT" , .rev = 1 ,
1901
+ .oem_id = oem_id , .oem_table_id = oem_table_id };
1902
+
1903
+ acpi_table_begin (& table , table_data );
1904
+
1869
1905
for (i = 0 ; i < table_offsets -> len ; ++ i ) {
1870
1906
uint64_t ref_tbl_offset = g_array_index (table_offsets , uint32_t , i );
1871
- uint64_t xsdt_entry_offset = xsdt_entries_offset + xsdt_entry_size * i ;
1907
+ uint64_t xsdt_entry_offset = table . array -> len ;
1872
1908
1873
- /* xsdt->table_offset_entry to be filled by Guest linker */
1909
+ /* reserve space for entry */
1910
+ build_append_int_noprefix (table .array , 0 , 8 );
1911
+
1912
+ /* mark position of RSDT entry to be filled by Guest linker */
1874
1913
bios_linker_loader_add_pointer (linker ,
1875
- ACPI_BUILD_TABLE_FILE , xsdt_entry_offset , xsdt_entry_size ,
1914
+ ACPI_BUILD_TABLE_FILE , xsdt_entry_offset , 8 ,
1876
1915
ACPI_BUILD_TABLE_FILE , ref_tbl_offset );
1877
1916
}
1878
- build_header (linker , table_data ,
1879
- (void * )(table_data -> data + xsdt_start ),
1880
- "XSDT" , xsdt_len , 1 , oem_id , oem_table_id );
1917
+ acpi_table_end (linker , & table );
1881
1918
}
1882
1919
1883
- void build_srat_memory (AcpiSratMemoryAffinity * numamem , uint64_t base ,
1920
+ /*
1921
+ * ACPI spec, Revision 4.0
1922
+ * 5.2.16.2 Memory Affinity Structure
1923
+ */
1924
+ void build_srat_memory (GArray * table_data , uint64_t base ,
1884
1925
uint64_t len , int node , MemoryAffinityFlags flags )
1885
1926
{
1886
- numamem -> type = ACPI_SRAT_MEMORY ;
1887
- numamem -> length = sizeof (* numamem );
1888
- numamem -> proximity = cpu_to_le32 (node );
1889
- numamem -> flags = cpu_to_le32 (flags );
1890
- numamem -> base_addr = cpu_to_le64 (base );
1891
- numamem -> range_length = cpu_to_le64 (len );
1927
+ build_append_int_noprefix (table_data , 1 , 1 ); /* Type */
1928
+ build_append_int_noprefix (table_data , 40 , 1 ); /* Length */
1929
+ build_append_int_noprefix (table_data , node , 4 ); /* Proximity Domain */
1930
+ build_append_int_noprefix (table_data , 0 , 2 ); /* Reserved */
1931
+ build_append_int_noprefix (table_data , base , 4 ); /* Base Address Low */
1932
+ /* Base Address High */
1933
+ build_append_int_noprefix (table_data , base >> 32 , 4 );
1934
+ build_append_int_noprefix (table_data , len , 4 ); /* Length Low */
1935
+ build_append_int_noprefix (table_data , len >> 32 , 4 ); /* Length High */
1936
+ build_append_int_noprefix (table_data , 0 , 4 ); /* Reserved */
1937
+ build_append_int_noprefix (table_data , flags , 4 ); /* Flags */
1938
+ build_append_int_noprefix (table_data , 0 , 8 ); /* Reserved */
1892
1939
}
1893
1940
1894
1941
/*
@@ -1898,11 +1945,12 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
1898
1945
void build_slit (GArray * table_data , BIOSLinker * linker , MachineState * ms ,
1899
1946
const char * oem_id , const char * oem_table_id )
1900
1947
{
1901
- int slit_start , i , j ;
1902
- slit_start = table_data -> len ;
1948
+ int i , j ;
1903
1949
int nb_numa_nodes = ms -> numa_state -> num_nodes ;
1950
+ AcpiTable table = { .sig = "SLIT" , .rev = 1 ,
1951
+ .oem_id = oem_id , .oem_table_id = oem_table_id };
1904
1952
1905
- acpi_data_push ( table_data , sizeof ( AcpiTableHeader ) );
1953
+ acpi_table_begin ( & table , table_data );
1906
1954
1907
1955
build_append_int_noprefix (table_data , nb_numa_nodes , 8 );
1908
1956
for (i = 0 ; i < nb_numa_nodes ; i ++ ) {
@@ -1913,21 +1961,18 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
1913
1961
1 );
1914
1962
}
1915
1963
}
1916
-
1917
- build_header (linker , table_data ,
1918
- (void * )(table_data -> data + slit_start ),
1919
- "SLIT" ,
1920
- table_data -> len - slit_start , 1 , oem_id , oem_table_id );
1964
+ acpi_table_end (linker , & table );
1921
1965
}
1922
1966
1923
1967
/* build rev1/rev3/rev5.1 FADT */
1924
1968
void build_fadt (GArray * tbl , BIOSLinker * linker , const AcpiFadtData * f ,
1925
1969
const char * oem_id , const char * oem_table_id )
1926
1970
{
1927
1971
int off ;
1928
- int fadt_start = tbl -> len ;
1972
+ AcpiTable table = { .sig = "FACP" , .rev = f -> rev ,
1973
+ .oem_id = oem_id , .oem_table_id = oem_table_id };
1929
1974
1930
- acpi_data_push ( tbl , sizeof ( AcpiTableHeader ) );
1975
+ acpi_table_begin ( & table , tbl );
1931
1976
1932
1977
/* FACS address to be filled by Guest linker at runtime */
1933
1978
off = tbl -> len ;
@@ -1991,7 +2036,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
1991
2036
build_append_int_noprefix (tbl , f -> flags , 4 ); /* Flags */
1992
2037
1993
2038
if (f -> rev == 1 ) {
1994
- goto build_hdr ;
2039
+ goto done ;
1995
2040
}
1996
2041
1997
2042
build_append_gas_from_struct (tbl , & f -> reset_reg ); /* RESET_REG */
@@ -2028,7 +2073,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
2028
2073
build_append_gas (tbl , AML_AS_SYSTEM_MEMORY , 0 , 0 , 0 , 0 ); /* X_GPE1_BLK */
2029
2074
2030
2075
if (f -> rev <= 4 ) {
2031
- goto build_hdr ;
2076
+ goto done ;
2032
2077
}
2033
2078
2034
2079
/* SLEEP_CONTROL_REG */
@@ -2039,9 +2084,8 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
2039
2084
/* TODO: extra fields need to be added to support revisions above rev5 */
2040
2085
assert (f -> rev == 5 );
2041
2086
2042
- build_hdr :
2043
- build_header (linker , tbl , (void * )(tbl -> data + fadt_start ),
2044
- "FACP" , tbl -> len - fadt_start , f -> rev , oem_id , oem_table_id );
2087
+ done :
2088
+ acpi_table_end (linker , & table );
2045
2089
}
2046
2090
2047
2091
#ifdef CONFIG_TPM
@@ -2054,13 +2098,14 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
2054
2098
const char * oem_id , const char * oem_table_id )
2055
2099
{
2056
2100
uint8_t start_method_params [12 ] = {};
2057
- unsigned log_addr_offset , tpm2_start ;
2101
+ unsigned log_addr_offset ;
2058
2102
uint64_t control_area_start_address ;
2059
2103
TPMIf * tpmif = tpm_find ();
2060
2104
uint32_t start_method ;
2105
+ AcpiTable table = { .sig = "TPM2" , .rev = 4 ,
2106
+ .oem_id = oem_id , .oem_table_id = oem_table_id };
2061
2107
2062
- tpm2_start = table_data -> len ;
2063
- acpi_data_push (table_data , sizeof (AcpiTableHeader ));
2108
+ acpi_table_begin (& table , table_data );
2064
2109
2065
2110
/* Platform Class */
2066
2111
build_append_int_noprefix (table_data , TPM2_ACPI_CLASS_CLIENT , 2 );
@@ -2098,9 +2143,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
2098
2143
bios_linker_loader_add_pointer (linker , ACPI_BUILD_TABLE_FILE ,
2099
2144
log_addr_offset , 8 ,
2100
2145
ACPI_BUILD_TPMLOG_FILE , 0 );
2101
- build_header (linker , table_data ,
2102
- (void * )(table_data -> data + tpm2_start ),
2103
- "TPM2" , table_data -> len - tpm2_start , 4 , oem_id , oem_table_id );
2146
+ acpi_table_end (linker , & table );
2104
2147
}
2105
2148
#endif
2106
2149
0 commit comments