15b69db07SJason Zhu /* 25b69db07SJason Zhu * Copyright (C) 2016 The Android Open Source Project 35b69db07SJason Zhu * 45b69db07SJason Zhu * Permission is hereby granted, free of charge, to any person 55b69db07SJason Zhu * obtaining a copy of this software and associated documentation 65b69db07SJason Zhu * files (the "Software"), to deal in the Software without 75b69db07SJason Zhu * restriction, including without limitation the rights to use, copy, 85b69db07SJason Zhu * modify, merge, publish, distribute, sublicense, and/or sell copies 95b69db07SJason Zhu * of the Software, and to permit persons to whom the Software is 105b69db07SJason Zhu * furnished to do so, subject to the following conditions: 115b69db07SJason Zhu * 125b69db07SJason Zhu * The above copyright notice and this permission notice shall be 135b69db07SJason Zhu * included in all copies or substantial portions of the Software. 145b69db07SJason Zhu * 155b69db07SJason Zhu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 165b69db07SJason Zhu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 175b69db07SJason Zhu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 185b69db07SJason Zhu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 195b69db07SJason Zhu * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 205b69db07SJason Zhu * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 215b69db07SJason Zhu * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 225b69db07SJason Zhu * SOFTWARE. 235b69db07SJason Zhu */ 245b69db07SJason Zhu 255b69db07SJason Zhu /* 265b69db07SJason Zhu #if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION) 275b69db07SJason Zhu #error "Never include this file directly, include libavb.h instead." 285b69db07SJason Zhu #endif 295b69db07SJason Zhu */ 305b69db07SJason Zhu 315b69db07SJason Zhu #ifndef AVB_OPS_H_ 325b69db07SJason Zhu #define AVB_OPS_H_ 335b69db07SJason Zhu 345b69db07SJason Zhu #include <android_avb/avb_sysdeps.h> 355b69db07SJason Zhu 365b69db07SJason Zhu #ifdef __cplusplus 375b69db07SJason Zhu extern "C" { 385b69db07SJason Zhu #endif 395b69db07SJason Zhu 40ab608f80SJason Zhu /* Well-known names of named persistent values. */ 41ab608f80SJason Zhu #define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest." 4269fdc596SJason Zhu #define AVB_NPV_MANAGED_VERITY_MODE "avb.managed_verity_mode" 43ab608f80SJason Zhu 445b69db07SJason Zhu /* Return codes used for I/O operations. 455b69db07SJason Zhu * 465b69db07SJason Zhu * AVB_IO_RESULT_OK is returned if the requested operation was 475b69db07SJason Zhu * successful. 485b69db07SJason Zhu * 495b69db07SJason Zhu * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk 505b69db07SJason Zhu * or other subsystem) encountered an I/O error. 515b69db07SJason Zhu * 525b69db07SJason Zhu * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory. 535b69db07SJason Zhu * 545b69db07SJason Zhu * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested 555b69db07SJason Zhu * partition does not exist. 565b69db07SJason Zhu * 575b69db07SJason Zhu * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the 585b69db07SJason Zhu * range of bytes requested to be read or written is outside the range 595b69db07SJason Zhu * of the partition. 60ab608f80SJason Zhu * 61ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value 62ab608f80SJason Zhu * does not exist. 63ab608f80SJason Zhu * 64ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent 65ab608f80SJason Zhu * value size is not supported or does not match the expected size. 66ab608f80SJason Zhu * 67ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small 68ab608f80SJason Zhu * for the requested operation. 695b69db07SJason Zhu */ 705b69db07SJason Zhu typedef enum { 715b69db07SJason Zhu AVB_IO_RESULT_OK, 725b69db07SJason Zhu AVB_IO_RESULT_ERROR_OOM, 735b69db07SJason Zhu AVB_IO_RESULT_ERROR_IO, 745b69db07SJason Zhu AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, 75ab608f80SJason Zhu AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION, 76ab608f80SJason Zhu AVB_IO_RESULT_ERROR_NO_SUCH_VALUE, 77ab608f80SJason Zhu AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE, 78ab608f80SJason Zhu AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, 795b69db07SJason Zhu } AvbIOResult; 805b69db07SJason Zhu 815b69db07SJason Zhu struct AvbOps; 825b69db07SJason Zhu typedef struct AvbOps AvbOps; 835b69db07SJason Zhu 845b69db07SJason Zhu /* Forward-declaration of operations in libavb_ab. */ 855b69db07SJason Zhu struct AvbABOps; 865b69db07SJason Zhu 875b69db07SJason Zhu /* Forward-declaration of operations in libavb_atx. */ 885b69db07SJason Zhu struct AvbAtxOps; 895b69db07SJason Zhu 905b69db07SJason Zhu /* High-level operations/functions/methods that are platform 915b69db07SJason Zhu * dependent. 925b69db07SJason Zhu * 935b69db07SJason Zhu * Operations may be added in the future so when implementing it 945b69db07SJason Zhu * always make sure to zero out sizeof(AvbOps) bytes of the struct to 955b69db07SJason Zhu * ensure that unimplemented operations are set to NULL. 965b69db07SJason Zhu */ 975b69db07SJason Zhu struct AvbOps { 985b69db07SJason Zhu /* This pointer can be used by the application/bootloader using 995b69db07SJason Zhu * libavb and is typically used in each operation to get a pointer 1005b69db07SJason Zhu * to platform-specific resources. It cannot be used by libraries. 1015b69db07SJason Zhu */ 1025b69db07SJason Zhu void* user_data; 1035b69db07SJason Zhu 1045b69db07SJason Zhu /* If libavb_ab is used, this should point to the 1055b69db07SJason Zhu * AvbABOps. Otherwise it must be set to NULL. 1065b69db07SJason Zhu */ 1075b69db07SJason Zhu struct AvbABOps* ab_ops; 1085b69db07SJason Zhu 1095b69db07SJason Zhu /* If libavb_atx is used, this should point to the 1105b69db07SJason Zhu * AvbAtxOps. Otherwise it must be set to NULL. 1115b69db07SJason Zhu */ 1125b69db07SJason Zhu struct AvbAtxOps* atx_ops; 1135b69db07SJason Zhu 1145b69db07SJason Zhu /* Reads |num_bytes| from offset |offset| from partition with name 1155b69db07SJason Zhu * |partition| (NUL-terminated UTF-8 string). If |offset| is 1165b69db07SJason Zhu * negative, its absolute value should be interpreted as the number 1175b69db07SJason Zhu * of bytes from the end of the partition. 1185b69db07SJason Zhu * 1195b69db07SJason Zhu * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if 1205b69db07SJason Zhu * there is no partition with the given name, 1215b69db07SJason Zhu * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested 1225b69db07SJason Zhu * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if 1235b69db07SJason Zhu * there was an I/O error from the underlying I/O subsystem. If the 1245b69db07SJason Zhu * operation succeeds as requested AVB_IO_RESULT_OK is returned and 1255b69db07SJason Zhu * the data is available in |buffer|. 1265b69db07SJason Zhu * 1275b69db07SJason Zhu * The only time partial I/O may occur is if reading beyond the end 1285b69db07SJason Zhu * of the partition. In this case the value returned in 1295b69db07SJason Zhu * |out_num_read| may be smaller than |num_bytes|. 1305b69db07SJason Zhu */ 1315b69db07SJason Zhu AvbIOResult (*read_from_partition)(AvbOps* ops, 1325b69db07SJason Zhu const char* partition, 1335b69db07SJason Zhu int64_t offset, 1345b69db07SJason Zhu size_t num_bytes, 1355b69db07SJason Zhu void* buffer, 1365b69db07SJason Zhu size_t* out_num_read); 1375b69db07SJason Zhu 13837a7bc39SJason Zhu /* Gets the starting pointer of a partition that is pre-loaded in memory, and 13937a7bc39SJason Zhu * save it to |out_pointer|. The preloaded partition is expected to be 14037a7bc39SJason Zhu * |num_bytes|, where the actual preloaded byte count is returned in 14137a7bc39SJason Zhu * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than 14237a7bc39SJason Zhu * |num_bytes|. 14337a7bc39SJason Zhu * 14437a7bc39SJason Zhu * This provides an alternative way to access a partition that is preloaded 14537a7bc39SJason Zhu * into memory without a full memory copy. When this function pointer is not 14637a7bc39SJason Zhu * set (has value NULL), or when the |out_pointer| is set to NULL as a result, 14737a7bc39SJason Zhu * |read_from_partition| will be used as the fallback. This function is mainly 14837a7bc39SJason Zhu * used for accessing the entire partition content to calculate its hash. 14937a7bc39SJason Zhu * 15037a7bc39SJason Zhu * Preloaded partition data must outlive the lifespan of the 15137a7bc39SJason Zhu * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs. 15237a7bc39SJason Zhu */ 15337a7bc39SJason Zhu AvbIOResult (*get_preloaded_partition)(AvbOps* ops, 15437a7bc39SJason Zhu const char* partition, 15537a7bc39SJason Zhu size_t num_bytes, 15637a7bc39SJason Zhu uint8_t** out_pointer, 157*27e62cd7SJoseph Chen size_t* out_num_bytes_preloaded, 158*27e62cd7SJoseph Chen int allow_verification_error); 15937a7bc39SJason Zhu 1605b69db07SJason Zhu /* Writes |num_bytes| from |bffer| at offset |offset| to partition 1615b69db07SJason Zhu * with name |partition| (NUL-terminated UTF-8 string). If |offset| 1625b69db07SJason Zhu * is negative, its absolute value should be interpreted as the 1635b69db07SJason Zhu * number of bytes from the end of the partition. 1645b69db07SJason Zhu * 1655b69db07SJason Zhu * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if 1665b69db07SJason Zhu * there is no partition with the given name, 1675b69db07SJason Zhu * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested 1685b69db07SJason Zhu * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO 1695b69db07SJason Zhu * if there was an I/O error from the underlying I/O subsystem. If 1705b69db07SJason Zhu * the operation succeeds as requested AVB_IO_RESULT_OK is 1715b69db07SJason Zhu * returned. 1725b69db07SJason Zhu * 1735b69db07SJason Zhu * This function never does any partial I/O, it either transfers all 1745b69db07SJason Zhu * of the requested bytes or returns an error. 1755b69db07SJason Zhu */ 1765b69db07SJason Zhu AvbIOResult (*write_to_partition)(AvbOps* ops, 1775b69db07SJason Zhu const char* partition, 1785b69db07SJason Zhu int64_t offset, 1795b69db07SJason Zhu size_t num_bytes, 1805b69db07SJason Zhu const void* buffer); 1815b69db07SJason Zhu 1825b69db07SJason Zhu /* Checks if the given public key used to sign the 'vbmeta' 1835b69db07SJason Zhu * partition is trusted. Boot loaders typically compare this with 1845b69db07SJason Zhu * embedded key material generated with 'avbtool 1855b69db07SJason Zhu * extract_public_key'. 1865b69db07SJason Zhu * 1875b69db07SJason Zhu * The public key is in the array pointed to by |public_key_data| 1885b69db07SJason Zhu * and is of |public_key_length| bytes. 1895b69db07SJason Zhu * 1905b69db07SJason Zhu * If there is no public key metadata (set with the avbtool option 1915b69db07SJason Zhu * --public_key_metadata) then |public_key_metadata| will be set to 1925b69db07SJason Zhu * NULL. Otherwise this field points to the data which is 1935b69db07SJason Zhu * |public_key_metadata_length| bytes long. 1945b69db07SJason Zhu * 1955b69db07SJason Zhu * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - 1965b69db07SJason Zhu * true if trusted or false if untrusted. 19769fdc596SJason Zhu * 19869fdc596SJason Zhu * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to 19969fdc596SJason Zhu * avb_slot_verify() then this operation is never used. Instead, the 20069fdc596SJason Zhu * validate_public_key_for_partition() operation is used 2015b69db07SJason Zhu */ 2025b69db07SJason Zhu AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops, 2035b69db07SJason Zhu const uint8_t* public_key_data, 2045b69db07SJason Zhu size_t public_key_length, 2055b69db07SJason Zhu const uint8_t* public_key_metadata, 2065b69db07SJason Zhu size_t public_key_metadata_length, 2075b69db07SJason Zhu bool* out_is_trusted); 2085b69db07SJason Zhu 2095b69db07SJason Zhu /* Gets the rollback index corresponding to the location given by 2105b69db07SJason Zhu * |rollback_index_location|. The value is returned in 2115b69db07SJason Zhu * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback 2125b69db07SJason Zhu * index was retrieved, otherwise an error code. 2135b69db07SJason Zhu * 2145b69db07SJason Zhu * A device may have a limited amount of rollback index locations (say, 2155b69db07SJason Zhu * one or four) so may error out if |rollback_index_location| exceeds 2165b69db07SJason Zhu * this number. 2175b69db07SJason Zhu */ 2185b69db07SJason Zhu AvbIOResult (*read_rollback_index)(AvbOps* ops, 2195b69db07SJason Zhu size_t rollback_index_location, 2205b69db07SJason Zhu uint64_t* out_rollback_index); 2215b69db07SJason Zhu 2225b69db07SJason Zhu /* Sets the rollback index corresponding to the location given by 2235b69db07SJason Zhu * |rollback_index_location| to |rollback_index|. Returns 2245b69db07SJason Zhu * AVB_IO_RESULT_OK if the rollback index was set, otherwise an 2255b69db07SJason Zhu * error code. 2265b69db07SJason Zhu * 2275b69db07SJason Zhu * A device may have a limited amount of rollback index locations (say, 2285b69db07SJason Zhu * one or four) so may error out if |rollback_index_location| exceeds 2295b69db07SJason Zhu * this number. 2305b69db07SJason Zhu */ 2315b69db07SJason Zhu AvbIOResult (*write_rollback_index)(AvbOps* ops, 2325b69db07SJason Zhu size_t rollback_index_location, 2335b69db07SJason Zhu uint64_t rollback_index); 2345b69db07SJason Zhu 2355b69db07SJason Zhu /* Gets whether the device is unlocked. The value is returned in 2365b69db07SJason Zhu * |out_is_unlocked| (true if unlocked, false otherwise). Returns 2375b69db07SJason Zhu * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error 2385b69db07SJason Zhu * code. 2395b69db07SJason Zhu */ 2405b69db07SJason Zhu AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked); 2415b69db07SJason Zhu 24237a7bc39SJason Zhu /* write the device lock flag. Returns 24337a7bc39SJason Zhu * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error 24437a7bc39SJason Zhu * code. 24537a7bc39SJason Zhu */ 24637a7bc39SJason Zhu AvbIOResult (*write_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked); 24769fdc596SJason Zhu 2485b69db07SJason Zhu /* Gets the unique partition GUID for a partition with name in 2495b69db07SJason Zhu * |partition| (NUL-terminated UTF-8 string). The GUID is copied as 2505b69db07SJason Zhu * a string into |guid_buf| of size |guid_buf_size| and will be NUL 2515b69db07SJason Zhu * terminated. The string must be lower-case and properly 2525b69db07SJason Zhu * hyphenated. For example: 2535b69db07SJason Zhu * 2545b69db07SJason Zhu * 527c1c6d-6361-4593-8842-3c78fcd39219 2555b69db07SJason Zhu * 2565b69db07SJason Zhu * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 2575b69db07SJason Zhu */ 2585b69db07SJason Zhu AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops, 2595b69db07SJason Zhu const char* partition, 2605b69db07SJason Zhu char* guid_buf, 2615b69db07SJason Zhu size_t guid_buf_size); 2625b69db07SJason Zhu 2635b69db07SJason Zhu /* Gets the size of a partition with the name in |partition| 2645b69db07SJason Zhu * (NUL-terminated UTF-8 string). Returns the value in 2655b69db07SJason Zhu * |out_size_num_bytes|. 2665b69db07SJason Zhu * 26769fdc596SJason Zhu * If the partition doesn't exist the AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION 26869fdc596SJason Zhu * error code should be returned. 26969fdc596SJason Zhu * 2705b69db07SJason Zhu * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 2715b69db07SJason Zhu */ 2725b69db07SJason Zhu AvbIOResult (*get_size_of_partition)(AvbOps* ops, 2735b69db07SJason Zhu const char* partition, 2745b69db07SJason Zhu uint64_t* out_size_num_bytes); 275ab608f80SJason Zhu 276ab608f80SJason Zhu /* Reads a persistent value corresponding to the given |name|. The value is 277ab608f80SJason Zhu * returned in |out_buffer| which must point to |buffer_size| bytes. On 278ab608f80SJason Zhu * success |out_num_bytes_read| contains the number of bytes read into 279ab608f80SJason Zhu * |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned, 280ab608f80SJason Zhu * |out_num_bytes_read| contains the number of bytes that would have been read 281ab608f80SJason Zhu * which can be used to allocate a buffer. 282ab608f80SJason Zhu * 283ab608f80SJason Zhu * The |buffer_size| may be zero and the |out_buffer| may be NULL, but if 284ab608f80SJason Zhu * |out_buffer| is NULL then |buffer_size| *must* be zero. 285ab608f80SJason Zhu * 286ab608f80SJason Zhu * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 287ab608f80SJason Zhu * 288ab608f80SJason Zhu * If the value does not exist, is not supported, or is not populated, returns 289ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the 290ab608f80SJason Zhu * size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE. 291ab608f80SJason Zhu * 29269fdc596SJason Zhu * This operation is currently only used to support persistent digests or the 29369fdc596SJason Zhu * AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a 29469fdc596SJason Zhu * device does not use one of these features this function pointer can be set 29569fdc596SJason Zhu * to NULL. 296ab608f80SJason Zhu */ 297ab608f80SJason Zhu AvbIOResult (*read_persistent_value)(AvbOps* ops, 298ab608f80SJason Zhu const char* name, 299ab608f80SJason Zhu size_t buffer_size, 300ab608f80SJason Zhu uint8_t* out_buffer, 301ab608f80SJason Zhu size_t* out_num_bytes_read); 302ab608f80SJason Zhu 303ab608f80SJason Zhu /* Writes a persistent value corresponding to the given |name|. The value is 304ab608f80SJason Zhu * supplied in |value| which must point to |value_size| bytes. Any existing 305ab608f80SJason Zhu * value with the same name is overwritten. If |value_size| is zero, future 306ab608f80SJason Zhu * calls to |read_persistent_value| will return 307ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. 308ab608f80SJason Zhu * 309ab608f80SJason Zhu * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 310ab608f80SJason Zhu * 311ab608f80SJason Zhu * If the value |name| is not supported, returns 312ab608f80SJason Zhu * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported, 313ab608f80SJason Zhu * returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE. 314ab608f80SJason Zhu * 31569fdc596SJason Zhu * This operation is currently only used to support persistent digests or the 31669fdc596SJason Zhu * AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO hashtree error mode. If a 31769fdc596SJason Zhu * device does not use one of these features this function pointer can be set 31869fdc596SJason Zhu * to NULL. 319ab608f80SJason Zhu */ 320ab608f80SJason Zhu AvbIOResult (*write_persistent_value)(AvbOps* ops, 321ab608f80SJason Zhu const char* name, 322ab608f80SJason Zhu size_t value_size, 323ab608f80SJason Zhu const uint8_t* value); 32469fdc596SJason Zhu 32569fdc596SJason Zhu /* Like validate_vbmeta_public_key() but for when the flag 32669fdc596SJason Zhu * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the 32769fdc596SJason Zhu * partition to get the public key for is passed in |partition_name|. 32869fdc596SJason Zhu * 32969fdc596SJason Zhu * Also returns the rollback index location to use for the partition, in 33069fdc596SJason Zhu * |out_rollback_index_location|. 33169fdc596SJason Zhu * 33269fdc596SJason Zhu * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 33369fdc596SJason Zhu */ 33469fdc596SJason Zhu AvbIOResult (*validate_public_key_for_partition)( 33569fdc596SJason Zhu AvbOps* ops, 33669fdc596SJason Zhu const char* partition, 33769fdc596SJason Zhu const uint8_t* public_key_data, 33869fdc596SJason Zhu size_t public_key_length, 33969fdc596SJason Zhu const uint8_t* public_key_metadata, 34069fdc596SJason Zhu size_t public_key_metadata_length, 34169fdc596SJason Zhu bool* out_is_trusted, 34269fdc596SJason Zhu uint32_t* out_rollback_index_location); 3435b69db07SJason Zhu }; 3445b69db07SJason Zhu 3455b69db07SJason Zhu #ifdef __cplusplus 3465b69db07SJason Zhu } 3475b69db07SJason Zhu #endif 3485b69db07SJason Zhu 3495b69db07SJason Zhu #endif /* AVB_OPS_H_ */ 350