Beispiel #1
0
void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index)
{
    int index = start_index;
    esp_partition_pos_t part;
    esp_image_metadata_t image_data;

    if(start_index == TEST_APP_INDEX) {
        if (try_load_partition(&bs->test, &image_data)) {
            load_image(&image_data);
        } else {
            ESP_LOGE(TAG, "No bootable test partition in the partition table");
            bootloader_reset();
        }
    }

    /* work backwards from start_index, down to the factory app */
    for(index = start_index; index >= FACTORY_INDEX; index--) {
        part = index_to_partition(bs, index);
        if (part.size == 0) {
            continue;
        }
        ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size);
        if (try_load_partition(&part, &image_data)) {
            load_image(&image_data);
        }
        log_invalid_app_partition(index);
    }

    /* failing that work forwards from start_index, try valid OTA slots */
    for(index = start_index + 1; index < bs->app_count; index++) {
        part = index_to_partition(bs, index);
        if (part.size == 0) {
            continue;
        }
        ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size);
        if (try_load_partition(&part, &image_data)) {
            load_image(&image_data);
        }
        log_invalid_app_partition(index);
    }

    if (try_load_partition(&bs->test, &image_data)) {
        ESP_LOGW(TAG, "Falling back to test app as only bootable partition");
        load_image(&image_data);
    }

    ESP_LOGE(TAG, "No bootable app partitions in the partition table");
    bzero(&image_data, sizeof(esp_image_metadata_t));
    bootloader_reset();
}
Beispiel #2
0
// Copy loaded segments to RAM, set up caches for mapped segments, and start application.
static void load_image(const esp_image_metadata_t* image_data)
{
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
    esp_err_t err;
#endif
#ifdef CONFIG_SECURE_BOOT_ENABLED
    /* Generate secure digest from this bootloader to protect future
       modifications */
    ESP_LOGI(TAG, "Checking secure boot...");
    err = esp_secure_boot_permanently_enable();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
        /* Allow booting to continue, as the failure is probably
           due to user-configured EFUSEs for testing...
        */
    }
#endif

#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
    /* encrypt flash */
    ESP_LOGI(TAG, "Checking flash encryption...");
    bool flash_encryption_enabled = esp_flash_encryption_enabled();
    err = esp_flash_encrypt_check_and_update();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
        return;
    }

    if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
        /* Flash encryption was just enabled for the first time,
           so issue a system reset to ensure flash encryption
           cache resets properly */
        ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
        bootloader_reset();
    }
#endif

    ESP_LOGI(TAG, "Disabling RNG early entropy source...");
    bootloader_random_disable();

    // copy loaded segments to RAM, set up caches for mapped segments, and start application
    unpack_load_app(image_data);
}
Beispiel #3
0
int main(int argc, char **argv)
{
	bool do_verify = false;
	bool do_reset = false;
	char **itr;
	const char *opt;
	const char *filename = NULL;
	uint16_t vid = 0, pid = 0;
	bool vidpid_valid;
	struct bootloader *bl;
	int res;

	if (argc < 2) {
		print_usage(argv[0]);
		return 1;
	}
	
	/* Parse the command line. */
	itr = argv+1;
	opt = *itr;
	while (opt) {
		if (opt[0] == '-') {
			/* Option parameter */
			if (opt[1] == '-') {
				/* Long option, two dashes. */
				if (!strcmp(opt, "--help")) {
					print_usage(argv[0]);
					return 1;
				}
				else if (!strcmp(opt, "--reset"))
					do_reset = true;
				else if (!strcmp(opt, "--verify"))
					do_verify = true;
				else if (!strncmp(opt, "--dev", 5)) {
					if (opt[5] != '=') {
						fprintf(stderr, "--dev requires vid/pid pair\n\n");
						return 1;
					}
					vidpid_valid = parse_vid_pid(opt+6, &vid, &pid);
					if (!vidpid_valid) {
						fprintf(stderr, "Invalid VID/PID pair\n\n");
						return 1;
					}
				}
				else {
					fprintf(stderr, "Invalid Parameter %s\n\n", opt);
					return 1;
				}
			}
			else {
				const char *c = opt + 1;
				if (!*c) {
					/* This is a parameter of a single
					   hyphen, which means read from
					   stdin. */
					filename = opt;
				}
				while (*c) {
					/* Short option, only one dash */
					switch (*c) {
					case 'v':
						do_verify = true;
						break;
					case 'r':
						do_reset = true;
						break;
					case 'd':
						itr++;
						opt = *itr;
						if (!opt) {
							fprintf(stderr, "Must specify vid:pid after -d\n\n");
							return 1;
						}
						vidpid_valid = parse_vid_pid(opt, &vid, &pid);
						if (!vidpid_valid) {
							fprintf(stderr, "Invalid VID/PID pair\n\n");
							return 1;
						}
						break;
					default:
						fprintf(stderr, "Invalid parameter '%c'\n\n", *c);
						return 1;
					}
					c++;
				}
			}
		}
		else {
			/* Doesn't start with a dash. Must be the filename */
			if (filename) {
				fprintf(stderr, "Multiple filenames listed. This is not supported\n\n");
				return 1;
			}
			
			filename = opt;
		}
		itr++;
		opt = *itr;
	}

	vid = vidpid_valid? vid: DEFAULT_VID;
	pid = vidpid_valid? pid: DEFAULT_PID;
	
	if (!filename) {
	        fprintf(stderr, "No Filename specified. Specify a filename of use \"-\" to read from stdin.\n");
	        return 1;
	}

	/* Command line parsing is done. Do the programming of the device. */

	/* Open the device */
	res = bootloader_init(&bl, filename, vid, pid);
	if (res == BOOTLOADER_CANT_OPEN_FILE) {
		fprintf(stderr, "Unable to open file %s\n", filename);
		return 1;
	}
	else if (res == BOOTLOADER_CANT_OPEN_DEVICE) {
		fprintf(stderr, "\nUnable to open device %04hx:%04hx "
			"for programming.\n"
			"Make sure that the device is connected "
			"and that you have proper permissions\nto "
			"open it.\n", vid, pid);
		return 1;
	}
	else if (res == BOOTLOADER_CANT_QUERY_DEVICE) {
		fprintf(stderr, "Unable to query device parameters\n");
		return 1;
	}
	else if (res == BOOTLOADER_MULTIPLE_CONNECTED) {
		fprintf(stderr, "Multiple devices are connected. Remove all but one.\n");
	}
	else if (res < 0) {
		fprintf(stderr, "Unspecified error initializing bootloader %d\n", res);
		return 1;
	}
	
	/* Erase */
	res = bootloader_erase(bl);
	if (res < 0) {
		fprintf(stderr, "Erasing of device failed\n");
		return 1;
	}

	/* Program */
	res = bootloader_program(bl);
	if (res < 0) {
		fprintf(stderr, "Programming of device failed\n");
		return 1;
	}

	/* Verify */
	if (do_verify) {
		res = bootloader_verify(bl);
		if (res < 0) {
			fprintf(stderr, "Verification of programmed memory failed\n");
			return 1;
		}
	}

	/* Reset */
	if (do_reset) {
		res = bootloader_reset(bl);
		if (res < 0) {
			fprintf(stderr, "Device Reset failed\n");
			return 1;
		}
	}

	/* Close */
	bootloader_free(bl);

	return 0;
}