1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 
10 #include "shared/source/utilities/arrayref.h"
11 #include "shared/source/utilities/const_stringref.h"
12 
13 #include <cstddef>
14 #include <cstdint>
15 #include <igfxfmid.h>
16 #include <memory>
17 #include <vector>
18 
19 namespace NEO {
20 struct ProgramInfo;
21 
22 enum class DeviceBinaryFormat : uint8_t {
23     Unknown,
24     OclElf,
25     OclLibrary,
26     OclCompiledObject,
27     Patchtokens,
28     Archive,
29     Zebin
30 };
31 
32 enum class DecodeError : uint8_t {
33     Success,
34     Undefined,
35     InvalidBinary,
36     UnhandledBinary
37 };
38 
asString(DecodeError err)39 inline const char *asString(DecodeError err) {
40     switch (err) {
41     default:
42         return "with invalid binary";
43         break;
44     case DecodeError::UnhandledBinary:
45         return "with unhandled binary";
46         break;
47     case DecodeError::Success:
48         return "decoded successfully";
49         break;
50     case DecodeError::Undefined:
51         return "in undefined status";
52         break;
53     }
54 }
55 
56 struct TargetDevice {
57     GFXCORE_FAMILY coreFamily = IGFX_UNKNOWN_CORE;
58     PRODUCT_FAMILY productFamily = IGFX_UNKNOWN;
59     uint32_t stepping = 0U;
60     uint32_t maxPointerSizeInBytes = 4U;
61     uint32_t grfSize = 32U;
62 };
63 
64 struct SingleDeviceBinary {
65     DeviceBinaryFormat format = DeviceBinaryFormat::Unknown;
66     ArrayRef<const uint8_t> deviceBinary;
67     ArrayRef<const uint8_t> debugData;
68     ArrayRef<const uint8_t> intermediateRepresentation;
69     ConstStringRef buildOptions;
70     TargetDevice targetDevice;
71 };
72 
73 template <DeviceBinaryFormat Format>
74 bool isDeviceBinaryFormat(const ArrayRef<const uint8_t> binary);
75 
76 template <>
77 bool isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>);
78 template <>
79 bool isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>);
80 template <>
81 bool isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>);
82 template <>
83 bool isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(const ArrayRef<const uint8_t>);
84 
isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)85 inline bool isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
86     if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
87         return true;
88     }
89     if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(binary)) {
90         return true;
91     }
92     if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
93         return true;
94     }
95     if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary)) {
96         return true;
97     }
98     return false;
99 }
100 
101 template <DeviceBinaryFormat Format>
102 SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
103                                             std::string &outErrReason, std::string &outWarning);
104 
105 template <>
106 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
107 template <>
108 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
109 template <>
110 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
111 template <>
112 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Zebin>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
113 
unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive,const ConstStringRef requestedProductAbbreviation,const TargetDevice & requestedTargetDevice,std::string & outErrReason,std::string & outWarning)114 inline SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
115                                                    std::string &outErrReason, std::string &outWarning) {
116     SingleDeviceBinary ret = {};
117     ret.format = DeviceBinaryFormat::Unknown;
118     if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(archive)) {
119         return unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
120     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(archive)) {
121         return unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
122     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(archive)) {
123         return unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
124     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(archive)) {
125         return unpackSingleDeviceBinary<DeviceBinaryFormat::Zebin>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
126     } else {
127         outErrReason = "Unknown format";
128     }
129     return ret;
130 }
131 
132 template <DeviceBinaryFormat Format>
133 std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
134 
135 template <>
136 std::vector<uint8_t> packDeviceBinary<DeviceBinaryFormat::OclElf>(const SingleDeviceBinary, std::string &, std::string &);
137 
138 std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
139 
isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)140 inline bool isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
141     if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
142         return true;
143     }
144     if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
145         return true;
146     }
147     if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary)) {
148         return true;
149     }
150     return false;
151 }
152 
isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)153 inline bool isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
154     return ((false == isAnyPackedDeviceBinaryFormat(binary)) && isAnyDeviceBinaryFormat(binary)) || isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary);
155 }
156 
157 template <DeviceBinaryFormat Format>
158 DecodeError decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning);
159 
160 template <>
161 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
162 template <>
163 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
164 template <>
165 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
166 template <>
167 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Zebin>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
168 
decodeSingleDeviceBinary(ProgramInfo & dst,const SingleDeviceBinary & src,std::string & outErrReason,std::string & outWarning)169 inline std::pair<DecodeError, DeviceBinaryFormat> decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
170     std::pair<DecodeError, DeviceBinaryFormat> ret;
171     ret.first = DecodeError::InvalidBinary;
172     ret.second = DeviceBinaryFormat::Unknown;
173     if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(src.deviceBinary)) {
174         ret.second = DeviceBinaryFormat::OclElf;
175         ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(dst, src, outErrReason, outWarning);
176     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(src.deviceBinary)) {
177         ret.second = DeviceBinaryFormat::Patchtokens;
178         ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(dst, src, outErrReason, outWarning);
179     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(src.deviceBinary)) {
180         ret.second = DeviceBinaryFormat::Archive;
181         ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(dst, src, outErrReason, outWarning);
182     } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(src.deviceBinary)) {
183         ret.second = DeviceBinaryFormat::Zebin;
184         ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Zebin>(dst, src, outErrReason, outWarning);
185     } else {
186         outErrReason = "Unknown format";
187     }
188     return ret;
189 }
190 
191 } // namespace NEO
192