1/* 2 * Mikrotik's RouterBOOT specific prom routines 3 * 4 * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation. 9 * 10 */ 11 12#include <linux/types.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/string.h> 16#include <linux/module.h> 17#include <linux/routerboot.h> 18 19#include <asm/bootinfo.h> 20#include <asm/addrspace.h> 21 22#include <asm/mach-adm5120/adm5120_defs.h> 23#include <prom/routerboot.h> 24#include "prom_read.h" 25 26struct rb_hard_settings rb_hs; 27static int rb_found; 28 29static int __init routerboot_load_hs(u8 *buf, u16 buflen) 30{ 31 u16 id, len; 32 33 memset(&rb_hs, 0, sizeof(rb_hs)); 34 35 if (buflen < 4) 36 return -1; 37 38 if (prom_read_le32(buf) != RB_MAGIC_HARD) 39 return -1; 40 41 /* skip magic value */ 42 buf += 4; 43 buflen -= 4; 44 45 while (buflen > 2) { 46 id = prom_read_le16(buf); 47 buf += 2; 48 buflen -= 2; 49 if (id == RB_ID_TERMINATOR || buflen < 2) 50 break; 51 52 len = prom_read_le16(buf); 53 buf += 2; 54 buflen -= 2; 55 56 if (buflen < len) 57 break; 58 59 switch (id) { 60 case RB_ID_BIOS_VERSION: 61 rb_hs.bios_ver = (char *)buf; 62 break; 63 case RB_ID_BOARD_NAME: 64 rb_hs.name = (char *)buf; 65 break; 66 case RB_ID_MEMORY_SIZE: 67 rb_hs.mem_size = prom_read_le32(buf); 68 break; 69 case RB_ID_MAC_ADDRESS_COUNT: 70 rb_hs.mac_count = prom_read_le32(buf); 71 break; 72 case RB_ID_MAC_ADDRESS_PACK: 73 if ((len / RB_MAC_SIZE) > 0) 74 rb_hs.mac_base = buf; 75 break; 76 } 77 78 buf += len; 79 buflen -= len; 80 81 } 82 83 return 0; 84} 85 86#define RB_BS_OFFS 0x14 87#define RB_OFFS_MAX (128*1024) 88 89int __init routerboot_present(void) 90{ 91 struct rb_bios_settings *bs; 92 u8 *base; 93 u32 off, len; 94 95 if (rb_found) 96 goto out; 97 98 base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE); 99 bs = (struct rb_bios_settings *)(base + RB_BS_OFFS); 100 101 off = prom_read_le32(&bs->hs_offs); 102 len = prom_read_le32(&bs->hs_size); 103 if (off > RB_OFFS_MAX) 104 goto out; 105 106 if (routerboot_load_hs(base+off, len) != 0) 107 goto out; 108 109 rb_found = 1; 110 111out: 112 return rb_found; 113} 114 115char *routerboot_get_boardname(void) 116{ 117 if (rb_found == 0) 118 return NULL; 119 120 return rb_hs.name; 121} 122