xref: /rk3399_rockchip-uboot/lib/avb/rk_avb_user/rk_avb_ops_user.c (revision f05ce84792cbd2e5573a414010d421eb8fbb7689)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <image.h>
9 #include <android_image.h>
10 #include <malloc.h>
11 #include <mapmem.h>
12 #include <errno.h>
13 #include <command.h>
14 #include <mmc.h>
15 #include <blk.h>
16 #include <part.h>
17 #include <android_avb/avb_ops_user.h>
18 #include <android_avb/libavb_ab.h>
19 #include <android_avb/avb_atx_validate.h>
20 #include <android_avb/avb_atx_types.h>
21 #include <optee_include/OpteeClientInterface.h>
22 #include <optee_include/tee_api_defines.h>
23 #include <android_avb/avb_vbmeta_image.h>
24 #include <android_avb/avb_atx_validate.h>
25 #include <android_avb/rk_avb_ops_user.h>
26 #include <boot_rkimg.h>
27 
28 /* rk used */
29 int rk_avb_read_slot_count(char *slot_count)
30 {
31 	*slot_count = SLOT_NUM;
32 
33 	return 0;
34 }
35 
36 int rk_avb_read_slot_suffixes(char *slot_suffixes)
37 {
38 	memcpy(slot_suffixes, CURR_SYSTEM_SLOT_SUFFIX,
39 	       strlen(CURR_SYSTEM_SLOT_SUFFIX));
40 
41 	return 0;
42 }
43 
44 int rk_avb_set_slot_active(unsigned int *slot_number)
45 {
46 	AvbOps* ops;
47 	ops = avb_ops_user_new();
48 	int ret = 0;
49 
50 	if (ops == NULL) {
51 		printf("avb_ops_user_new() failed!\n");
52 		return -1;
53 	}
54 
55 	debug("set_slot_active\n");
56 	if (avb_ab_mark_slot_active(ops->ab_ops, *slot_number) != 0) {
57 		printf("set_slot_active error!\n");
58 		ret = -1;
59 	}
60 
61 	avb_ops_user_free(ops);
62 	return ret;
63 }
64 
65 static bool slot_is_bootable(AvbABSlotData* slot) {
66 	return (slot->priority > 0) &&
67 	       (slot->successful_boot || (slot->tries_remaining > 0));
68 }
69 
70 AvbABFlowResult rk_avb_ab_slot_select(AvbABOps* ab_ops,char* select_slot)
71 {
72 	AvbABFlowResult ret = AVB_AB_FLOW_RESULT_OK;
73 	AvbIOResult io_ret = AVB_IO_RESULT_OK;
74 	AvbABData ab_data;
75 	size_t slot_index_to_boot;
76 
77 	io_ret = ab_ops->read_ab_metadata(ab_ops, &ab_data);
78 	if (io_ret != AVB_IO_RESULT_OK) {
79 		avb_error("I/O error while loading A/B metadata.\n");
80 		ret = AVB_AB_FLOW_RESULT_ERROR_IO;
81 		goto out;
82 	}
83 	if (slot_is_bootable(&ab_data.slots[0]) && slot_is_bootable(&ab_data.slots[1])) {
84 		if (ab_data.slots[1].priority > ab_data.slots[0].priority) {
85 			slot_index_to_boot = 1;
86 		} else {
87 			slot_index_to_boot = 0;
88 		}
89 	} else if(slot_is_bootable(&ab_data.slots[0])) {
90 		slot_index_to_boot = 0;
91 	} else if(slot_is_bootable(&ab_data.slots[1])) {
92 		slot_index_to_boot = 1;
93 	} else {
94 		avb_error("No bootable slots found.\n");
95 		ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
96 		goto out;
97 	}
98 
99 	if (slot_index_to_boot == 0) {
100 		strcpy(select_slot, "_a");
101 	} else if(slot_index_to_boot == 1) {
102 		strcpy(select_slot, "_b");
103 	}
104 out:
105 	return ret;
106 }
107 
108 int rk_avb_get_current_slot(char *select_slot)
109 {
110 	AvbOps* ops;
111 	int ret = 0;
112 
113 	ops = avb_ops_user_new();
114 	if (ops == NULL) {
115 		printf("avb_ops_user_new() failed!\n");
116 		return -1;
117 	}
118 
119 	if (rk_avb_ab_slot_select(ops->ab_ops, select_slot) != 0) {
120 		printf("get_current_slot error!\n");
121 		ret = -1;
122 	}
123 
124 	avb_ops_user_free(ops);
125 	return ret;
126 }
127 
128 int rk_avb_read_permanent_attributes(uint8_t *attributes, uint32_t size)
129 {
130 #ifdef CONFIG_OPTEE_CLIENT
131 	if(trusty_read_permanent_attributes(attributes, size) != 0) {
132 		printf("trusty_read_permanent_attributes failed!\n");
133 		return -1;
134 	}
135 
136 	return 0;
137 #else
138 	return -1;
139 #endif
140 }
141 
142 int rk_avb_write_permanent_attributes(uint8_t *attributes, uint32_t size)
143 {
144 #ifdef CONFIG_OPTEE_CLIENT
145 	if(trusty_write_permanent_attributes(attributes, size) != 0) {
146 		printf("trusty_write_permanent_attributes failed!\n");
147 		return -1;
148 	}
149 
150 	return 0;
151 #else
152 	return -1;
153 #endif
154 }
155 
156 int rk_avb_read_flash_lock_state(uint8_t *flash_lock_state)
157 {
158 #ifdef CONFIG_OPTEE_CLIENT
159 	int ret;
160 
161 	ret = trusty_read_flash_lock_state(flash_lock_state);
162 	switch (ret) {
163 	case TEE_SUCCESS:
164 		break;
165 	case TEE_ERROR_GENERIC:
166 	case TEE_ERROR_NO_DATA:
167 	case TEE_ERROR_ITEM_NOT_FOUND:
168 		*flash_lock_state = 1;
169 		if (trusty_write_flash_lock_state(*flash_lock_state)) {
170 			avb_error("trusty_write_flash_lock_state error!");
171 			ret = -1;
172 		} else {
173 			ret = trusty_read_flash_lock_state(flash_lock_state);
174 		}
175 		break;
176 	default:
177 		printf("%s: trusty_read_flash_lock_state failed\n", __FILE__);
178 	}
179 
180 	return ret;
181 #else
182 	return -1;
183 #endif
184 }
185 
186 int rk_avb_write_flash_lock_state(uint8_t flash_lock_state)
187 {
188 #ifdef CONFIG_OPTEE_CLIENT
189 	if (trusty_write_flash_lock_state(flash_lock_state)) {
190 		printf("trusty_write_flash_lock_state error!\n");
191 		return -1;
192 	}
193 
194 	return 0;
195 #else
196 	return -1;
197 #endif
198 }
199 
200 int rk_avb_write_lock_state(uint8_t lock_state)
201 {
202 #ifdef CONFIG_OPTEE_CLIENT
203 	if (trusty_write_lock_state(lock_state)) {
204 		printf("trusty_write_lock_state error!\n");
205 		return -1;
206 	}
207 
208 	return 0;
209 #else
210 	return -1;
211 #endif
212 }
213 
214 int rk_avb_read_lock_state(uint8_t *lock_state)
215 {
216 #ifdef CONFIG_OPTEE_CLIENT
217 	int ret;
218 
219 	ret = trusty_read_lock_state(lock_state);
220 	switch (ret) {
221 	case TEE_SUCCESS:
222 		break;
223 	case TEE_ERROR_GENERIC:
224 	case TEE_ERROR_NO_DATA:
225 	case TEE_ERROR_ITEM_NOT_FOUND:
226 		*lock_state = 1;
227 		if (rk_avb_write_lock_state(*lock_state)) {
228 			avb_error("avb_write_lock_state error!");
229 			ret = -1;
230 		} else {
231 			ret = trusty_read_lock_state(lock_state);
232 		}
233 		break;
234 	default:
235 		printf("%s: trusty_read_lock_state failed\n", __FILE__);
236 	}
237 
238 	return ret;
239 #else
240 	return -1;
241 #endif
242 }
243 
244 int rk_avb_write_perm_attr_flag(uint8_t flag)
245 {
246 #ifdef CONFIG_OPTEE_CLIENT
247 	if (trusty_write_permanent_attributes_flag(flag)) {
248 		printf("trusty_write_permanent_attributes_flag error!\n");
249 		return -1;
250 	}
251 
252 	return 0;
253 #else
254 	return -1;
255 #endif
256 }
257 
258 int rk_avb_read_perm_attr_flag(uint8_t *flag)
259 {
260 #ifdef CONFIG_OPTEE_CLIENT
261 	int ret;
262 
263 	ret = trusty_read_permanent_attributes_flag(flag);
264 	switch (ret) {
265 	case TEE_SUCCESS:
266 		break;
267 	case TEE_ERROR_GENERIC:
268 	case TEE_ERROR_NO_DATA:
269 	case TEE_ERROR_ITEM_NOT_FOUND:
270 		*flag = 0;
271 		if (rk_avb_write_perm_attr_flag(*flag)) {
272 			avb_error("avb_write_perm_attr_flag error!");
273 			ret = -1;
274 		} else {
275 			ret = trusty_read_permanent_attributes_flag(flag);
276 		}
277 		break;
278 	default:
279 		printf("%s: trusty_read_permanent_attributes_flag failed",
280 		       __FILE__);
281 	}
282 
283 	return ret;
284 #else
285 	return -1;
286 #endif
287 }
288 
289 int rk_avb_read_vbootkey_hash(uint8_t *buf, uint8_t length)
290 {
291 #ifdef CONFIG_OPTEE_CLIENT
292 	if (trusty_read_vbootkey_hash((uint32_t *)buf,
293 				      (uint32_t)length / sizeof(uint32_t))) {
294 		printf("trusty_read_vbootkey_hash error!\n");
295 		return -1;
296 	}
297 
298 	return 0;
299 #else
300 	return -1;
301 #endif
302 }
303 
304 int rk_avb_write_vbootkey_hash(uint8_t *buf, uint8_t length)
305 {
306 #ifdef CONFIG_OPTEE_CLIENT
307 	if (trusty_write_vbootkey_hash((uint32_t *)buf,
308 				       (uint32_t)length / sizeof(uint32_t))) {
309 		printf("trusty_write_vbootkey_hash error!\n");
310 		return -1;
311 	}
312 
313 	return 0;
314 #else
315 	return -1;
316 #endif
317 }
318 
319 int rk_avb_close_optee_client(void)
320 {
321 #ifdef CONFIG_OPTEE_CLIENT
322 	if(trusty_notify_optee_uboot_end()) {
323 		printf("trusty_notify_optee_uboot_end error!\n");
324 		return -1;
325 	}
326 
327 	return 0;
328 #else
329 	return -1;
330 #endif
331 }
332 
333 int rk_avb_read_attribute_hash(uint8_t *buf, uint8_t length)
334 {
335 #ifdef CONFIG_OPTEE_CLIENT
336 	if (trusty_read_attribute_hash((uint32_t *)buf,
337 	    (uint32_t)(length/sizeof(uint32_t)))) {
338 		printf("trusty_read_attribute_hash error!\n");
339 		return -1;
340 	}
341 
342 	return 0;
343 #else
344 	return -1;
345 #endif
346 }
347 
348 int rk_avb_write_attribute_hash(uint8_t *buf, uint8_t length)
349 {
350 #ifdef CONFIG_OPTEE_CLIENT
351 	if (trusty_write_attribute_hash((uint32_t *)buf,
352 	    (uint32_t)(length/sizeof(uint32_t)))) {
353 		printf("trusty_write_attribute_hash error!\n");
354 		return -1;
355 	}
356 
357 	return 0;
358 #else
359 	return -1;
360 #endif
361 }
362 
363 int rk_avb_read_all_rollback_index(char *buffer)
364 {
365 	AvbOps* ops;
366 	uint64_t stored_rollback_index = 0;
367 	AvbIOResult io_ret;
368 	char temp[ROLLBACK_MAX_SIZE] = {0};
369 	int n;
370 
371 	ops = avb_ops_user_new();
372 	if (ops == NULL) {
373 		printf("avb_ops_user_new() failed!\n");
374 		return -1;
375 	}
376 
377 	for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
378 		io_ret = ops->read_rollback_index(
379 			ops, n, &stored_rollback_index);
380 		if (io_ret != AVB_IO_RESULT_OK)
381 			goto out;
382 		snprintf(temp, sizeof(int) + 1, "%d", n);
383 		strncat(buffer, temp, ROLLBACK_MAX_SIZE);
384 		strncat(buffer, ":", 1);
385 		snprintf(temp, sizeof(uint64_t) + 1, "%lld",
386 			 stored_rollback_index);
387 		strncat(buffer, temp, ROLLBACK_MAX_SIZE);
388 		strncat(buffer, ",", 1);
389 	}
390 
391 	io_ret =
392 		ops->read_rollback_index(ops,
393 					 AVB_ATX_PIK_VERSION_LOCATION,
394 					 &stored_rollback_index);
395 	if (io_ret != AVB_IO_RESULT_OK) {
396 		avb_error("Failed to read PIK minimum version.\n");
397 		goto out;
398 	}
399 	/* PIK rollback index */
400 	snprintf(temp, sizeof(int) + 1, "%d", AVB_ATX_PIK_VERSION_LOCATION);
401 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
402 	strncat(buffer, ":", 1);
403 	snprintf(temp, sizeof(uint64_t) + 1, "%lld", stored_rollback_index);
404 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
405 	strncat(buffer, ",", 1);
406 	io_ret = ops->read_rollback_index(ops,
407 					  AVB_ATX_PSK_VERSION_LOCATION,
408 					  &stored_rollback_index);
409 	if (io_ret != AVB_IO_RESULT_OK) {
410 		avb_error("Failed to read PSK minimum version.\n");
411 		goto out;
412 	}
413 	/* PSK rollback index */
414 	snprintf(temp, sizeof(int) + 1, "%d", AVB_ATX_PSK_VERSION_LOCATION);
415 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
416 	strncat(buffer, ":", 1);
417 	snprintf(temp, sizeof(uint64_t) + 1, "%lld", stored_rollback_index);
418 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
419 	debug("%s\n", buffer);
420 	avb_ops_user_free(ops);
421 
422 	return 0;
423 out:
424 	avb_ops_user_free(ops);
425 
426 	return -1;
427 }
428 
429 int rk_avb_read_bootloader_locked_flag(uint8_t *flag)
430 {
431 #ifdef CONFIG_OPTEE_CLIENT
432 	if (trusty_read_vbootkey_enable_flag(flag)) {
433 		return -1;
434 	}
435 	return 0;
436 #else
437 	return -1;
438 #endif
439 }
440 
441 #ifdef CONFIG_SUPPORT_EMMC_RPMB
442 static int curr_device = -1;
443 
444 int rk_bootloader_rollback_index_read(uint32_t offset, uint32_t bytes,
445 				      void *rb_index)
446 {
447 
448 	struct mmc *mmc;
449 	uint8_t rpmb_buf[256] = {0};
450 	uint32_t n;
451 	char original_part;
452 
453 	if ((offset + bytes) > 256)
454 		return -1;
455 
456 	if (curr_device < 0) {
457 		if (get_mmc_num() > 0)
458 			curr_device = 0;
459 		else {
460 			avb_error("No MMC device available");
461 			return -1;
462 		}
463 	}
464 
465 	mmc = find_mmc_device(curr_device);
466 	/* Switch to the RPMB partition */
467 #ifndef CONFIG_BLK
468 	original_part = mmc->block_dev.hwpart;
469 #else
470 	original_part = mmc_get_blk_desc(mmc)->hwpart;
471 #endif
472 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
473 	    0)
474 		return -1;
475 
476 	n =  mmc_rpmb_read(mmc, rpmb_buf, RPMB_BASE_ADDR, 1, NULL);
477 	if (n != 1)
478 		return -1;
479 
480 	/* Return to original partition */
481 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
482 	    0)
483 		return -1;
484 
485 	memcpy(rb_index, (void*)&rpmb_buf[offset], bytes);
486 
487 	return 0;
488 }
489 
490 int rk_avb_get_bootloader_min_version(char *buffer)
491 {
492 	uint32_t rb_index;
493 	char temp[ROLLBACK_MAX_SIZE] = {0};
494 
495 	if (rk_bootloader_rollback_index_read(UBOOT_RB_INDEX_OFFSET,
496 					      sizeof(uint32_t), &rb_index)) {
497 		avb_error("Can not read uboot rollback index");
498 		return -1;
499 	}
500 	snprintf(temp, sizeof(int) + 1, "%d", 0);
501 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
502 	strncat(buffer, ":", 1);
503 	snprintf(temp, sizeof(uint32_t) + 1, "%d", rb_index);
504 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
505 	strncat(buffer, ",", 1);
506 
507 	if (rk_bootloader_rollback_index_read(TRUST_RB_INDEX_OFFSET,
508 					      sizeof(uint32_t), &rb_index)) {
509 		avb_error("Can not read trust rollback index");
510 		return -1;
511 	}
512 
513 	snprintf(temp, sizeof(int) + 1, "%d", 1);
514 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
515 	strncat(buffer, ":", 1);
516 	snprintf(temp, sizeof(uint32_t) + 1, "%d", rb_index);
517 	strncat(buffer, temp, ROLLBACK_MAX_SIZE);
518 
519 	return 0;
520 }
521 #endif
522 
523 void rk_avb_get_at_vboot_state(char *buf)
524 {
525 	char temp_flag = 0;
526 	char *lock_val = NULL;
527 	char *unlock_dis_val = NULL;
528 	char *perm_attr_flag = NULL;
529 	char *bootloader_locked_flag = NULL;
530 	char *rollback_indices;
531 	char min_versions[ROLLBACK_MAX_SIZE + 1] = {0};
532 	int n;
533 
534 	if (rk_avb_read_perm_attr_flag((uint8_t *)&temp_flag)) {
535 		avb_error("Can not read perm_attr_flag!");
536 		perm_attr_flag = "";
537 	} else {
538 		perm_attr_flag = temp_flag ? "1" : "0";
539 	}
540 
541 	temp_flag = 0;
542 	if (rk_avb_read_lock_state((uint8_t *)&temp_flag)) {
543 		avb_error("Can not read lock state!");
544 		lock_val = "";
545 		unlock_dis_val = "";
546 	} else {
547 		lock_val = (temp_flag & LOCK_MASK) ? "0" : "1";
548 		unlock_dis_val = (temp_flag & UNLOCK_DISABLE_MASK) ? "1" : "0";
549 	}
550 
551 	temp_flag = 0;
552 	if (rk_avb_read_bootloader_locked_flag((uint8_t *)&temp_flag)) {
553 		avb_error("Can not read bootloader locked flag!");
554 		bootloader_locked_flag = "";
555 	} else {
556 		bootloader_locked_flag = temp_flag ? "1" : "0";
557 	}
558 
559 	rollback_indices = malloc(VBOOT_STATE_SIZE);
560 	if (!rollback_indices) {
561 		avb_error("No buff to malloc!");
562 		return;
563 	}
564 
565 	memset(rollback_indices, 0, VBOOT_STATE_SIZE);
566 	if (rk_avb_read_all_rollback_index(rollback_indices))
567 		avb_error("Can not read avb_min_ver!");
568 
569 	/* bootloader-min-versions */
570 	if (rk_avb_get_bootloader_min_version(min_versions))
571 		avb_error("Call rk_avb_get_bootloader_min_version error!");
572 
573 	n = snprintf(buf, VBOOT_STATE_SIZE - 1,
574 		     "avb-perm-attr-set=%s\n"
575 		     "avb-locked=%s\n"
576 		     "avb-unlock-disabled=%s\n"
577 		     "bootloader-locked=%s\n"
578 		     "avb-min-versions=%s\n"
579 		     "bootloader-min-versions=%s\n",
580 		     perm_attr_flag,
581 		     lock_val,
582 		     unlock_dis_val,
583 		     bootloader_locked_flag,
584 		     rollback_indices,
585 		     min_versions);
586 	if (n >= VBOOT_STATE_SIZE) {
587 		avb_error("The VBOOT_STATE buf is truncated\n");
588 		buf[VBOOT_STATE_SIZE - 1] = 0;
589 	}
590 	debug("The vboot state buf is %s\n", buf);
591 	free(rollback_indices);
592 }
593 
594 int rk_avb_get_ab_info(AvbABData* ab_data)
595 {
596 	AvbOps* ops;
597 	AvbIOResult io_ret = AVB_IO_RESULT_OK;
598 	int ret = 0;
599 
600 	ops = avb_ops_user_new();
601 	if (ops == NULL) {
602 		printf("%s: avb_ops_user_new() failed!\n", __FILE__);
603 		return -1;
604 	}
605 
606 	io_ret = ops->ab_ops->read_ab_metadata(ops->ab_ops, ab_data);
607 	if (io_ret != AVB_IO_RESULT_OK) {
608 		avb_error("I/O error while loading A/B metadata.\n");
609 		ret = -1;
610 	}
611 
612 	avb_ops_user_free(ops);
613 
614 	return ret;
615 }
616 
617 int rk_avb_get_part_has_slot_info(const char *base_name)
618 {
619 	char *part_name;
620 	int part_num;
621 	size_t part_name_len;
622 	disk_partition_t part_info;
623 	struct blk_desc *dev_desc;
624 	const char *slot_suffix = "_a";
625 
626 	dev_desc = rockchip_get_bootdev();
627 	if (!dev_desc) {
628 		printf("%s: Could not find device!\n", __func__);
629 		return -1;
630 	}
631 
632 	if (base_name == NULL) {
633 		printf("The base_name is NULL!\n");
634 		return -1;
635 	}
636 
637 	part_name_len = strlen(base_name) + 1;
638 	part_name_len += strlen(slot_suffix);
639 	part_name = malloc(part_name_len);
640 	if (!part_name) {
641 		printf("%s can not malloc a buffer!\n", __FILE__);
642 		return -1;
643 	}
644 
645 	memset(part_name, 0, part_name_len);
646 	snprintf(part_name, part_name_len, "%s%s", base_name, slot_suffix);
647 	part_num = part_get_info_by_name(dev_desc, part_name, &part_info);
648 	if (part_num < 0) {
649 		printf("Could not find partition \"%s\"\n", part_name);
650 		part_num = -1;
651 	}
652 
653 	free(part_name);
654 	return part_num;
655 }
656 
657 int rk_auth_unlock(void *buffer, char *out_is_trusted)
658 {
659 	AvbOps* ops;
660 
661 	ops = avb_ops_user_new();
662 	if (ops == NULL) {
663 		avb_error("avb_ops_user_new() failed!");
664 		return -1;
665 	}
666 
667 	if (avb_atx_validate_unlock_credential(ops->atx_ops,
668 					   (AvbAtxUnlockCredential*)buffer,
669 					   (bool*)out_is_trusted)) {
670 		avb_ops_user_free(ops);
671 		return -1;
672 	}
673 	avb_ops_user_free(ops);
674 	if (*out_is_trusted == true)
675 		return 0;
676 	else
677 		return -1;
678 }
679 
680 int rk_generate_unlock_challenge(void *buffer, uint32_t *challenge_len)
681 {
682 	AvbOps* ops;
683 	AvbIOResult result = AVB_IO_RESULT_OK;
684 
685 	ops = avb_ops_user_new();
686 	if (ops == NULL) {
687 		avb_error("avb_ops_user_new() failed!");
688 		return -1;
689 	}
690 
691 	result = avb_atx_generate_unlock_challenge(ops->atx_ops,
692 						   (AvbAtxUnlockChallenge *)buffer);
693 	avb_ops_user_free(ops);
694 	*challenge_len = sizeof(AvbAtxUnlockChallenge);
695 	if (result == AVB_IO_RESULT_OK)
696 		return 0;
697 	else
698 		return -1;
699 }
700