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.

251 lines
7.9 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: create the mac's address for android
* Author: bsp
* Create: 2019-12-15
*/
#ifdef SOCT_MINIBOOT_SUPPORT
#include "app.h"
#else
#include <common.h>
#include <asm/arch/platform.h>
#include <malloc.h>
#include <environment.h>
#include <asm/io.h>
#include <linux/string.h>
#include <linux/mtd/mtd.h>
#include "common_ext.h"
#include "pdm_ext.h"
#endif
#include "flash_ext.h"
#include "fixmac.h"
#define CFG_TIMERBASE23 REG_BASE_TIMER23
#define CFG_TIMER2_CTRL 0xC2
#define READ_TIMER2 (*(volatile unsigned long *)(CFG_TIMERBASE23 + REG_TIMER_VALUE))
#define FIXMAC_SUCCESS 0
#define FIXMAC_ERROR (-1)
#define MAC_LENTH 18
#define FASTBOOT_DEVICE_INFO_OFFSET 0
#define FASTBOOT_DEVICE_INFO_NAME "deviceinfo"
struct device_info {
char mac[MAC_LENTH];
};
static int check_mac_format(const char *mac, const int len)
{
int i;
if ((EXT_PDM_MAC_ADDR_LEN < MAC_LENTH) || (len < MAC_LENTH)) {
printf("strlen = %d, error!\n", EXT_PDM_MAC_ADDR_LEN);
return -1;
}
for (i = 0; i < MAC_LENTH - 1; ++i) {
if (i % 0x3 == 0x2) {
if (mac[i] != ':') {
return -1;
}
}
}
return 0;
}
static void mac_to_string(char *eth_str, const size_t eth_len, const unsigned char *mac, const int mac_len)
{
if (mac_len < 6) { // EtherAddr is 6 byte
printf("maclen = %d, error!\n", mac_len);
return;
}
if (sprintf_s(eth_str, eth_len, "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0x0], mac[0x1], mac[0x2],
mac[0x3], mac[0x4], mac[0x5]) < 0) {
printf("sprintf_s ethStr failed!\n");
}
}
static void random_ether_addr(unsigned char *mac, const int len)
{
if (len < 6) { // EtherAddr is 6 byte
printf("maclen = %d, error!\n", len);
return;
}
#ifdef SOCT_MINIBOOT_SUPPORT
int loop = 6; // EtherAddr is 6 byte
uint8 *ptr = mac;
srand(get_timer_value());
while (loop-- > 0) {
*ptr++ = (uint8)(rand() % 0xFF);
}
mac[0] &= ~0x01;
#else
unsigned long eth_addr_low;
unsigned long eth_addr_high;
srand((unsigned int)(READ_TIMER2 & 0xFFFFFFFF));
/*
* setting the 2nd LSB in the most significant byte of
* the address makes it a locally administered ethernet
* address
*/
eth_addr_high = (unsigned long)(rand() & 0xfeff) | 0x0200;
eth_addr_low = (unsigned long)rand();
mac[0] = eth_addr_high >> 8; /* 8 : create first mac's address */
mac[1] = eth_addr_high & 0xff;
mac[2] = eth_addr_low >> 24; /* 24 : create third mac's address */
mac[3] = (eth_addr_low >> 16) & 0xff; /* 16 : create fourth mac's address, 3:fourth mac's address */
mac[4] = (eth_addr_low >> 8) & 0xff; /* 8 : create fifth mac's address, 4:fifth mac's address */
mac[5] = eth_addr_low & 0xff; /* 5:sixth mac's address */
mac[0] &= 0xfe; /* clear multicast bit */
mac[0] |= 0x02; /* set local assignment bit (IEEE802) */
#endif
}
int eth_addr_process(void)
{
td_s32 ret = -1;
td_u8 mac[6] = {0};
ext_pdm_config_info cfg_info = {0};
ext_pdm_config_info cfg_info_2 = {0};
#ifndef SOCT_MINIBOOT_SUPPORT
__raw_writel(0, CFG_TIMERBASE23 + REG_TIMER_CONTROL);
__raw_writel(~0, CFG_TIMERBASE23 + REG_TIMER_RELOAD);
__raw_writel(CFG_TIMER2_CTRL, CFG_TIMERBASE23 + REG_TIMER_CONTROL);
#endif
ret = ext_drv_pdm_get_cfg_info(&cfg_info);
printf("ext_drv_pdm_get_cfg_info x%x \n", ret);
cfg_info.mac_addr[MAC_LENTH - 1] = 0;
printf("[%s:%d]mac:%s\n", __func__, __LINE__, (char*)cfg_info.mac_addr);
if (ret == TD_SUCCESS) {
ret = check_mac_format((char*)cfg_info.mac_addr, sizeof(cfg_info.mac_addr));
if (ret == TD_SUCCESS) {
printf("[%s:%d]mac:%s\n", __func__, __LINE__, (char*)cfg_info.mac_addr);
env_set("ethaddr", (char *)cfg_info.mac_addr);
return ret;
}
}
eth_env_get_enetaddr("ethaddr", mac);
if (env_get("ethaddr") == NULL) {
random_ether_addr(mac, sizeof(mac));
}
ret = memset_s(cfg_info.mac_addr, EXT_PDM_MAC_ADDR_LEN, 0, EXT_PDM_MAC_ADDR_LEN);
if (ret < 0) {
printf("memset_s cfg_info.mac_addr faild, error:x%x\n", ret);
return ret;
}
mac_to_string((char*)cfg_info.mac_addr, sizeof(cfg_info.mac_addr), mac, sizeof(mac));
ret = ext_drv_pdm_update_cfg_info(&cfg_info);
if (ret != TD_SUCCESS) {
printf("ext_drv_pdm_update_cfg_info x%x error\n", ret);
return ret;
}
env_set("ethaddr", (char *)cfg_info.mac_addr);
ret = ext_drv_pdm_get_cfg_info(&cfg_info_2);
printf("ext_drv_pdm_get_cfg_info x%x \n", ret);
return ret;
}
static int eth_get_device_info(td_handle *flashhandle, unsigned char *tmp_buf,
td_u32 *tmp_buf_length, struct device_info *tmp_dev_info)
{
td_s32 ret;
ext_flash_internal_info flash_info;
*flashhandle = ext_flash_open_by_name(FASTBOOT_DEVICE_INFO_NAME);
if ((*flashhandle == 0) || (*flashhandle == TD_INVALID_HANDLE)) {
printf("EXT_Flash_Open partion %s error\n", FASTBOOT_DEVICE_INFO_NAME);
return FIXMAC_ERROR;
}
ret = ext_flash_get_info(*flashhandle, &flash_info);
*tmp_buf_length = flash_info.block_size;
tmp_buf = (unsigned char *)malloc(*tmp_buf_length * sizeof(char));
if (tmp_buf == NULL) {
printf("can not alloc mem for read buf!\n");
ext_flash_close(*flashhandle);
return FIXMAC_ERROR;
}
ret = ext_flash_read(*flashhandle, FASTBOOT_DEVICE_INFO_OFFSET, tmp_buf, *tmp_buf_length, UAPI_FLASH_RW_FLAG_RAW);
if (ret == TD_FAILURE) {
printf("ext_flash_read partion %s error\n", FASTBOOT_DEVICE_INFO_NAME);
goto ERROR;
}
tmp_dev_info = (struct device_info *)malloc(sizeof(struct device_info));
if (tmp_dev_info == NULL) {
printf("can not alloc mem for mac address!\n");
goto ERROR;
}
return FIXMAC_SUCCESS;
ERROR:
free(tmp_buf);
tmp_buf = NULL;
ext_flash_close(*flashhandle);
return FIXMAC_ERROR;
}
int set_default_eth_addr(void)
{
td_handle flashhandle;
unsigned char *tmp_buf = NULL;
td_u32 tmp_buf_length;
struct device_info *tmp_dev_info = NULL;
unsigned char mac[6];
td_s32 fix_mac_ret = FIXMAC_ERROR;
#ifndef SOCT_MINIBOOT_SUPPORT
__raw_writel(0, CFG_TIMERBASE23 + REG_TIMER_CONTROL);
__raw_writel(~0, CFG_TIMERBASE23 + REG_TIMER_RELOAD);
__raw_writel(CFG_TIMER2_CTRL, CFG_TIMERBASE23 + REG_TIMER_CONTROL);
#endif
if (eth_get_device_info(&flashhandle, tmp_buf, &tmp_buf_length, tmp_dev_info) != FIXMAC_SUCCESS) {
return FIXMAC_ERROR;
}
if (memcpy_s(tmp_dev_info, sizeof(struct device_info), tmp_buf, sizeof(struct device_info)) < 0) {
printf("memcpy_s tmp_dev_info faild!\n");
goto OUT;
}
if (check_mac_format(tmp_dev_info->mac, sizeof(tmp_dev_info->mac)) == 0) {
printf("mac:%s\n", tmp_dev_info->mac);
env_set("ethaddr", tmp_dev_info->mac);
fix_mac_ret = FIXMAC_SUCCESS;
goto OUT;
} else {
random_ether_addr(mac, sizeof(mac));
mac_to_string(tmp_dev_info->mac, sizeof(tmp_dev_info->mac), mac, sizeof(mac));
if (memcpy_s(tmp_buf, tmp_buf_length * sizeof(char), tmp_dev_info, sizeof(struct device_info)) < 0) {
printf("memcpy_s tmp_dev_info faild!\n");
goto OUT;
}
if (ext_flash_write(flashhandle, FASTBOOT_DEVICE_INFO_OFFSET, tmp_buf, tmp_buf_length,
UAPI_FLASH_RW_FLAG_ERASE_FIRST) == TD_FAILURE) {
printf("ext_flash_write partion %s error\n", FASTBOOT_DEVICE_INFO_NAME);
fix_mac_ret = FIXMAC_ERROR;
goto OUT;
}
printf("mac:%s\n", tmp_dev_info->mac);
env_set("ethaddr", tmp_dev_info->mac);
fix_mac_ret = FIXMAC_SUCCESS;
goto OUT;
}
OUT:
free(tmp_buf);
free(tmp_dev_info);
tmp_buf = NULL;
tmp_dev_info = NULL;
ext_flash_close(flashhandle);
return fix_mac_ret;
}