github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/storage_debug.go (about)

     1  // Copyright 2023 The Armored Witness OS authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build fake_storage
    16  // +build fake_storage
    17  
    18  package main
    19  
    20  import (
    21  	"fmt"
    22  	"log"
    23  
    24  	usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2"
    25  	"github.com/usbarmory/tamago/soc/nxp/imx6ul"
    26  	"github.com/usbarmory/tamago/soc/nxp/usdhc"
    27  )
    28  
    29  const (
    30  	// fakeCardBlockSize is the number of bytes in a single memory block.
    31  	fakeCardBlockSize = int64(512)
    32  	// fakeCardNumBlocks defines the claimed size of the storage.
    33  	fakeCardNumBlocks = int64(4<<30) / fakeCardBlockSize
    34  )
    35  
    36  // storage will return MMC backed storage if running on real hardware, or
    37  // a fake in-memory storage device otherwise.
    38  func storage() Card {
    39  	if imx6ul.Native {
    40  		return usbarmory.MMC
    41  	}
    42  	return newFakeCard(fakeCardNumBlocks)
    43  }
    44  
    45  // fakeCard is an implementation of an in-memory storage device.
    46  //
    47  // Rather than allocating a slab of RAM to emulate the entire device, it
    48  // uses a map internally to associate slices (<= fakeCardBlockSize bytes)
    49  // with sector numbers - this allows us to save RAM on unused/unwritten blocks.
    50  type fakeCard struct {
    51  	info usdhc.CardInfo
    52  	mem  map[int64][]byte
    53  }
    54  
    55  // Read returns size bytes at offset in the fake storage
    56  func (fc *fakeCard) Read(offset int64, size int64) ([]byte, error) {
    57  	l := int64(fakeCardNumBlocks * fakeCardBlockSize)
    58  	if offset >= l {
    59  		return nil, fmt.Errorf("offset (%d) past end of storage (%d)", offset, l)
    60  	}
    61  	if offset+size > l {
    62  		size = l - offset
    63  	}
    64  	if offset%fakeCardBlockSize != 0 {
    65  		panic(fmt.Sprintf("non sector-aligned read at %d", offset))
    66  	}
    67  	r := make([]byte, size)
    68  	base := offset / fakeCardBlockSize
    69  	for i, rem := int64(0), size; rem > 0; i, rem = i+1, rem-fakeCardBlockSize {
    70  		copy(r[i*fakeCardBlockSize:], fc.mem[base+i])
    71  	}
    72  	return r, nil
    73  }
    74  
    75  func (fc *fakeCard) WriteBlocks(lba int, b []byte) error {
    76  	if l := fakeCardNumBlocks; int64(lba) >= l {
    77  		return fmt.Errorf("lba (%d) >= device blocks (%d)", lba, l)
    78  	}
    79  	// If the data isn't a multiple of the blocksize, pad it up
    80  	// so that it is.
    81  	if r := int64(len(b)) % fakeCardBlockSize; r != 0 {
    82  		b = append(b, make([]byte, fakeCardBlockSize-r)...)
    83  	}
    84  	for i, rem := int64(0), int64(len(b)); rem > 0; i, rem = i+1, rem-fakeCardBlockSize {
    85  		buf := make([]byte, fakeCardBlockSize)
    86  		copy(buf, b[i*fakeCardBlockSize:])
    87  		fc.mem[int64(lba)+i] = buf
    88  	}
    89  	return nil
    90  }
    91  
    92  func (fc *fakeCard) Info() usdhc.CardInfo {
    93  	return fc.info
    94  }
    95  
    96  func (fc *fakeCard) Detect() error {
    97  	log.Println("Using fake MMC storage")
    98  	return nil
    99  }
   100  
   101  // newFakeCard creates a new in-memory block device.
   102  func newFakeCard(numBlocks int64) *fakeCard {
   103  	return &fakeCard{
   104  		mem: make(map[int64][]byte),
   105  		info: usdhc.CardInfo{
   106  			BlockSize: int(fakeCardBlockSize),
   107  			Blocks:    int(numBlocks),
   108  		},
   109  	}
   110  }