|
Packit |
534379 |
// Copyright(c) 2018-2020, Intel Corporation
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// Redistribution and use in source and binary forms, with or without
|
|
Packit |
534379 |
// modification, are permitted provided that the following conditions are met:
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer.
|
|
Packit |
534379 |
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
534379 |
// this list of conditions and the following disclaimer in the documentation
|
|
Packit |
534379 |
// and/or other materials provided with the distribution.
|
|
Packit |
534379 |
// * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
534379 |
// may be used to endorse or promote products derived from this software
|
|
Packit |
534379 |
// without specific prior written permission.
|
|
Packit |
534379 |
//
|
|
Packit |
534379 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
534379 |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
534379 |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
534379 |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
534379 |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
534379 |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
534379 |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
534379 |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
534379 |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
534379 |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
534379 |
// POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
534379 |
#include <config.h>
|
|
Packit |
534379 |
#endif // HAVE_CONFIG_H
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <stdio.h>
|
|
Packit |
534379 |
#include <errno.h>
|
|
Packit |
534379 |
#include <sys/types.h>
|
|
Packit |
534379 |
#include <sys/stat.h>
|
|
Packit |
534379 |
#include <unistd.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <uuid/uuid.h>
|
|
Packit |
534379 |
#include <json-c/json.h>
|
|
Packit |
534379 |
#include "bitstream.h"
|
|
Packit |
534379 |
#include "bits_utils.h"
|
|
Packit |
534379 |
#include "metadatav1.h"
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include <opae/log.h>
|
|
Packit |
534379 |
#include <opae/properties.h>
|
|
Packit |
534379 |
#include <opae/sysobject.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_result opae_bitstream_read_file(const char *file,
|
|
Packit |
534379 |
uint8_t **buf,
|
|
Packit |
534379 |
size_t *len)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
FILE *fp;
|
|
Packit |
534379 |
fpga_result res = FPGA_EXCEPTION;
|
|
Packit |
534379 |
long pos;
|
|
Packit |
534379 |
size_t sz;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fp = fopen(file, "rb");
|
|
Packit |
534379 |
if (!fp) {
|
|
Packit |
534379 |
OPAE_ERR("fopen failed");
|
|
Packit |
534379 |
return FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (fseek(fp, 0, SEEK_END) < 0) {
|
|
Packit |
534379 |
OPAE_ERR("fseek failed");
|
|
Packit |
534379 |
goto out_close;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
pos = ftell(fp);
|
|
Packit |
534379 |
if (pos < 0) {
|
|
Packit |
534379 |
OPAE_ERR("ftell failed");
|
|
Packit |
534379 |
goto out_close;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
*len = (size_t)pos;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
*buf = (uint8_t *)malloc(*len);
|
|
Packit |
534379 |
if (!*buf) {
|
|
Packit |
534379 |
OPAE_ERR("malloc failed");
|
|
Packit |
534379 |
res = FPGA_NO_MEMORY;
|
|
Packit |
534379 |
*len = 0;
|
|
Packit |
534379 |
goto out_close;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (fseek(fp, 0, SEEK_SET) < 0) {
|
|
Packit |
534379 |
OPAE_ERR("fseek failed");
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
sz = fread(*buf, 1, *len, fp);
|
|
Packit |
534379 |
if (ferror(fp)) {
|
|
Packit |
534379 |
OPAE_ERR("ferror after read");
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (sz != *len) {
|
|
Packit |
534379 |
OPAE_ERR("file size and number "
|
|
Packit |
534379 |
"of bytes read mismatch");
|
|
Packit |
534379 |
goto out_free;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fclose(fp);
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_free:
|
|
Packit |
534379 |
free(*buf);
|
|
Packit |
534379 |
*buf = NULL;
|
|
Packit |
534379 |
*len = 0;
|
|
Packit |
534379 |
out_close:
|
|
Packit |
534379 |
fclose(fp);
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
bool opae_is_legacy_bitstream(opae_bitstream_info *info)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
opae_legacy_bitstream_header *hdr;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (info->data_len < sizeof(opae_legacy_bitstream_header))
|
|
Packit |
534379 |
return false;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
hdr = (opae_legacy_bitstream_header *)info->data;
|
|
Packit |
534379 |
if (hdr->legacy_magic == OPAE_LEGACY_BITSTREAM_MAGIC)
|
|
Packit |
534379 |
return true;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return false;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC void opae_resolve_legacy_bitstream(opae_bitstream_info *info)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
opae_legacy_bitstream_header *hdr =
|
|
Packit |
534379 |
(opae_legacy_bitstream_header *)info->data;
|
|
Packit |
534379 |
uint8_t *p = &hdr->legacy_pr_ifc_id[15];
|
|
Packit |
534379 |
int i = 0;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// The guid is encoded backwards.
|
|
Packit |
534379 |
// Reverse it.
|
|
Packit |
534379 |
while (p >= hdr->legacy_pr_ifc_id) {
|
|
Packit |
534379 |
info->pr_interface_id[i++] = *p--;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
info->rbf_data = info->data + sizeof(opae_legacy_bitstream_header);
|
|
Packit |
534379 |
info->rbf_len = info->data_len - sizeof(opae_legacy_bitstream_header);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC void *opae_bitstream_parse_metadata(const char *metadata,
|
|
Packit |
534379 |
fpga_guid pr_interface_id,
|
|
Packit |
534379 |
int *version)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
json_object *root = NULL;
|
|
Packit |
534379 |
json_object *j_version = NULL;
|
|
Packit |
534379 |
enum json_tokener_error j_err = json_tokener_success;
|
|
Packit |
534379 |
void *parsed = NULL;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
root = json_tokener_parse_verbose(metadata, &j_err);
|
|
Packit |
534379 |
if (!root) {
|
|
Packit |
534379 |
OPAE_ERR("invalid JSON metadata: %s",
|
|
Packit |
534379 |
json_tokener_error_desc(j_err));
|
|
Packit |
534379 |
return NULL;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (!json_object_object_get_ex(root,
|
|
Packit |
534379 |
"version",
|
|
Packit |
534379 |
&j_version)) {
|
|
Packit |
534379 |
OPAE_ERR("metadata: failed to find \"version\" key");
|
|
Packit |
534379 |
goto out_put;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (!json_object_is_type(j_version, json_type_int)) {
|
|
Packit |
534379 |
OPAE_ERR("metadata: \"version\" key not integer");
|
|
Packit |
534379 |
goto out_put;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
*version = json_object_get_int(j_version);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (*version) {
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// Some invalid GBS's around the BBS 6.4.0 and
|
|
Packit |
534379 |
// BBS 6.5.0 eras incorrectly set the metadata
|
|
Packit |
534379 |
// version to 640/650 respectively.
|
|
Packit |
534379 |
// Allow 640/650 to serve as an alias for 1.
|
|
Packit |
534379 |
case 650:
|
|
Packit |
534379 |
case 640:
|
|
Packit |
534379 |
*version = 1; /* FALLTHROUGH */
|
|
Packit |
534379 |
case 1:
|
|
Packit |
534379 |
parsed = opae_bitstream_parse_metadata_v1(root,
|
|
Packit |
534379 |
pr_interface_id);
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
default:
|
|
Packit |
534379 |
OPAE_ERR("metadata: unsupported version: %d", *version);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
out_put:
|
|
Packit |
534379 |
json_object_put(root);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return parsed;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
STATIC fpga_guid valid_GBS_guid = {
|
|
Packit |
534379 |
0x58, 0x65, 0x6f, 0x6e,
|
|
Packit |
534379 |
0x46, 0x50,
|
|
Packit |
534379 |
0x47, 0x41,
|
|
Packit |
534379 |
0xb7, 0x47,
|
|
Packit |
534379 |
0x42, 0x53, 0x76, 0x30, 0x30, 0x31
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
STATIC fpga_result opae_resolve_bitstream(opae_bitstream_info *info)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
opae_bitstream_header *hdr;
|
|
Packit |
534379 |
size_t sz;
|
|
Packit |
534379 |
char *buf;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (info->data_len < sizeof(opae_bitstream_header)) {
|
|
Packit |
534379 |
OPAE_ERR("file length smaller than bitstream header: "
|
|
Packit |
534379 |
"\"%s\"", info->filename);
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
hdr = (opae_bitstream_header *)info->data;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (uuid_compare(hdr->valid_gbs_guid, valid_GBS_guid) != 0) {
|
|
Packit |
534379 |
OPAE_ERR("GBS guid is invalid: \"%s\"", info->filename);
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// Check that metadata_length makes sense
|
|
Packit |
534379 |
// given that we know the total file size.
|
|
Packit |
534379 |
|
|
Packit |
534379 |
sz = sizeof(fpga_guid) + sizeof(uint32_t);
|
|
Packit |
534379 |
sz += (size_t)hdr->metadata_length;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (sz > info->data_len) {
|
|
Packit |
534379 |
OPAE_ERR("invalid metadata length in \"%s\"", info->filename);
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
info->rbf_data = info->data + sz;
|
|
Packit |
534379 |
info->rbf_len = info->data_len - sz;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
buf = (char *)malloc(hdr->metadata_length + 1);
|
|
Packit |
534379 |
if (!buf) {
|
|
Packit |
534379 |
OPAE_ERR("malloc failed");
|
|
Packit |
534379 |
return FPGA_NO_MEMORY;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
memcpy(buf, hdr->metadata, hdr->metadata_length);
|
|
Packit |
534379 |
buf[hdr->metadata_length] = '\0';
|
|
Packit |
534379 |
|
|
Packit |
534379 |
info->parsed_metadata =
|
|
Packit |
534379 |
opae_bitstream_parse_metadata(buf,
|
|
Packit |
534379 |
info->pr_interface_id,
|
|
Packit |
534379 |
&info->metadata_version);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
free(buf);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return info->parsed_metadata ? FPGA_OK : FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result opae_load_bitstream(const char *file, opae_bitstream_info *info)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result res;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (!file || !info)
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (!opae_bitstream_path_is_valid(file,
|
|
Packit |
534379 |
OPAE_BITSTREAM_PATH_NO_SYMLINK)) {
|
|
Packit |
534379 |
OPAE_ERR("invalid bitstream path \"%s\"", file);
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
memset(info, 0, sizeof(opae_bitstream_info));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
res = opae_bitstream_read_file(file, &info->data, &info->data_len);
|
|
Packit |
534379 |
if (res != FPGA_OK) {
|
|
Packit |
534379 |
OPAE_ERR("error loading \"%s\"", file);
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
info->filename = file;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (opae_is_legacy_bitstream(info)) {
|
|
Packit |
534379 |
opae_resolve_legacy_bitstream(info);
|
|
Packit |
534379 |
OPAE_MSG("Legacy bitstream (GBS) format detected.");
|
|
Packit |
534379 |
OPAE_MSG("Legacy GBS support is deprecated "
|
|
Packit |
534379 |
"and will be removed in a future release.");
|
|
Packit |
534379 |
return FPGA_OK;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return opae_resolve_bitstream(info);
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
fpga_result opae_unload_bitstream(opae_bitstream_info *info)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
fpga_result res = FPGA_OK;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (!info)
|
|
Packit |
534379 |
return FPGA_INVALID_PARAM;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (info->data)
|
|
Packit |
534379 |
free(info->data);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (info->parsed_metadata) {
|
|
Packit |
534379 |
|
|
Packit |
534379 |
switch (info->metadata_version) {
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case 1:
|
|
Packit |
534379 |
opae_bitstream_release_metadata_v1(
|
|
Packit |
534379 |
(opae_bitstream_metadata_v1 *)info->parsed_metadata);
|
|
Packit |
534379 |
break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
default:
|
|
Packit |
534379 |
OPAE_ERR("metadata: unsupported version: %d",
|
|
Packit |
534379 |
info->metadata_version);
|
|
Packit |
534379 |
res = FPGA_EXCEPTION;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
memset(info, 0, sizeof(opae_bitstream_info));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
return res;
|
|
Packit |
534379 |
}
|