Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zephyr Firmware
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kestrel Collaboration
Kestrel Firmware
Zephyr Firmware
Commits
169264ab
Commit
169264ab
authored
Apr 20, 2021
by
Raptor Engineering Development Team
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add initial (primitive) firmware upload / Flash write support
parent
9b539060
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
426 additions
and
67 deletions
+426
-67
kestrel/src/kestrel.c
kestrel/src/kestrel.c
+236
-57
kestrel/src/kestrel.h
kestrel/src/kestrel.h
+11
-0
kestrel/src/shell.c
kestrel/src/shell.c
+65
-3
kestrel/src/webservice.c
kestrel/src/webservice.c
+102
-3
prj.conf
prj.conf
+12
-4
No files found.
kestrel/src/kestrel.c
View file @
169264ab
This diff is collapsed.
Click to expand it.
kestrel/src/kestrel.h
View file @
169264ab
...
...
@@ -11,6 +11,16 @@
#define KESTREL_SERVICE_THREAD_PRIORITY K_PRIO_COOP(1)
#endif
struct
firmware_buffer_region
{
uint8_t
*
buffer_address
;
unsigned
long
long
buffer_length
;
uintptr_t
current_write_offset
;
uint8_t
locked
;
uint8_t
overflow
;
};
extern
struct
firmware_buffer_region
main_firmware_buffer
;
extern
uint8_t
kestrel_basic_init_complete
;
extern
uint8_t
host_background_service_task_active
;
extern
uint8_t
host_console_service_task_requested
;
...
...
@@ -25,6 +35,7 @@ int kestrel_init(void);
int
power_on_host
(
void
);
void
power_off_chassis
(
void
);
void
print_chassis_status
(
void
);
int
write_flash_buffer_to_flash
(
void
);
int
primary_service_event_loop
(
void
);
...
...
kestrel/src/shell.c
View file @
169264ab
...
...
@@ -31,14 +31,14 @@ static void kestrel_console_thread(const void *p1, const void *p2)
void
*
active_log_backend
=
(
void
*
)
p2
;
uint32_t
active_log_level
=
CONFIG_LOG_DEFAULT_LEVEL
;
// Get shell printf context
const
struct
shell_fprintf
*
sh_fprintf
=
shell
->
fprintf_ctx
;
// Get shell printf context
const
struct
shell_fprintf
*
sh_fprintf
=
shell
->
fprintf_ctx
;
k_mutex_lock
(
&
shell
->
ctx
->
wr_mtx
,
K_FOREVER
);
shell_stop
(
shell
);
sh_fprintf
->
fwrite
((
const
struct
shell
*
)
sh_fprintf
->
user_ctx
,
CONSOLE_ATTACH_BANNER
,
strlen
(
CONSOLE_ATTACH_BANNER
));
sh_fprintf
->
fwrite
((
const
struct
shell
*
)
sh_fprintf
->
user_ctx
,
CONSOLE_ATTACH_BANNER
,
strlen
(
CONSOLE_ATTACH_BANNER
));
attach_to_host_console
(
shell
);
...
...
@@ -93,6 +93,14 @@ static void print_kestrel_utility_command_usage(const struct shell *shell, char*
shell_print
(
shell
,
"Usage: %s <poweron chassison chassisoff>"
,
command_name
);
}
static
void
print_kestrel_reflash_command_usage
(
const
struct
shell
*
shell
,
char
*
command_name
)
{
shell_print
(
shell
,
"Usage: %s <pnor>"
,
command_name
);
}
static
void
print_kestrel_memdump_command_usage
(
const
struct
shell
*
shell
,
char
*
command_name
)
{
shell_print
(
shell
,
"Usage: %s <address> [length]"
,
command_name
);
}
static
int
kestrel_shell_cmd_utility
(
const
struct
shell
*
shell
,
size_t
argc
,
char
**
argv
)
{
if
(
argc
<
2
)
{
...
...
@@ -118,6 +126,56 @@ static int kestrel_shell_cmd_utility(const struct shell *shell, size_t argc, cha
}
}
static
int
kestrel_shell_cmd_reflash
(
const
struct
shell
*
shell
,
size_t
argc
,
char
**
argv
)
{
if
(
argc
<
2
)
{
print_kestrel_reflash_command_usage
(
shell
,
argv
[
0
]);
return
-
1
;
}
if
(
strcmp
(
argv
[
1
],
"pnor"
)
==
0
)
{
VERIFY_KESTREL_START_COMPLETE
(
shell
)
return
write_flash_buffer_to_flash
();
}
else
{
shell_print
(
shell
,
"%s: Invalid parameter"
,
argv
[
0
]);
print_kestrel_reflash_command_usage
(
shell
,
argv
[
0
]);
return
-
1
;
}
}
static
int
kestrel_shell_cmd_memdump
(
const
struct
shell
*
shell
,
size_t
argc
,
char
**
argv
)
{
uintptr_t
address
;
size_t
length
;
int
pos
;
int
remaining
;
if
(
argc
<
2
)
{
print_kestrel_memdump_command_usage
(
shell
,
argv
[
0
]);
return
-
1
;
}
address
=
strtoul
(
argv
[
1
],
NULL
,
16
);
if
(
argc
>
2
)
{
length
=
strtoul
(
argv
[
2
],
NULL
,
16
);
}
else
{
length
=
1
;
}
for
(
pos
=
0
;
pos
<
length
;
pos
+=
remaining
)
{
remaining
=
MIN
(
length
-
pos
,
SHELL_HEXDUMP_BYTES_IN_LINE
);
shell_hexdump_line
(
shell
,
address
,
(
uint8_t
*
)
address
,
remaining
);
address
+=
remaining
;
}
shell_print
(
shell
,
""
);
return
0
;
}
static
int
kestrel_shell_cmd_console
(
const
struct
shell
*
shell
,
size_t
argc
,
char
**
argv
)
{
const
void
*
active_log_backend
=
NULL
;
...
...
@@ -153,6 +211,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_kestrel,
SHELL_CMD
(
obmcutil
,
NULL
,
"OBMC-compatible utilty command"
,
kestrel_shell_cmd_utility
),
// OpenBMC console command (compat)
SHELL_CMD
(
obmc
-
console
-
client
,
NULL
,
"OBMC-compatible console command"
,
kestrel_shell_cmd_console
),
// Flash programming command
SHELL_CMD
(
reflash
,
NULL
,
"Simple Flash utility"
,
kestrel_shell_cmd_reflash
),
// Arbitrary memory dump command
SHELL_CMD
(
memdump
,
NULL
,
"Memory dump tool"
,
kestrel_shell_cmd_memdump
),
// Command list array terminator
SHELL_SUBCMD_SET_END
);
...
...
kestrel/src/webservice.c
View file @
169264ab
...
...
@@ -10,6 +10,9 @@
#include "civetweb.h"
#define WITH_ZEPHYR 1
#include "kestrel.h"
#define HTTP_PORT 8080
#define HTTPS_PORT 4443
...
...
@@ -54,6 +57,7 @@ int hello_world_handler(struct mg_connection *conn, void *cbdata)
mg_printf
(
conn
,
"<ul>
\n
"
);
mg_printf
(
conn
,
"<li><a href=/info>system info</a></li>
\n
"
);
mg_printf
(
conn
,
"<li><a href=/history>cookie demo</a></li>
\n
"
);
mg_printf
(
conn
,
"<li><a href=/firmwareupload>firmware upload</a></li>
\n
"
);
mg_printf
(
conn
,
"</ul>
\n
"
);
mg_printf
(
conn
,
"</body></html>
\n
"
);
...
...
@@ -141,6 +145,98 @@ int history_handler(struct mg_connection *conn, void *cbdata)
return
200
;
}
int
firmware_upload_form_handler
(
struct
mg_connection
*
conn
,
void
*
cbdata
)
{
mg_printf
(
conn
,
"HTTP/1.1 200 OK
\r\n
Content-Type: text/html
\r\n
Connection: "
"close
\r\n\r\n
"
);
mg_printf
(
conn
,
"<!DOCTYPE html>
\n
"
);
mg_printf
(
conn
,
"<html>
\n
<head>
\n
"
);
mg_printf
(
conn
,
"<meta charset=
\"
UTF-8
\"
>
\n
"
);
mg_printf
(
conn
,
"<title>File upload</title>
\n
"
);
mg_printf
(
conn
,
"</head>
\n
<body>
\n
"
);
mg_printf
(
conn
,
"<form action=
\"
%s
\"
method=
\"
POST
\"
"
"enctype=
\"
multipart/form-data
\"
>
\n
"
,
(
const
char
*
)
cbdata
);
mg_printf
(
conn
,
"<input type=
\"
file
\"
name=
\"
firmwarefile
\"
multiple>
\n
"
);
mg_printf
(
conn
,
"<input type=
\"
submit
\"
value=
\"
Submit
\"
>
\n
"
);
mg_printf
(
conn
,
"</form>
\n
</body>
\n
</html>
\n
"
);
return
200
;
}
int
fw_field_received
(
const
char
*
key
,
const
char
*
filename
,
char
*
path
,
size_t
pathlen
,
void
*
user_data
)
{
(
void
)
key
;
(
void
)
path
;
(
void
)
pathlen
;
if
(
strcmp
(
key
,
"firmwarefile"
)
==
0
)
{
return
MG_FORM_FIELD_STORAGE_GET
;
}
return
MG_FORM_FIELD_STORAGE_ABORT
;
}
int
fw_data_received
(
const
char
*
key
,
const
char
*
value
,
size_t
valuelen
,
void
*
user_data
)
{
struct
firmware_buffer_region
*
fw_data
=
(
struct
firmware_buffer_region
*
)
user_data
;
if
((
fw_data
->
current_write_offset
+
valuelen
)
>
fw_data
->
buffer_length
)
{
// Buffer overflow!
// Discard the extra data...
valuelen
=
fw_data
->
buffer_length
-
fw_data
->
current_write_offset
;
fw_data
->
overflow
=
1
;
}
memcpy
(
fw_data
->
buffer_address
+
fw_data
->
current_write_offset
,
value
,
valuelen
);
fw_data
->
current_write_offset
+=
valuelen
;
return
0
;
}
int
firmware_upload_handler
(
struct
mg_connection
*
conn
,
void
*
cbdata
)
{
/* Handler may access the request info using mg_get_request_info */
const
struct
mg_request_info
*
req_info
=
mg_get_request_info
(
conn
);
int
ret
;
struct
mg_form_data_handler
fdh
=
{
fw_field_received
,
fw_data_received
,
0
,
(
void
*
)
&
main_firmware_buffer
};
/* It would be possible to check the request info here before calling
* mg_handle_form_request. */
(
void
)
req_info
;
mg_printf
(
conn
,
"HTTP/1.1 200 OK
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
);
main_firmware_buffer
.
locked
=
1
;
main_firmware_buffer
.
overflow
=
0
;
main_firmware_buffer
.
current_write_offset
=
0
;
/* Call the form handler */
mg_printf
(
conn
,
"File(s) uploaded:"
);
ret
=
mg_handle_form_request
(
conn
,
&
fdh
);
main_firmware_buffer
.
locked
=
0
;
mg_printf
(
conn
,
"
\r\n
%i files
\r\n
"
,
ret
);
mg_printf
(
conn
,
"
\r\n
%ld bytes
\r\n
"
,
main_firmware_buffer
.
current_write_offset
);
if
(
main_firmware_buffer
.
overflow
)
{
mg_printf
(
conn
,
"
\r\n
WARNING: Data was discarded due to buffer overflow!r
\n
"
);
return
500
;
}
return
200
;
}
void
*
main_pthread
(
void
*
arg
)
{
static
const
char
*
const
options
[]
=
{
...
...
@@ -166,9 +262,12 @@ void *main_pthread(void *arg)
return
0
;
}
mg_set_request_handler
(
ctx
,
"/$"
,
hello_world_handler
,
0
);
mg_set_request_handler
(
ctx
,
"/info$"
,
system_info_handler
,
0
);
mg_set_request_handler
(
ctx
,
"/history"
,
history_handler
,
0
);
mg_set_request_handler
(
ctx
,
"/$"
,
hello_world_handler
,
(
void
*
)
0
);
mg_set_request_handler
(
ctx
,
"/info$"
,
system_info_handler
,
(
void
*
)
0
);
mg_set_request_handler
(
ctx
,
"/history"
,
history_handler
,
(
void
*
)
0
);
mg_set_request_handler
(
ctx
,
"/firmwareupload"
,
firmware_upload_form_handler
,
(
void
*
)
"/firmwareupload.callback"
);
mg_set_request_handler
(
ctx
,
"/firmwareupload.callback"
,
firmware_upload_handler
,
(
void
*
)
0
);
return
0
;
}
...
...
prj.conf
View file @
169264ab
...
...
@@ -12,6 +12,8 @@ CONFIG_DEVICE_SHELL=y
CONFIG_POSIX_CLOCK
=
y
CONFIG_DATE_SHELL
=
y
CONFIG_NET_SHELL
=
y
CONFIG_FLASH_SHELL
=
y
CONFIG_FLASH_MAP_SHELL
=
y
CONFIG_SHELL_CMDS_SELECT
=
y
CONFIG_SHELL_BACKEND_SERIAL
=
y
CONFIG_SHELL_BACKEND_TELNET
=
y
...
...
@@ -28,6 +30,12 @@ CONFIG_FILE_SYSTEM_LITTLEFS=y
# Kestrel specific configuration
CONFIG_NET_TC_THREAD_PREEMPTIVE
=
y
CONFIG_NET_TC_TX_COUNT
=
1
# The Kestrel CPU is quite slow, and it's easy to starve the CivetWeb process
# during file uploads if the TCP queues have a higher preempt priority than
# the CivetWeb process (by default, this is true)...
CONFIG_NUM_PREEMPT_PRIORITIES
=
1
# Kernel options
CONFIG_TEST_RANDOM_GENERATOR
=
y
...
...
@@ -70,10 +78,10 @@ CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT
=
y
# Network buffers
CONFIG_NET_PKT_RX_COUNT
=
96
CONFIG_NET_PKT_TX_COUNT
=
96
CONFIG_NET_BUF_RX_COUNT
=
128
CONFIG_NET_BUF_TX_COUNT
=
128
CONFIG_NET_PKT_RX_COUNT
=
40
96
CONFIG_NET_PKT_TX_COUNT
=
40
96
CONFIG_NET_BUF_RX_COUNT
=
4096
CONFIG_NET_BUF_TX_COUNT
=
4096
CONFIG_NET_CONTEXT_NET_PKT_POOL
=
y
CONFIG_NET_BUF_POOL_USAGE
=
y
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment