From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54214C433F5 for ; Wed, 27 Oct 2021 18:58:08 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A5F9960296 for ; Wed, 27 Oct 2021 18:58:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A5F9960296 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8DE0C8357A; Wed, 27 Oct 2021 20:57:56 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="LCmfmbkg"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0077A83484; Wed, 27 Oct 2021 20:57:24 +0200 (CEST) Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9B5758347C for ; Wed, 27 Oct 2021 20:57:12 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=kabel@kernel.org Received: by mail.kernel.org (Postfix) with ESMTPSA id 6D0276023F; Wed, 27 Oct 2021 18:57:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1635361032; bh=blwqLMkpl7HqwdQmoATIDlNuBIAzPRszRYM5ZC+Gpxc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LCmfmbkgIcLqKp5/eC05Hr26/TTzyHoSuYMD81Ujs6ZKFHYSIu7a41NppXzoQYL2P U4VZfJ0G4I0PubydaOxA5nEDcg8esXLhN9GkXeltMN/kEEviQqbWe5Mg8lJsctWtrn MX4TpSUACyIcRZaODllsgBKyLCC70VsqjNmYm1/VAs6ue14p1jHSfBokdMwRwIwnob mzugovDQQIx3QACfOGsLiUeQHZAQwhQ6UM9nROGjZwZaHDNW+A1xWGM6RiK5+33Ze5 oy3QxMGK/npQOH5/BC0Ep3rMnduf1rhbVBwauKmOgZPkvW4mIMmBOOJQf09LP2nvi8 87MRza/lDJjpw== From: =?UTF-8?q?Marek=20Beh=C3=BAn?= To: Stefan Roese Cc: u-boot@lists.denx.de, =?UTF-8?q?Pali=20Roh=C3=A1r?= , =?UTF-8?q?Marek=20Beh=C3=BAn?= Subject: [PATCH u-boot-marvell 5/5] tools: kwboot: Do not use stack when setting baudrate back to default value Date: Wed, 27 Oct 2021 20:57:02 +0200 Message-Id: <20211027185702.8186-6-kabel@kernel.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20211027185702.8186-1-kabel@kernel.org> References: <20211027185702.8186-1-kabel@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean From: Pali Rohár The ARM code we inject into the image to change baudrate back to the default value of 115200 Baud, which is run after successful UART transfer of the whole image, cannot use stack as at this stage stack pointer is not initialized yet. Stack can only be used when BootROM is executing binary header, to preserve state of registers, since BootROM expects that. Change the ARM baudrate code to not use stack at all and put binary header specific pre + post code (which stores and restores registers) into separate arrays. The baudrate change code now jumps at it's end and expects that there is either code which returns to the BootROM or jumps to the original exec address. Signed-off-by: Pali Rohár Reviewed-by: Marek Behún --- tools/kwboot.c | 112 ++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 62c218ef64..359b43c0d8 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -78,14 +78,7 @@ struct kwboot_block { #define KWBOOT_BLK_RSP_TIMEO 1000 /* ms */ #define KWBOOT_HDR_RSP_TIMEO 10000 /* ms */ -/* ARM code making baudrate changing function return to original exec address */ -static unsigned char kwboot_pre_baud_code[] = { - /* exec_addr: */ - 0x00, 0x00, 0x00, 0x00, /* .word 0 */ - 0x0c, 0xe0, 0x1f, 0xe5, /* ldr lr, exec_addr */ -}; - -/* ARM code for binary header injection to change baudrate */ +/* ARM code to change baudrate */ static unsigned char kwboot_baud_code[] = { /* ; #define UART_BASE 0xd0012000 */ /* ; #define THR 0x00 */ @@ -123,14 +116,12 @@ static unsigned char kwboot_baud_code[] = { /* ; return 0; */ /* ; } */ - 0xfe, 0x5f, 0x2d, 0xe9, /* push { r1 - r12, lr } */ - /* ; r0 = UART_BASE */ 0x0d, 0x02, 0xa0, 0xe3, /* mov r0, #0xd0000000 */ 0x12, 0x0a, 0x80, 0xe3, /* orr r0, r0, #0x12000 */ /* ; r2 = address of preamble string */ - 0xcc, 0x20, 0x8f, 0xe2, /* adr r2, preamble */ + 0xc8, 0x20, 0x8f, 0xe2, /* adr r2, preamble */ /* ; Send preamble string over UART */ /* .Lloop_preamble: */ @@ -177,7 +168,7 @@ static unsigned char kwboot_baud_code[] = { /* ; Read old baudrate value */ /* ; r2 = old_baudrate */ - 0x88, 0x20, 0x9f, 0xe5, /* ldr r2, old_baudrate */ + 0x84, 0x20, 0x9f, 0xe5, /* ldr r2, old_baudrate */ /* ; Calculate base clock */ /* ; r1 = r2 * r1 */ @@ -185,7 +176,7 @@ static unsigned char kwboot_baud_code[] = { /* ; Read new baudrate value */ /* ; r2 = new_baudrate */ - 0x84, 0x20, 0x9f, 0xe5, /* ldr r2, new_baudrate */ + 0x80, 0x20, 0x9f, 0xe5, /* ldr r2, new_baudrate */ /* ; Calculate new Divisor Latch */ /* ; r1 = DIV_ROUND(r1, r2) = */ @@ -234,9 +225,7 @@ static unsigned char kwboot_baud_code[] = { 0x00, 0x00, 0x51, 0xe3, /* cmp r1, #0 */ 0xfc, 0xff, 0xff, 0x1a, /* bne .Lloop_sleep */ - /* ; Return 0 - no error */ - 0x00, 0x00, 0xa0, 0xe3, /* mov r0, #0 */ - 0xfe, 0x9f, 0xbd, 0xe8, /* pop { r1 - r12, pc } */ + 0x05, 0x00, 0x00, 0xea, /* b end */ /* ; Preamble string */ /* preamble: */ @@ -252,10 +241,29 @@ static unsigned char kwboot_baud_code[] = { /* ; Placeholder for new baudrate value */ /* new_baudrate: */ 0x00, 0x00, 0x00, 0x00, /* .word 0 */ + + /* end: */ +}; + +/* ARM code for storing registers for future returning back to the bootrom */ +static unsigned char kwboot_baud_code_binhdr_pre[] = { + 0xfe, 0x5f, 0x2d, 0xe9, /* push { r1 - r12, lr } */ }; -#define KWBOOT_BAUDRATE_BIN_HEADER_SZ (sizeof(kwboot_baud_code) + \ - sizeof(struct opt_hdr_v1) + 8 + 16) +/* ARM code for returning back to the bootrom */ +static unsigned char kwboot_baud_code_binhdr_post[] = { + /* ; Return 0 - no error */ + 0x00, 0x00, 0xa0, 0xe3, /* mov r0, #0 */ + 0xfe, 0x9f, 0xbd, 0xe8, /* pop { r1 - r12, pc } */ +}; + +/* ARM code for jumping to the original image exec_addr */ +static unsigned char kwboot_baud_code_data_jump[] = { + 0x04, 0xf0, 0x1f, 0xe5, /* ldr pc, exec_addr */ + /* ; Placeholder for exec_addr */ + /* exec_addr: */ + 0x00, 0x00, 0x00, 0x00, /* .word 0 */ +}; static const char kwb_baud_magic[16] = "$baudratechange"; @@ -1409,44 +1417,51 @@ kwboot_add_bin_ohdr_v1(void *img, size_t *size, uint32_t binsz) } static void -_inject_baudrate_change_code(void *img, size_t *size, int pre, +_inject_baudrate_change_code(void *img, size_t *size, int for_data, int old_baud, int new_baud) { - uint32_t codesz = sizeof(kwboot_baud_code); struct main_hdr_v1 *hdr = img; + uint32_t orig_datasz; + uint32_t codesz; uint8_t *code; - if (pre) { - uint32_t presz = sizeof(kwboot_pre_baud_code); - uint32_t orig_datasz; - + if (for_data) { orig_datasz = le32_to_cpu(hdr->blocksize) - sizeof(uint32_t); - code = kwboot_img_grow_data_right(img, size, presz + codesz); - - /* - * We need to prepend code that loads lr register with original - * value of hdr->execaddr. We do this by putting the original - * exec address before the code that loads it relatively from - * it's beginning. - * Afterwards we change the exec address to this code (which is - * at offset 4, because the first 4 bytes contain the original - * exec address). - */ - memcpy(code, kwboot_pre_baud_code, presz); - *(uint32_t *)code = hdr->execaddr; - - hdr->execaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) + - orig_datasz + 4); - - code += presz; + codesz = sizeof(kwboot_baud_code) + + sizeof(kwboot_baud_code_data_jump); + code = kwboot_img_grow_data_right(img, size, codesz); } else { + codesz = sizeof(kwboot_baud_code_binhdr_pre) + + sizeof(kwboot_baud_code) + + sizeof(kwboot_baud_code_binhdr_post); code = kwboot_add_bin_ohdr_v1(img, size, codesz); + + codesz = sizeof(kwboot_baud_code_binhdr_pre); + memcpy(code, kwboot_baud_code_binhdr_pre, codesz); + code += codesz; } - memcpy(code, kwboot_baud_code, codesz - 8); - *(uint32_t *)(code + codesz - 8) = cpu_to_le32(old_baud); - *(uint32_t *)(code + codesz - 4) = cpu_to_le32(new_baud); + codesz = sizeof(kwboot_baud_code) - 2 * sizeof(uint32_t); + memcpy(code, kwboot_baud_code, codesz); + code += codesz; + *(uint32_t *)code = cpu_to_le32(old_baud); + code += sizeof(uint32_t); + *(uint32_t *)code = cpu_to_le32(new_baud); + code += sizeof(uint32_t); + + if (for_data) { + codesz = sizeof(kwboot_baud_code_data_jump) - sizeof(uint32_t); + memcpy(code, kwboot_baud_code_data_jump, codesz); + code += codesz; + *(uint32_t *)code = hdr->execaddr; + code += sizeof(uint32_t); + hdr->execaddr = cpu_to_le32(le32_to_cpu(hdr->destaddr) + orig_datasz); + } else { + codesz = sizeof(kwboot_baud_code_binhdr_post); + memcpy(code, kwboot_baud_code_binhdr_post, codesz); + code += codesz; + } } static int @@ -1729,10 +1744,13 @@ main(int argc, char **argv) baudrate = 0; else /* ensure we have enough space for baudrate change code */ - after_img_rsv += KWBOOT_BAUDRATE_BIN_HEADER_SZ + + after_img_rsv += sizeof(struct opt_hdr_v1) + 8 + 16 + + sizeof(kwboot_baud_code_binhdr_pre) + + sizeof(kwboot_baud_code) + + sizeof(kwboot_baud_code_binhdr_post) + KWBOOT_XM_BLKSZ + - sizeof(kwboot_pre_baud_code) + sizeof(kwboot_baud_code) + + sizeof(kwboot_baud_code_data_jump) + KWBOOT_XM_BLKSZ; if (imgpath) { -- 2.32.0