Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 1 | /* |
| 2 | * partitioned_file.h, read and write binary file "partitions" described by FMAP |
| 3 | * |
| 4 | * Copyright (C) 2015 Google, Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
Patrick Georgi | b890a12 | 2015-03-26 15:17:45 +0100 | [diff] [blame^] | 17 | * Foundation, Inc. |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 18 | */ |
| 19 | |
| 20 | #ifndef PARITITONED_FILE_H_ |
| 21 | #define PARITITONED_FILE_H_ |
| 22 | |
| 23 | #include "common.h" |
| 24 | #include "flashmap/fmap.h" |
| 25 | |
| 26 | #include <stdbool.h> |
| 27 | #include <stddef.h> |
| 28 | |
| 29 | typedef struct partitioned_file partitioned_file_t; |
| 30 | |
| 31 | /** @return Whether the specific existing file should be opened in flat mode. */ |
| 32 | typedef bool (*partitioned_file_flat_decider_t)(struct buffer *buffer); |
| 33 | |
| 34 | /** Pass to partitioned_file_reopen() to force opening as a partitioned file. */ |
| 35 | #define partitioned_file_open_as_partitioned NULL |
| 36 | |
| 37 | /** Pass to partitioned_file_reopen() to force opening as a flat file. */ |
| 38 | extern const partitioned_file_flat_decider_t partitioned_file_open_as_flat; |
| 39 | |
| 40 | /** |
| 41 | * Create a new filesystem-backed flat buffer. |
| 42 | * This backwards-compatibility function creates a new in-memory buffer and |
| 43 | * backing binary file of the specified size. Although the file won't actually |
| 44 | * have multiple regions, it'll still be possible to access and manipulate it |
| 45 | * using this module; this is accomplished by requesting the special region |
| 46 | * whose name matches SECTION_NAME_PRIMARY_CBFS, which maps to the whole file. |
| 47 | * Note that the caller will be responsible for calling partitioned_file_close() |
| 48 | * on the returned object, and that this function will overwrite any existing |
| 49 | * file with the given name without warning. |
| 50 | * |
| 51 | * @param filename Name of the backing file |
| 52 | * @param image_size Size of the image |
| 53 | * @return Caller-owned partitioned file, or NULL on error |
| 54 | */ |
| 55 | partitioned_file_t *partitioned_file_create_flat(const char *filename, |
| 56 | size_t image_size); |
| 57 | |
| 58 | /** |
| 59 | * Create a new filesystem-backed partitioned buffer. |
| 60 | * This creates a new in-memory buffer and backing binary file. Both are |
| 61 | * segmented into regions according to the provided flashmap's sections, and the |
| 62 | * flashmap itself is automatically copied into the region named |
| 63 | * SECTION_NAME_FMAP: a section with this name must already exist in the FMAP. |
| 64 | * After calling this function, it is safe for the caller to clean up flashmap |
| 65 | * at any time. The partitioned_file_t returned from this function is separately |
| 66 | * owned by the caller, and must later be passed to partitioned_file_close(). |
| 67 | * Note that this function will overwrite any existing file with the given name |
| 68 | * without warning. |
| 69 | * |
| 70 | * @param filename Name of the backing file |
| 71 | * @param flashmap Buffer containing an FMAP file layout |
| 72 | * @return Caller-owned partitioned file, or NULL on error |
| 73 | */ |
| 74 | partitioned_file_t *partitioned_file_create(const char *filename, |
| 75 | struct buffer *flashmap); |
| 76 | |
| 77 | /** |
| 78 | * Read a file back in from the disk. |
| 79 | * An in-memory buffer is created and populated with the file's contents. If |
| 80 | * flat_override is NULL and the image contains an FMAP, it will be opened as a |
| 81 | * full partitioned file; otherwise, it will be opened as a flat file as if it |
| 82 | * had been created by partitioned_file_create_flat(). This selection behavior |
| 83 | * is extensible: if a flat_override function is provided, it is invoked before |
| 84 | * searching for an FMAP, and has the option of explicitly instructing the |
| 85 | * module to open the image as a flat file based on its contents. |
| 86 | * The partitioned_file_t returned from this function is separately owned by the |
| 87 | * caller, and must later be passed to partitioned_file_close(); |
| 88 | * |
| 89 | * @param filename Name of the file to read in |
| 90 | * @param flat_override Callback that can decide to open it as flat, or NULL |
| 91 | * @return Caller-owned partitioned file, or NULL on error |
| 92 | */ |
| 93 | partitioned_file_t *partitioned_file_reopen(const char *filename, |
| 94 | partitioned_file_flat_decider_t flat_override); |
| 95 | |
| 96 | /** |
| 97 | * Write a buffer's contents to its original region within a segmented file. |
| 98 | * This function should only be called on buffers originally retrieved by a call |
| 99 | * to partitioned_file_read_region() on the same partitioned file object. The |
| 100 | * contents of this buffer are copied back to the same region of the buffer and |
| 101 | * backing file that the region occupied before. |
| 102 | * |
| 103 | * @param file Partitioned file to which to write the data |
| 104 | * @param buffer Modified buffer obtained from partitioned_file_read_region() |
| 105 | * @return Whether the operation was successful |
| 106 | */ |
| 107 | bool partitioned_file_write_region(partitioned_file_t *file, |
| 108 | const struct buffer *buffer); |
| 109 | |
| 110 | /** |
| 111 | * Obtain one particular region of a segmented file. |
| 112 | * The result is owned by the partitioned_file_t and shared among every caller |
| 113 | * of this function. Thus, it is an error to buffer_delete() it; instead, clean |
| 114 | * up the entire partitioned_file_t once it's no longer needed with a single |
| 115 | * call to partitioned_file_close(). |
| 116 | * Note that, if the buffer obtained from this function is modified, the changes |
| 117 | * will be reflected in any buffers handed out---whether earlier or later---for |
| 118 | * any region inclusive of the altered location(s). However, the backing file |
| 119 | * will not be updated until someone calls partitioned_file_write_region() on a |
| 120 | * buffer that includes the alterations. |
| 121 | * |
| 122 | * @param dest Empty destination buffer for the data |
| 123 | * @param file Partitioned file from which to read the data |
| 124 | * @param region Name of the desired FMAP region |
| 125 | * @return Whether the copy was performed successfully |
| 126 | */ |
| 127 | bool partitioned_file_read_region(struct buffer *dest, |
| 128 | const partitioned_file_t *file, const char *region); |
| 129 | |
| 130 | /** @param file Partitioned file to flush and cleanup */ |
| 131 | void partitioned_file_close(partitioned_file_t *file); |
| 132 | |
| 133 | /** @return Whether the file is partitioned (i.e. not flat). */ |
| 134 | bool partitioned_file_is_partitioned(const partitioned_file_t *file); |
| 135 | |
Sol Boucher | 67d5998 | 2015-05-07 02:39:22 -0700 | [diff] [blame] | 136 | /** @return The image's overall filesize, regardless of whether it's flat. */ |
| 137 | size_t partitioned_file_total_size(const partitioned_file_t *file); |
| 138 | |
Sol Boucher | e3260a0 | 2015-03-25 13:40:08 -0700 | [diff] [blame] | 139 | /** @return Whether the specified region begins with the magic bytes. */ |
| 140 | bool partitioned_file_region_check_magic(const partitioned_file_t *file, |
| 141 | const char *region, const char *magic, size_t magic_len); |
| 142 | |
| 143 | /** @return Whether the specified region exists and contains nested regions. */ |
| 144 | bool partitioned_file_region_contains_nested(const partitioned_file_t *file, |
| 145 | const char *region); |
| 146 | |
| 147 | /** @return An immutable reference to the FMAP, or NULL for flat images. */ |
| 148 | const struct fmap *partitioned_file_get_fmap(const partitioned_file_t *file); |
| 149 | |
| 150 | /** @return Whether to include area in the running count. */ |
| 151 | typedef bool (*partitioned_file_fmap_selector_t) |
| 152 | (const struct fmap_area *area, const void *arg); |
| 153 | |
| 154 | /** |
| 155 | * Count the number of FMAP entries fulfilling a certain criterion. |
| 156 | * The result is always 0 if run on a flat (non-partitioned) image. |
| 157 | * |
| 158 | * @param file File on whose FMAP entries the operation should be run |
| 159 | * @param callback Decider answering whether each individual region should count |
| 160 | * @param arg Additional information to furnish to the decider on each call |
| 161 | * @return The number of FMAP sections with that property |
| 162 | */ |
| 163 | unsigned partitioned_file_fmap_count(const partitioned_file_t *file, |
| 164 | partitioned_file_fmap_selector_t callback, const void *arg); |
| 165 | |
| 166 | /** Selector that counts every single FMAP section. */ |
| 167 | extern const partitioned_file_fmap_selector_t partitioned_file_fmap_select_all; |
| 168 | |
| 169 | /** Selector that counts FMAP sections that are descendants of fmap_area arg. */ |
| 170 | extern const partitioned_file_fmap_selector_t |
| 171 | partitioned_file_fmap_select_children_of; |
| 172 | |
| 173 | /** Selector that counts FMAP sections that contain the fmap_area arg. */ |
| 174 | extern const partitioned_file_fmap_selector_t |
| 175 | partitioned_file_fmap_select_parents_of; |
| 176 | |
| 177 | #endif |