1*523fa7a6SAndroid Build Coastguard Worker /*
2*523fa7a6SAndroid Build Coastguard Worker * Copyright (c) Meta Platforms, Inc. and affiliates.
3*523fa7a6SAndroid Build Coastguard Worker * All rights reserved.
4*523fa7a6SAndroid Build Coastguard Worker *
5*523fa7a6SAndroid Build Coastguard Worker * This source code is licensed under the BSD-style license found in the
6*523fa7a6SAndroid Build Coastguard Worker * LICENSE file in the root directory of this source tree.
7*523fa7a6SAndroid Build Coastguard Worker */
8*523fa7a6SAndroid Build Coastguard Worker
9*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/vulkan/runtime/VulkanDelegateHeader.h>
10*523fa7a6SAndroid Build Coastguard Worker
11*523fa7a6SAndroid Build Coastguard Worker #include <cstring>
12*523fa7a6SAndroid Build Coastguard Worker
13*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/error.h>
14*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/result.h>
15*523fa7a6SAndroid Build Coastguard Worker
16*523fa7a6SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated"
17*523fa7a6SAndroid Build Coastguard Worker
18*523fa7a6SAndroid Build Coastguard Worker namespace executorch {
19*523fa7a6SAndroid Build Coastguard Worker namespace backends {
20*523fa7a6SAndroid Build Coastguard Worker namespace vulkan {
21*523fa7a6SAndroid Build Coastguard Worker
22*523fa7a6SAndroid Build Coastguard Worker using executorch::runtime::Error;
23*523fa7a6SAndroid Build Coastguard Worker using executorch::runtime::Result;
24*523fa7a6SAndroid Build Coastguard Worker
25*523fa7a6SAndroid Build Coastguard Worker namespace {
26*523fa7a6SAndroid Build Coastguard Worker
27*523fa7a6SAndroid Build Coastguard Worker struct ByteSlice {
28*523fa7a6SAndroid Build Coastguard Worker size_t offset;
29*523fa7a6SAndroid Build Coastguard Worker size_t size;
30*523fa7a6SAndroid Build Coastguard Worker };
31*523fa7a6SAndroid Build Coastguard Worker
32*523fa7a6SAndroid Build Coastguard Worker constexpr size_t kExpectedSize = 30;
33*523fa7a6SAndroid Build Coastguard Worker constexpr char kExpectedMagic[4] = {'V', 'H', '0', '0'};
34*523fa7a6SAndroid Build Coastguard Worker
35*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kMagic = {4, 4};
36*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kHeaderSize = {8, 2};
37*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kFlatbufferOffset = {10, 4};
38*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kFlatbufferSize = {14, 4};
39*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kBytesOffset = {18, 4};
40*523fa7a6SAndroid Build Coastguard Worker constexpr ByteSlice kBytesSize = {22, 8};
41*523fa7a6SAndroid Build Coastguard Worker
42*523fa7a6SAndroid Build Coastguard Worker } // namespace
43*523fa7a6SAndroid Build Coastguard Worker
44*523fa7a6SAndroid Build Coastguard Worker /// Interprets the 8 bytes at `data` as a little-endian uint64_t.
getUInt64LE(const uint8_t * data)45*523fa7a6SAndroid Build Coastguard Worker uint64_t getUInt64LE(const uint8_t* data) {
46*523fa7a6SAndroid Build Coastguard Worker return (uint64_t)data[0] | ((uint64_t)data[1] << 8) |
47*523fa7a6SAndroid Build Coastguard Worker ((uint64_t)data[2] << 16) | ((uint64_t)data[3] << 24) |
48*523fa7a6SAndroid Build Coastguard Worker ((uint64_t)data[4] << 32) | ((uint64_t)data[5] << 40) |
49*523fa7a6SAndroid Build Coastguard Worker ((uint64_t)data[6] << 48) | ((uint64_t)data[7] << 56);
50*523fa7a6SAndroid Build Coastguard Worker }
51*523fa7a6SAndroid Build Coastguard Worker
52*523fa7a6SAndroid Build Coastguard Worker /// Interprets the 4 bytes at `data` as a little-endian uint32_t.
getUInt32LE(const uint8_t * data)53*523fa7a6SAndroid Build Coastguard Worker uint32_t getUInt32LE(const uint8_t* data) {
54*523fa7a6SAndroid Build Coastguard Worker return (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
55*523fa7a6SAndroid Build Coastguard Worker ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
56*523fa7a6SAndroid Build Coastguard Worker }
57*523fa7a6SAndroid Build Coastguard Worker
58*523fa7a6SAndroid Build Coastguard Worker /// Interprets the 2 bytes at `data` as a little-endian uint32_t.
getUInt16LE(const uint8_t * data)59*523fa7a6SAndroid Build Coastguard Worker uint32_t getUInt16LE(const uint8_t* data) {
60*523fa7a6SAndroid Build Coastguard Worker return (uint32_t)data[0] | ((uint32_t)data[1] << 8);
61*523fa7a6SAndroid Build Coastguard Worker }
62*523fa7a6SAndroid Build Coastguard Worker
is_valid() const63*523fa7a6SAndroid Build Coastguard Worker bool VulkanDelegateHeader::is_valid() const {
64*523fa7a6SAndroid Build Coastguard Worker if (header_size < kExpectedSize) {
65*523fa7a6SAndroid Build Coastguard Worker return false;
66*523fa7a6SAndroid Build Coastguard Worker }
67*523fa7a6SAndroid Build Coastguard Worker if (flatbuffer_offset < header_size) {
68*523fa7a6SAndroid Build Coastguard Worker return false;
69*523fa7a6SAndroid Build Coastguard Worker }
70*523fa7a6SAndroid Build Coastguard Worker if (flatbuffer_size == 0) {
71*523fa7a6SAndroid Build Coastguard Worker return false;
72*523fa7a6SAndroid Build Coastguard Worker }
73*523fa7a6SAndroid Build Coastguard Worker if (bytes_offset < flatbuffer_offset + flatbuffer_size) {
74*523fa7a6SAndroid Build Coastguard Worker return false;
75*523fa7a6SAndroid Build Coastguard Worker }
76*523fa7a6SAndroid Build Coastguard Worker if (bytes_size < 0) {
77*523fa7a6SAndroid Build Coastguard Worker return false;
78*523fa7a6SAndroid Build Coastguard Worker }
79*523fa7a6SAndroid Build Coastguard Worker
80*523fa7a6SAndroid Build Coastguard Worker return true;
81*523fa7a6SAndroid Build Coastguard Worker }
82*523fa7a6SAndroid Build Coastguard Worker
parse(const void * data)83*523fa7a6SAndroid Build Coastguard Worker Result<VulkanDelegateHeader> VulkanDelegateHeader::parse(const void* data) {
84*523fa7a6SAndroid Build Coastguard Worker const uint8_t* header_data = (const uint8_t*)data;
85*523fa7a6SAndroid Build Coastguard Worker
86*523fa7a6SAndroid Build Coastguard Worker const uint8_t* magic_start = header_data + kMagic.offset;
87*523fa7a6SAndroid Build Coastguard Worker if (std::memcmp(magic_start, kExpectedMagic, kMagic.size) != 0) {
88*523fa7a6SAndroid Build Coastguard Worker return Error::NotFound;
89*523fa7a6SAndroid Build Coastguard Worker }
90*523fa7a6SAndroid Build Coastguard Worker
91*523fa7a6SAndroid Build Coastguard Worker VulkanDelegateHeader header = VulkanDelegateHeader{
92*523fa7a6SAndroid Build Coastguard Worker getUInt16LE(header_data + kHeaderSize.offset),
93*523fa7a6SAndroid Build Coastguard Worker getUInt32LE(header_data + kFlatbufferOffset.offset),
94*523fa7a6SAndroid Build Coastguard Worker getUInt32LE(header_data + kFlatbufferSize.offset),
95*523fa7a6SAndroid Build Coastguard Worker getUInt32LE(header_data + kBytesOffset.offset),
96*523fa7a6SAndroid Build Coastguard Worker getUInt64LE(header_data + kBytesSize.offset),
97*523fa7a6SAndroid Build Coastguard Worker };
98*523fa7a6SAndroid Build Coastguard Worker
99*523fa7a6SAndroid Build Coastguard Worker if (!header.is_valid()) {
100*523fa7a6SAndroid Build Coastguard Worker return Error::InvalidArgument;
101*523fa7a6SAndroid Build Coastguard Worker }
102*523fa7a6SAndroid Build Coastguard Worker
103*523fa7a6SAndroid Build Coastguard Worker return header;
104*523fa7a6SAndroid Build Coastguard Worker }
105*523fa7a6SAndroid Build Coastguard Worker
106*523fa7a6SAndroid Build Coastguard Worker } // namespace vulkan
107*523fa7a6SAndroid Build Coastguard Worker } // namespace backends
108*523fa7a6SAndroid Build Coastguard Worker } // namespace executorch
109