# Copyright (C) 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("@gbl_llvm_prebuilts//:info.bzl", "LLVM_PREBUILTS_C_INCLUDE") load("@rules_rust//bindgen:defs.bzl", "rust_bindgen") load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") package( default_visibility = ["//visibility:public"], ) # Newer version of `rust_bindgen` requires a `cc_library` target that actually produces a static # library and instead of only headers. Thus we generate a placeholder source file to meet the # requirement. genrule( name = "bindgen_noop_cc", outs = ["bindgen_noop_cc.cc"], cmd = "touch $(OUTS)", ) cc_library( name = "efi_c_headers", srcs = [":bindgen_noop_cc"], hdrs = [ "defs/boot_service.h", "defs/efi.h", "defs/protocols/android_boot_protocol.h", "defs/protocols/block_io_protocol.h", "defs/protocols/device_path_protocol.h", "defs/protocols/loaded_image_protocol.h", "defs/protocols/riscv_efi_boot_protocol.h", "defs/protocols/simple_network_protocol.h", "defs/protocols/simple_text_input_protocol.h", "defs/protocols/simple_text_output_protocol.h", "defs/runtime_service.h", "defs/system_table.h", "defs/types.h", ], includes = ["defs"], ) # Side note: function pointers for UEFI interfaces need to specify the "efiapi" ABI. i.e. # "unsafe extern "efiapi" fn(...)". bindgen uses "extern "C"" by default. We are currently fine # because for x86_64/x86_32/aarch64, we use dedicated rust UEFI compiler which uses EFIAPI ABI by # default. For riscv64 which we use ELF compiler, the efiapi calling convention is the same as C # calling convention according to the UEFI spec at the time of writing. If we do eventually run # into problems, we need to use a newer version of bindgen 0.65.0 or above, which offers # "--override-abi" with "efiapi" option. rust_bindgen( name = "efi_defs_bindgen", bindgen_flags = [ "--ctypes-prefix", "core::ffi", "--use-core", "--with-derive-partialeq", "--with-derive-default", "--with-derive-custom-struct=EfiMemoryDescriptor=AsBytes,FromBytes,FromZeroes", "--allowlist-type", "(Efi.*)", "--raw-line", """ #![allow(non_camel_case_types)] #![allow(non_snake_case)] use zerocopy::{AsBytes, FromBytes, FromZeroes};""", ], cc_lib = ":efi_c_headers", # For x86_32, we need to explicitly specify 32bit architecture. clang_flags = select({ "@gbl//toolchain:gbl_rust_uefi_x86_32": ["-m32"], "//conditions:default": ["-m64"], }) + [ "-I{}".format(LLVM_PREBUILTS_C_INCLUDE), "-nostdinc", ], header = "defs/efi.h", ) # Copy the generated source to "src/defs.rs" in the output assembly, so that libefi can include it # as a source. genrule( name = "efi_defs_genrule", srcs = [":efi_defs_bindgen"], outs = ["src/defs.rs"], cmd = "cat $(location :efi_defs_bindgen) > $@", ) rust_library( name = "libefi", srcs = [ "src/allocation.rs", "src/defs.rs", # Generated by :efi_defs_genrule "src/lib.rs", "src/protocol.rs", "src/protocol/android_boot.rs", "src/protocol/block_io.rs", "src/protocol/device_path.rs", "src/protocol/loaded_image.rs", "src/protocol/riscv.rs", "src/protocol/simple_network.rs", "src/protocol/simple_text_input.rs", "src/protocol/simple_text_output.rs", ], crate_name = "efi", data = [":efi_defs_genrule"], deps = ["@zerocopy"], ) rust_test( name = "libefi_test", crate = ":libefi", )