Home | History | Annotate | Download | only in common
      1 /*
      2  * (C) Copyright 2018, Linaro Limited
      3  *
      4  * SPDX-License-Identifier:	GPL-2.0+
      5  */
      6 
      7 #include <avb_verify.h>
      8 #include <fastboot.h>
      9 #include <image.h>
     10 #include <malloc.h>
     11 #include <part.h>
     12 
     13 const unsigned char avb_root_pub[1032] = {
     14 	0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
     15 	0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
     16 	0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
     17 	0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
     18 	0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
     19 	0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
     20 	0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
     21 	0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
     22 	0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
     23 	0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
     24 	0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
     25 	0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
     26 	0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
     27 	0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
     28 	0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
     29 	0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
     30 	0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
     31 	0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
     32 	0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
     33 	0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
     34 	0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
     35 	0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
     36 	0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
     37 	0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
     38 	0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
     39 	0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
     40 	0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
     41 	0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
     42 	0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
     43 	0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
     44 	0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
     45 	0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
     46 	0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
     47 	0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
     48 	0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
     49 	0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
     50 	0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
     51 	0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
     52 	0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
     53 	0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
     54 	0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
     55 	0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
     56 	0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
     57 	0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
     58 	0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
     59 	0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
     60 	0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
     61 	0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
     62 	0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
     63 	0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
     64 	0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
     65 	0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
     66 	0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
     67 	0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
     68 	0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
     69 	0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
     70 	0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
     71 	0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
     72 	0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
     73 	0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
     74 	0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
     75 	0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
     76 	0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
     77 	0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
     78 	0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
     79 	0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
     80 	0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
     81 	0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
     82 	0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
     83 	0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
     84 	0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
     85 	0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
     86 	0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
     87 	0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
     88 	0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
     89 	0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
     90 	0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
     91 	0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
     92 	0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
     93 	0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
     94 	0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
     95 	0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
     96 	0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
     97 	0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
     98 	0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
     99 	0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
    100 	0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
    101 	0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
    102 	0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
    103 	0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
    104 	0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
    105 	0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
    106 	0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
    107 	0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
    108 	0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
    109 	0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
    110 	0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
    111 	0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
    112 	0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
    113 	0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
    114 	0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
    115 	0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
    116 	0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
    117 	0xd8, 0x7e,
    118 };
    119 
    120 /**
    121  * ============================================================================
    122  * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
    123  * ============================================================================
    124  */
    125 char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
    126 {
    127 	struct AvbOpsData *data;
    128 	char *cmdline = NULL;
    129 
    130 	if (!ops)
    131 		return NULL;
    132 
    133 	data = (struct AvbOpsData *)ops->user_data;
    134 	if (!data)
    135 		return NULL;
    136 
    137 	data->boot_state = boot_state;
    138 	switch (boot_state) {
    139 	case AVB_GREEN:
    140 		cmdline = "androidboot.verifiedbootstate=green";
    141 		break;
    142 	case AVB_YELLOW:
    143 		cmdline = "androidboot.verifiedbootstate=yellow";
    144 		break;
    145 	case AVB_ORANGE:
    146 		cmdline = "androidboot.verifiedbootstate=orange";
    147 	case AVB_RED:
    148 		break;
    149 	}
    150 
    151 	return cmdline;
    152 }
    153 
    154 char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
    155 {
    156 	char *cmd_line;
    157 
    158 	if (!cmdline_new)
    159 		return cmdline_orig;
    160 
    161 	if (cmdline_orig)
    162 		cmd_line = cmdline_orig;
    163 	else
    164 		cmd_line = " ";
    165 
    166 	cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
    167 
    168 	return cmd_line;
    169 }
    170 
    171 static int avb_find_dm_args(char **args, char *str)
    172 {
    173 	int i;
    174 
    175 	if (!str)
    176 		return -1;
    177 
    178 	for (i = 0; i < AVB_MAX_ARGS, args[i]; ++i) {
    179 		if (strstr(args[i], str))
    180 			return i;
    181 	}
    182 
    183 	return -1;
    184 }
    185 
    186 static char *avb_set_enforce_option(const char *cmdline, const char *option)
    187 {
    188 	char *cmdarg[AVB_MAX_ARGS];
    189 	char *newargs = NULL;
    190 	int i = 0;
    191 	int total_args;
    192 
    193 	memset(cmdarg, 0, sizeof(cmdarg));
    194 	cmdarg[i++] = strtok((char *)cmdline, " ");
    195 
    196 	do {
    197 		cmdarg[i] = strtok(NULL, " ");
    198 		if (!cmdarg[i])
    199 			break;
    200 
    201 		if (++i >= AVB_MAX_ARGS) {
    202 			printf("%s: Can't handle more then %d args\n",
    203 			       __func__, i);
    204 			return NULL;
    205 		}
    206 	} while (true);
    207 
    208 	total_args = i;
    209 	i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
    210 	if (i >= 0) {
    211 		cmdarg[i] = (char *)option;
    212 	} else {
    213 		i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
    214 		if (i < 0) {
    215 			printf("%s: No verity options found\n", __func__);
    216 			return NULL;
    217 		}
    218 
    219 		cmdarg[i] = (char *)option;
    220 	}
    221 
    222 	for (i = 0; i <= total_args; i++)
    223 		newargs = append_cmd_line(newargs, cmdarg[i]);
    224 
    225 	return newargs;
    226 }
    227 
    228 char *avb_set_ignore_corruption(const char *cmdline)
    229 {
    230 	char *newargs = NULL;
    231 
    232 	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
    233 	if (newargs)
    234 		newargs = append_cmd_line(newargs,
    235 					  "androidboot.veritymode=eio");
    236 
    237 	return newargs;
    238 }
    239 
    240 char *avb_set_enforce_verity(const char *cmdline)
    241 {
    242 	char *newargs;
    243 
    244 	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
    245 	if (newargs)
    246 		newargs = append_cmd_line(newargs,
    247 					  "androidboot.veritymode=enforcing");
    248 	return newargs;
    249 }
    250 
    251 /**
    252  * ============================================================================
    253  * IO(mmc) auxiliary functions
    254  * ============================================================================
    255  */
    256 static unsigned long mmc_read_and_flush(struct mmc_part *part,
    257 					lbaint_t start,
    258 					lbaint_t sectors,
    259 					void *buffer)
    260 {
    261 	unsigned long blks;
    262 	void *tmp_buf;
    263 	size_t buf_size;
    264 	bool unaligned = is_buf_unaligned(buffer);
    265 
    266 	if (start < part->info.start) {
    267 		printf("%s: partition start out of bounds\n", __func__);
    268 		return 0;
    269 	}
    270 	if ((start + sectors) > (part->info.start + part->info.size)) {
    271 		sectors = part->info.start + part->info.size - start;
    272 		printf("%s: read sector aligned to partition bounds (%ld)\n",
    273 		       __func__, sectors);
    274 	}
    275 
    276 	/*
    277 	 * Reading fails on unaligned buffers, so we have to
    278 	 * use aligned temporary buffer and then copy to destination
    279 	 */
    280 
    281 	if (unaligned) {
    282 		printf("Handling unaligned read buffer..\n");
    283 		tmp_buf = get_sector_buf();
    284 		buf_size = get_sector_buf_size();
    285 		if (sectors > buf_size / part->info.blksz)
    286 			sectors = buf_size / part->info.blksz;
    287 	} else {
    288 		tmp_buf = buffer;
    289 	}
    290 
    291 	blks = part->mmc->block_dev.block_read(part->mmc_blk,
    292 				start, sectors, tmp_buf);
    293 	/* flush cache after read */
    294 	flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
    295 
    296 	if (unaligned)
    297 		memcpy(buffer, tmp_buf, sectors * part->info.blksz);
    298 
    299 	return blks;
    300 }
    301 
    302 static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
    303 			       lbaint_t sectors, void *buffer)
    304 {
    305 	void *tmp_buf;
    306 	size_t buf_size;
    307 	bool unaligned = is_buf_unaligned(buffer);
    308 
    309 	if (start < part->info.start) {
    310 		printf("%s: partition start out of bounds\n", __func__);
    311 		return 0;
    312 	}
    313 	if ((start + sectors) > (part->info.start + part->info.size)) {
    314 		sectors = part->info.start + part->info.size - start;
    315 		printf("%s: sector aligned to partition bounds (%ld)\n",
    316 		       __func__, sectors);
    317 	}
    318 	if (unaligned) {
    319 		tmp_buf = get_sector_buf();
    320 		buf_size = get_sector_buf_size();
    321 		printf("Handling unaligned wrire buffer..\n");
    322 		if (sectors > buf_size / part->info.blksz)
    323 			sectors = buf_size / part->info.blksz;
    324 
    325 		memcpy(tmp_buf, buffer, sectors * part->info.blksz);
    326 	} else {
    327 		tmp_buf = buffer;
    328 	}
    329 
    330 	return part->mmc->block_dev.block_write(part->mmc_blk,
    331 				start, sectors, tmp_buf);
    332 }
    333 
    334 static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
    335 {
    336 	int ret;
    337 	u8 dev_num;
    338 	int part_num = 0;
    339 	struct mmc_part *part;
    340 	struct blk_desc *mmc_blk;
    341 
    342 	part = malloc(sizeof(struct mmc_part));
    343 	if (!part)
    344 		return NULL;
    345 
    346 	dev_num = get_boot_device(ops);
    347 	part->mmc = find_mmc_device(dev_num);
    348 	if (!part->mmc) {
    349 		printf("No MMC device at slot %x\n", dev_num);
    350 		return NULL;
    351 	}
    352 
    353 	if (mmc_init(part->mmc)) {
    354 		printf("MMC initialization failed\n");
    355 		return NULL;
    356 	}
    357 
    358 	ret = mmc_switch_part(part->mmc, part_num);
    359 	if (ret)
    360 		return NULL;
    361 
    362 	mmc_blk = mmc_get_blk_desc(part->mmc);
    363 	if (!mmc_blk) {
    364 		printf("Error - failed to obtain block descriptor\n");
    365 		return NULL;
    366 	}
    367 
    368 	ret = part_get_info_by_name(mmc_blk, partition, &part->info);
    369 	if (!ret) {
    370 		printf("Can't find partition '%s'\n", partition);
    371 		return NULL;
    372 	}
    373 
    374 	part->dev_num = dev_num;
    375 	part->mmc_blk = mmc_blk;
    376 
    377 	return part;
    378 }
    379 
    380 static AvbIOResult mmc_byte_io(AvbOps *ops,
    381 			       const char *partition,
    382 			       s64 offset,
    383 			       size_t num_bytes,
    384 			       void *buffer,
    385 			       size_t *out_num_read,
    386 			       enum mmc_io_type io_type)
    387 {
    388 	ulong ret;
    389 	struct mmc_part *part;
    390 	u64 start_offset, start_sector, sectors, residue;
    391 	u8 *tmp_buf;
    392 	size_t io_cnt = 0;
    393 
    394 	if (!partition || !buffer || io_type > IO_WRITE)
    395 		return AVB_IO_RESULT_ERROR_IO;
    396 
    397 	part = get_partition(ops, partition);
    398 	if (!part)
    399 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
    400 
    401 	start_offset = calc_offset(part, offset);
    402 	while (num_bytes) {
    403 		start_sector = start_offset / part->info.blksz;
    404 		sectors = num_bytes / part->info.blksz;
    405 		/* handle non block-aligned reads */
    406 		if (start_offset % part->info.blksz ||
    407 		    num_bytes < part->info.blksz) {
    408 			tmp_buf = get_sector_buf();
    409 			if (start_offset % part->info.blksz) {
    410 				residue = part->info.blksz -
    411 					(start_offset % part->info.blksz);
    412 				if (residue > num_bytes)
    413 					residue = num_bytes;
    414 			} else {
    415 				residue = num_bytes;
    416 			}
    417 
    418 			if (io_type == IO_READ) {
    419 				ret = mmc_read_and_flush(part,
    420 							 part->info.start +
    421 							 start_sector,
    422 							 1, tmp_buf);
    423 
    424 				if (ret != 1) {
    425 					printf("%s: read error (%ld, %lld)\n",
    426 					       __func__, ret, start_sector);
    427 					return AVB_IO_RESULT_ERROR_IO;
    428 				}
    429 				/*
    430 				 * if this is not aligned at sector start,
    431 				 * we have to adjust the tmp buffer
    432 				 */
    433 				tmp_buf += (start_offset % part->info.blksz);
    434 				memcpy(buffer, (void *)tmp_buf, residue);
    435 			} else {
    436 				ret = mmc_read_and_flush(part,
    437 							 part->info.start +
    438 							 start_sector,
    439 							 1, tmp_buf);
    440 
    441 				if (ret != 1) {
    442 					printf("%s: read error (%ld, %lld)\n",
    443 					       __func__, ret, start_sector);
    444 					return AVB_IO_RESULT_ERROR_IO;
    445 				}
    446 				memcpy((void *)tmp_buf +
    447 					start_offset % part->info.blksz,
    448 					buffer, residue);
    449 
    450 				ret = mmc_write(part, part->info.start +
    451 						start_sector, 1, tmp_buf);
    452 				if (ret != 1) {
    453 					printf("%s: write error (%ld, %lld)\n",
    454 					       __func__, ret, start_sector);
    455 					return AVB_IO_RESULT_ERROR_IO;
    456 				}
    457 			}
    458 
    459 			io_cnt += residue;
    460 			buffer += residue;
    461 			start_offset += residue;
    462 			num_bytes -= residue;
    463 			continue;
    464 		}
    465 
    466 		if (sectors) {
    467 			if (io_type == IO_READ) {
    468 				ret = mmc_read_and_flush(part,
    469 							 part->info.start +
    470 							 start_sector,
    471 							 sectors, buffer);
    472 			} else {
    473 				ret = mmc_write(part,
    474 						part->info.start +
    475 						start_sector,
    476 						sectors, buffer);
    477 			}
    478 
    479 			if (!ret) {
    480 				printf("%s: sector read error\n", __func__);
    481 				return AVB_IO_RESULT_ERROR_IO;
    482 			}
    483 
    484 			io_cnt += ret * part->info.blksz;
    485 			buffer += ret * part->info.blksz;
    486 			start_offset += ret * part->info.blksz;
    487 			num_bytes -= ret * part->info.blksz;
    488 		}
    489 	}
    490 
    491 	/* Set counter for read operation */
    492 	if (io_type == IO_READ && out_num_read)
    493 		*out_num_read = io_cnt;
    494 
    495 	return AVB_IO_RESULT_OK;
    496 }
    497 
    498 /**
    499  * ============================================================================
    500  * AVB 2.0 operations
    501  * ============================================================================
    502  */
    503 
    504 /**
    505  * read_from_partition() - reads @num_bytes from  @offset from partition
    506  * identified by a string name
    507  *
    508  * @ops: contains AVB ops handlers
    509  * @partition_name: partition name, NUL-terminated UTF-8 string
    510  * @offset: offset from the beginning of partition
    511  * @num_bytes: amount of bytes to read
    512  * @buffer: destination buffer to store data
    513  * @out_num_read:
    514  *
    515  * @return:
    516  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
    517  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
    518  *            subsystem
    519  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
    520  *      the given name
    521  */
    522 static AvbIOResult read_from_partition(AvbOps *ops,
    523 				       const char *partition_name,
    524 				       s64 offset_from_partition,
    525 				       size_t num_bytes,
    526 				       void *buffer,
    527 				       size_t *out_num_read)
    528 {
    529 	return mmc_byte_io(ops, partition_name, offset_from_partition,
    530 			   num_bytes, buffer, out_num_read, IO_READ);
    531 }
    532 
    533 /**
    534  * write_to_partition() - writes N bytes to a partition identified by a string
    535  * name
    536  *
    537  * @ops: AvbOps, contains AVB ops handlers
    538  * @partition_name: partition name
    539  * @offset_from_partition: offset from the beginning of partition
    540  * @num_bytes: amount of bytes to write
    541  * @buf: data to write
    542  * @out_num_read:
    543  *
    544  * @return:
    545  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
    546  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
    547  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
    548  *            @partition_name was not found
    549  */
    550 static AvbIOResult write_to_partition(AvbOps *ops,
    551 				      const char *partition_name,
    552 				      s64 offset_from_partition,
    553 				      size_t num_bytes,
    554 				      const void *buffer)
    555 {
    556 	return mmc_byte_io(ops, partition_name, offset_from_partition,
    557 			   num_bytes, (void *)buffer, NULL, IO_WRITE);
    558 }
    559 
    560 /**
    561  * validate_vmbeta_public_key() - checks if the given public key used to sign
    562  * the vbmeta partition is trusted
    563  *
    564  * @ops: AvbOps, contains AVB ops handlers
    565  * @public_key_data: public key for verifying vbmeta partition signature
    566  * @public_key_length: length of public key
    567  * @public_key_metadata:
    568  * @public_key_metadata_length:
    569  * @out_key_is_trusted:
    570  *
    571  * @return:
    572  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
    573  */
    574 static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
    575 					      const u8 *public_key_data,
    576 					      size_t public_key_length,
    577 					      const u8
    578 					      *public_key_metadata,
    579 					      size_t
    580 					      public_key_metadata_length,
    581 					      bool *out_key_is_trusted)
    582 {
    583 	if (!public_key_length || !public_key_data || !out_key_is_trusted)
    584 		return AVB_IO_RESULT_ERROR_IO;
    585 
    586 	*out_key_is_trusted = false;
    587 	if (public_key_length != sizeof(avb_root_pub))
    588 		return AVB_IO_RESULT_ERROR_IO;
    589 
    590 	if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
    591 		*out_key_is_trusted = true;
    592 
    593 	return AVB_IO_RESULT_OK;
    594 }
    595 
    596 /**
    597  * read_rollback_index() - gets the rollback index corresponding to the
    598  * location of given by @out_rollback_index.
    599  *
    600  * @ops: contains AvbOps handlers
    601  * @rollback_index_slot:
    602  * @out_rollback_index: used to write a retrieved rollback index.
    603  *
    604  * @return
    605  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
    606  */
    607 static AvbIOResult read_rollback_index(AvbOps *ops,
    608 				       size_t rollback_index_slot,
    609 				       u64 *out_rollback_index)
    610 {
    611 	/* For now we always return 0 as the stored rollback index. */
    612 	printf("%s not supported yet\n", __func__);
    613 
    614 	if (out_rollback_index)
    615 		*out_rollback_index = 0;
    616 
    617 	return AVB_IO_RESULT_OK;
    618 }
    619 
    620 /**
    621  * write_rollback_index() - sets the rollback index corresponding to the
    622  * location of given by @out_rollback_index.
    623  *
    624  * @ops: contains AvbOps handlers
    625  * @rollback_index_slot:
    626  * @rollback_index: rollback index to write.
    627  *
    628  * @return
    629  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
    630  */
    631 static AvbIOResult write_rollback_index(AvbOps *ops,
    632 					size_t rollback_index_slot,
    633 					u64 rollback_index)
    634 {
    635 	/* For now this is a no-op. */
    636 	printf("%s not supported yet\n", __func__);
    637 
    638 	return AVB_IO_RESULT_OK;
    639 }
    640 
    641 /**
    642  * read_is_device_unlocked() - gets whether the device is unlocked
    643  *
    644  * @ops: contains AVB ops handlers
    645  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
    646  *       false otherwise
    647  *
    648  * @return:
    649  *       AVB_IO_RESULT_OK: state is retrieved successfully
    650  *       AVB_IO_RESULT_ERROR_IO: an error occurred
    651  */
    652 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
    653 {
    654 	/* For now we always return that the device is unlocked. */
    655 
    656 	printf("%s not supported yet\n", __func__);
    657 
    658 	*out_is_unlocked = true;
    659 
    660 	return AVB_IO_RESULT_OK;
    661 }
    662 
    663 /**
    664  * get_unique_guid_for_partition() - gets the GUID for a partition identified
    665  * by a string name
    666  *
    667  * @ops: contains AVB ops handlers
    668  * @partition: partition name (NUL-terminated UTF-8 string)
    669  * @guid_buf: buf, used to copy in GUID string. Example of value:
    670  *      527c1c6d-6361-4593-8842-3c78fcd39219
    671  * @guid_buf_size: @guid_buf buffer size
    672  *
    673  * @return:
    674  *      AVB_IO_RESULT_OK, on success (GUID found)
    675  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
    676  *             provided
    677  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
    678  */
    679 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
    680 						 const char *partition,
    681 						 char *guid_buf,
    682 						 size_t guid_buf_size)
    683 {
    684 	struct mmc_part *part;
    685 	size_t uuid_size;
    686 
    687 	part = get_partition(ops, partition);
    688 	if (!part)
    689 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
    690 
    691 	uuid_size = sizeof(part->info.uuid);
    692 	if (uuid_size > guid_buf_size)
    693 		return AVB_IO_RESULT_ERROR_IO;
    694 
    695 	memcpy(guid_buf, part->info.uuid, uuid_size);
    696 	guid_buf[uuid_size - 1] = 0;
    697 
    698 	return AVB_IO_RESULT_OK;
    699 }
    700 
    701 /**
    702  * ============================================================================
    703  * AVB2.0 AvbOps alloc/initialisation/free
    704  * ============================================================================
    705  */
    706 AvbOps *avb_ops_alloc(int boot_device)
    707 {
    708 	struct AvbOpsData *ops_data;
    709 
    710 	ops_data = avb_calloc(sizeof(struct AvbOpsData));
    711 	if (!ops_data)
    712 		return NULL;
    713 
    714 	ops_data->ops.user_data = ops_data;
    715 
    716 	ops_data->ops.read_from_partition = read_from_partition;
    717 	ops_data->ops.write_to_partition = write_to_partition;
    718 	ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
    719 	ops_data->ops.read_rollback_index = read_rollback_index;
    720 	ops_data->ops.write_rollback_index = write_rollback_index;
    721 	ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
    722 	ops_data->ops.get_unique_guid_for_partition =
    723 		get_unique_guid_for_partition;
    724 
    725 	ops_data->mmc_dev = boot_device;
    726 
    727 	return &ops_data->ops;
    728 }
    729 
    730 void avb_ops_free(AvbOps *ops)
    731 {
    732 	struct AvbOpsData *ops_data;
    733 
    734 	if (ops)
    735 		return;
    736 
    737 	ops_data = ops->user_data;
    738 
    739 	if (ops_data)
    740 		avb_free(ops_data);
    741 }
    742