Linux 2.6 kernel module for sparc64 / sunblade100

overwrites the IDPROM with random ethernet-mac / serial
look at the source if you want other values...

just make and load with insmod:
$ make
$ insmod idprom-repair.ko
$ dmesg | tail
found eeprom on ebus: addr: 0x1FFF1000000 - 0x1FFF1001FFF
IDPROM: HostID: 83da60af Serial:   12917598
IDPROM: Ethernet address: 00:03:ba:da:60:af
This commit is contained in:
ore 2007-02-07 16:29:44 +01:00
commit b972ffd82c
2 changed files with 169 additions and 0 deletions

9
Makefile Normal file
View File

@ -0,0 +1,9 @@
obj-m += idprom-repair.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean

160
idprom-repair.c Normal file
View File

@ -0,0 +1,160 @@
/*
* Copyright (C) 02/2007 by Olaf Rempel
* razzor@kopf-tisch.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/random.h>
#include <asm/ebus.h>
#include <asm/idprom.h>
/* position of the idprom data */
#define IDPROM_POS 0x1FD8
/* position of the clock registers */
#define CLOCK_POS 0x1FF8
/* M48T59 has 8192 byte NVRAM */
#define NVRAM_END 0x1FFF
static struct resource * get_eeprom_resource(void)
{
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (strcmp(edev->prom_node->name, "eeprom") == 0) {
return &edev->resource[0];
}
}
}
return NULL;
}
static void init_nvram(struct resource *res)
{
long addr;
/* reset nvram-data, but do not overwrite the clock registers */
for (addr = 0x0000; addr < CLOCK_POS; addr += 4)
outl(0x0, res->start + addr);
/* todo: kickstart clock? */
}
static void load_idprom_data(struct resource *res, struct idprom *data)
{
long addr;
for (addr = 0; addr < sizeof(struct idprom); addr++)
*((u8 *)data + addr) = inb(res->start + IDPROM_POS + addr);
}
static void save_idprom_data(struct resource *res, struct idprom *data)
{
long addr;
for (addr = 0; addr < sizeof(struct idprom); addr++)
outb(*((u8 *)data + addr), res->start + IDPROM_POS + addr);
}
/* Calculate the IDPROM checksum (xor of the data bytes). */
static unsigned char calc_idprom_cksum(struct idprom *idprom)
{
unsigned char cksum, i, *ptr = (unsigned char *)idprom;
for (i = cksum = 0; i <= 0x0E; i++)
cksum ^= *ptr++;
return cksum;
}
static void show_idprom(struct idprom *data)
{
if (data->id_format != 0x01)
printk(KERN_DEBUG "IDPROM: Warning, unknown format type!\n");
if (data->id_cksum != calc_idprom_cksum(data))
printk(KERN_DEBUG "IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n",
data->id_cksum, calc_idprom_cksum(data));
printk(KERN_DEBUG "IDPROM: HostID: %02x%02x%02x%02x Serial: %10d\n",
data->id_machtype, data->id_ethaddr[3],
data->id_ethaddr[4], data->id_ethaddr[5],
data->id_sernum);
printk(KERN_DEBUG "IDPROM: Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
data->id_ethaddr[0], data->id_ethaddr[1],
data->id_ethaddr[2], data->id_ethaddr[3],
data->id_ethaddr[4], data->id_ethaddr[5]);
}
static void randomize_idprom(struct idprom *data)
{
int sernum;
memset(data, 0, sizeof(struct idprom));
// sunblade 100
data->id_format = 0x01;
data->id_machtype = 0x83;
// ethernet MAC
get_random_bytes(data->id_ethaddr, 6);
data->id_ethaddr[0] = 0x00;
data->id_ethaddr[1] = 0x03;
data->id_ethaddr[2] = 0xba;
// serial number (4bytes after date)
get_random_bytes(&sernum, sizeof(sernum));
data->id_sernum = sernum;
// xor checksum
data->id_cksum = calc_idprom_cksum(data);
}
static int repair_init(void)
{
struct idprom idprom_buffer;
struct resource *res = get_eeprom_resource();
if (res) {
printk(KERN_DEBUG "found eeprom on ebus: addr: 0x%08lX - 0x%08lX\n",
res->start, res->end);
} else {
printk(KERN_DEBUG "no eeprom resource found!\n");
return -1;
}
load_idprom_data(res, &idprom_buffer);
randomize_idprom(&idprom_buffer);
show_idprom(&idprom_buffer);
init_nvram(res);
save_idprom_data(res, &idprom_buffer);
return -1;
}
static void repair_cleanup(void)
{
}
module_init(repair_init);
module_exit(repair_cleanup);
MODULE_DESCRIPTION("Repairs SUN Blade 100 IDPROM");
MODULE_AUTHOR("(C) 2007 Olaf Rempel <razzor@kopf-tisch.de>");
MODULE_LICENSE("GPL");