xref: /openbmc/u-boot/common/avb_verify.c (revision 6663e074)
13af30e44SIgor Opaniuk /*
23af30e44SIgor Opaniuk  * (C) Copyright 2018, Linaro Limited
33af30e44SIgor Opaniuk  *
43af30e44SIgor Opaniuk  * SPDX-License-Identifier:	GPL-2.0+
53af30e44SIgor Opaniuk  */
63af30e44SIgor Opaniuk 
73af30e44SIgor Opaniuk #include <avb_verify.h>
8e9ee7398SIgor Opaniuk #include <blk.h>
93af30e44SIgor Opaniuk #include <fastboot.h>
103af30e44SIgor Opaniuk #include <image.h>
113af30e44SIgor Opaniuk #include <malloc.h>
123af30e44SIgor Opaniuk #include <part.h>
13*6663e074SJens Wiklander #include <tee.h>
14*6663e074SJens Wiklander #include <tee/optee_ta_avb.h>
153af30e44SIgor Opaniuk 
1655d56d23SEugeniu Rosca static const unsigned char avb_root_pub[1032] = {
173af30e44SIgor Opaniuk 	0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
183af30e44SIgor Opaniuk 	0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
193af30e44SIgor Opaniuk 	0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
203af30e44SIgor Opaniuk 	0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
213af30e44SIgor Opaniuk 	0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
223af30e44SIgor Opaniuk 	0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
233af30e44SIgor Opaniuk 	0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
243af30e44SIgor Opaniuk 	0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
253af30e44SIgor Opaniuk 	0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
263af30e44SIgor Opaniuk 	0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
273af30e44SIgor Opaniuk 	0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
283af30e44SIgor Opaniuk 	0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
293af30e44SIgor Opaniuk 	0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
303af30e44SIgor Opaniuk 	0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
313af30e44SIgor Opaniuk 	0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
323af30e44SIgor Opaniuk 	0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
333af30e44SIgor Opaniuk 	0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
343af30e44SIgor Opaniuk 	0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
353af30e44SIgor Opaniuk 	0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
363af30e44SIgor Opaniuk 	0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
373af30e44SIgor Opaniuk 	0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
383af30e44SIgor Opaniuk 	0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
393af30e44SIgor Opaniuk 	0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
403af30e44SIgor Opaniuk 	0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
413af30e44SIgor Opaniuk 	0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
423af30e44SIgor Opaniuk 	0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
433af30e44SIgor Opaniuk 	0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
443af30e44SIgor Opaniuk 	0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
453af30e44SIgor Opaniuk 	0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
463af30e44SIgor Opaniuk 	0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
473af30e44SIgor Opaniuk 	0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
483af30e44SIgor Opaniuk 	0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
493af30e44SIgor Opaniuk 	0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
503af30e44SIgor Opaniuk 	0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
513af30e44SIgor Opaniuk 	0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
523af30e44SIgor Opaniuk 	0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
533af30e44SIgor Opaniuk 	0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
543af30e44SIgor Opaniuk 	0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
553af30e44SIgor Opaniuk 	0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
563af30e44SIgor Opaniuk 	0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
573af30e44SIgor Opaniuk 	0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
583af30e44SIgor Opaniuk 	0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
593af30e44SIgor Opaniuk 	0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
603af30e44SIgor Opaniuk 	0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
613af30e44SIgor Opaniuk 	0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
623af30e44SIgor Opaniuk 	0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
633af30e44SIgor Opaniuk 	0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
643af30e44SIgor Opaniuk 	0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
653af30e44SIgor Opaniuk 	0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
663af30e44SIgor Opaniuk 	0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
673af30e44SIgor Opaniuk 	0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
683af30e44SIgor Opaniuk 	0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
693af30e44SIgor Opaniuk 	0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
703af30e44SIgor Opaniuk 	0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
713af30e44SIgor Opaniuk 	0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
723af30e44SIgor Opaniuk 	0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
733af30e44SIgor Opaniuk 	0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
743af30e44SIgor Opaniuk 	0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
753af30e44SIgor Opaniuk 	0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
763af30e44SIgor Opaniuk 	0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
773af30e44SIgor Opaniuk 	0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
783af30e44SIgor Opaniuk 	0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
793af30e44SIgor Opaniuk 	0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
803af30e44SIgor Opaniuk 	0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
813af30e44SIgor Opaniuk 	0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
823af30e44SIgor Opaniuk 	0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
833af30e44SIgor Opaniuk 	0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
843af30e44SIgor Opaniuk 	0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
853af30e44SIgor Opaniuk 	0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
863af30e44SIgor Opaniuk 	0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
873af30e44SIgor Opaniuk 	0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
883af30e44SIgor Opaniuk 	0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
893af30e44SIgor Opaniuk 	0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
903af30e44SIgor Opaniuk 	0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
913af30e44SIgor Opaniuk 	0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
923af30e44SIgor Opaniuk 	0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
933af30e44SIgor Opaniuk 	0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
943af30e44SIgor Opaniuk 	0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
953af30e44SIgor Opaniuk 	0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
963af30e44SIgor Opaniuk 	0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
973af30e44SIgor Opaniuk 	0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
983af30e44SIgor Opaniuk 	0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
993af30e44SIgor Opaniuk 	0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
1003af30e44SIgor Opaniuk 	0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
1013af30e44SIgor Opaniuk 	0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
1023af30e44SIgor Opaniuk 	0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
1033af30e44SIgor Opaniuk 	0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
1043af30e44SIgor Opaniuk 	0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
1053af30e44SIgor Opaniuk 	0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
1063af30e44SIgor Opaniuk 	0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
1073af30e44SIgor Opaniuk 	0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
1083af30e44SIgor Opaniuk 	0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
1093af30e44SIgor Opaniuk 	0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
1103af30e44SIgor Opaniuk 	0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
1113af30e44SIgor Opaniuk 	0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
1123af30e44SIgor Opaniuk 	0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
1133af30e44SIgor Opaniuk 	0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
1143af30e44SIgor Opaniuk 	0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
1153af30e44SIgor Opaniuk 	0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
1163af30e44SIgor Opaniuk 	0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
1173af30e44SIgor Opaniuk 	0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
1183af30e44SIgor Opaniuk 	0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
1193af30e44SIgor Opaniuk 	0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
1203af30e44SIgor Opaniuk 	0xd8, 0x7e,
1213af30e44SIgor Opaniuk };
1223af30e44SIgor Opaniuk 
1233af30e44SIgor Opaniuk /**
1243af30e44SIgor Opaniuk  * ============================================================================
1255d4fd877SIgor Opaniuk  * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
1265d4fd877SIgor Opaniuk  * ============================================================================
1275d4fd877SIgor Opaniuk  */
avb_set_state(AvbOps * ops,enum avb_boot_state boot_state)1285d4fd877SIgor Opaniuk char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
1295d4fd877SIgor Opaniuk {
1305d4fd877SIgor Opaniuk 	struct AvbOpsData *data;
1315d4fd877SIgor Opaniuk 	char *cmdline = NULL;
1325d4fd877SIgor Opaniuk 
1335d4fd877SIgor Opaniuk 	if (!ops)
1345d4fd877SIgor Opaniuk 		return NULL;
1355d4fd877SIgor Opaniuk 
1365d4fd877SIgor Opaniuk 	data = (struct AvbOpsData *)ops->user_data;
1375d4fd877SIgor Opaniuk 	if (!data)
1385d4fd877SIgor Opaniuk 		return NULL;
1395d4fd877SIgor Opaniuk 
1405d4fd877SIgor Opaniuk 	data->boot_state = boot_state;
1415d4fd877SIgor Opaniuk 	switch (boot_state) {
1425d4fd877SIgor Opaniuk 	case AVB_GREEN:
1435d4fd877SIgor Opaniuk 		cmdline = "androidboot.verifiedbootstate=green";
1445d4fd877SIgor Opaniuk 		break;
1455d4fd877SIgor Opaniuk 	case AVB_YELLOW:
1465d4fd877SIgor Opaniuk 		cmdline = "androidboot.verifiedbootstate=yellow";
1475d4fd877SIgor Opaniuk 		break;
1485d4fd877SIgor Opaniuk 	case AVB_ORANGE:
1495d4fd877SIgor Opaniuk 		cmdline = "androidboot.verifiedbootstate=orange";
1505d4fd877SIgor Opaniuk 	case AVB_RED:
1515d4fd877SIgor Opaniuk 		break;
1525d4fd877SIgor Opaniuk 	}
1535d4fd877SIgor Opaniuk 
1545d4fd877SIgor Opaniuk 	return cmdline;
1555d4fd877SIgor Opaniuk }
1565d4fd877SIgor Opaniuk 
append_cmd_line(char * cmdline_orig,char * cmdline_new)1575d4fd877SIgor Opaniuk char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
1585d4fd877SIgor Opaniuk {
1595d4fd877SIgor Opaniuk 	char *cmd_line;
1605d4fd877SIgor Opaniuk 
1615d4fd877SIgor Opaniuk 	if (!cmdline_new)
1625d4fd877SIgor Opaniuk 		return cmdline_orig;
1635d4fd877SIgor Opaniuk 
1645d4fd877SIgor Opaniuk 	if (cmdline_orig)
1655d4fd877SIgor Opaniuk 		cmd_line = cmdline_orig;
1665d4fd877SIgor Opaniuk 	else
1675d4fd877SIgor Opaniuk 		cmd_line = " ";
1685d4fd877SIgor Opaniuk 
1695d4fd877SIgor Opaniuk 	cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
1705d4fd877SIgor Opaniuk 
1715d4fd877SIgor Opaniuk 	return cmd_line;
1725d4fd877SIgor Opaniuk }
1735d4fd877SIgor Opaniuk 
avb_find_dm_args(char ** args,char * str)1745d4fd877SIgor Opaniuk static int avb_find_dm_args(char **args, char *str)
1755d4fd877SIgor Opaniuk {
1765d4fd877SIgor Opaniuk 	int i;
1775d4fd877SIgor Opaniuk 
1785d4fd877SIgor Opaniuk 	if (!str)
1795d4fd877SIgor Opaniuk 		return -1;
1805d4fd877SIgor Opaniuk 
1812e2067b8SEugeniu Rosca 	for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
1825d4fd877SIgor Opaniuk 		if (strstr(args[i], str))
1835d4fd877SIgor Opaniuk 			return i;
1845d4fd877SIgor Opaniuk 	}
1855d4fd877SIgor Opaniuk 
1865d4fd877SIgor Opaniuk 	return -1;
1875d4fd877SIgor Opaniuk }
1885d4fd877SIgor Opaniuk 
avb_set_enforce_option(const char * cmdline,const char * option)1895d4fd877SIgor Opaniuk static char *avb_set_enforce_option(const char *cmdline, const char *option)
1905d4fd877SIgor Opaniuk {
1915d4fd877SIgor Opaniuk 	char *cmdarg[AVB_MAX_ARGS];
1925d4fd877SIgor Opaniuk 	char *newargs = NULL;
1935d4fd877SIgor Opaniuk 	int i = 0;
1945d4fd877SIgor Opaniuk 	int total_args;
1955d4fd877SIgor Opaniuk 
1965d4fd877SIgor Opaniuk 	memset(cmdarg, 0, sizeof(cmdarg));
1975d4fd877SIgor Opaniuk 	cmdarg[i++] = strtok((char *)cmdline, " ");
1985d4fd877SIgor Opaniuk 
1995d4fd877SIgor Opaniuk 	do {
2005d4fd877SIgor Opaniuk 		cmdarg[i] = strtok(NULL, " ");
2015d4fd877SIgor Opaniuk 		if (!cmdarg[i])
2025d4fd877SIgor Opaniuk 			break;
2035d4fd877SIgor Opaniuk 
2045d4fd877SIgor Opaniuk 		if (++i >= AVB_MAX_ARGS) {
2055d4fd877SIgor Opaniuk 			printf("%s: Can't handle more then %d args\n",
2065d4fd877SIgor Opaniuk 			       __func__, i);
2075d4fd877SIgor Opaniuk 			return NULL;
2085d4fd877SIgor Opaniuk 		}
2095d4fd877SIgor Opaniuk 	} while (true);
2105d4fd877SIgor Opaniuk 
2115d4fd877SIgor Opaniuk 	total_args = i;
2125d4fd877SIgor Opaniuk 	i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
2135d4fd877SIgor Opaniuk 	if (i >= 0) {
2145d4fd877SIgor Opaniuk 		cmdarg[i] = (char *)option;
2155d4fd877SIgor Opaniuk 	} else {
2165d4fd877SIgor Opaniuk 		i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
2175d4fd877SIgor Opaniuk 		if (i < 0) {
2185d4fd877SIgor Opaniuk 			printf("%s: No verity options found\n", __func__);
2195d4fd877SIgor Opaniuk 			return NULL;
2205d4fd877SIgor Opaniuk 		}
2215d4fd877SIgor Opaniuk 
2225d4fd877SIgor Opaniuk 		cmdarg[i] = (char *)option;
2235d4fd877SIgor Opaniuk 	}
2245d4fd877SIgor Opaniuk 
2255d4fd877SIgor Opaniuk 	for (i = 0; i <= total_args; i++)
2265d4fd877SIgor Opaniuk 		newargs = append_cmd_line(newargs, cmdarg[i]);
2275d4fd877SIgor Opaniuk 
2285d4fd877SIgor Opaniuk 	return newargs;
2295d4fd877SIgor Opaniuk }
2305d4fd877SIgor Opaniuk 
avb_set_ignore_corruption(const char * cmdline)2315d4fd877SIgor Opaniuk char *avb_set_ignore_corruption(const char *cmdline)
2325d4fd877SIgor Opaniuk {
2335d4fd877SIgor Opaniuk 	char *newargs = NULL;
2345d4fd877SIgor Opaniuk 
2355d4fd877SIgor Opaniuk 	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
2365d4fd877SIgor Opaniuk 	if (newargs)
2375d4fd877SIgor Opaniuk 		newargs = append_cmd_line(newargs,
2385d4fd877SIgor Opaniuk 					  "androidboot.veritymode=eio");
2395d4fd877SIgor Opaniuk 
2405d4fd877SIgor Opaniuk 	return newargs;
2415d4fd877SIgor Opaniuk }
2425d4fd877SIgor Opaniuk 
avb_set_enforce_verity(const char * cmdline)2435d4fd877SIgor Opaniuk char *avb_set_enforce_verity(const char *cmdline)
2445d4fd877SIgor Opaniuk {
2455d4fd877SIgor Opaniuk 	char *newargs;
2465d4fd877SIgor Opaniuk 
2475d4fd877SIgor Opaniuk 	newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
2485d4fd877SIgor Opaniuk 	if (newargs)
2495d4fd877SIgor Opaniuk 		newargs = append_cmd_line(newargs,
2505d4fd877SIgor Opaniuk 					  "androidboot.veritymode=enforcing");
2515d4fd877SIgor Opaniuk 	return newargs;
2525d4fd877SIgor Opaniuk }
2535d4fd877SIgor Opaniuk 
2545d4fd877SIgor Opaniuk /**
2555d4fd877SIgor Opaniuk  * ============================================================================
2563af30e44SIgor Opaniuk  * IO(mmc) auxiliary functions
2573af30e44SIgor Opaniuk  * ============================================================================
2583af30e44SIgor Opaniuk  */
mmc_read_and_flush(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)2593af30e44SIgor Opaniuk static unsigned long mmc_read_and_flush(struct mmc_part *part,
2603af30e44SIgor Opaniuk 					lbaint_t start,
2613af30e44SIgor Opaniuk 					lbaint_t sectors,
2623af30e44SIgor Opaniuk 					void *buffer)
2633af30e44SIgor Opaniuk {
2643af30e44SIgor Opaniuk 	unsigned long blks;
2653af30e44SIgor Opaniuk 	void *tmp_buf;
2663af30e44SIgor Opaniuk 	size_t buf_size;
2673af30e44SIgor Opaniuk 	bool unaligned = is_buf_unaligned(buffer);
2683af30e44SIgor Opaniuk 
2693af30e44SIgor Opaniuk 	if (start < part->info.start) {
2703af30e44SIgor Opaniuk 		printf("%s: partition start out of bounds\n", __func__);
2713af30e44SIgor Opaniuk 		return 0;
2723af30e44SIgor Opaniuk 	}
2733af30e44SIgor Opaniuk 	if ((start + sectors) > (part->info.start + part->info.size)) {
2743af30e44SIgor Opaniuk 		sectors = part->info.start + part->info.size - start;
2753af30e44SIgor Opaniuk 		printf("%s: read sector aligned to partition bounds (%ld)\n",
2763af30e44SIgor Opaniuk 		       __func__, sectors);
2773af30e44SIgor Opaniuk 	}
2783af30e44SIgor Opaniuk 
2793af30e44SIgor Opaniuk 	/*
2803af30e44SIgor Opaniuk 	 * Reading fails on unaligned buffers, so we have to
2813af30e44SIgor Opaniuk 	 * use aligned temporary buffer and then copy to destination
2823af30e44SIgor Opaniuk 	 */
2833af30e44SIgor Opaniuk 
2843af30e44SIgor Opaniuk 	if (unaligned) {
2853af30e44SIgor Opaniuk 		printf("Handling unaligned read buffer..\n");
2863af30e44SIgor Opaniuk 		tmp_buf = get_sector_buf();
2873af30e44SIgor Opaniuk 		buf_size = get_sector_buf_size();
2883af30e44SIgor Opaniuk 		if (sectors > buf_size / part->info.blksz)
2893af30e44SIgor Opaniuk 			sectors = buf_size / part->info.blksz;
2903af30e44SIgor Opaniuk 	} else {
2913af30e44SIgor Opaniuk 		tmp_buf = buffer;
2923af30e44SIgor Opaniuk 	}
2933af30e44SIgor Opaniuk 
294e9ee7398SIgor Opaniuk 	blks = blk_dread(part->mmc_blk,
2953af30e44SIgor Opaniuk 			 start, sectors, tmp_buf);
2963af30e44SIgor Opaniuk 	/* flush cache after read */
2973af30e44SIgor Opaniuk 	flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
2983af30e44SIgor Opaniuk 
2993af30e44SIgor Opaniuk 	if (unaligned)
3003af30e44SIgor Opaniuk 		memcpy(buffer, tmp_buf, sectors * part->info.blksz);
3013af30e44SIgor Opaniuk 
3023af30e44SIgor Opaniuk 	return blks;
3033af30e44SIgor Opaniuk }
3043af30e44SIgor Opaniuk 
mmc_write(struct mmc_part * part,lbaint_t start,lbaint_t sectors,void * buffer)3053af30e44SIgor Opaniuk static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
3063af30e44SIgor Opaniuk 			       lbaint_t sectors, void *buffer)
3073af30e44SIgor Opaniuk {
3083af30e44SIgor Opaniuk 	void *tmp_buf;
3093af30e44SIgor Opaniuk 	size_t buf_size;
3103af30e44SIgor Opaniuk 	bool unaligned = is_buf_unaligned(buffer);
3113af30e44SIgor Opaniuk 
3123af30e44SIgor Opaniuk 	if (start < part->info.start) {
3133af30e44SIgor Opaniuk 		printf("%s: partition start out of bounds\n", __func__);
3143af30e44SIgor Opaniuk 		return 0;
3153af30e44SIgor Opaniuk 	}
3163af30e44SIgor Opaniuk 	if ((start + sectors) > (part->info.start + part->info.size)) {
3173af30e44SIgor Opaniuk 		sectors = part->info.start + part->info.size - start;
3183af30e44SIgor Opaniuk 		printf("%s: sector aligned to partition bounds (%ld)\n",
3193af30e44SIgor Opaniuk 		       __func__, sectors);
3203af30e44SIgor Opaniuk 	}
3213af30e44SIgor Opaniuk 	if (unaligned) {
3223af30e44SIgor Opaniuk 		tmp_buf = get_sector_buf();
3233af30e44SIgor Opaniuk 		buf_size = get_sector_buf_size();
3243af30e44SIgor Opaniuk 		printf("Handling unaligned wrire buffer..\n");
3253af30e44SIgor Opaniuk 		if (sectors > buf_size / part->info.blksz)
3263af30e44SIgor Opaniuk 			sectors = buf_size / part->info.blksz;
3273af30e44SIgor Opaniuk 
3283af30e44SIgor Opaniuk 		memcpy(tmp_buf, buffer, sectors * part->info.blksz);
3293af30e44SIgor Opaniuk 	} else {
3303af30e44SIgor Opaniuk 		tmp_buf = buffer;
3313af30e44SIgor Opaniuk 	}
3323af30e44SIgor Opaniuk 
333e9ee7398SIgor Opaniuk 	return blk_dwrite(part->mmc_blk,
3343af30e44SIgor Opaniuk 			  start, sectors, tmp_buf);
3353af30e44SIgor Opaniuk }
3363af30e44SIgor Opaniuk 
get_partition(AvbOps * ops,const char * partition)3373af30e44SIgor Opaniuk static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
3383af30e44SIgor Opaniuk {
3393af30e44SIgor Opaniuk 	int ret;
3403af30e44SIgor Opaniuk 	u8 dev_num;
3413af30e44SIgor Opaniuk 	int part_num = 0;
3423af30e44SIgor Opaniuk 	struct mmc_part *part;
3433af30e44SIgor Opaniuk 	struct blk_desc *mmc_blk;
3443af30e44SIgor Opaniuk 
3453af30e44SIgor Opaniuk 	part = malloc(sizeof(struct mmc_part));
3463af30e44SIgor Opaniuk 	if (!part)
3473af30e44SIgor Opaniuk 		return NULL;
3483af30e44SIgor Opaniuk 
3493af30e44SIgor Opaniuk 	dev_num = get_boot_device(ops);
3503af30e44SIgor Opaniuk 	part->mmc = find_mmc_device(dev_num);
3513af30e44SIgor Opaniuk 	if (!part->mmc) {
3523af30e44SIgor Opaniuk 		printf("No MMC device at slot %x\n", dev_num);
353047bc5c7SEugeniu Rosca 		goto err;
3543af30e44SIgor Opaniuk 	}
3553af30e44SIgor Opaniuk 
3563af30e44SIgor Opaniuk 	if (mmc_init(part->mmc)) {
3573af30e44SIgor Opaniuk 		printf("MMC initialization failed\n");
358047bc5c7SEugeniu Rosca 		goto err;
3593af30e44SIgor Opaniuk 	}
3603af30e44SIgor Opaniuk 
3613af30e44SIgor Opaniuk 	ret = mmc_switch_part(part->mmc, part_num);
3623af30e44SIgor Opaniuk 	if (ret)
363047bc5c7SEugeniu Rosca 		goto err;
3643af30e44SIgor Opaniuk 
3653af30e44SIgor Opaniuk 	mmc_blk = mmc_get_blk_desc(part->mmc);
3663af30e44SIgor Opaniuk 	if (!mmc_blk) {
3673af30e44SIgor Opaniuk 		printf("Error - failed to obtain block descriptor\n");
368047bc5c7SEugeniu Rosca 		goto err;
3693af30e44SIgor Opaniuk 	}
3703af30e44SIgor Opaniuk 
3713af30e44SIgor Opaniuk 	ret = part_get_info_by_name(mmc_blk, partition, &part->info);
3723af30e44SIgor Opaniuk 	if (!ret) {
3733af30e44SIgor Opaniuk 		printf("Can't find partition '%s'\n", partition);
374047bc5c7SEugeniu Rosca 		goto err;
3753af30e44SIgor Opaniuk 	}
3763af30e44SIgor Opaniuk 
3773af30e44SIgor Opaniuk 	part->dev_num = dev_num;
3783af30e44SIgor Opaniuk 	part->mmc_blk = mmc_blk;
3793af30e44SIgor Opaniuk 
3803af30e44SIgor Opaniuk 	return part;
381047bc5c7SEugeniu Rosca err:
382047bc5c7SEugeniu Rosca 	free(part);
383047bc5c7SEugeniu Rosca 	return NULL;
3843af30e44SIgor Opaniuk }
3853af30e44SIgor Opaniuk 
mmc_byte_io(AvbOps * ops,const char * partition,s64 offset,size_t num_bytes,void * buffer,size_t * out_num_read,enum mmc_io_type io_type)3863af30e44SIgor Opaniuk static AvbIOResult mmc_byte_io(AvbOps *ops,
3873af30e44SIgor Opaniuk 			       const char *partition,
3883af30e44SIgor Opaniuk 			       s64 offset,
3893af30e44SIgor Opaniuk 			       size_t num_bytes,
3903af30e44SIgor Opaniuk 			       void *buffer,
3913af30e44SIgor Opaniuk 			       size_t *out_num_read,
3923af30e44SIgor Opaniuk 			       enum mmc_io_type io_type)
3933af30e44SIgor Opaniuk {
3943af30e44SIgor Opaniuk 	ulong ret;
3953af30e44SIgor Opaniuk 	struct mmc_part *part;
3963af30e44SIgor Opaniuk 	u64 start_offset, start_sector, sectors, residue;
3973af30e44SIgor Opaniuk 	u8 *tmp_buf;
3983af30e44SIgor Opaniuk 	size_t io_cnt = 0;
3993af30e44SIgor Opaniuk 
4003af30e44SIgor Opaniuk 	if (!partition || !buffer || io_type > IO_WRITE)
4013af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_IO;
4023af30e44SIgor Opaniuk 
4033af30e44SIgor Opaniuk 	part = get_partition(ops, partition);
4043af30e44SIgor Opaniuk 	if (!part)
4053af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
4063af30e44SIgor Opaniuk 
407e1904f45SEugeniu Rosca 	if (!part->info.blksz)
408e1904f45SEugeniu Rosca 		return AVB_IO_RESULT_ERROR_IO;
409e1904f45SEugeniu Rosca 
4103af30e44SIgor Opaniuk 	start_offset = calc_offset(part, offset);
4113af30e44SIgor Opaniuk 	while (num_bytes) {
4123af30e44SIgor Opaniuk 		start_sector = start_offset / part->info.blksz;
4133af30e44SIgor Opaniuk 		sectors = num_bytes / part->info.blksz;
4143af30e44SIgor Opaniuk 		/* handle non block-aligned reads */
4153af30e44SIgor Opaniuk 		if (start_offset % part->info.blksz ||
4163af30e44SIgor Opaniuk 		    num_bytes < part->info.blksz) {
4173af30e44SIgor Opaniuk 			tmp_buf = get_sector_buf();
4183af30e44SIgor Opaniuk 			if (start_offset % part->info.blksz) {
4193af30e44SIgor Opaniuk 				residue = part->info.blksz -
4203af30e44SIgor Opaniuk 					(start_offset % part->info.blksz);
4213af30e44SIgor Opaniuk 				if (residue > num_bytes)
4223af30e44SIgor Opaniuk 					residue = num_bytes;
4233af30e44SIgor Opaniuk 			} else {
4243af30e44SIgor Opaniuk 				residue = num_bytes;
4253af30e44SIgor Opaniuk 			}
4263af30e44SIgor Opaniuk 
4273af30e44SIgor Opaniuk 			if (io_type == IO_READ) {
4283af30e44SIgor Opaniuk 				ret = mmc_read_and_flush(part,
4293af30e44SIgor Opaniuk 							 part->info.start +
4303af30e44SIgor Opaniuk 							 start_sector,
4313af30e44SIgor Opaniuk 							 1, tmp_buf);
4323af30e44SIgor Opaniuk 
4333af30e44SIgor Opaniuk 				if (ret != 1) {
4343af30e44SIgor Opaniuk 					printf("%s: read error (%ld, %lld)\n",
4353af30e44SIgor Opaniuk 					       __func__, ret, start_sector);
4363af30e44SIgor Opaniuk 					return AVB_IO_RESULT_ERROR_IO;
4373af30e44SIgor Opaniuk 				}
4383af30e44SIgor Opaniuk 				/*
4393af30e44SIgor Opaniuk 				 * if this is not aligned at sector start,
4403af30e44SIgor Opaniuk 				 * we have to adjust the tmp buffer
4413af30e44SIgor Opaniuk 				 */
4423af30e44SIgor Opaniuk 				tmp_buf += (start_offset % part->info.blksz);
4433af30e44SIgor Opaniuk 				memcpy(buffer, (void *)tmp_buf, residue);
4443af30e44SIgor Opaniuk 			} else {
4453af30e44SIgor Opaniuk 				ret = mmc_read_and_flush(part,
4463af30e44SIgor Opaniuk 							 part->info.start +
4473af30e44SIgor Opaniuk 							 start_sector,
4483af30e44SIgor Opaniuk 							 1, tmp_buf);
4493af30e44SIgor Opaniuk 
4503af30e44SIgor Opaniuk 				if (ret != 1) {
4513af30e44SIgor Opaniuk 					printf("%s: read error (%ld, %lld)\n",
4523af30e44SIgor Opaniuk 					       __func__, ret, start_sector);
4533af30e44SIgor Opaniuk 					return AVB_IO_RESULT_ERROR_IO;
4543af30e44SIgor Opaniuk 				}
4553af30e44SIgor Opaniuk 				memcpy((void *)tmp_buf +
4563af30e44SIgor Opaniuk 					start_offset % part->info.blksz,
4573af30e44SIgor Opaniuk 					buffer, residue);
4583af30e44SIgor Opaniuk 
4593af30e44SIgor Opaniuk 				ret = mmc_write(part, part->info.start +
4603af30e44SIgor Opaniuk 						start_sector, 1, tmp_buf);
4613af30e44SIgor Opaniuk 				if (ret != 1) {
4623af30e44SIgor Opaniuk 					printf("%s: write error (%ld, %lld)\n",
4633af30e44SIgor Opaniuk 					       __func__, ret, start_sector);
4643af30e44SIgor Opaniuk 					return AVB_IO_RESULT_ERROR_IO;
4653af30e44SIgor Opaniuk 				}
4663af30e44SIgor Opaniuk 			}
4673af30e44SIgor Opaniuk 
4683af30e44SIgor Opaniuk 			io_cnt += residue;
4693af30e44SIgor Opaniuk 			buffer += residue;
4703af30e44SIgor Opaniuk 			start_offset += residue;
4713af30e44SIgor Opaniuk 			num_bytes -= residue;
4723af30e44SIgor Opaniuk 			continue;
4733af30e44SIgor Opaniuk 		}
4743af30e44SIgor Opaniuk 
4753af30e44SIgor Opaniuk 		if (sectors) {
4763af30e44SIgor Opaniuk 			if (io_type == IO_READ) {
4773af30e44SIgor Opaniuk 				ret = mmc_read_and_flush(part,
4783af30e44SIgor Opaniuk 							 part->info.start +
4793af30e44SIgor Opaniuk 							 start_sector,
4803af30e44SIgor Opaniuk 							 sectors, buffer);
4813af30e44SIgor Opaniuk 			} else {
4823af30e44SIgor Opaniuk 				ret = mmc_write(part,
4833af30e44SIgor Opaniuk 						part->info.start +
4843af30e44SIgor Opaniuk 						start_sector,
4853af30e44SIgor Opaniuk 						sectors, buffer);
4863af30e44SIgor Opaniuk 			}
4873af30e44SIgor Opaniuk 
4883af30e44SIgor Opaniuk 			if (!ret) {
4893af30e44SIgor Opaniuk 				printf("%s: sector read error\n", __func__);
4903af30e44SIgor Opaniuk 				return AVB_IO_RESULT_ERROR_IO;
4913af30e44SIgor Opaniuk 			}
4923af30e44SIgor Opaniuk 
4933af30e44SIgor Opaniuk 			io_cnt += ret * part->info.blksz;
4943af30e44SIgor Opaniuk 			buffer += ret * part->info.blksz;
4953af30e44SIgor Opaniuk 			start_offset += ret * part->info.blksz;
4963af30e44SIgor Opaniuk 			num_bytes -= ret * part->info.blksz;
4973af30e44SIgor Opaniuk 		}
4983af30e44SIgor Opaniuk 	}
4993af30e44SIgor Opaniuk 
5003af30e44SIgor Opaniuk 	/* Set counter for read operation */
5013af30e44SIgor Opaniuk 	if (io_type == IO_READ && out_num_read)
5023af30e44SIgor Opaniuk 		*out_num_read = io_cnt;
5033af30e44SIgor Opaniuk 
5043af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
5053af30e44SIgor Opaniuk }
5063af30e44SIgor Opaniuk 
5073af30e44SIgor Opaniuk /**
5083af30e44SIgor Opaniuk  * ============================================================================
5093af30e44SIgor Opaniuk  * AVB 2.0 operations
5103af30e44SIgor Opaniuk  * ============================================================================
5113af30e44SIgor Opaniuk  */
5123af30e44SIgor Opaniuk 
5133af30e44SIgor Opaniuk /**
5143af30e44SIgor Opaniuk  * read_from_partition() - reads @num_bytes from  @offset from partition
5153af30e44SIgor Opaniuk  * identified by a string name
5163af30e44SIgor Opaniuk  *
5173af30e44SIgor Opaniuk  * @ops: contains AVB ops handlers
5183af30e44SIgor Opaniuk  * @partition_name: partition name, NUL-terminated UTF-8 string
5193af30e44SIgor Opaniuk  * @offset: offset from the beginning of partition
5203af30e44SIgor Opaniuk  * @num_bytes: amount of bytes to read
5213af30e44SIgor Opaniuk  * @buffer: destination buffer to store data
5223af30e44SIgor Opaniuk  * @out_num_read:
5233af30e44SIgor Opaniuk  *
5243af30e44SIgor Opaniuk  * @return:
5253af30e44SIgor Opaniuk  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
5263af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
5273af30e44SIgor Opaniuk  *            subsystem
5283af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
5293af30e44SIgor Opaniuk  *      the given name
5303af30e44SIgor Opaniuk  */
read_from_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,void * buffer,size_t * out_num_read)5313af30e44SIgor Opaniuk static AvbIOResult read_from_partition(AvbOps *ops,
5323af30e44SIgor Opaniuk 				       const char *partition_name,
5333af30e44SIgor Opaniuk 				       s64 offset_from_partition,
5343af30e44SIgor Opaniuk 				       size_t num_bytes,
5353af30e44SIgor Opaniuk 				       void *buffer,
5363af30e44SIgor Opaniuk 				       size_t *out_num_read)
5373af30e44SIgor Opaniuk {
5383af30e44SIgor Opaniuk 	return mmc_byte_io(ops, partition_name, offset_from_partition,
5393af30e44SIgor Opaniuk 			   num_bytes, buffer, out_num_read, IO_READ);
5403af30e44SIgor Opaniuk }
5413af30e44SIgor Opaniuk 
5423af30e44SIgor Opaniuk /**
5433af30e44SIgor Opaniuk  * write_to_partition() - writes N bytes to a partition identified by a string
5443af30e44SIgor Opaniuk  * name
5453af30e44SIgor Opaniuk  *
5463af30e44SIgor Opaniuk  * @ops: AvbOps, contains AVB ops handlers
5473af30e44SIgor Opaniuk  * @partition_name: partition name
5483af30e44SIgor Opaniuk  * @offset_from_partition: offset from the beginning of partition
5493af30e44SIgor Opaniuk  * @num_bytes: amount of bytes to write
5503af30e44SIgor Opaniuk  * @buf: data to write
5513af30e44SIgor Opaniuk  * @out_num_read:
5523af30e44SIgor Opaniuk  *
5533af30e44SIgor Opaniuk  * @return:
5543af30e44SIgor Opaniuk  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
5553af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_IO, if input/output error occurred
5563af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
5573af30e44SIgor Opaniuk  *            @partition_name was not found
5583af30e44SIgor Opaniuk  */
write_to_partition(AvbOps * ops,const char * partition_name,s64 offset_from_partition,size_t num_bytes,const void * buffer)5593af30e44SIgor Opaniuk static AvbIOResult write_to_partition(AvbOps *ops,
5603af30e44SIgor Opaniuk 				      const char *partition_name,
5613af30e44SIgor Opaniuk 				      s64 offset_from_partition,
5623af30e44SIgor Opaniuk 				      size_t num_bytes,
5633af30e44SIgor Opaniuk 				      const void *buffer)
5643af30e44SIgor Opaniuk {
5653af30e44SIgor Opaniuk 	return mmc_byte_io(ops, partition_name, offset_from_partition,
5663af30e44SIgor Opaniuk 			   num_bytes, (void *)buffer, NULL, IO_WRITE);
5673af30e44SIgor Opaniuk }
5683af30e44SIgor Opaniuk 
5693af30e44SIgor Opaniuk /**
5703af30e44SIgor Opaniuk  * validate_vmbeta_public_key() - checks if the given public key used to sign
5713af30e44SIgor Opaniuk  * the vbmeta partition is trusted
5723af30e44SIgor Opaniuk  *
5733af30e44SIgor Opaniuk  * @ops: AvbOps, contains AVB ops handlers
5743af30e44SIgor Opaniuk  * @public_key_data: public key for verifying vbmeta partition signature
5753af30e44SIgor Opaniuk  * @public_key_length: length of public key
5763af30e44SIgor Opaniuk  * @public_key_metadata:
5773af30e44SIgor Opaniuk  * @public_key_metadata_length:
5783af30e44SIgor Opaniuk  * @out_key_is_trusted:
5793af30e44SIgor Opaniuk  *
5803af30e44SIgor Opaniuk  * @return:
5813af30e44SIgor Opaniuk  *      AVB_IO_RESULT_OK, if partition was found and read operation succeed
5823af30e44SIgor Opaniuk  */
validate_vbmeta_public_key(AvbOps * ops,const u8 * public_key_data,size_t public_key_length,const u8 * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)5833af30e44SIgor Opaniuk static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
5843af30e44SIgor Opaniuk 					      const u8 *public_key_data,
5853af30e44SIgor Opaniuk 					      size_t public_key_length,
5863af30e44SIgor Opaniuk 					      const u8
5873af30e44SIgor Opaniuk 					      *public_key_metadata,
5883af30e44SIgor Opaniuk 					      size_t
5893af30e44SIgor Opaniuk 					      public_key_metadata_length,
5903af30e44SIgor Opaniuk 					      bool *out_key_is_trusted)
5913af30e44SIgor Opaniuk {
5923af30e44SIgor Opaniuk 	if (!public_key_length || !public_key_data || !out_key_is_trusted)
5933af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_IO;
5943af30e44SIgor Opaniuk 
5953af30e44SIgor Opaniuk 	*out_key_is_trusted = false;
5963af30e44SIgor Opaniuk 	if (public_key_length != sizeof(avb_root_pub))
5973af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_IO;
5983af30e44SIgor Opaniuk 
5993af30e44SIgor Opaniuk 	if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
6003af30e44SIgor Opaniuk 		*out_key_is_trusted = true;
6013af30e44SIgor Opaniuk 
6023af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
6033af30e44SIgor Opaniuk }
6043af30e44SIgor Opaniuk 
605*6663e074SJens Wiklander #ifdef CONFIG_OPTEE_TA_AVB
get_open_session(struct AvbOpsData * ops_data)606*6663e074SJens Wiklander static int get_open_session(struct AvbOpsData *ops_data)
607*6663e074SJens Wiklander {
608*6663e074SJens Wiklander 	struct udevice *tee = NULL;
609*6663e074SJens Wiklander 
610*6663e074SJens Wiklander 	while (!ops_data->tee) {
611*6663e074SJens Wiklander 		const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
612*6663e074SJens Wiklander 		struct tee_open_session_arg arg;
613*6663e074SJens Wiklander 		int rc;
614*6663e074SJens Wiklander 
615*6663e074SJens Wiklander 		tee = tee_find_device(tee, NULL, NULL, NULL);
616*6663e074SJens Wiklander 		if (!tee)
617*6663e074SJens Wiklander 			return -ENODEV;
618*6663e074SJens Wiklander 
619*6663e074SJens Wiklander 		memset(&arg, 0, sizeof(arg));
620*6663e074SJens Wiklander 		tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
621*6663e074SJens Wiklander 		rc = tee_open_session(tee, &arg, 0, NULL);
622*6663e074SJens Wiklander 		if (!rc) {
623*6663e074SJens Wiklander 			ops_data->tee = tee;
624*6663e074SJens Wiklander 			ops_data->session = arg.session;
625*6663e074SJens Wiklander 		}
626*6663e074SJens Wiklander 	}
627*6663e074SJens Wiklander 
628*6663e074SJens Wiklander 	return 0;
629*6663e074SJens Wiklander }
630*6663e074SJens Wiklander 
invoke_func(struct AvbOpsData * ops_data,u32 func,ulong num_param,struct tee_param * param)631*6663e074SJens Wiklander static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
632*6663e074SJens Wiklander 			       ulong num_param, struct tee_param *param)
633*6663e074SJens Wiklander {
634*6663e074SJens Wiklander 	struct tee_invoke_arg arg;
635*6663e074SJens Wiklander 
636*6663e074SJens Wiklander 	if (get_open_session(ops_data))
637*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_IO;
638*6663e074SJens Wiklander 
639*6663e074SJens Wiklander 	memset(&arg, 0, sizeof(arg));
640*6663e074SJens Wiklander 	arg.func = func;
641*6663e074SJens Wiklander 	arg.session = ops_data->session;
642*6663e074SJens Wiklander 
643*6663e074SJens Wiklander 	if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
644*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_IO;
645*6663e074SJens Wiklander 	switch (arg.ret) {
646*6663e074SJens Wiklander 	case TEE_SUCCESS:
647*6663e074SJens Wiklander 		return AVB_IO_RESULT_OK;
648*6663e074SJens Wiklander 	case TEE_ERROR_OUT_OF_MEMORY:
649*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_OOM;
650*6663e074SJens Wiklander 	case TEE_ERROR_TARGET_DEAD:
651*6663e074SJens Wiklander 		/*
652*6663e074SJens Wiklander 		 * The TA has paniced, close the session to reload the TA
653*6663e074SJens Wiklander 		 * for the next request.
654*6663e074SJens Wiklander 		 */
655*6663e074SJens Wiklander 		tee_close_session(ops_data->tee, ops_data->session);
656*6663e074SJens Wiklander 		ops_data->tee = NULL;
657*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_IO;
658*6663e074SJens Wiklander 	default:
659*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_IO;
660*6663e074SJens Wiklander 	}
661*6663e074SJens Wiklander }
662*6663e074SJens Wiklander #endif
663*6663e074SJens Wiklander 
6643af30e44SIgor Opaniuk /**
6653af30e44SIgor Opaniuk  * read_rollback_index() - gets the rollback index corresponding to the
6663af30e44SIgor Opaniuk  * location of given by @out_rollback_index.
6673af30e44SIgor Opaniuk  *
6683af30e44SIgor Opaniuk  * @ops: contains AvbOps handlers
6693af30e44SIgor Opaniuk  * @rollback_index_slot:
6703af30e44SIgor Opaniuk  * @out_rollback_index: used to write a retrieved rollback index.
6713af30e44SIgor Opaniuk  *
6723af30e44SIgor Opaniuk  * @return
6733af30e44SIgor Opaniuk  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
6743af30e44SIgor Opaniuk  */
read_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 * out_rollback_index)6753af30e44SIgor Opaniuk static AvbIOResult read_rollback_index(AvbOps *ops,
6763af30e44SIgor Opaniuk 				       size_t rollback_index_slot,
6773af30e44SIgor Opaniuk 				       u64 *out_rollback_index)
6783af30e44SIgor Opaniuk {
679*6663e074SJens Wiklander #ifndef CONFIG_OPTEE_TA_AVB
6803af30e44SIgor Opaniuk 	/* For now we always return 0 as the stored rollback index. */
6815d4fd877SIgor Opaniuk 	printf("%s not supported yet\n", __func__);
6823af30e44SIgor Opaniuk 
6833af30e44SIgor Opaniuk 	if (out_rollback_index)
6843af30e44SIgor Opaniuk 		*out_rollback_index = 0;
6853af30e44SIgor Opaniuk 
6863af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
687*6663e074SJens Wiklander #else
688*6663e074SJens Wiklander 	AvbIOResult rc;
689*6663e074SJens Wiklander 	struct tee_param param[2];
690*6663e074SJens Wiklander 
691*6663e074SJens Wiklander 	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
692*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
693*6663e074SJens Wiklander 
694*6663e074SJens Wiklander 	memset(param, 0, sizeof(param));
695*6663e074SJens Wiklander 	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
696*6663e074SJens Wiklander 	param[0].u.value.a = rollback_index_slot;
697*6663e074SJens Wiklander 	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
698*6663e074SJens Wiklander 
699*6663e074SJens Wiklander 	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
700*6663e074SJens Wiklander 			 ARRAY_SIZE(param), param);
701*6663e074SJens Wiklander 	if (rc)
702*6663e074SJens Wiklander 		return rc;
703*6663e074SJens Wiklander 
704*6663e074SJens Wiklander 	*out_rollback_index = (u64)param[1].u.value.a << 32 |
705*6663e074SJens Wiklander 			      (u32)param[1].u.value.b;
706*6663e074SJens Wiklander 	return AVB_IO_RESULT_OK;
707*6663e074SJens Wiklander #endif
7083af30e44SIgor Opaniuk }
7093af30e44SIgor Opaniuk 
7103af30e44SIgor Opaniuk /**
7113af30e44SIgor Opaniuk  * write_rollback_index() - sets the rollback index corresponding to the
7123af30e44SIgor Opaniuk  * location of given by @out_rollback_index.
7133af30e44SIgor Opaniuk  *
7143af30e44SIgor Opaniuk  * @ops: contains AvbOps handlers
7153af30e44SIgor Opaniuk  * @rollback_index_slot:
7163af30e44SIgor Opaniuk  * @rollback_index: rollback index to write.
7173af30e44SIgor Opaniuk  *
7183af30e44SIgor Opaniuk  * @return
7193af30e44SIgor Opaniuk  *       AVB_IO_RESULT_OK, if the roolback index was retrieved
7203af30e44SIgor Opaniuk  */
write_rollback_index(AvbOps * ops,size_t rollback_index_slot,u64 rollback_index)7213af30e44SIgor Opaniuk static AvbIOResult write_rollback_index(AvbOps *ops,
7223af30e44SIgor Opaniuk 					size_t rollback_index_slot,
7233af30e44SIgor Opaniuk 					u64 rollback_index)
7243af30e44SIgor Opaniuk {
725*6663e074SJens Wiklander #ifndef CONFIG_OPTEE_TA_AVB
7263af30e44SIgor Opaniuk 	/* For now this is a no-op. */
7275d4fd877SIgor Opaniuk 	printf("%s not supported yet\n", __func__);
7283af30e44SIgor Opaniuk 
7293af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
730*6663e074SJens Wiklander #else
731*6663e074SJens Wiklander 	struct tee_param param[2];
732*6663e074SJens Wiklander 
733*6663e074SJens Wiklander 	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
734*6663e074SJens Wiklander 		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
735*6663e074SJens Wiklander 
736*6663e074SJens Wiklander 	memset(param, 0, sizeof(param));
737*6663e074SJens Wiklander 	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
738*6663e074SJens Wiklander 	param[0].u.value.a = rollback_index_slot;
739*6663e074SJens Wiklander 	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
740*6663e074SJens Wiklander 	param[1].u.value.a = (u32)(rollback_index >> 32);
741*6663e074SJens Wiklander 	param[1].u.value.b = (u32)rollback_index;
742*6663e074SJens Wiklander 
743*6663e074SJens Wiklander 	return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
744*6663e074SJens Wiklander 			   ARRAY_SIZE(param), param);
745*6663e074SJens Wiklander #endif
7463af30e44SIgor Opaniuk }
7473af30e44SIgor Opaniuk 
7483af30e44SIgor Opaniuk /**
7493af30e44SIgor Opaniuk  * read_is_device_unlocked() - gets whether the device is unlocked
7503af30e44SIgor Opaniuk  *
7513af30e44SIgor Opaniuk  * @ops: contains AVB ops handlers
7523af30e44SIgor Opaniuk  * @out_is_unlocked: device unlock state is stored here, true if unlocked,
7533af30e44SIgor Opaniuk  *       false otherwise
7543af30e44SIgor Opaniuk  *
7553af30e44SIgor Opaniuk  * @return:
7563af30e44SIgor Opaniuk  *       AVB_IO_RESULT_OK: state is retrieved successfully
7573af30e44SIgor Opaniuk  *       AVB_IO_RESULT_ERROR_IO: an error occurred
7583af30e44SIgor Opaniuk  */
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)7593af30e44SIgor Opaniuk static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
7603af30e44SIgor Opaniuk {
761*6663e074SJens Wiklander #ifndef CONFIG_OPTEE_TA_AVB
7623af30e44SIgor Opaniuk 	/* For now we always return that the device is unlocked. */
7633af30e44SIgor Opaniuk 
7645d4fd877SIgor Opaniuk 	printf("%s not supported yet\n", __func__);
7653af30e44SIgor Opaniuk 
7663af30e44SIgor Opaniuk 	*out_is_unlocked = true;
7673af30e44SIgor Opaniuk 
7683af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
769*6663e074SJens Wiklander #else
770*6663e074SJens Wiklander 	AvbIOResult rc;
771*6663e074SJens Wiklander 	struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
772*6663e074SJens Wiklander 
773*6663e074SJens Wiklander 	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
774*6663e074SJens Wiklander 	if (rc)
775*6663e074SJens Wiklander 		return rc;
776*6663e074SJens Wiklander 	*out_is_unlocked = !param.u.value.a;
777*6663e074SJens Wiklander 	return AVB_IO_RESULT_OK;
778*6663e074SJens Wiklander #endif
7793af30e44SIgor Opaniuk }
7803af30e44SIgor Opaniuk 
7813af30e44SIgor Opaniuk /**
7823af30e44SIgor Opaniuk  * get_unique_guid_for_partition() - gets the GUID for a partition identified
7833af30e44SIgor Opaniuk  * by a string name
7843af30e44SIgor Opaniuk  *
7853af30e44SIgor Opaniuk  * @ops: contains AVB ops handlers
7863af30e44SIgor Opaniuk  * @partition: partition name (NUL-terminated UTF-8 string)
7873af30e44SIgor Opaniuk  * @guid_buf: buf, used to copy in GUID string. Example of value:
7883af30e44SIgor Opaniuk  *      527c1c6d-6361-4593-8842-3c78fcd39219
7893af30e44SIgor Opaniuk  * @guid_buf_size: @guid_buf buffer size
7903af30e44SIgor Opaniuk  *
7913af30e44SIgor Opaniuk  * @return:
7923af30e44SIgor Opaniuk  *      AVB_IO_RESULT_OK, on success (GUID found)
7933af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
7943af30e44SIgor Opaniuk  *             provided
7953af30e44SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
7963af30e44SIgor Opaniuk  */
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)7973af30e44SIgor Opaniuk static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
7983af30e44SIgor Opaniuk 						 const char *partition,
7993af30e44SIgor Opaniuk 						 char *guid_buf,
8003af30e44SIgor Opaniuk 						 size_t guid_buf_size)
8013af30e44SIgor Opaniuk {
8023af30e44SIgor Opaniuk 	struct mmc_part *part;
8033af30e44SIgor Opaniuk 	size_t uuid_size;
8043af30e44SIgor Opaniuk 
8053af30e44SIgor Opaniuk 	part = get_partition(ops, partition);
8063af30e44SIgor Opaniuk 	if (!part)
8073af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
8083af30e44SIgor Opaniuk 
8093af30e44SIgor Opaniuk 	uuid_size = sizeof(part->info.uuid);
8103af30e44SIgor Opaniuk 	if (uuid_size > guid_buf_size)
8113af30e44SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_IO;
8123af30e44SIgor Opaniuk 
8133af30e44SIgor Opaniuk 	memcpy(guid_buf, part->info.uuid, uuid_size);
8143af30e44SIgor Opaniuk 	guid_buf[uuid_size - 1] = 0;
8153af30e44SIgor Opaniuk 
8163af30e44SIgor Opaniuk 	return AVB_IO_RESULT_OK;
8173af30e44SIgor Opaniuk }
8183af30e44SIgor Opaniuk 
8193af30e44SIgor Opaniuk /**
8207a5fbfe6SIgor Opaniuk  * get_size_of_partition() - gets the size of a partition identified
8217a5fbfe6SIgor Opaniuk  * by a string name
8227a5fbfe6SIgor Opaniuk  *
8237a5fbfe6SIgor Opaniuk  * @ops: contains AVB ops handlers
8247a5fbfe6SIgor Opaniuk  * @partition: partition name (NUL-terminated UTF-8 string)
8257a5fbfe6SIgor Opaniuk  * @out_size_num_bytes: returns the value of a partition size
8267a5fbfe6SIgor Opaniuk  *
8277a5fbfe6SIgor Opaniuk  * @return:
8287a5fbfe6SIgor Opaniuk  *      AVB_IO_RESULT_OK, on success (GUID found)
8297a5fbfe6SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
8307a5fbfe6SIgor Opaniuk  *      AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
8317a5fbfe6SIgor Opaniuk  */
get_size_of_partition(AvbOps * ops,const char * partition,u64 * out_size_num_bytes)8327a5fbfe6SIgor Opaniuk static AvbIOResult get_size_of_partition(AvbOps *ops,
8337a5fbfe6SIgor Opaniuk 					 const char *partition,
8347a5fbfe6SIgor Opaniuk 					 u64 *out_size_num_bytes)
8357a5fbfe6SIgor Opaniuk {
8367a5fbfe6SIgor Opaniuk 	struct mmc_part *part;
8377a5fbfe6SIgor Opaniuk 
8387a5fbfe6SIgor Opaniuk 	if (!out_size_num_bytes)
8397a5fbfe6SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
8407a5fbfe6SIgor Opaniuk 
8417a5fbfe6SIgor Opaniuk 	part = get_partition(ops, partition);
8427a5fbfe6SIgor Opaniuk 	if (!part)
8437a5fbfe6SIgor Opaniuk 		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
8447a5fbfe6SIgor Opaniuk 
8457a5fbfe6SIgor Opaniuk 	*out_size_num_bytes = part->info.blksz * part->info.size;
8467a5fbfe6SIgor Opaniuk 
8477a5fbfe6SIgor Opaniuk 	return AVB_IO_RESULT_OK;
8487a5fbfe6SIgor Opaniuk }
8497a5fbfe6SIgor Opaniuk 
8507a5fbfe6SIgor Opaniuk /**
8513af30e44SIgor Opaniuk  * ============================================================================
8523af30e44SIgor Opaniuk  * AVB2.0 AvbOps alloc/initialisation/free
8533af30e44SIgor Opaniuk  * ============================================================================
8543af30e44SIgor Opaniuk  */
avb_ops_alloc(int boot_device)8553af30e44SIgor Opaniuk AvbOps *avb_ops_alloc(int boot_device)
8563af30e44SIgor Opaniuk {
8573af30e44SIgor Opaniuk 	struct AvbOpsData *ops_data;
8583af30e44SIgor Opaniuk 
8593af30e44SIgor Opaniuk 	ops_data = avb_calloc(sizeof(struct AvbOpsData));
8603af30e44SIgor Opaniuk 	if (!ops_data)
8613af30e44SIgor Opaniuk 		return NULL;
8623af30e44SIgor Opaniuk 
8633af30e44SIgor Opaniuk 	ops_data->ops.user_data = ops_data;
8643af30e44SIgor Opaniuk 
8653af30e44SIgor Opaniuk 	ops_data->ops.read_from_partition = read_from_partition;
8663af30e44SIgor Opaniuk 	ops_data->ops.write_to_partition = write_to_partition;
8673af30e44SIgor Opaniuk 	ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
8683af30e44SIgor Opaniuk 	ops_data->ops.read_rollback_index = read_rollback_index;
8693af30e44SIgor Opaniuk 	ops_data->ops.write_rollback_index = write_rollback_index;
8703af30e44SIgor Opaniuk 	ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
8713af30e44SIgor Opaniuk 	ops_data->ops.get_unique_guid_for_partition =
8723af30e44SIgor Opaniuk 		get_unique_guid_for_partition;
8737a5fbfe6SIgor Opaniuk 	ops_data->ops.get_size_of_partition = get_size_of_partition;
8743af30e44SIgor Opaniuk 	ops_data->mmc_dev = boot_device;
8753af30e44SIgor Opaniuk 
8763af30e44SIgor Opaniuk 	return &ops_data->ops;
8773af30e44SIgor Opaniuk }
8783af30e44SIgor Opaniuk 
avb_ops_free(AvbOps * ops)8793af30e44SIgor Opaniuk void avb_ops_free(AvbOps *ops)
8803af30e44SIgor Opaniuk {
8813af30e44SIgor Opaniuk 	struct AvbOpsData *ops_data;
8823af30e44SIgor Opaniuk 
88347e41631SEugeniu Rosca 	if (!ops)
8843af30e44SIgor Opaniuk 		return;
8853af30e44SIgor Opaniuk 
8863af30e44SIgor Opaniuk 	ops_data = ops->user_data;
8873af30e44SIgor Opaniuk 
888*6663e074SJens Wiklander 	if (ops_data) {
889*6663e074SJens Wiklander #ifdef CONFIG_OPTEE_TA_AVB
890*6663e074SJens Wiklander 		if (ops_data->tee)
891*6663e074SJens Wiklander 			tee_close_session(ops_data->tee, ops_data->session);
892*6663e074SJens Wiklander #endif
8933af30e44SIgor Opaniuk 		avb_free(ops_data);
8943af30e44SIgor Opaniuk 	}
895*6663e074SJens Wiklander }
896