/ util / cbfstool / cbfs_image.h
cbfs_image.h
  1  /* CBFS Image Manipulation */
  2  /* SPDX-License-Identifier: GPL-2.0-only */
  3  
  4  #ifndef __CBFS_IMAGE_H
  5  #define __CBFS_IMAGE_H
  6  #include "common.h"
  7  #include "cbfs.h"
  8  
  9  
 10  #define HEADER_OFFSET_UNKNOWN (~0u)
 11  
 12  /* CBFS image processing */
 13  
 14  struct cbfs_image {
 15  	struct buffer buffer;
 16  	/* An image has a header iff it's a legacy CBFS. */
 17  	bool has_header;
 18  	/* Only meaningful if has_header is selected. */
 19  	struct cbfs_header header;
 20  };
 21  
 22  /* Given the string name of a compression algorithm, return the corresponding
 23   * enum comp_algo if it's supported, or a number < 0 otherwise. */
 24  int cbfs_parse_comp_algo(const char *name);
 25  
 26  /* Given the string name of a hash algorithm, return the corresponding
 27   * id if it's supported, or a number < 0 otherwise. */
 28  int cbfs_parse_hash_algo(const char *name);
 29  
 30  /* Given a pointer, serialize the header from host-native byte format
 31   * to cbfs format, i.e. big-endian. */
 32  void cbfs_put_header(void *dest, const struct cbfs_header *header);
 33  /* Or deserialize into host-native format */
 34  void cbfs_get_header(struct cbfs_header *header, void *src);
 35  
 36  /* Populates a CBFS with a single empty entry filling all available space
 37   * (entries_size bytes). If image's header field is already present, its
 38   * contents will be used to place an empty entry of the requested length at the
 39   * appropriate position in the existing buffer; otherwise, if not has_header,
 40   * the first entries_size bytes of buffer will be filled exclusively with the
 41   * single empty entry (and no CBFS master header).
 42   * Returns 0 on success, otherwise nonzero. */
 43  int cbfs_image_create(struct cbfs_image *image, size_t entries_size);
 44  
 45  /* Creates an empty CBFS image by given size, and description to its content
 46   * (bootblock, align, header location, starting offset of CBFS entries).
 47   * The output image will contain a valid cbfs_header, with one cbfs_file
 48   * entry with type CBFS_TYPE_NULL, with max available size.
 49   * Only call this if you want a legacy CBFS with a master header.
 50   * Returns 0 on success, otherwise nonzero. */
 51  int cbfs_legacy_image_create(struct cbfs_image *image,
 52  			      uint32_t arch,
 53  			      uint32_t align,
 54  			      struct buffer *bootblock,
 55  			      uint32_t bootblock_offset,
 56  			      uint32_t header_offset,
 57  			      uint32_t entries_offset);
 58  
 59  /* Constructs a cbfs_image from a buffer. The resulting image contains a shallow
 60   * copy of the buffer; releasing either one is the legal way to clean up after
 61   * both of them at once. Always produces a cbfs_image, but...
 62   * Returns 0 if it contains a valid CBFS, non-zero if it's unrecognized data. */
 63  int cbfs_image_from_buffer(struct cbfs_image *out, struct buffer *in,
 64  			   uint32_t offset);
 65  
 66  /* Create a duplicate CBFS image. Returns 0 on success, otherwise non-zero.
 67   * Will not succeed on new-style images without a master header. */
 68  int cbfs_copy_instance(struct cbfs_image *image, struct buffer *dst);
 69  
 70  /* Compact a fragmented CBFS image by placing all the non-empty files at the
 71   * beginning of the image. Returns 0 on success, otherwise non-zero.  */
 72  int cbfs_compact_instance(struct cbfs_image *image);
 73  
 74  /* Expand a CBFS image inside an fmap region to the entire region's space.
 75     Returns 0 on success, otherwise non-zero. */
 76  int cbfs_expand_to_region(struct buffer *region);
 77  
 78  /* Truncate a CBFS by removing a trailing "empty" file if it exists.
 79     Returns 0 on success, otherwise non-zero and passes the CBFS' remaining
 80     size in the size argument. */
 81  int cbfs_truncate_space(struct buffer *region, uint32_t *size);
 82  
 83  /* Releases the CBFS image. Returns 0 on success, otherwise non-zero. */
 84  int cbfs_image_delete(struct cbfs_image *image);
 85  
 86  /* Returns a pointer to entry by name, or NULL if name is not found. */
 87  struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name);
 88  
 89  /* Exports an entry to external file. If do_processing is true, file contents
 90   * will be decompressed, and also turned into an ELF if appropriate.
 91   * Returns 0 on success, otherwise (ex, not found) non-zero. */
 92  int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 93  		      const char *filename, uint32_t arch, bool do_processing);
 94  
 95  /* Adds an entry to CBFS image by given name and type. If content_offset is
 96   * non-zero, try to align "content" (CBFS_SUBHEADER(p)) at content_offset.
 97   * Never pass this function a top-aligned address: convert it to an offset.
 98   * Returns 0 on success, otherwise non-zero. */
 99  int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
