| // Copyright 2016 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Library to provide access to the Chrome OS master configuration |
| |
| #ifndef CHROMEOS_CONFIG_LIBCROS_CONFIG_CROS_CONFIG_H_ |
| #define CHROMEOS_CONFIG_LIBCROS_CONFIG_CROS_CONFIG_H_ |
| |
| #include "chromeos-config/libcros_config/cros_config_interface.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include <base/files/file.h> |
| #include <base/files/file_path.h> |
| #include <base/macros.h> |
| #include <base/values.h> |
| #include <brillo/brillo_export.h> |
| |
| namespace base { |
| class CommandLine; |
| class FilePath; |
| } // namespace base |
| |
| namespace brillo { |
| |
| struct SmbiosTable; |
| |
| class BRILLO_EXPORT CrosConfig : public CrosConfigInterface { |
| public: |
| CrosConfig(); |
| ~CrosConfig() override; |
| |
| // Prepare the configuration system for for access to the configuration for |
| // the model this is running on. This reads the configuration file into |
| // memory. |
| // @return true if OK, false on error. |
| bool InitModel(); |
| |
| // Alias for the above, since this is used by several clients. |
| bool Init(); |
| |
| // Prepare the configuration system for testing. |
| // This reads in the given configuration file and selects the supplied |
| // model name. |
| // @filepath: Path to configuration .dtb file. |
| // @name: Platform name as returned by 'mosys platform id'. |
| // @sku_id: SKU ID as returned by 'mosys platform sku'. |
| // @customization_id: VPD customization ID from 'mosys platform customization' |
| // @return true if OK, false on error. |
| bool InitForTest(const base::FilePath& filepath, const std::string& name, |
| int sku_id, const std::string& customization_id); |
| |
| // Internal function to obtain a property value and return a list of log |
| // messages on failure. Public for tests. |
| // @path: Path to locate. Must start with "/". |
| // @prop: Property name to look up |
| // @val_out: returns the string value found, if any |
| // @log_msgs_out: returns a list of error messages if this function fails |
| // @return true if found, false if not found |
| bool GetString(const std::string& path, const std::string& prop, |
| std::string* val_out, std::vector<std::string>* log_msgs_out); |
| |
| // CrosConfigInterface: |
| bool GetString(const std::string& path, |
| const std::string& prop, |
| std::string* val_out) override; |
| |
| // CrosConfigInterface: |
| bool GetAbsPath(const std::string& path, const std::string& prop, |
| std::string* val_out) override; |
| |
| private: |
| // Init for a particular config file |
| // This calls InitCommon() with the given file after reading the identity |
| // information for this device. |
| // @filepath: Path to configuration file to use |
| bool InitForConfig(const base::FilePath& filepath); |
| |
| // Common init function for both production and test code. |
| // @filepath: path to configuration .dtb file. |
| // @smbios_file: File containing memory to scan (typically this is /dev/mem) |
| // @vpd_file: File containing the customization_id from VPD. Typically this |
| // is '/sys/firmware/vpd/ro/customization_id'. |
| bool InitCommon(const base::FilePath& filepath, |
| const base::FilePath& smbios_file, |
| const base::FilePath& vpd_file); |
| |
| // Runs a quick init check and prints an error to stderr if it fails. |
| // @return true if OK, false on error. |
| bool InitCheck() const; |
| |
| // Obtain the full path for the node at a given offset. |
| // @offset: offset of the node to check. |
| // @return path to node, or "unknown" if it 256 characters or more (due to |
| // limited buffer space). This is much longer than any expected length so |
| // should not happen. |
| std::string GetFullPath(int offset); |
| |
| // Obtain offset of a given path, relative to the base node. |
| // @base_offset: offset of base node. |
| // @path: Path to locate (relative to @base). Must start with "/". |
| // @return node offset of the node found, or negative value on error. |
| int GetPathOffset(int base_offset, const std::string& path); |
| |
| // Internal function to obtain a property value based on a node offset |
| // This looks up a property for a path, relative to a given base node offset. |
| // @base_offset: offset of base node for the search. |
| // @path: Path to locate (relative to @base). Must start with "/". |
| // @prop: Property name to look up |
| // @val_out: returns the string value found, if any |
| // @log_msgs_out: returns a list of error messages if this function fails |
| // @return true if found, false if not found |
| bool GetString(int base_offset, const std::string& path, |
| const std::string& prop, std::string* val_out, |
| std::vector<std::string>* log_msgs_out); |
| |
| // Look up a phandle in a node. |
| // Looks up a phandle with the given property name in the given node. |
| // @node_offset: Offset of node to look in. |
| // @prop_name: Name of property to look up. |
| // @offset_out: Returns the offset of the node the phandle points to, if |
| // found. |
| // @return true if found, false if not. |
| bool LookupPhandle(int node_offset, const std::string& prop_name, |
| int *offset_out); |
| |
| // Select the model / submodel to use |
| // Looks up the given name and sku_id in the mapping table and sets the |
| // model and submodel that will be used for the duration of execution. |
| // @find_name: Platform name to search for |
| // @find_sku_id: SKU ID to search for |
| // @find_customization_id: Customization ID to search for |
| // @return true on success, false on failure |
| bool SelectModelConfigByIDs(const std::string& find_name, int find_sku_id, |
| const std::string& find_customization_id); |
| |
| // Check a single sku-map node for a match |
| // This searches the given sku-map node to see if it is a match for the given |
| // SKU ID. |
| // @node: 'sku-map' node to examine |
| // @find_sku_id: SKU ID to search for. This is not required (can be -1) for |
| // single-sku matching |
| // @find_name: Platform name to search for. Can be empty if the name does |
| // not need to be checked (no smbios-name-match property). This only works |
| // on x86 devices at present although it should be easily extensible to ARM. |
| // @platform_name_out: Returns platform name for this SKU, if found |
| // @return the phandle to a model or submodel node that was found (> 0), or 0 |
| // if not found, or negative on error |
| int FindIDsInMap(int node, const std::string& find_name, int find_sku_id, |
| std::string* platform_name_out); |
| |
| // Check all sku-map nodes for a match |
| // This searches all the sku-map subnodes to see if one is a match for the |
| // given SKU ID. |
| // @mapping_node: 'mapping' node to examine |
| // @find_name: platform name to search for |
| // @find_sku_id: SKU ID to search for |
| // @platform_name_out: Returns platform name for this SKU, if found |
| // @return the phandle to a model or submodel node that was found (> 0), or 0 |
| // if not found, or negative on error |
| int FindIDsInAllMaps(int mapping_node, const std::string& find_name, |
| int find_sku_id, std::string* platform_name_out); |
| |
| // Find the model node pointed to by a phandle |
| // Note that a SKU map can point to either a model node or a submodel node. |
| // In the latter case, this function still returns the model node, but the |
| // submodel node is available in @target_out. |
| // @phandle: Phandle to look up |
| // @target_out: Returns the target node of the phandle, which may be a model |
| // node or a submodel node |
| // @return model node for this phandle, or negative on error |
| int FollowPhandle(int phandle, int* target_out); |
| |
| // Read the device identity information |
| // On x86 platforms the identify generally comes from two bits of information |
| // in the SMBIOS system table. These are set up by AP firmware, so in effect |
| // AP firmware sets the device identity. We also support using the VPD |
| // (customization_id) to dynamically determine device identity. This has |
| // been used to support Whitelabels/Zergs in the past, but can be used to |
| // support any applicable use case. |
| // |
| // For ARM systems we could instead look at the device-tree compatible string, |
| // which should be enough to identify the device. Again this is set up by AP |
| // firmware, but in fact is built as part of the kernel. The note above about |
| // VPD applies to ARM as well. |
| // |
| // For now we just implement x86 identity, requiring access to memory (to |
| // read the SMBIOS table) and the VPD device (to read the customization ID). |
| // |
| // @smbios_file: File containing memory to scan (typically this is /dev/mem) |
| // @vpd_file: File containing the customization_id from VPD. Typically this |
| // is '/sys/firmware/vpd/ro/customization_id'. |
| // @name_out: Platform name read from SMBIOS system table |
| // @sku_id_out: SKU ID read from SMBIOS system table |
| // @customization_id_out: Whitelabel name read from system table |
| bool ReadIdentity(const base::FilePath& smbios_file, |
| const base::FilePath& vpd_file, std::string* name_out, |
| int* sku_id_out, std::string* customization_id_out); |
| |
| // Read a string from an SMBIOS string table |
| // See the System Management BIOS (SMBIOS) Reference Specification for full |
| // details. |
| // @table: Table to read from |
| // @string_id: ID of string to read. The value 1 means to pick the first |
| // string from the the table, i.e. strings are numbered from 1, not 0. |
| // @return string found, or "" if not found |
| std::string GetSmbiosString(const SmbiosTable& table, unsigned int string_id); |
| |
| // Read the system table from memory |
| // @smbios_file: File containing SMBIOS tables to scan (typically this is |
| // /sys/firmware/dmi/tables/DMI) |
| // @table_out: Returns a copy of the table found |
| // @return true if found, false if not |
| bool GetSystemTable(const base::FilePath& smbios_file, |
| SmbiosTable* table_out); |
| |
| // SMBIOS Table Types |
| // We only use the system table, but for testing purposes we include BIOS. |
| enum SmbiosTypes { |
| SMBIOS_TYPE_BIOS = 0, |
| SMBIOS_TYPE_SYSTEM, |
| }; |
| |
| // Search through some tables looking for particular table type. |
| // All data is copied into the output table, so that the caller does not need |
| // to reference the memory region to obtain table information. |
| // @type: Type to search for |
| // @base_ptr: Start of memory region to search |
| // @size: Size of region in bytes |
| // @table_out: Returns a copy of the table found |
| // @return true if found, false if not |
| bool FindAndCopyTable(SmbiosTypes type, const char* base_ptr, |
| unsigned int size, SmbiosTable* table_out); |
| |
| // Calculates the length of an SMBIOS string table |
| // The strings are stored one after another, each with a trailing nul, and |
| // with a final additional nul after the last string. An empty table consists |
| // of two nul bytes. |
| // @ptr: Pointer to start of table (and therefore first string) |
| // @return length of table in bytes |
| unsigned int StringTableLength(const char* ptr); |
| |
| // Write out files containing fake identity information, used for testing. |
| // The two files returned mirror the contents of the files that ReadIdentity() |
| // uses to ready identity information. |
| // @name: Platform name to write (e.g. 'Reef') |
| // @sku_id: SKU ID number to write (e.g. 8) |
| // @customization_id: Whitelabel name to write |
| // @smbios_file_out: Returns the 'dev/mem'-style file write that was written |
| // @vpd_file_out: Returns the '/sys/firmware/vpd/ro/customization_id'-style |
| // file that was written |
| // @return true if OK, false on error |
| bool FakeIdentity(const std::string& name, int sku_id, |
| const std::string& customization_id, |
| base::FilePath* smbios_file_out, |
| base::FilePath* vpd_file_out); |
| |
| // Write SMBIOS tables to a file, for testing |
| // Tables are read from /dev/mem. This function writes the tables in the same |
| // format as they are found in memory. |
| // This is suitable for parsing as a normal SMBIOS structure in memory. |
| // We only write a few things, in a very simplistic way, to avoid pulling in |
| // an entire SMBIOS library. |
| // @smbios_file: File to write to |
| // @name: Platform name to write (e.g. 'Reef') |
| // @sku_id: SKU ID number to write (e.g. 8) |
| // @return true if OK, false on error |
| bool WriteFakeTables(base::File* smbios_file, const std::string& name, |
| int sku_id); |
| |
| // Decode the device identifiers to resolve the model / submodel |
| // The decodes the output from 'mosys platform id' into the two fields |
| // @output: Output string from mosys |
| // @name_out: Returns the platform name (which may be an empty string) |
| // @sku_id_out: Returns the SKU ID (which may be -1 if there is none) |
| // @customization_id_out: Returns the customization id (may be empty string) |
| // @return true on success, false on failure |
| bool DecodeIdentifiers(const std::string &output, std::string* name_out, |
| int* sku_id_out, std::string* customization_id_out); |
| |
| std::string blob_; // Device tree binary blob |
| std::string model_; // Model name for this device |
| int model_offset_ = -1; // Device tree offset of the model's node |
| int submodel_offset_ = -1; // Device tree offset of the submodel's node |
| std::string model_name_; // Name of current model |
| std::string submodel_name_; // Name of current submodel |
| std::string platform_name_; // Platform name associated with the SKU map |
| int whitelabel_offset_ = -1; // Device tree offset of the whitelabel model |
| |
| // We support a special-case 'whitelabel' node which is inside a model. This |
| // holds the device tree offset of that node. We check this first on any |
| // property reads, since it overrides the model itself. |
| int whitelabel_tag_offset_ = -1; |
| int target_dirs_offset_ = -1; // Device tree offset of the target-dirs node |
| std::vector<int> default_offsets_; // Device tree offset of default modes |
| bool inited_ = false; // true if the class is ready for use (Init*ed) |
| |
| |
| // JSON configuration |
| std::unique_ptr<const base::Value> json_config_ = nullptr; |
| const base::DictionaryValue* model_dict_ = nullptr; // Model root |
| |
| DISALLOW_COPY_AND_ASSIGN(CrosConfig); |
| }; |
| |
| } // namespace brillo |
| |
| #endif // CHROMEOS_CONFIG_LIBCROS_CONFIG_CROS_CONFIG_H_ |