Skip to content

Commit 1d8ef29

Browse files
jgangemiclaude
andcommitted
fix: cache security info from ROM before stub loads
GET_SECURITY_INFO (0x14) is ROM-only; stub returns 0xC0. Cache the response during detectChip() and return it from readSecurityInfo(). When stub is loaded and no cached info is available, return UnsupportedCommandError with guidance to use ChipAuto. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b52d778 commit 1d8ef29

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

pkg/espflasher/security_info.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ func (f *Flasher) readSecurityInfo() (*SecurityInfo, error) {
3737
if len(f.secInfo) > 0 {
3838
res = f.secInfo
3939
} else {
40+
// GET_SECURITY_INFO (opcode 0x14) is ROM-only; stub returns 0xC0.
41+
// If stub is loaded and we have no cached info, it's too late.
42+
if f.conn.isStub() {
43+
return nil, &UnsupportedCommandError{
44+
Command: "GET_SECURITY_INFO requires ROM bootloader; not available after stub is loaded (use ChipAuto to cache during connect)",
45+
}
46+
}
47+
4048
res, err = f.conn.securityInfo()
4149
if err != nil {
4250
return nil, err

pkg/espflasher/security_info_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,34 @@ func TestSecurityInfoCachingWithStubFailure(t *testing.T) {
323323
t.Errorf("expected only 1 connection call (second should use cache), got %d", callCount)
324324
}
325325
}
326+
327+
func TestSecurityInfoStubWithoutCache(t *testing.T) {
328+
// Test that when stub is running and no cached security info is available,
329+
// readSecurityInfo() returns UnsupportedCommandError.
330+
mc := &mockConnection{
331+
securityInfoFunc: func() ([]byte, error) {
332+
return nil, errors.New("stub does not support command 0x14")
333+
},
334+
stubMode: true, // Simulate stub is running
335+
}
336+
f := &Flasher{conn: mc}
337+
338+
// Call without cache and stub running should return UnsupportedCommandError
339+
si, err := f.readSecurityInfo()
340+
if err == nil {
341+
t.Fatal("expected error, got nil")
342+
}
343+
344+
var unsupErr *UnsupportedCommandError
345+
if !errors.As(err, &unsupErr) {
346+
t.Fatalf("expected UnsupportedCommandError, got %T: %v", err, err)
347+
}
348+
349+
if unsupErr.Command != "GET_SECURITY_INFO requires ROM bootloader; not available after stub is loaded (use ChipAuto to cache during connect)" {
350+
t.Errorf("unexpected error message: %s", unsupErr.Command)
351+
}
352+
353+
if si != nil {
354+
t.Errorf("expected nil SecurityInfo, got %v", si)
355+
}
356+
}

0 commit comments

Comments
 (0)