100  		   uint32_t content_offset, struct cbfs_file *header,
101  		   const size_t len_align);
102  
103  /* Removes an entry from CBFS image. Returns 0 on success, otherwise non-zero. */
104  int cbfs_remove_entry(struct cbfs_image *image, const char *name);
105  
106  /* Create a new cbfs file header structure to work with.
107     Returns newly allocated memory that the caller needs to free after use. */
108  struct cbfs_file *cbfs_create_file_header(int type, size_t len,
109  	const char *name);
110  
111  /* Initializes a new empty (type = NULL) entry with size and name in CBFS image.
112   * Returns 0 on success, otherwise (ex, not found) non-zero. */
113  int cbfs_create_empty_entry(struct cbfs_file *entry, int type,
114  			    size_t len, const char *name);
115  
116  /* Finds a location to put given content by specified criteria:
117   *  "page_size" limits the content to fit on same memory page, and
118   *  "align" specifies starting address alignment.
119   * Returns a valid offset, or -1 on failure. */
120  int32_t cbfs_locate_entry(struct cbfs_image *image, size_t size,
121  			  size_t page_size, size_t align, size_t metadata_size);
122  
123  /* Callback function used by cbfs_legacy_walk.
124   * Returns 0 on success, or non-zero to stop further iteration. */
125  typedef int (*cbfs_entry_callback)(struct cbfs_image *image,
126  				   struct cbfs_file *file,
127  				   void *arg);
128  
129  /* Iterates through all entries in CBFS image, and invoke with callback.
130   * Stops if callback returns non-zero values. Unlike the commonlib cbfs_walk(),
131   * this can deal with different alignments in legacy CBFS (with master header).
132   * Returns number of entries invoked. */
133  int cbfs_legacy_walk(struct cbfs_image *image, cbfs_entry_callback callback,
134  		     void *arg);
135  
136  /* Primitive CBFS utilities */
137  
138  /* Returns a pointer to the only valid CBFS header in give buffer, otherwise
139   * NULL (including when multiple headers were found). If there is a X86 ROM
140   * style signature (pointer at 0xfffffffc) found in ROM, it will be selected as
141   * the only header.*/
142  struct cbfs_header *cbfs_find_header(char *data, size_t size,
143  				     uint32_t forced_offset);
144  
145  /* Returns the first cbfs_file entry in CBFS image by CBFS header (no matter if
146   * the entry has valid content or not), otherwise NULL. */
147  struct cbfs_file *cbfs_find_first_entry(struct cbfs_image *image);
148  
149  /* Returns next cbfs_file entry (no matter if its content is valid or not), or
150   * NULL on failure. */
151  struct cbfs_file *cbfs_find_next_entry(struct cbfs_image *image,
152  				       struct cbfs_file *entry);
153  
154  /* Returns ROM address (offset) of entry.
155   * This is different from entry->offset (pointer to content). */
156  uint32_t cbfs_get_entry_addr(struct cbfs_image *image, struct cbfs_file *entry);
157  
158  /* Returns 1 if valid new-format CBFS (without a master header), otherwise 0. */
159  int cbfs_is_valid_cbfs(struct cbfs_image *image);
160  
161  /* Returns 1 if valid legacy CBFS (with a master header), otherwise 0. */
162  int cbfs_is_legacy_cbfs(struct cbfs_image *image);
163  
164  /* Returns 1 if entry has valid data (by checking magic number), otherwise 0. */
165  int cbfs_is_valid_entry(struct cbfs_image *image, struct cbfs_file *entry);
166  
167  /* Print CBFS component information. */
168  void cbfs_print_directory(struct cbfs_image *image);
169  void cbfs_print_parseable_directory(struct cbfs_image *image);
170  int cbfs_print_header_info(struct cbfs_image *image);
171  int cbfs_print_entry_info(struct cbfs_image *image, struct cbfs_file *entry,
172  			  void *arg);
173  
174  /* Merge empty entries starting from given entry.
175   * Returns 0 on success, otherwise non-zero. */
176  int cbfs_merge_empty_entry(struct cbfs_image *image, struct cbfs_file *entry,
177  			   void *arg);
178  
179  /* Returns the size of a cbfs file header with no extensions */
180  size_t cbfs_calculate_file_header_size(const char *name);
181  
182  /* Given a cbfs_file, return the first file attribute, or NULL. */
183  struct cbfs_file_attribute *cbfs_file_first_attr(struct cbfs_file *file);
184  
185  /* Given a cbfs_file and a cbfs_file_attribute, return the attribute that
186   * follows it, or NULL. */
187  struct cbfs_file_attribute *cbfs_file_next_attr(struct cbfs_file *file,
188  	struct cbfs_file_attribute *attr);
189  
190  /* Adds to header a new extended attribute tagged 'tag', sized 'size'.
191   * Returns pointer to the new attribute, or NULL on error. */
192  struct cbfs_file_attribute *cbfs_add_file_attr(struct cbfs_file *header,
193  					       uint32_t tag,
194  					       uint32_t size);
195  
196  /* Adds an extended attribute to header, containing a hash of buffer's data of
197   * the type specified by hash_type.
198   * Returns 0 on success, -1 on error. */
199  int cbfs_add_file_hash(struct cbfs_file *header, struct buffer *buffer,
200  	enum vb2_hash_algorithm hash_type);
201  #endif