Skip to content

Commit 8982682

Browse files
committed
Add chainloader test
closes #101
1 parent 07fb63a commit 8982682

File tree

8 files changed

+359
-33
lines changed

8 files changed

+359
-33
lines changed

06_uart_chainloader/Makefile

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ DOCKER_ARG_DIR_UTILS = -v $(shell pwd)/../utils:/work/utils
7070
DOCKER_ARG_DEV = --privileged -v /dev:/dev
7171

7272
DOCKER_QEMU = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
73+
DOCKER_TEST = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DIR_UTILS) $(DOCKER_IMAGE)
7374
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
7475

7576
# Dockerize commands that require USB device passthrough only on Linux
@@ -79,8 +80,9 @@ ifeq ($(UNAME_S),Linux)
7980
DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_UTILS) $(DOCKER_IMAGE)
8081
endif
8182

82-
EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
83-
EXEC_MINIPUSH = ruby ../utils/minipush.rb
83+
EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
84+
EXEC_MINIPUSH = ruby ../utils/minipush.rb
85+
EXEC_QEMU_MINIPUSH = ruby tests/qemu_minipush.rb
8486

8587
.PHONY: all $(KERNEL_ELF) $(KERNEL_BIN) doc qemu qemuasm chainboot clippy clean readelf objdump nm \
8688
check
@@ -99,7 +101,7 @@ doc:
99101
@$(DOC_CMD) --document-private-items --open
100102

101103
ifeq ($(QEMU_MACHINE_TYPE),)
102-
qemu:
104+
qemu test:
103105
$(call colorecho, "\n$(QEMU_MISSING_STRING)")
104106
else
105107
qemu: $(KERNEL_BIN)
@@ -109,6 +111,12 @@ qemu: $(KERNEL_BIN)
109111
qemuasm: $(KERNEL_BIN)
110112
$(call colorecho, "\nLaunching QEMU with ASM output")
111113
@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -d in_asm
114+
115+
test: $(KERNEL_BIN)
116+
$(call colorecho, "\nTesting chainloading - $(BSP)")
117+
@$(DOCKER_TEST) $(EXEC_QEMU_MINIPUSH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) \
118+
-kernel $(KERNEL_BIN) $(CHAINBOOT_DEMO_PAYLOAD)
119+
112120
endif
113121

114122
chainboot:

06_uart_chainloader/README.md

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,32 +153,54 @@ diff -uNr 05_drivers_gpio_uart/Makefile 06_uart_chainloader/Makefile
153153
endif
154154

155155
# Export for build.rs
156-
@@ -74,13 +76,14 @@
156+
@@ -68,19 +70,22 @@
157+
DOCKER_ARG_DEV = --privileged -v /dev:/dev
158+
159+
DOCKER_QEMU = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
160+
+DOCKER_TEST = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DIR_UTILS) $(DOCKER_IMAGE)
161+
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
162+
163+
# Dockerize commands that require USB device passthrough only on Linux
157164
ifeq ($(UNAME_S),Linux)
158165
DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV)
159166

160167
- DOCKER_MINITERM = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_UTILS) $(DOCKER_IMAGE)
161168
+ DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_UTILS) $(DOCKER_IMAGE)
162169
endif
163170

164-
EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
171+
-EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
165172
-EXEC_MINITERM = ruby ../utils/miniterm.rb
166-
+EXEC_MINIPUSH = ruby ../utils/minipush.rb
173+
+EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
174+
+EXEC_MINIPUSH = ruby ../utils/minipush.rb
175+
+EXEC_QEMU_MINIPUSH = ruby tests/qemu_minipush.rb
167176

168177
-.PHONY: all $(KERNEL_ELF) $(KERNEL_BIN) doc qemu miniterm clippy clean readelf objdump nm check
169178
+.PHONY: all $(KERNEL_ELF) $(KERNEL_BIN) doc qemu qemuasm chainboot clippy clean readelf objdump nm \
170179
+ check
171180

172181
all: $(KERNEL_BIN)
173182

174-
@@ -102,10 +105,14 @@
183+
@@ -96,16 +101,26 @@
184+
@$(DOC_CMD) --document-private-items --open
185+
186+
ifeq ($(QEMU_MACHINE_TYPE),)
187+
-qemu:
188+
+qemu test:
189+
$(call colorecho, "\n$(QEMU_MISSING_STRING)")
190+
else
175191
qemu: $(KERNEL_BIN)
176192
$(call colorecho, "\nLaunching QEMU")
177193
@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
178194
+
179195
+qemuasm: $(KERNEL_BIN)
180196
+ $(call colorecho, "\nLaunching QEMU with ASM output")
181197
+ @$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -d in_asm
198+
+
199+
+test: $(KERNEL_BIN)
200+
+ $(call colorecho, "\nTesting chainloading - $(BSP)")
201+
+ @$(DOCKER_TEST) $(EXEC_QEMU_MINIPUSH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) \
202+
+ -kernel $(KERNEL_BIN) $(CHAINBOOT_DEMO_PAYLOAD)
203+
+
182204
endif
183205

184206
-miniterm:
@@ -470,6 +492,93 @@ diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs
470492
+ kernel()
471493
}
472494

