Add firmware download support

parent 0ecfd43a
......@@ -132,10 +132,12 @@ static int parse_range_header(const char *header, int64_t *a, int64_t *b)
return sscanf(header, "bytes=%lld-%lld", a, b);
}
void civetweb_send_file_data(struct mg_connection *conn, const uint8_t* data, int64_t len)
void civetweb_send_file_data(struct mg_connection *conn, const uint8_t* data, int64_t len, int use_chunked_encoding)
{
char buf[MG_BUF_LEN];
int to_read, num_written;
int to_read;
int to_write;
int num_written;
if (!data || !conn) {
return;
......@@ -147,17 +149,35 @@ void civetweb_send_file_data(struct mg_connection *conn, const uint8_t* data, in
if ((int64_t)to_read > len) {
to_read = (int)len;
}
if (use_chunked_encoding) {
/* Cap at a chunk size of 16k */
to_write = to_read;
if (to_write > 16384) {
to_write = 16384;
}
/* Send read bytes to the client, exit the loop on error */
if ((num_written = mg_send_chunk(conn, data, (size_t)to_write))
< to_write) {
break;
}
}
else {
/* Send read bytes to the client, exit the loop on error */
if ((num_written = mg_write(conn, data, (size_t)to_read))
!= to_read) {
break;
}
}
data += num_written;
/* Both read and were successful, adjust counters */
len -= num_written;
}
if (use_chunked_encoding) {
mg_send_chunk(conn, NULL, 0);
}
}
void civetweb_send_file(struct mg_connection *conn, const char* content_type, const uint8_t* data, size_t length)
......@@ -166,18 +186,24 @@ void civetweb_send_file(struct mg_connection *conn, const char* content_type, co
char range[128]; /* large enough, so there will be no overflow */
const char *range_hdr;
int64_t cl, r1, r2;
int n, truncated;
int n;
const char *encoding = 0;
const char *origin_hdr;
const char *cors_orig_cfg;
const char *cors1, *cors2;
// const char *cors_orig_cfg;
const char *cors1;
// const char *cors2;
int status_code;
int is_head_request;
int use_chunked_encoding = 0;
const struct mg_request_info *request_info;
// FIXME
// Set to some future date for images to avoid constant reloads from the overtaxed Kestrel web server...
uint64_t last_modified = 0;
request_info = mg_get_request_info(conn);
is_head_request = !strcmp(request_info->request_method, "HEAD");
cl = (int64_t)length;
status_code = 200;
range[0] = '\0';
......@@ -207,7 +233,7 @@ void civetweb_send_file(struct mg_connection *conn, const char* content_type, co
/* Standard CORS header */
origin_hdr = mg_get_header(conn, "Origin");
cors1 = "Access-Control-Allow-Origin";
cors2 = cors_orig_cfg;
//cors2 = cors_orig_cfg;
/* Prepare Etag, and Last-Modified headers. */
gmt_time_string(lm, sizeof(lm), &last_modified);
......@@ -227,9 +253,9 @@ void civetweb_send_file(struct mg_connection *conn, const char* content_type, co
"Content-Type",
content_type,
(int)strlen(content_type));
if (cors1[0] != 0) {
mg_response_header_add(conn, cors1, cors2, -1);
}
// if (cors1[0] != 0) {
// mg_response_header_add(conn, cors1, cors2, -1);
// }
mg_response_header_add(conn, "Last-Modified", lm, -1);
mg_response_header_add(conn, "Etag", etag, -1);
......@@ -240,11 +266,13 @@ void civetweb_send_file(struct mg_connection *conn, const char* content_type, co
int trunc = 0;
mg_snprintf(conn, &trunc, len, sizeof(len), "%lld", cl);
if (!trunc) {
if ((!trunc) && (!use_chunked_encoding)) {
mg_response_header_add(conn, "Content-Length", len, -1);
}
if (!use_chunked_encoding) {
mg_response_header_add(conn, "Accept-Ranges", "bytes", -1);
}
if (encoding) {
mg_response_header_add(conn, "Content-Encoding", encoding, -1);
......@@ -252,11 +280,14 @@ void civetweb_send_file(struct mg_connection *conn, const char* content_type, co
if (range[0] != 0) {
mg_response_header_add(conn, "Content-Range", range, -1);
}
if (use_chunked_encoding) {
mg_response_header_add(conn, "Transfer-Encoding", "chunked", -1);
}
/* Send all headers */
mg_response_header_send(conn);
if (!is_head_request) {
civetweb_send_file_data(conn, data + r1, cl);
civetweb_send_file_data(conn, data + r1, cl, use_chunked_encoding);
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
<div class="sidebar_nav">
<a href="/info">Info</a>
<a href="/firmwareupload$">Firmware</a>
<a href="/firmwareupload">Firmware</a>
</div>
<div class="header">
......
......@@ -18,6 +18,7 @@ LOG_MODULE_REGISTER(webportal, LOG_LEVEL_DBG);
#define WITH_ZEPHYR 1
#include "kestrel.h"
#include <generated/mem.h>
#define STANDARD_HEADER(title) \
"<head>" \
......@@ -42,6 +43,13 @@ static int static_file_##name##_handler(struct mg_connection *conn, void *cbdata
return 200; \
}
#define KESTREL_WEBSERVICE_DEFINE_PSEUDO_FILE_HANDLER(name, type) \
static int static_file_##name##_handler(struct mg_connection *conn, void *cbdata) \
{ \
civetweb_send_file(conn, type, embedded_file_##name##_pointer, embedded_file_##name##_length); \
return 200; \
}
#define KESTREL_WEBSERVICE_DEFINE_PAGE_HANDLER(name, type, title) \
static int static_file_##name##_handler(struct mg_connection *conn, void *cbdata) \
{ \
......@@ -58,17 +66,26 @@ static int static_file_##name##_handler(struct mg_connection *conn, void *cbdata
#define KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(name, path) \
mg_set_request_handler(ctx, path, static_file_##name##_handler, (void *)0);
// Set this as small as possible
#define MAX_REQUEST_SIZE_BYTES 1024
#define MAX_REQUEST_SIZE_BYTES 8192
// Define ports
#define HTTP_PORT 8080
#define HTTPS_PORT 4443
uint8_t* embedded_file_fpga_firmware_raw_pointer = (uint8_t*)((uintptr_t)BMCSPIFLASH_BASE + 0x0);
size_t embedded_file_fpga_firmware_raw_length = 0x800000;
uint8_t* embedded_file_bmc_firmware_raw_pointer = (uint8_t*)((uintptr_t)BMCSPIFLASH_BASE + 0x800000);
size_t embedded_file_bmc_firmware_raw_length = 0x400000;
uint8_t* embedded_file_pnor_firmware_raw_pointer = (uint8_t*)((uintptr_t)HOSTSPIFLASH_BASE);
size_t embedded_file_pnor_firmware_raw_length = 0x400000;
KESTREL_WEBSERVICE_DEFINE_PAGE_HANDLER(index_html, "text/html", "Kestrel SoftBMC")
KESTREL_WEBSERVICE_DEFINE_FILE_HANDLER(style_css, "text/css")
KESTREL_WEBSERVICE_DEFINE_FILE_HANDLER(raptor_logo_jpg, "image/jpeg")
KESTREL_WEBSERVICE_DEFINE_FILE_HANDLER(kestrel_avatar_small_png, "image/png")
KESTREL_WEBSERVICE_DEFINE_PSEUDO_FILE_HANDLER(fpga_firmware_raw, "application/octet-stream")
KESTREL_WEBSERVICE_DEFINE_PSEUDO_FILE_HANDLER(bmc_firmware_raw, "application/octet-stream")
KESTREL_WEBSERVICE_DEFINE_PSEUDO_FILE_HANDLER(pnor_firmware_raw, "application/octet-stream")
struct civetweb_info {
const char *version;
......@@ -137,7 +154,7 @@ int firmware_upload_form_handler(struct mg_connection *conn, void *cbdata)
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
"close\r\n\r\n");
SEND_STANDARD_HEADER(conn, "Firmware Upload")
SEND_STANDARD_HEADER(conn, "Firmware Management")
mg_printf(conn, "<h3>Firmware Upload</h3>");
mg_printf(conn,
......@@ -148,6 +165,12 @@ int firmware_upload_form_handler(struct mg_connection *conn, void *cbdata)
mg_printf(conn, "<input type=\"submit\" value=\"Upload\">\n");
mg_printf(conn, "</form>\n");
mg_printf(conn, "<p>\n");
mg_printf(conn, "<h3>Firmware Download</h3>\n");
mg_printf(conn, "<a href=\"/firmware/fpga.img\">FPGA</a><br>\n");
mg_printf(conn, "<a href=\"/firmware/bmc.img\">BMC</a><br>\n");
mg_printf(conn, "<a href=\"/firmware/pnor.img\">PNOR</a><br>\n");
SEND_STANDARD_FOOTER(conn);
return 200;
......@@ -237,7 +260,7 @@ void *web_portal_pthread(void *arg)
"listening_ports",
STRINGIFY(HTTP_PORT),
"num_threads",
"1",
"16",
"max_request_size",
STRINGIFY(MAX_REQUEST_SIZE_BYTES),
NULL
......@@ -263,6 +286,9 @@ void *web_portal_pthread(void *arg)
// Static files
KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(raptor_logo_jpg, "/raptor_logo.jpg$")
KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(kestrel_avatar_small_png, "/kestrel_avatar_small.png$")
KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(fpga_firmware_raw, "/firmware/fpga.img$")
KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(bmc_firmware_raw, "/firmware/bmc.img$")
KESTREL_WEBSERVICE_REGISTER_FILE_HANDLER(pnor_firmware_raw, "/firmware/pnor.img$")
// Dynamic pages
mg_set_request_handler(ctx, "/info$", system_info_handler, (void *)0);
......
......@@ -52,7 +52,8 @@ CONFIG_LOG_PRINTK=n
CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=0
# POSIX options
CONFIG_POSIX_MAX_FDS=20
CONFIG_POSIX_MAX_FDS=32
CONFIG_MAX_PTHREAD_COUNT=64
CONFIG_POSIX_API=y
CONFIG_PTHREAD_IPC=y
CONFIG_POSIX_MQUEUE=y
......@@ -73,18 +74,20 @@ CONFIG_NET_IPV6=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_MAX_CONN=20
CONFIG_NET_MAX_CONTEXTS=20
CONFIG_NET_MAX_CONN=32
CONFIG_NET_MAX_CONTEXTS=32
CONFIG_NET_STATISTICS=y
CONFIG_NET_CONNECTION_MANAGER=y
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_TCP_BACKLOG_SIZE=16
# Network buffers
CONFIG_NET_PKT_RX_COUNT=4096
CONFIG_NET_PKT_TX_COUNT=4096
CONFIG_NET_BUF_RX_COUNT=4096
CONFIG_NET_BUF_TX_COUNT=4096
CONFIG_NET_BUF_RX_COUNT=32768
CONFIG_NET_BUF_TX_COUNT=32768
CONFIG_NET_BUF_DATA_SIZE=128
CONFIG_NET_CONTEXT_NET_PKT_POOL=y
CONFIG_NET_BUF_POOL_USAGE=y
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment