You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.6 KiB
118 lines
3.6 KiB
package recoveryrequest
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestEncodeMatchesRockchipBootloaderMessageLayout(t *testing.T) {
|
|
encoded, err := Encode("fw-0123456789abcdef")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(encoded) != Size {
|
|
t.Fatalf("size = %d, want %d", len(encoded), Size)
|
|
}
|
|
if got := field(encoded, commandOffset, commandSize); got != Command {
|
|
t.Fatalf("command = %q", got)
|
|
}
|
|
if got := field(encoded, statusOffset, statusSize); got != "" {
|
|
t.Fatalf("status = %q", got)
|
|
}
|
|
if got := field(encoded, recoveryOffset, recoverySize); got != "recovery\n--tera-update\n--operation=fw-0123456789abcdef\n" {
|
|
t.Fatalf("recovery = %q", got)
|
|
}
|
|
if got := field(encoded, stageOffset, stageSize); got != "" {
|
|
t.Fatalf("stage = %q", got)
|
|
}
|
|
message, err := Decode(encoded)
|
|
if err != nil || message.OperationID != "fw-0123456789abcdef" {
|
|
t.Fatalf("Decode = %+v, %v", message, err)
|
|
}
|
|
}
|
|
|
|
func TestWriteAtTouchesOnlyTheBCBAndReadsBack(t *testing.T) {
|
|
device := bytes.NewReader(bytes.Repeat([]byte{0xa5}, int(Offset)+Size+4096))
|
|
buffer := &memoryDevice{data: make([]byte, device.Size())}
|
|
if _, err := device.ReadAt(buffer.data, 0); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded, _ := Encode("operation-1")
|
|
if err := WriteAt(buffer, encoded); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(buffer.data[:Offset], bytes.Repeat([]byte{0xa5}, int(Offset))) {
|
|
t.Fatal("bytes before the BCB changed")
|
|
}
|
|
if !bytes.Equal(buffer.data[Offset+Size:], bytes.Repeat([]byte{0xa5}, len(buffer.data)-int(Offset)-Size)) {
|
|
t.Fatal("bytes after the BCB changed")
|
|
}
|
|
message, err := ReadAt(buffer)
|
|
if err != nil || message.OperationID != "operation-1" {
|
|
t.Fatalf("ReadAt = %+v, %v", message, err)
|
|
}
|
|
}
|
|
|
|
func TestRejectsInvalidOrForeignMessages(t *testing.T) {
|
|
for _, value := range []string{"", " space", "slash/value", string(bytes.Repeat([]byte{'a'}, 65))} {
|
|
if _, err := Encode(value); err == nil {
|
|
t.Fatalf("Encode(%q) succeeded", value)
|
|
}
|
|
}
|
|
foreign := make([]byte, Size)
|
|
copy(foreign, "boot-recovery")
|
|
copy(foreign[recoveryOffset:], "recovery\n--wipe_data\n")
|
|
if _, err := Decode(foreign); err == nil {
|
|
t.Fatal("foreign recovery message was accepted")
|
|
}
|
|
if _, err := Decode(Clear()); err == nil {
|
|
t.Fatal("cleared message was accepted")
|
|
}
|
|
}
|
|
|
|
func TestClearIsExactZeroRecord(t *testing.T) {
|
|
cleared := Clear()
|
|
if len(cleared) != Size {
|
|
t.Fatalf("Clear size = %d, want %d", len(cleared), Size)
|
|
}
|
|
if !bytes.Equal(cleared, make([]byte, Size)) {
|
|
t.Fatal("Clear returned a non-zero BCB byte")
|
|
}
|
|
}
|
|
|
|
func TestWriteRequestFileRequiresClearRecordAndPreservesSurroundingBytes(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "misc.img")
|
|
contents := bytes.Repeat([]byte{0xa5}, int(Offset)+Size+4096)
|
|
copy(contents[Offset:Offset+Size], Clear())
|
|
if err := os.WriteFile(path, contents, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := WriteRequestFile(path, "operation-1", true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
updated, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(updated[:Offset], contents[:Offset]) || !bytes.Equal(updated[Offset+Size:], contents[Offset+Size:]) {
|
|
t.Fatal("WriteRequestFile changed bytes outside the BCB")
|
|
}
|
|
if IsClear(updated[Offset : Offset+Size]) {
|
|
t.Fatal("request remained clear")
|
|
}
|
|
if err := WriteRequestFile(path, "operation-2", true); err == nil {
|
|
t.Fatal("non-cleared recovery request was overwritten")
|
|
}
|
|
}
|
|
|
|
type memoryDevice struct{ data []byte }
|
|
|
|
func (d *memoryDevice) ReadAt(p []byte, off int64) (int, error) {
|
|
return copy(p, d.data[int(off):]), nil
|
|
}
|
|
|
|
func (d *memoryDevice) WriteAt(p []byte, off int64) (int, error) {
|
|
return copy(d.data[int(off):], p), nil
|
|
}
|
|
|