blob: d2ac9af64dde3419aff47c876bf55a7b2d69ffde [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <string.h>
#include <os/mynewt.h>
#include "enc_flash/enc_flash.h"
#include "enc_flash/enc_flash_int.h"
#define HAL_TO_ENC(dev) (struct enc_flash_dev *)(dev)
static int enc_flash_read(const struct hal_flash *h_dev, uint32_t addr,
void *buf, uint32_t len);
static int enc_flash_write(const struct hal_flash *h_dev, uint32_t addr,
const void *buf, uint32_t len);
static int enc_flash_erase_sector(const struct hal_flash *h_dev,
uint32_t addr);
static int enc_flash_sector_info(const struct hal_flash *h_dev, int idx,
uint32_t *addr, uint32_t *sz);
static int enc_flash_is_empty(const struct hal_flash *h_dev, uint32_t addr,
void *buf, uint32_t len);
static int enc_flash_init(const struct hal_flash *h_dev);
const struct hal_flash_funcs enc_flash_funcs = {
.hff_read = enc_flash_read,
.hff_write = enc_flash_write,
.hff_erase_sector = enc_flash_erase_sector,
.hff_sector_info = enc_flash_sector_info,
.hff_is_empty = enc_flash_is_empty,
.hff_init = enc_flash_init,
};
/*
* Read first all the data in to provided memory area, then apply the
* cipher -> text conversion.
*/
static int
enc_flash_read(const struct hal_flash *h_dev, uint32_t addr, void *buf,
uint32_t len)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
uint8_t *bufb = buf;
int i;
int blk_end;
int rc = 0;
h_dev = dev->efd_hwdev;
rc = h_dev->hf_itf->hff_read(h_dev, addr, buf, len);
if (rc) {
return rc;
}
i = addr & (ENC_FLASH_BLK - 1);
addr &= ~(ENC_FLASH_BLK - 1);
blk_end = ENC_FLASH_BLK;
if (blk_end > i + len) {
blk_end = i + len;
}
while (1) {
enc_flash_crypt_arch(dev, addr, bufb, bufb, i, blk_end - i);
len -= (blk_end - i);
bufb += (blk_end - i);
if (len == 0) {
break;
}
i = 0;
addr += ENC_FLASH_BLK;
blk_end = ENC_FLASH_BLK;
if (blk_end > len) {
blk_end = len;
}
}
return rc;
}
static int
enc_flash_write(const struct hal_flash *h_dev, uint32_t addr,
const void *buf, uint32_t len)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
const uint8_t *bufb = buf;
int i;
int blksz;
int rc = 0;
uint8_t ctext[ENC_FLASH_BLK];
h_dev = dev->efd_hwdev;
i = addr & (ENC_FLASH_BLK - 1);
blksz = ENC_FLASH_BLK - i;
if (blksz > len) {
blksz = len;
}
while (1) {
enc_flash_crypt_arch(dev, addr & ~(ENC_FLASH_BLK - 1), bufb, ctext,
i, blksz);
len -= blksz;
bufb += blksz;
rc = h_dev->hf_itf->hff_write(h_dev, addr, ctext, blksz);
if (rc) {
return rc;
}
if (len == 0) {
break;
}
i = 0;
addr += blksz;
blksz = ENC_FLASH_BLK;
if (blksz > len) {
blksz = len;
}
}
return rc;
}
static int
enc_flash_erase_sector(const struct hal_flash *h_dev, uint32_t addr)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
h_dev = dev->efd_hwdev;
return h_dev->hf_itf->hff_erase_sector(h_dev, addr);
}
static int
enc_flash_sector_info(const struct hal_flash *h_dev, int idx,
uint32_t *addr, uint32_t *sz)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
h_dev = dev->efd_hwdev;
return h_dev->hf_itf->hff_sector_info(h_dev, idx, addr, sz);
}
static int
enc_flash_is_empty(const struct hal_flash *h_dev, uint32_t addr, void *buf,
uint32_t len)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
const struct hal_flash *hwdev;
int rc;
hwdev = dev->efd_hwdev;
if (hwdev->hf_itf->hff_is_empty) {
return hwdev->hf_itf->hff_is_empty(hwdev, addr, buf, len);
} else {
rc = hal_flash_is_erased(hwdev, addr, buf, len);
/*
* If error or low-level flash is erased, avoid reading it.
*/
if (rc < 0 || rc == 1) {
return rc;
}
/*
* Also read the underlying data.
*/
return enc_flash_read(h_dev, addr, buf, len);
}
}
void
enc_flash_setkey(struct hal_flash *h_dev, uint8_t *key)
{
enc_flash_setkey_arch(HAL_TO_ENC(h_dev), key);
}
static int
enc_flash_init(const struct hal_flash *h_dev)
{
struct enc_flash_dev *dev = HAL_TO_ENC(h_dev);
h_dev = dev->efd_hwdev;
dev->efd_hal.hf_base_addr = h_dev->hf_base_addr;
dev->efd_hal.hf_size = h_dev->hf_size;
dev->efd_hal.hf_sector_cnt = h_dev->hf_sector_cnt;
dev->efd_hal.hf_align = h_dev->hf_align;
dev->efd_hal.hf_erased_val = h_dev->hf_erased_val;
enc_flash_init_arch(dev);
return 0;
}