Jump to content

    

U-Boot + BareMetal application

 
Quote

Приветствую.

Не могу понять возможно ли это (платформа ZynqMP), хочу при помощи U-Boot грузить BareMetal прошивки на отдельные ядра. Для начала хотелось бы хотя бы одну. Команды bootelf и go не работают, вроде бы пишет, что стартует приложение по такому-то адресу, но ничего не происходит.

Нужен совет в каком направлении копать.

Спасибо.

 

Share this post


Link to post
Share on other sites
5 часов назад, doom13 сказал:

хочу при помощи U-Boot грузить BareMetal прошивки

Смысл убута для BareMetal?  Просто сразу загрузить прошивку?

5 часов назад, doom13 сказал:

пишет, что стартует приложение по такому-то адресу, но ничего не происходит

А прога скомпилирована по этому адресу? Смотрели конфиг линкера?

Share this post


Link to post
Share on other sites

U-Boot сам вроде как не релокейтит .elf, в случае с цинком этим явно занимается bootgen

Share this post


Link to post
Share on other sites
18 hours ago, mantech said:

Смысл убута для BareMetal?  Просто сразу загрузить прошивку? 

Он уже умеет лить прошивку по TFTP в RAM, писать во flash, и вроде как должен уметь стартануть elf/bin, то что мне и необходимо. Лень делать то, что уже сделано.

18 hours ago, mantech said:

А прога скомпилирована по этому адресу? Смотрели конфиг линкера?

С этим всё норм. По JTAG всё льётся и работает.

14 hours ago, sasamy said:

u-boot какой версии ? elf64 он относительно недавно стал поддерживать

Сливалась с git где-то в марте, т.е. почти свежая. В elf.c нахожу такое:

/*
 * A very simple ELF64 loader, assumes the image is valid, returns the
 * entry point address.
 *
 * Note if U-Boot is 32-bit, the loader assumes the to segment's
 * physical address and size is within the lower 32-bit address space.
 */
static unsigned long load_elf64_image_phdr(unsigned long addr)
{
	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
	Elf64_Phdr *phdr; /* Program header structure pointer */
	int i;

	ehdr = (Elf64_Ehdr *)addr;
	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);

	/* Load each program header */
	for (i = 0; i < ehdr->e_phnum; ++i) {
		void *dst = (void *)(ulong)phdr->p_paddr;
		void *src = (void *)addr + phdr->p_offset;

		debug("Loading phdr %i to 0x%p (%lu bytes)\n",
		      i, dst, (ulong)phdr->p_filesz);
		if (phdr->p_filesz)
			memcpy(dst, src, phdr->p_filesz);
		if (phdr->p_filesz != phdr->p_memsz)
			memset(dst + phdr->p_filesz, 0x00,
			       phdr->p_memsz - phdr->p_filesz);
		flush_cache((unsigned long)dst, phdr->p_filesz);
		++phdr;
	}

	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
					    EF_PPC64_ELFV1_ABI)) {
		/*
		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
		 * descriptor pointer with the first double word being the
		 * address of the entry point of the function.
		 */
		uintptr_t addr = ehdr->e_entry;

		return *(Elf64_Addr *)addr;
	}

	return ehdr->e_entry;
}

 

17 hours ago, gosha-z said:

U-Boot сам вроде как не релокейтит .elf, в случае с цинком этим явно занимается bootgen

Вот не получается стартануть моего elf-a из u-boot. Пробовал команду bootelf для elf, перегнал elf в bin и пробовал те же bootelf и go, попробовал переконвертить bin в img и стартануть при помощи bootm, но всё не то, пишет что стартую приложение по такому-то адресу и опа. Исходники u-boot поковырял - делаю вывод, что и не может оно стартануть приложение с EL3.

Для go вызывает такую вот функцию

unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
			 char * const argv[])
{
	int ret = 0;

	printf ("2. In file zynqmp.c\n");

	if (current_el() > 1) {
		printf ("EL = %d\n", current_el());
		smp_kick_all_cpus();
		dcache_disable();
		armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
				    ES_TO_AARCH64);
	} else {
		printf("FAIL: current EL is not above EL1\n");
		ret = EINVAL;
	}
	return ret;
}

т.е. перед стартом на EL1 переключается.

Посмотрел asm, что работает при старте прошивы и вижу, что там похоже и дохнет, EL не совпадает с тем что SDK генерит. В BSP есть настройка для супервизора EL1, но это как понял совсем не мой случай.

Попробовал u-boot стартануть с настройкой для BIF-файла EL3 - не стартует. Стартует и нормально работает только с BL31 в EL3 и u-boot в EL2, все другие варианты - тишина.

Что посоветуете? Пилить свой загрузчик?

Share this post


Link to post
Share on other sites

Естественно, U-Boot работает на EL2, как ему (и не только ему) положено.

Share this post


Link to post
Share on other sites
5 minutes ago, gosha-z said:

Естественно, U-Boot работает на EL2, как ему (и не только ему) положено.

Что можете сказать по этому поводу: link

Или это ерунда какая-то

Share this post


Link to post
Share on other sites
1 minute ago, gosha-z said:

А чем вам так критичен EL3??

Пока вижу в нем проблему не запуска BareMetal, bsp которого компилится под EL3, и поменять это малой кровью я не могу.

Аналогичная проблема без ответа.

Возможно ли в U-Boot при переходе на BareMeta переключать EL в положение 3?

Share this post


Link to post
Share on other sites

А что конкретно он хочет от EL3? Прямого доступа к портам?

Share this post


Link to post
Share on other sites
2 minutes ago, gosha-z said:

А что конкретно он хочет от EL3? Прямого доступа к портам?

Я тут пока сам не пойму. Например для go U-boot выполняет:

unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
			 char * const argv[])
{
	int ret = 0;

	printf ("2. In file zynqmp.c\n");

	if (current_el() > 1) {
		printf ("EL = %d\n", current_el());
		smp_kick_all_cpus();
		dcache_disable();
		armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
				    ES_TO_AARCH64);
	} else {
		printf("FAIL: current EL is not above EL1\n");
		ret = EINVAL;
	}
	return ret;
}

т.е. переключает на EL1 и переходит на мой адрес старта boot.S, а там уже EL не совпадает и:

_prestart:
_boot:
	mov      x0, #0
	mov      x1, #0
	mov      x2, #0
	mov      x3, #0
	mov      x4, #0
	mov      x5, #0
	mov      x6, #0
	mov      x7, #0
	mov      x8, #0
	mov      x9, #0
	mov      x10, #0
	mov      x11, #0
	mov      x12, #0
	mov      x13, #0
	mov      x14, #0
	mov      x15, #0
	mov      x16, #0
	mov      x17, #0
	mov      x18, #0
	mov      x19, #0
	mov      x20, #0
	mov      x21, #0
	mov      x22, #0
	mov      x23, #0
	mov      x24, #0
	mov      x25, #0
	mov      x26, #0
	mov      x27, #0
	mov      x28, #0
	mov      x29, #0
	mov      x30, #0
#if 0 //dont put other a53 cpus in wfi
   //Which core am I
   // ----------------
	mrs      x0, MPIDR_EL1
	and      x0, x0, #0xFF                        //Mask off to leave Aff0
	cbz      x0, OKToRun                          //If core 0, run the primary init code
EndlessLoop0:
	wfi
	b        EndlessLoop0
#endif
OKToRun:

	mrs	x0, currentEL
	cmp	x0, #0xC
	beq	InitEL3

	cmp	x0, #0x4
	beq	InitEL1

	b 	error

и как понимаю, вероятнее всего попадает на error и там висит (такой результат работы наблюдаю, если BSP сгенерить под гипервизор с EL1, будет висеть на error)

Share this post


Link to post
Share on other sites

Для bootelf последовательность такая:

/* Interpreter command to boot an arbitrary ELF image from memory */
int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	unsigned long addr; /* Address of the ELF image */
	unsigned long rc; /* Return value from user code */
	char *sload = NULL;
	const char *ep = env_get("autostart");
	int rcode = 0;

	/* Consume 'bootelf' */
	argc--; argv++;

	/* Check for flag. */
	if (argc >= 1 && (argv[0][0] == '-' && \
				(argv[0][1] == 'p' || argv[0][1] == 's'))) {
		sload = argv[0];
		/* Consume flag. */
		argc--; argv++;
	}
	/* Check for address. */
	if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
		/* Consume address */
		argc--; argv++;
	} else
		addr = load_addr;

	if (!valid_elf_image(addr))
		return 1;

	if (sload && sload[1] == 'p')
		addr = load_elf_image_phdr(addr);
	else
		addr = load_elf_image_shdr(addr);

	if (ep && !strcmp(ep, "no"))
		return rcode;

	printf("## Starting application at 0x%08lx ...\n", addr);

	/*
	 * pass address parameter as argv[0] (aka command name),
	 * and all remaining args
	 */
	rc = do_bootelf_exec((void *)addr, argc, argv);
	if (rc != 0)
		rcode = 1;

	printf("## Application terminated, rc = 0x%lx\n", rc);

	return rcode;
}


/* Allow ports to override the default behavior */
static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
				     int argc, char * const argv[])
{
	unsigned long ret;

	/*
	 * pass address parameter as argv[0] (aka command name),
	 * and all remaining args
	 */
	ret = entry(argc, argv);

	return ret;
}

как понимаю, парсит elf и идёт на entry point, тут похоже останется в EL2, но мой BareMetal опять же хочет видеть EL3.

Тут тогда вопрос: может ли BL31 стартануть U-Boot c EL3? Тогда bootelf возможно и сработала бы.

Но у меня система с U-Boot стартует только если формирую бинарник таким образом:

//arch = zynqmp; split = false; format = BIN
the_ROM_image:
{
	[fsbl_config]a53_x64
	[bootloader]/home/andrei/workspace/ZynqMP/xczu9eg/xczu9eg.sdk/fsbl_a530/Debug/fsbl_a530.elf
	[pmufw_image]/home/andrei/workspace/ZynqMP/xczu9eg/xczu9eg.sdk/pmufw/Debug/pmufw.elf
	[destination_device = pl]/home/andrei/workspace/ZynqMP/xczu9eg/xczu9eg.runs/impl_1/xczu9eg.bit
	[destination_cpu = a53-0, exception_level = el-3, trustzone]/home/andrei/workspace/ZynqMP/linux/images/linux/bl31.elf
	[destination_cpu = a53-0, exception_level = el-2]/home/andrei/workspace/ZynqMP/u-boot-xlnx/u-boot.elf
}

 

Share this post


Link to post
Share on other sites
10 hours ago, doom13 said:

может ли BL31 стартануть U-Boot c EL3?

 

Если пропатчить - почему нет. Тут описание и патч для другой платформы, но переделать думаю не проблема

https://forum.armbian.com/topic/4165-re-buildingupdating-arm-trusted-firmware-and-u-boot-only/?tab=comments#comment-36024

Share this post


Link to post
Share on other sites

Нашёл, на форуме Xilinx это.

Каким-то чудом BareMetal стал стартовать по команде go с настройкой EL1 для BSP (предварительно правда пересобрал bl31). Пока так и не понял, что именно ему помогло запуститься. Остался вопрос с проектом под FreeRTOS, в этом случае в BSP не могу найти опцию для EL1.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this