Merge tag 'tpm-030822' of https://source.denx.de/u-boot/custodians/u-boot-tpm
[platform/kernel/u-boot.git] / cmd / load.c
index 63a9414..e44ae0d 100644 (file)
 #include <command.h>
 #include <console.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <env.h>
+#include <exports.h>
+#ifdef CONFIG_MTD_NOR_FLASH
 #include <flash.h>
+#endif
 #include <image.h>
-#include <s_record.h>
+#include <lmb.h>
+#include <mapmem.h>
 #include <net.h>
-#include <exports.h>
+#include <s_record.h>
 #include <serial.h>
 #include <xyzModem.h>
 #include <asm/cache.h>
+#include <asm/global_data.h>
 #include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -67,7 +73,7 @@ static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
                offset = simple_strtol(argv[1], NULL, 16);
        }
        if (argc == 3) {
-               load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+               load_baudrate = (int)dectoul(argv[2], NULL);
 
                /* default to current baudrate */
                if (load_baudrate == 0)
@@ -81,7 +87,7 @@ static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == '\r')
+                       if (getchar() == '\r')
                                break;
                }
        }
@@ -102,7 +108,7 @@ static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
         */
        for (i=0; i<100; ++i) {
                if (tstc()) {
-                       (void) getc();
+                       getchar();
                }
                udelay(1000);
        }
@@ -124,7 +130,7 @@ static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == 0x1B) /* ESC */
+                       if (getchar() == 0x1B) /* ESC */
                                break;
                }
        }
@@ -134,6 +140,7 @@ static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
 
 static ulong load_serial(long offset)
 {
+       struct lmb lmb;
        char    record[SREC_MAXRECLEN + 1];     /* buffer for one S-Record      */
        char    binbuf[SREC_MAXBINLEN];         /* buffer for binary data       */
        int     binlen;                         /* no. of data bytes in S-Rec.  */
@@ -144,6 +151,9 @@ static ulong load_serial(long offset)
        ulong   start_addr = ~0;
        ulong   end_addr   =  0;
        int     line_count =  0;
+       long ret;
+
+       lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
 
        while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
                type = srec_decode(record, &binlen, &addr, binbuf);
@@ -169,7 +179,14 @@ static ulong load_serial(long offset)
                    } else
 #endif
                    {
+                       ret = lmb_reserve(&lmb, store_addr, binlen);
+                       if (ret) {
+                               printf("\nCannot overwrite reserved area (%08lx..%08lx)\n",
+                                       store_addr, store_addr + binlen);
+                               return ret;
+                       }
                        memcpy((char *)(store_addr), binbuf, binlen);
+                       lmb_free(&lmb, store_addr, binlen);
                    }
                    if ((store_addr) < start_addr)
                        start_addr = store_addr;
@@ -212,7 +229,7 @@ static int read_record(char *buf, ulong len)
        --len;  /* always leave room for terminating '\0' byte */
 
        for (p=buf; p < buf+len; ++p) {
-               c = getc();             /* read character               */
+               c = getchar();          /* read character               */
                if (do_echo)
                        putc(c);        /* ... and echo it              */
 
@@ -228,12 +245,11 @@ static int read_record(char *buf, ulong len)
                        *p = c;
                }
 
-           /* Check for the console hangup (if any different from serial) */
-           if (gd->jt->getc != getc) {
-               if (ctrlc()) {
-                   return (-1);
+               /* Check for the console hangup (if any different from serial) */
+               if (gd->jt->getc != getchar) {
+                       if (ctrlc())
+                               return (-1);
                }
-           }
        }
 
        /* line too long - truncate */
@@ -255,14 +271,14 @@ int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
 #endif
 
        if (argc >= 2) {
-               offset = simple_strtoul(argv[1], NULL, 16);
+               offset = hextoul(argv[1], NULL);
        }
 #ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
        if (argc >= 3) {
-               size = simple_strtoul(argv[2], NULL, 16);
+               size = hextoul(argv[2], NULL);
        }
        if (argc == 4) {
-               save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
+               save_baudrate = (int)dectoul(argv[3], NULL);
 
                /* default to current baudrate */
                if (save_baudrate == 0)
@@ -276,19 +292,19 @@ int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == '\r')
+                       if (getchar() == '\r')
                                break;
                }
        }
 #else  /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
        if (argc == 3) {
-               size = simple_strtoul(argv[2], NULL, 16);
+               size = hextoul(argv[2], NULL);
        }
 #endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
 
        printf("## Ready for S-Record upload, press ENTER to proceed ...\n");
        for (;;) {
-               if (getc() == '\r')
+               if (getchar() == '\r')
                        break;
        }
        if (save_serial(offset, size)) {
@@ -305,7 +321,7 @@ int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == 0x1B) /* ESC */
+                       if (getchar() == 0x1B) /* ESC */
                                break;
                }
        }
