4 * Copyright (C) 2021 Avery Design Systems, Inc.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
11 #include "hw/pci/pci.h"
12 #include "hw/cxl/cxl.h"
13 #include "qapi/error.h"
14 #include "qemu/error-report.h"
16 static void cdat_len_check(CDATSubHeader
*hdr
, Error
**errp
)
19 assert(hdr
->reserved
== 0);
23 assert(hdr
->length
== sizeof(CDATDsmas
));
25 case CDAT_TYPE_DSLBIS
:
26 assert(hdr
->length
== sizeof(CDATDslbis
));
28 case CDAT_TYPE_DSMSCIS
:
29 assert(hdr
->length
== sizeof(CDATDsmscis
));
32 assert(hdr
->length
== sizeof(CDATDsis
));
34 case CDAT_TYPE_DSEMTS
:
35 assert(hdr
->length
== sizeof(CDATDsemts
));
37 case CDAT_TYPE_SSLBIS
:
38 assert(hdr
->length
>= sizeof(CDATSslbisHeader
));
39 assert((hdr
->length
- sizeof(CDATSslbisHeader
)) %
40 sizeof(CDATSslbe
) == 0);
43 error_setg(errp
, "Type %d is reserved", hdr
->type
);
47 static void ct3_build_cdat(CDATObject
*cdat
, Error
**errp
)
49 g_autofree CDATTableHeader
*cdat_header
= NULL
;
50 g_autofree CDATEntry
*cdat_st
= NULL
;
54 /* Use default table if fopen == NULL */
55 assert(cdat
->build_cdat_table
);
57 cdat_header
= g_malloc0(sizeof(*cdat_header
));
59 error_setg(errp
, "Failed to allocate CDAT header");
63 cdat
->built_buf_len
= cdat
->build_cdat_table(&cdat
->built_buf
, cdat
->private);
65 if (!cdat
->built_buf_len
) {
66 /* Build later as not all data available yet */
67 cdat
->to_update
= true;
70 cdat
->to_update
= false;
72 cdat_st
= g_malloc0(sizeof(*cdat_st
) * (cdat
->built_buf_len
+ 1));
74 error_setg(errp
, "Failed to allocate CDAT entry array");
78 /* Entry 0 for CDAT header, starts with Entry 1 */
79 for (ent
= 1; ent
< cdat
->built_buf_len
+ 1; ent
++) {
80 CDATSubHeader
*hdr
= cdat
->built_buf
[ent
- 1];
81 uint8_t *buf
= (uint8_t *)cdat
->built_buf
[ent
- 1];
83 cdat_st
[ent
].base
= hdr
;
84 cdat_st
[ent
].length
= hdr
->length
;
86 cdat_header
->length
+= hdr
->length
;
87 for (i
= 0; i
< hdr
->length
; i
++) {
93 cdat_header
->revision
= CXL_CDAT_REV
;
94 /* For now, no runtime updates */
95 cdat_header
->sequence
= 0;
96 cdat_header
->length
+= sizeof(CDATTableHeader
);
97 sum
+= cdat_header
->revision
+ cdat_header
->sequence
+
99 /* Sum of all bytes including checksum must be 0 */
100 cdat_header
->checksum
= ~sum
+ 1;
102 cdat_st
[0].base
= g_steal_pointer(&cdat_header
);
103 cdat_st
[0].length
= sizeof(*cdat_header
);
104 cdat
->entry_len
= 1 + cdat
->built_buf_len
;
105 cdat
->entry
= g_steal_pointer(&cdat_st
);
108 static void ct3_load_cdat(CDATObject
*cdat
, Error
**errp
)
110 g_autofree CDATEntry
*cdat_st
= NULL
;
111 g_autofree
char *buf
= NULL
;
117 GError
*error
= NULL
;
119 /* Read CDAT file and create its cache */
120 if (!g_file_get_contents(cdat
->filename
, (gchar
**)&buf
,
121 &file_size
, &error
)) {
122 error_setg(errp
, "CDAT: File read failed: %s", error
->message
);
126 if (file_size
< sizeof(CDATTableHeader
)) {
127 error_setg(errp
, "CDAT: File too short");
130 i
= sizeof(CDATTableHeader
);
132 while (i
< file_size
) {
133 hdr
= (CDATSubHeader
*)(buf
+ i
);
134 if (i
+ sizeof(CDATSubHeader
) > file_size
) {
135 error_setg(errp
, "CDAT: Truncated table");
138 cdat_len_check(hdr
, errp
);
141 error_setg(errp
, "CDAT: Truncated table");
146 if (i
!= file_size
) {
147 error_setg(errp
, "CDAT: File length mismatch");
151 cdat_st
= g_new0(CDATEntry
, num_ent
);
153 /* Set CDAT header, Entry = 0 */
154 cdat_st
[0].base
= buf
;
155 cdat_st
[0].length
= sizeof(CDATTableHeader
);
158 while (i
< cdat_st
[0].length
) {
162 /* Read CDAT structures */
163 while (i
< file_size
) {
164 hdr
= (CDATSubHeader
*)(buf
+ i
);
165 cdat_st
[ent
].base
= hdr
;
166 cdat_st
[ent
].length
= hdr
->length
;
168 while (buf
+ i
< (char *)cdat_st
[ent
].base
+ cdat_st
[ent
].length
) {
169 assert(i
< file_size
);
177 warn_report("CDAT: Found checksum mismatch in %s", cdat
->filename
);
179 cdat
->entry_len
= num_ent
;
180 cdat
->entry
= g_steal_pointer(&cdat_st
);
181 cdat
->buf
= g_steal_pointer(&buf
);
184 void cxl_doe_cdat_init(CXLComponentState
*cxl_cstate
, Error
**errp
)
186 CDATObject
*cdat
= &cxl_cstate
->cdat
;
188 if (cdat
->filename
) {
189 ct3_load_cdat(cdat
, errp
);
191 ct3_build_cdat(cdat
, errp
);
195 void cxl_doe_cdat_update(CXLComponentState
*cxl_cstate
, Error
**errp
)
197 CDATObject
*cdat
= &cxl_cstate
->cdat
;
199 if (cdat
->to_update
) {
200 ct3_build_cdat(cdat
, errp
);
204 void cxl_doe_cdat_release(CXLComponentState
*cxl_cstate
)
206 CDATObject
*cdat
= &cxl_cstate
->cdat
;
209 if (cdat
->built_buf
) {
210 cdat
->free_cdat_table(cdat
->built_buf
, cdat
->built_buf_len
,