Skip to content

Commit 3cd0fd1

Browse files
committed
add picoruby-crc and use it in shell startup
1 parent d2d7a2b commit 3cd0fd1

File tree

13 files changed

+166
-25
lines changed

13 files changed

+166
-25
lines changed

mrbgems/picoruby-bin-r2p2/tools/mrblib/app.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
begin
66
IO.wait_terminal and IO.clear_screen
7-
Shell.setup_system_files("#{Dir.pwd}/.r2p2", force: true)
7+
Shell.setup_system_files("#{Dir.pwd}/.r2p2")
88

99
Shell.bootstrap("../etc/init.d/r2p2")
1010

mrbgems/picoruby-crc/mrbgem.rake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
MRuby::Gem::Specification.new('picoruby-crc') do |spec|
2+
spec.license = 'MIT'
3+
spec.author = 'HASUMI Hitoshi'
4+
spec.summary = 'PicoRuby CRC library'
5+
end

mrbgems/picoruby-crc/sig/crc.rbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module CRC
2+
def self.crc32: (?String string, ?Integer crc) -> Integer
3+
end

mrbgems/picoruby-crc/src/crc.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <stdint.h>
2+
#include <stddef.h>
3+
4+
static uint32_t
5+
generate_crc32(uint8_t *str, size_t len, uint32_t crc)
6+
{
7+
uint32_t crc_value = ~crc;
8+
for (size_t i = 0; i < len; i++) {
9+
crc_value ^= str[i];
10+
for (int j = 0; j < 8; j++) {
11+
if (crc_value & 1) {
12+
crc_value = (crc_value >> 1) ^ 0xEDB88320;
13+
} else {
14+
crc_value >>= 1;
15+
}
16+
}
17+
}
18+
return ~crc_value;
19+
}
20+
21+
#if defined(PICORB_VM_MRUBY)
22+
23+
#include "mruby/crc.c"
24+
25+
#elif defined(PICORB_VM_MRUBYC)
26+
27+
#include "mrubyc/crc.c"
28+
29+
#endif
30+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "mruby.h"
2+
#include "mruby/presym.h"
3+
#include "mruby/class.h"
4+
#include "mruby/string.h"
5+
6+
/*
7+
* CRC.crc32(string = nil, crc = nil) -> Integer
8+
* when string is nil, returns the initial checksum value
9+
*/
10+
static mrb_value
11+
mrb_crc_s_crc32(mrb_state *mrb, mrb_value klass)
12+
{
13+
mrb_value string = mrb_nil_value();
14+
mrb_int crc = 0;
15+
mrb_get_args(mrb, "|Si", &string, &crc);
16+
if (mrb_nil_p(string)) {
17+
return mrb_fixnum_value(0);
18+
}
19+
uint32_t crc_value = generate_crc32((uint8_t *)RSTRING_PTR(string), (size_t)RSTRING_LEN(string), (uint32_t)crc);
20+
return mrb_int_value(mrb, crc_value);
21+
}
22+
23+
void
24+
mrb_picoruby_crc_gem_init(mrb_state* mrb)
25+
{
26+
struct RClass *module_CRC = mrb_define_module_id(mrb, MRB_SYM(CRC));
27+
28+
mrb_define_class_method_id(mrb, module_CRC, MRB_SYM(crc32), mrb_crc_s_crc32, MRB_ARGS_OPT(2));
29+
}
30+
31+
void
32+
mrb_picoruby_crc_gem_final(mrb_state* mrb)
33+
{
34+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "mrubyc.h"
2+
3+
/*
4+
* CRC.crc32(string = nil, crc = nil) -> Integer
5+
* when string is nil, returns the initial checksum value
6+
*/
7+
static void
8+
c_crc_crc32(mrbc_vm *vm, mrbc_value v[], int argc)
9+
{
10+
mrbc_value string = GET_ARG(1);
11+
mrbc_int_t crc = GET_INT_ARG(2);
12+
if (string.tt == MRBC_TT_NIL) {
13+
return mrb_fixnum_value(0);
14+
} else if (string.tt != MRBC_TT_STRING) {
15+
mrbc_raise(vm, MRBC_CLASS(TypeError), "string expected");
16+
return;
17+
}
18+
uint32_t crc_value = generate_crc32((uint8_t *)string.string->data, string.string->len, crc);
19+
SET_INT_RETURN(crc_value);
20+
}
21+
22+
void
23+
mrbc_crc_init(mrbc_vm *vm)
24+
{
25+
mrbc_class *module_CRC = mrbc_define_module(vm, "CRC");
26+
27+
mrbc_define_method(vm, module_CRC, "crc32", c_crc_crc32);
28+
}

mrbgems/picoruby-shell/mrbgem.rake

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
require 'stringio'
2+
require 'zlib'
3+
14
MRuby::Gem::Specification.new('picoruby-shell') do |spec|
25
spec.license = 'MIT'
36
spec.author = 'HASUMI Hitoshi'
@@ -9,6 +12,7 @@ MRuby::Gem::Specification.new('picoruby-shell') do |spec|
912
spec.add_dependency 'picoruby-editor'
1013
spec.add_dependency 'picoruby-sandbox'
1114
spec.add_dependency 'picoruby-env'
15+
spec.add_dependency 'picoruby-crc'
1216
if build.posix?
1317
if build.vm_mrubyc?
1418
spec.add_dependency('picoruby-dir')
@@ -44,7 +48,7 @@ MRuby::Gem::Specification.new('picoruby-shell') do |spec|
4448
mrbc.run(f, t.prerequisites[0], "executable_#{t.name.pathmap("%n").gsub('-', '_')}", cdump: false)
4549
end
4650
end
47-
executable_mrbfiles << mrbfile
51+
executable_mrbfiles << { mrbfile: mrbfile, rbfile: rbfile }
4852
objfile = "#{build_dir}/shell_executables/#{rbfile.pathmap('%n')}.o"
4953
file objfile => mrbfile
5054
build.libmruby_objs << objfile
@@ -58,15 +62,22 @@ MRuby::Gem::Specification.new('picoruby-shell') do |spec|
5862
end
5963
open(t.name, 'w') do |f|
6064
executable_mrbfiles.each do |vm_code|
61-
Rake::FileTask[vm_code].invoke
62-
f.puts "#include \"#{vm_code}\""
65+
Rake::FileTask[vm_code[:mrbfile]].invoke
66+
f.puts "#include \"#{vm_code[:mrbfile]}\""
6367
end
6468
f.puts
6569
f.puts "static shell_executables executables[] = {"
6670
executable_mrbfiles.each do |vm_code|
67-
basename = File.basename(vm_code, ".c")
71+
sio = StringIO.new("hoge", 'w+')
72+
sio.set_encoding('ASCII-8BIT')
73+
mrbc.compile_options = "--remove-lv -o-"
74+
mrbc.run(sio, vm_code[:rbfile], "", cdump: false)
75+
sio.rewind
76+
crc = Zlib.crc32(sio.read.chomp)
77+
sio.close
78+
basename = File.basename(vm_code[:mrbfile], ".c")
6879
dirname = pathmap.find { _1[:basename] == basename }[:dir]
69-
line = " {\"#{dirname}/#{basename}\", executable_#{basename.gsub('-', '_')}},"
80+
line = " {\"#{dirname}/#{basename}\", executable_#{basename.gsub('-', '_')}, #{crc}},"
7081
f.puts line
7182
end
7283
f.puts " {NULL, NULL} /* sentinel */"

mrbgems/picoruby-shell/mrblib/shell.rb

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,37 @@ def self.setup_root_volume(device, label: "PicoRuby")
3232
end
3333
end
3434

35+
def self.ensure_system_file(path, code, crc = nil)
36+
10.times do
37+
if File.file?(path)
38+
puts "Checking: #{path}"
39+
File.open(path, "r") do |f|
40+
actual_len = f.size
41+
actual_code = f.read if 0 < actual_len
42+
sleep_ms 10
43+
actual_crc = CRC.crc32(actual_code)
44+
if (actual_len == code.length) && ( crc.nil? || (actual_crc == crc) )
45+
puts " OK (#{code.length} bytes)"
46+
return
47+
else
48+
puts " NG. Updating... (len: #{code.size}<=>#{actual_len} crc: #{crc}<=>#{actual_crc})"
49+
end
50+
end
51+
File.unlink(path)
52+
sleep_ms 100
53+
else
54+
File.open(path, "w") do |f|
55+
puts "Creating: #{path}"
56+
f.expand(code.length) if f.respond_to?(:expand)
57+
f.write(code)
58+
end
59+
sleep_ms 10
60+
end
61+
end
62+
File.unlink(path) if File.file?(path)
63+
puts "Failed to save: #{path} (#{code.length} bytes)"
64+
end
65+
3566
def self.setup_system_files(root = nil, force: false)
3667
unless root.nil? || Dir.exist?(root)
3768
Dir.mkdir(root)
@@ -43,24 +74,14 @@ def self.setup_system_files(root = nil, force: false)
4374
Dir.chdir(root || "/") do
4475
%w(bin lib var home etc etc/init.d etc/network).each do |dir|
4576
Dir.mkdir(dir) unless Dir.exist?(dir)
46-
sleep_ms 100
77+
sleep_ms 10
4778
end
4879
while exe = Shell.next_executable
4980
path = "#{root}#{exe[:path]}"
50-
if force || !File.file?(path)
51-
f = File.open path, "w"
52-
f.expand exe[:code].length if f.respond_to? :expand
53-
f.write exe[:code]
54-
f.close
55-
sleep_ms 100
56-
end
81+
self.ensure_system_file(path, exe[:code], exe[:crc])
5782
end
5883
path = "#{root}/etc/machine-id"
59-
unless File.file?(path)
60-
f = File.open path, "w"
61-
f.write Machine.unique_id
62-
f.close
63-
end
84+
self.ensure_system_file(path, Machine.unique_id, nil)
6485
end
6586
Dir.chdir ENV['HOME']
6687
end
105 Bytes
Binary file not shown.

mrbgems/picoruby-shell/sig/shell.rbs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ class Shell
2020
AUTHOR_COLOR: String
2121
@editor: Editor::Line
2222

23-
def self.next_executable: -> {code: String, path: String}
23+
def self.next_executable: -> {code: String, path: String, crc: Integer}
2424
def self.setup_rtc: (rtc_t trc) -> void
2525
def self.setup_sdcard: (SPI spi) -> void
2626

2727
def self.setup_root_volume: (Symbol drive, ?label: String) -> void
28-
def self.setup_system_files: (?(String | nil) root, ?force: bool) -> void
28+
def self.ensure_system_file: (String path, String code, Integer | nil crc) -> void
29+
def self.setup_system_files: (?(String | nil) root) -> void
2930
def self.bootstrap: (String file) -> bool
3031

3132
def initialize: (?clean: bool) -> void

0 commit comments

Comments
 (0)