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