@@ -1997,6 +1997,20 @@ config CMD_NETCAT
netcat is a simple command to load/store kernel, or other files,
using netcat like manner over TCP.
+config CMD_HTTPD_UPLOAD
+ bool "HTTP server for file uploading"
+ depends on HTTPD_COMMON
+ help
+ HTTP/1.1 compatible server for file uploading.
+
+config CMD_HTTPD_UPLOAD_MAX_SIZE
+ int "Maximum uploading size"
+ depends on CMD_HTTPD_UPLOAD
+ default 209715200
+ help
+ This sets maximum size of uploaded file. Real transfer will be
+ slightly more than this limit.
+
config CMD_MII
bool "mii"
imply CMD_MDIO
@@ -22,6 +22,9 @@
#include <net/udp.h>
#include <net/sntp.h>
#include <net/ncsi.h>
+#if defined(CONFIG_CMD_HTTPD_UPLOAD)
+#include <net/httpd-upload.h>
+#endif
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -230,6 +233,23 @@ U_BOOT_CMD(
);
#endif
+#if defined(CONFIG_CMD_HTTPD_UPLOAD)
+static int do_httpd_upload(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc < 2)
+ return 1;
+
+ httpd_upload_prepare();
+ return netboot_common(HTTPD, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ httpd_upload, 2, 1, do_httpd_upload,
+ "starts httpd server for file uploading",
+ "[loadAddress]\n"
+);
+#endif
+
static void netboot_update_env(void)
{
char tmp[46];
new file mode 100644
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+ *
+ * httpd-upload include file
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+ */
+#ifndef __NET_HTTPD_UPLOAD_TCP_H__
+#define __NET_HTTPD_UPLOAD_TCP_H__
+
+void httpd_upload_prepare(void);
+
+#endif /* __NET_HTTPD_UPLOAD_TCP_H__ */
@@ -35,8 +35,27 @@ obj-$(CONFIG_PROT_TCP) += tcp.o
obj-$(CONFIG_CMD_WGET) += wget.o
obj-$(CONFIG_CMD_NETCAT) += netcat.o
obj-$(CONFIG_HTTPD_COMMON) += httpd.o
+obj-$(CONFIG_CMD_HTTPD_UPLOAD) += httpd-upload.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
# and this is intentional usage.
CFLAGS_eth_common.o += -Wno-format-extra-args
+
+STATIC_SUBST := 's/^\(unsigned char \)/static \1/'
+SIZE_REMOVE_SUBST := 's/^unsigned int .*//'
+
+httpd_upload_generated:
+ rm -rf $(src)/httpd_upload_generated
+ mkdir -p $(src)/httpd_upload_generated
+ cd $(src)/httpd_upload && find . -type f | while read fname; do \
+ name="$${fname##*/}" && \
+ name="$${name%%.*}" && \
+ set -o pipefail && xxd -i "$${fname##./}" | \
+ sed $(STATIC_SUBST) | \
+ sed $(SIZE_REMOVE_SUBST) > ../httpd_upload_generated/$${name}.h; \
+ done
+
+.PHONY: httpd_upload_generated
+
+net/httpd-upload.o: httpd_upload_generated
new file mode 100644
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * httpd-upload support driver
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+ */
+
+#include <command.h>
+#include <net.h>
+#include <net/httpd.h>
+#include <net/httpd-upload.h>
+
+#define MAX_FILE_SIZE CONFIG_CMD_HTTPD_UPLOAD_MAX_SIZE
+
+static enum net_loop_state httpd_on_stop(void);
+
+static enum httpd_req_check httpd_pre_post(void *req_id, const char *url,
+ struct httpd_post_data *post);
+static struct http_reply *httpd_get(void *req_id, const char *url);
+static struct http_reply *httpd_post(void *req_id, const char *url,
+ struct httpd_post_data *post);
+static void httpd_on_req_end(void *req_id);
+
+#include "httpd_upload_generated/error_400.h"
+#include "httpd_upload_generated/error_404.h"
+#include "httpd_upload_generated/index.h"
+#include "httpd_upload_generated/upload_ok.h"
+
+static struct http_reply error_400 = {
+ .code = 400,
+ .code_msg = "Bad Request",
+ .data_type = "text/html; charset=utf-8",
+ .data = error_400_html,
+ .len = sizeof(error_400_html)
+};
+
+static struct http_reply error_404 = {
+ .code = 404,
+ .code_msg = "Not Found",
+ .data_type = "text/html; charset=utf-8",
+ .data = error_404_html,
+ .len = sizeof(error_404_html)
+};
+
+static struct http_reply index = {
+ .code = 200,
+ .code_msg = "OK",
+ .data_type = "text/html; charset=utf-8",
+ .data = index_html,
+ .len = sizeof(index_html)
+};
+
+static struct http_reply upload_ok = {
+ .code = 200,
+ .code_msg = "OK",
+ .data_type = "text/html; charset=utf-8",
+ .data = upload_ok_html,
+ .len = sizeof(upload_ok_html)
+};
+
+static struct httpd_config cfg = {
+ .on_stop = httpd_on_stop,
+ .on_req_end = httpd_on_req_end,
+ .get = httpd_get,
+ .post = httpd_post,
+ .pre_post = httpd_pre_post,
+ .error_400 = &error_400,
+ .error_404 = &error_404,
+};
+
+static enum net_loop_state httpd_loop_state;
+static void *post_req_id;
+
+void httpd_upload_prepare(void)
+{
+ httpd_setup(&cfg);
+ httpd_loop_state = NETLOOP_FAIL;
+}
+
+static enum httpd_req_check httpd_pre_post(void *req_id, const char *url,
+ struct httpd_post_data *post)
+{
+ if (post->size > MAX_FILE_SIZE) {
+ printf("HTTPD: reset connection, upload file is too large\n");
+ return HTTPD_CLNT_RST;
+ }
+
+ post_req_id = req_id;
+ return HTTPD_REQ_OK;
+}
+
+static struct http_reply *httpd_post(void *req_id, const char *url,
+ struct httpd_post_data *post)
+{
+ if (strcmp(url, "/file_upload") != 0)
+ return &error_404;
+
+ httpd_loop_state = NETLOOP_SUCCESS;
+ printf("HTTPD: upload OK\n");
+ return &upload_ok;
+}
+
+static struct http_reply *httpd_get(void *req_id, const char *url)
+{
+ if (strcmp(url, "/") == 0)
+ return &index;
+ if (strcmp(url, "/index.html") == 0)
+ return &index;
+ return &error_404;
+}
+
+static void httpd_on_req_end(void *req_id)
+{
+ if (req_id == post_req_id) {
+ post_req_id = NULL;
+ httpd_stop();
+ }
+}
+
+static enum net_loop_state httpd_on_stop(void)
+{
+ return httpd_loop_state;
+}
new file mode 100644
@@ -0,0 +1,9 @@
+<html>
+ <head><title>400</title></head>
+ <body>
+ <h1>400 - Bad Request</h1>
+ <p>
+ Sorry, the request you are trying to do is wrong.
+ </p>
+ </body>
+</html>
new file mode 100644
@@ -0,0 +1,10 @@
+<html>
+ <head><title>404</title></head>
+ <body>
+ <h1>404 - Page not found</h1>
+ <p>
+ Sorry, the page you are requesting was not found on this
+ server.
+ </p>
+ </body>
+</html>
new file mode 100644
@@ -0,0 +1,14 @@
+<html>
+ <head><title>Upload File</title></head>
+ <body>
+ <h1>Upload File.</h1>
+ <p>This will write the uploaded file to the memory arear pointed by ${loadaddr}.
+ <form method="post" enctype="multipart/form-data" action="file_upload">
+ File to upload:
+ <input type="file" name="fileID" size="500" /><br />
+ <p> <input type="submit" value="upload" />
+ <p>It takes no more than a second after the file has been uploaded until status OK is shown.
+ </form>
+ </p>
+ </body>
+</html>
new file mode 100644
@@ -0,0 +1,7 @@
+<html>
+ <head><title>OK</title></head>
+ <body>
+ <h1>Upload OK</h1>
+ <p>The file was uploaded.</p>
+ </body>
+</html>
Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu> --- cmd/Kconfig | 14 ++++ cmd/net.c | 20 ++++++ include/net/httpd-upload.h | 12 ++++ net/Makefile | 19 +++++ net/httpd-upload.c | 123 ++++++++++++++++++++++++++++++++ net/httpd_upload/error_400.html | 9 +++ net/httpd_upload/error_404.html | 10 +++ net/httpd_upload/index.html | 14 ++++ net/httpd_upload/upload_ok.html | 7 ++ 9 files changed, 228 insertions(+) create mode 100644 include/net/httpd-upload.h create mode 100644 net/httpd-upload.c create mode 100644 net/httpd_upload/error_400.html create mode 100644 net/httpd_upload/error_404.html create mode 100644 net/httpd_upload/index.html create mode 100644 net/httpd_upload/upload_ok.html