495+
diff -uNr 05_drivers_gpio_uart/tests/qemu_minipush.rb 06_uart_chainloader/tests/qemu_minipush.rb
496+
--- 05_drivers_gpio_uart/tests/qemu_minipush.rb
497+
+++ 06_uart_chainloader/tests/qemu_minipush.rb
498+
@@ -0,0 +1,82 @@
499+
+# frozen_string_literal: true
500+
+
501+
+# SPDX-License-Identifier: MIT OR Apache-2.0
502+
+#
503+
+# Copyright (c) 2020-2021 Andre Richter <andre.o.richter@gmail.com>
504+
+
505+
+require_relative '../../utils/minipush'
506+
+require 'expect'
507+
+require 'timeout'
508+
+
509+
+# Match for the last print that 'demo_payload_rpiX.img' produces.
510+
+EXPECTED_PRINT = 'Echoing input now'
511+
+
512+
+# The main class
513+
+class QEMUMiniPush < MiniPush
514+
+ TIMEOUT_SECS = 3
515+
+
516+
+ # override
517+
+ def initialize(qemu_cmd, binary_image_path)
518+
+ super(nil, binary_image_path)
519+
+
520+
+ @qemu_cmd = qemu_cmd
521+
+ end
522+
+
523+
+ private
524+
+
525+
+ def quit_qemu_graceful
526+
+ Timeout.timeout(5) do
527+
+ pid = @target_serial.pid
528+
+ Process.kill('TERM', pid)
529+
+ Process.wait(pid)
530+
+ end
531+
+ end
532+
+
533+
+ # override
534+
+ def open_serial
535+
+ @target_serial = IO.popen(@qemu_cmd, 'r+', err: '/dev/null')
536+
+
537+
+ # Ensure all output is immediately flushed to the device.
538+
+ @target_serial.sync = true
539+
+
540+
+ puts "[#{@name_short}] ✅ Serial connected"
541+
+ end
542+
+
543+
+ # override
544+
+ def terminal
545+
+ result = @target_serial.expect(EXPECTED_PRINT, TIMEOUT_SECS)
546+
+ exit(1) if result.nil?
547+
+
548+
+ puts result
549+
+
550+
+ quit_qemu_graceful
551+
+ end
552+
+
553+
+ public
554+
+
555+
+ # override
556+
+ def connetion_reset; end
557+
+
558+
+ # override
559+
+ def handle_reconnect(error)
560+
+ handle_unexpected(error)
561+
+ end
562+
+end
563+
+
564+
+##--------------------------------------------------------------------------------------------------
565+
+## Execution starts here
566+
+##--------------------------------------------------------------------------------------------------
567+
+puts
568+
+puts 'QEMUMiniPush 1.0'.cyan
569+
+puts
570+
+
571+
+# CTRL + C handler. Only here to suppress Ruby's default exception print.
572+
+trap('INT') do
573+
+ # The `ensure` block from `QEMUMiniPush::run` will run after exit, restoring console state.
574+
+ exit
575+
+end
576+
+
577+
+binary_image_path = ARGV.pop
578+
+qemu_cmd = ARGV.join(' ')
579+
+
580+
+QEMUMiniPush.new(qemu_cmd, binary_image_path).run
581+
473582
diff -uNr 05_drivers_gpio_uart/update.sh 06_uart_chainloader/update.sh
474583
--- 05_drivers_gpio_uart/update.sh
475584
+++ 06_uart_chainloader/update.sh
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# frozen_string_literal: true
2+
3+
# SPDX-License-Identifier: MIT OR Apache-2.0
4+
#
5+
# Copyright (c) 2020-2021 Andre Richter <andre.o.richter@gmail.com>
6+
7+
require_relative '../../utils/minipush'
8+
require 'expect'
9+
require 'timeout'
10+
11+
# Match for the last print that 'demo_payload_rpiX.img' produces.
12+
EXPECTED_PRINT = 'Echoing input now'
13+
14+
# The main class
15+
class QEMUMiniPush < MiniPush
16+
TIMEOUT_SECS = 3
17+
18+
# override
19+
def initialize(qemu_cmd, binary_image_path)
20+
super(nil, binary_image_path)
21+
22+
@qemu_cmd = qemu_cmd
23+
end
24+
25+
private
26+
27+
def quit_qemu_graceful
28+
Timeout.timeout(5) do
29+
pid = @target_serial.pid
30+
Process.kill('TERM', pid)
31+
Process.wait(pid)
32+
end
33+
end
34+
35+
# override
36+
def open_serial
37+
@target_serial = IO.popen(@qemu_cmd, 'r+', err: '/dev/null')
38+
39+
# Ensure all output is immediately flushed to the device.
40+
@target_serial.sync = true
41+
42+
puts "[#{@name_short}] ✅ Serial connected"
43+
end
44+
45+
# override
46+
def terminal
47+
result = @target_serial.expect(EXPECTED_PRINT, TIMEOUT_SECS)
48+
exit(1) if result.nil?
49+
50+
puts result
51+
52+
quit_qemu_graceful
53+
end
54+
55+
public
56+
57+
# override
58+
def connetion_reset; end
59+
60+
# override
61+
def handle_reconnect(error)
62+
handle_unexpected(error)
63+
end
64+
end
65+
66+
##--------------------------------------------------------------------------------------------------
67+
## Execution starts here
68+
##--------------------------------------------------------------------------------------------------
69+
puts
70+
puts 'QEMUMiniPush 1.0'.cyan
71+
puts
72+
73+
# CTRL + C handler. Only here to suppress Ruby's default exception print.
74+
trap('INT') do
75+
# The `ensure` block from `QEMUMiniPush::run` will run after exit, restoring console state.
76+
exit
77+
end
78+
79+
binary_image_path = ARGV.pop
80+
qemu_cmd = ARGV.join(' ')
81+
82+
QEMUMiniPush.new(qemu_cmd, binary_image_path).run

0 commit comments

Comments
 (0)