@@ -436,15 +452,15 @@ static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
        /* pre-set offset from $loadaddr */
        s = env_get("loadaddr");
        if (s)
-               offset = simple_strtoul(s, NULL, 16);
+               offset = hextoul(s, NULL);
 
        load_baudrate = current_baudrate = gd->baudrate;
 
        if (argc >= 2) {
-               offset = simple_strtoul(argv[1], NULL, 16);
+               offset = hextoul(argv[1], NULL);
        }
        if (argc == 3) {
-               load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+               load_baudrate = (int)dectoul(argv[2], NULL);
 
                /* default to current baudrate */
                if (load_baudrate == 0)
@@ -459,7 +475,7 @@ static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == '\r')
+                       if (getchar() == '\r')
                                break;
                }
        }
@@ -472,6 +488,14 @@ static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
 
                addr = load_serial_ymodem(offset, xyzModem_ymodem);
 
+               if (addr == ~0) {
+                       image_load_addr = 0;
+                       printf("## Binary (ymodem) download aborted\n");
+                       rcode = 1;
+               } else {
+                       printf("## Start Addr      = 0x%08lX\n", addr);
+                       image_load_addr = addr;
+               }
        } else if (strcmp(argv[0],"loadx")==0) {
                printf("## Ready for binary (xmodem) download "
                        "to 0x%08lX at %d bps...\n",
@@ -480,6 +504,14 @@ static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
 
                addr = load_serial_ymodem(offset, xyzModem_xmodem);
 
+               if (addr == ~0) {
+                       image_load_addr = 0;
+                       printf("## Binary (xmodem) download aborted\n");
+                       rcode = 1;
+               } else {
+                       printf("## Start Addr      = 0x%08lX\n", addr);
+                       image_load_addr = addr;
+               }
        } else {
 
                printf("## Ready for binary (kermit) download "
@@ -505,7 +537,7 @@ static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
                serial_setbrg();
                udelay(50000);
                for (;;) {
-                       if (getc() == 0x1B) /* ESC */
+                       if (getchar() == 0x1B) /* ESC */
                                break;
                }
        }
@@ -528,11 +560,14 @@ static ulong load_serial_bin(ulong offset)
         */
        for (i=0; i<100; ++i) {
                if (tstc()) {
-                       (void) getc();
+                       getchar();
                }
                udelay(1000);
        }
 
+       if (size == 0)
+               return ~0; /* Download aborted */
+
        flush_cache(offset, size);
 
        printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
@@ -831,7 +866,7 @@ static int k_recv(void)
                /* get a packet */
                /* wait for the starting character or ^C */
                for (;;) {
-                       switch (getc ()) {
+                       switch (getchar()) {
                        case START_CHAR:        /* start packet */
                                goto START;
                        case ETX_CHAR:          /* ^C waiting for packet */
@@ -843,13 +878,13 @@ static int k_recv(void)
 START:
                /* get length of packet */
                sum = 0;
-               new_char = getc();
+               new_char = getchar();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
                length = untochar(new_char);
                /* get sequence number */
-               new_char = getc();
+               new_char = getchar();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
@@ -876,7 +911,7 @@ START:
                /* END NEW CODE */
 
                /* get packet type */
-               new_char = getc();
+               new_char = getchar();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                sum += new_char & 0xff;
@@ -886,19 +921,19 @@ START:
                if (length == -2) {
                        /* (length byte was 0, decremented twice) */
                        /* get the two length bytes */
-                       new_char = getc();
+                       new_char = getchar();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
                        len_hi = untochar(new_char);
-                       new_char = getc();
+                       new_char = getchar();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
                        len_lo = untochar(new_char);
                        length = len_hi * 95 + len_lo;
                        /* check header checksum */
-                       new_char = getc();
+                       new_char = getchar();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
@@ -908,7 +943,7 @@ START:
                }
                /* bring in rest of packet */
                while (length > 1) {
-                       new_char = getc();
+                       new_char = getchar();
                        if ((new_char & 0xE0) == 0)
                                goto packet_error;
                        sum += new_char & 0xff;
@@ -925,13 +960,13 @@ START:
                        }
                }
                /* get and validate checksum character */
-               new_char = getc();
+               new_char = getchar();
                if ((new_char & 0xE0) == 0)
                        goto packet_error;
                if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
                        goto packet_error;
                /* get END_CHAR */
-               new_char = getc();
+               new_char = getchar();
                if (new_char != END_CHAR) {
                  packet_error:
                        /* restore state machines */
@@ -955,7 +990,7 @@ START:
 
 static int getcxmodem(void) {
        if (tstc())
-               return (getc());
+               return (getchar());
        return -1;
 }
 static ulong load_serial_ymodem(ulong offset, int mode)
@@ -973,6 +1008,7 @@ static ulong load_serial_ymodem(ulong offset, int mode)
        res = xyzModem_stream_open(&info, &err);
        if (!res) {
 
+               err = 0;
                while ((res =
                        xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
                        store_addr = addr + offset;
@@ -985,6 +1021,9 @@ static ulong load_serial_ymodem(ulong offset, int mode)
                                rc = flash_write((char *) ymodemBuf,
                                                  store_addr, res);
                                if (rc != 0) {
+                                       xyzModem_stream_terminate(true, &getcxmodem);
+                                       xyzModem_stream_close(&err);
+                                       printf("\n");
                                        flash_perror(rc);
                                        return (~0);
                                }
@@ -996,12 +1035,24 @@ static ulong load_serial_ymodem(ulong offset, int mode)
                        }
 
                }
+               if (err) {
+                       xyzModem_stream_terminate((err == xyzModem_cancel) ? false : true, &getcxmodem);
+                       xyzModem_stream_close(&err);
+                       printf("\n%s\n", xyzModem_error(err));
+                       return (~0); /* Download aborted */
+               }
+
+               if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+                       efi_set_bootdev("Uart", "", "",
+                                       map_sysmem(offset, 0), size);
+
        } else {
-               printf("%s\n", xyzModem_error(err));
+               printf("\n%s\n", xyzModem_error(err));
+               return (~0); /* Download aborted */
        }
 
-       xyzModem_stream_close(&err);
        xyzModem_stream_terminate(false, &getcxmodem);
+       xyzModem_stream_close(&err);
 
 
        flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
@@ -1014,6 +1065,44 @@ static ulong load_serial_ymodem(ulong offset, int mode)
 
 #endif
 
+#if defined(CONFIG_CMD_LOADM)
+static int do_load_memory_bin(struct cmd_tbl *cmdtp, int flag, int argc,
+                             char *const argv[])
+{
+       ulong   addr, dest, size;
+       void    *src, *dst;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+
+       dest = simple_strtoul(argv[2], NULL, 16);
+
+       size = simple_strtoul(argv[3], NULL, 16);
+
+       if (!size) {
+               printf("loadm: can not load zero bytes\n");
+               return 1;
+       }
+
+       src = map_sysmem(addr, size);
+       dst = map_sysmem(dest, size);
+
+       memcpy(dst, src, size);
+
+       unmap_sysmem(src);
+       unmap_sysmem(dst);
+
+       if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+               efi_set_bootdev("Mem", "", "", map_sysmem(dest, 0), size);
+
+       printf("loaded bin to memory: size: %lu\n", size);
+
+       return 0;
+}
+#endif
+
 /* -------------------------------------------------------------------- */
 
 #if defined(CONFIG_CMD_LOADS)
@@ -1066,25 +1155,35 @@ U_BOOT_CMD(
 U_BOOT_CMD(
        loadb, 3, 0,    do_load_serial_bin,
        "load binary file over serial line (kermit mode)",
-       "[ off ] [ baud ]\n"
+       "[ addr [ baud ] ]\n"
        "    - load binary file over serial line"
-       " with offset 'off' and baudrate 'baud'"
+       " at address 'addr' with baudrate 'baud'"
 );
 
 U_BOOT_CMD(
        loadx, 3, 0,    do_load_serial_bin,
        "load binary file over serial line (xmodem mode)",
-       "[ off ] [ baud ]\n"
+       "[ addr [ baud ] ]\n"
        "    - load binary file over serial line"
-       " with offset 'off' and baudrate 'baud'"
+       " at address 'addr' with baudrate 'baud'"
 );
 
 U_BOOT_CMD(
        loady, 3, 0,    do_load_serial_bin,
        "load binary file over serial line (ymodem mode)",
-       "[ off ] [ baud ]\n"
+       "[ addr [ baud ] ]\n"
        "    - load binary file over serial line"
-       " with offset 'off' and baudrate 'baud'"
+       " at address 'addr' with baudrate 'baud'"
 );
 
 #endif /* CONFIG_CMD_LOADB */
+
+#if defined(CONFIG_CMD_LOADM)
+U_BOOT_CMD(
+       loadm, 4, 0,    do_load_memory_bin,
+       "load binary blob from source address to destination address",
+       "[src_addr] [dst_addr] [size]\n"
+       "     - load a binary blob from one memory location to other"
+       " from src_addr to dst_addr by size bytes"
+);
+#endif /* CONFIG_CMD_LOADM */