|  | // Copyright 2020 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef SRC_STORAGE_FSHOST_PKGFS_LOADER_SERVICE_H_ | 
|  | #define SRC_STORAGE_FSHOST_PKGFS_LOADER_SERVICE_H_ | 
|  |  | 
|  | #include <lib/async-loop/cpp/loop.h> | 
|  | #include <lib/async/dispatcher.h> | 
|  | #include <lib/zx/status.h> | 
|  | #include <lib/zx/vmo.h> | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include <fbl/unique_fd.h> | 
|  |  | 
|  | #include "src/lib/loader_service/loader_service.h" | 
|  | #include "src/storage/fshost/fshost-boot-args.h" | 
|  |  | 
|  | namespace fshost { | 
|  |  | 
|  | // We bootstrap pkgfs from blobfs by using a custom loader service. This bootstrap is necessary | 
|  | // because pkgfs itself is what provides "symbolic filename to blobfs merkleroot resolution" for the | 
|  | // rest of the system. | 
|  | // | 
|  | // Kernel command line arguments with the prefix "zircon.system.pkgfs.file." define the | 
|  | // file-to-merkleroot mapping that this loader service uses. For example, when the loader service | 
|  | // receives a LoadObject("foo.so") request, it looks for a kernel command line argument with key | 
|  | // "zircon.system.pkgfs.file.lib/foo.so". If such a key exists, its value is treated as a blobfs | 
|  | // merkleroot and used to load the file from blobfs. | 
|  | class PkgfsLoaderService : public loader::LoaderServiceBase { | 
|  | public: | 
|  | static std::shared_ptr<PkgfsLoaderService> Create(fbl::unique_fd blob_dir, | 
|  | std::shared_ptr<FshostBootArgs> boot_args); | 
|  |  | 
|  | zx::status<zx::vmo> LoadPkgfsFile(std::string path); | 
|  |  | 
|  | private: | 
|  | PkgfsLoaderService(std::unique_ptr<async::Loop> loop, fbl::unique_fd blob_dir, | 
|  | std::shared_ptr<FshostBootArgs> boot_args) | 
|  | : LoaderServiceBase(loop->dispatcher(), "pkgfs"), | 
|  | loop_(std::move(loop)), | 
|  | blob_dir_(std::move(blob_dir)), | 
|  | boot_args_(boot_args) {} | 
|  |  | 
|  | virtual zx::status<zx::vmo> LoadObjectImpl(std::string path) override; | 
|  |  | 
|  | zx::status<zx::vmo> LoadBlob(std::string merkleroot); | 
|  |  | 
|  | // This loader automatically creates and owns its own async::Loop to match historical behavior. If | 
|  | // fshost's threading model is cleaned up then PkgfsLoaderService could be changed to just accept | 
|  | // an async_dispatcher_t* for an existing loop. | 
|  | // Also, this is wrapped in unique_ptr purely because async::Loop has a deleted move constructor. | 
|  | std::unique_ptr<async::Loop> loop_; | 
|  |  | 
|  | // PkgfsLoaderService's lifetime is tied to the pkgfs process because open connections keep the | 
|  | // loader alive (see LoaderServiceBase), so we take care to hold onto only owned state. (weak_ptr | 
|  | // would be fine too, just no raw pointers.) | 
|  | fbl::unique_fd blob_dir_; | 
|  | std::shared_ptr<FshostBootArgs> boot_args_; | 
|  | }; | 
|  |  | 
|  | }  // namespace fshost | 
|  |  | 
|  | #endif  // SRC_STORAGE_FSHOST_PKGFS_LOADER_SERVICE_H_ |