xref: /aosp_15_r20/external/executorch/backends/vulkan/runtime/VulkanDelegateHeader.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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