Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 157453
b: refs/heads/master
c: 684d2fd
h: refs/heads/master
i:
  157451: c471358
v: v3
  • Loading branch information
Hendrik Brueckner authored and Martin Schwidefsky committed Sep 11, 2009
1 parent 9536cde commit aeb8aaa
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6292b9ef5a4e85d6b782412a85725dd38df24b85
refs/heads/master: 684d2fd48e718e70dad21ef7c528649578147e48
5 changes: 4 additions & 1 deletion trunk/arch/s390/include/asm/ipl.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct ipl_block_fcp {
} __attribute__((packed));

#define DIAG308_VMPARM_SIZE 64
#define DIAG308_SCPDATA_SIZE (PAGE_SIZE - (sizeof(struct ipl_list_hdr) + \
offsetof(struct ipl_block_fcp, scp_data)))

struct ipl_block_ccw {
u8 load_parm[8];
Expand Down Expand Up @@ -91,7 +93,8 @@ extern void do_halt(void);
extern void do_poff(void);
extern void ipl_save_parameters(void);
extern void ipl_update_parameters(void);
extern void get_ipl_vmparm(char *);
extern size_t append_ipl_vmparm(char *, size_t);
extern size_t append_ipl_scpdata(char *, size_t);

enum {
IPL_DEVNO_VALID = 1,
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/s390/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#ifndef _ASM_S390_SETUP_H
#define _ASM_S390_SETUP_H

#define COMMAND_LINE_SIZE 1024
#define COMMAND_LINE_SIZE 4096

#define ARCH_COMMAND_LINE_SIZE 896

Expand Down
35 changes: 25 additions & 10 deletions trunk/arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ asm(
" br 14\n"
" .size savesys_ipl_nss, .-savesys_ipl_nss\n");

static __initdata char upper_command_line[COMMAND_LINE_SIZE];

static noinline __init void create_kernel_nss(void)
{
unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
Expand All @@ -90,7 +92,6 @@ static noinline __init void create_kernel_nss(void)
int response;
size_t len;
char *savesys_ptr;
char upper_command_line[COMMAND_LINE_SIZE];
char defsys_cmd[DEFSYS_CMD_SIZE];
char savesys_cmd[SAVESYS_CMD_SIZE];

Expand Down Expand Up @@ -367,21 +368,35 @@ static __init void rescue_initrd(void)
}

/* Set up boot command line */
static void __init setup_boot_command_line(void)
static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t))
{
char *parm = NULL;
char *parm, *delim;
size_t rc, len;

len = strlen(boot_command_line);

delim = boot_command_line + len; /* '\0' character position */
parm = boot_command_line + len + 1; /* append right after '\0' */

rc = ipl_data(parm, COMMAND_LINE_SIZE - len - 1);
if (rc) {
if (*parm == '=')
memmove(boot_command_line, parm + 1, rc);
else
*delim = ' '; /* replace '\0' with space */
}
}

static void __init setup_boot_command_line(void)
{
/* copy arch command line */
strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);

/* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM) {
parm = boot_command_line + strlen(boot_command_line);
*parm++ = ' ';
get_ipl_vmparm(parm);
if (parm[0] == '=')
memmove(boot_command_line, parm + 1, strlen(parm));
}
if (MACHINE_IS_VM)
append_to_cmdline(append_ipl_vmparm);

append_to_cmdline(append_ipl_scpdata);
}


Expand Down
157 changes: 142 additions & 15 deletions trunk/arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,17 +272,18 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);

/* VM IPL PARM routines */
static void reipl_get_ascii_vmparm(char *dest,
size_t reipl_get_ascii_vmparm(char *dest, size_t size,
const struct ipl_parameter_block *ipb)
{
int i;
int len = 0;
size_t len;
char has_lowercase = 0;

len = 0;
if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
(ipb->ipl_info.ccw.vm_parm_len > 0)) {

len = ipb->ipl_info.ccw.vm_parm_len;
len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
/* If at least one character is lowercase, we assume mixed
* case; otherwise we convert everything to lowercase.
Expand All @@ -299,25 +300,77 @@ static void reipl_get_ascii_vmparm(char *dest,
EBCASC(dest, len);
}
dest[len] = 0;

return len;
}

void get_ipl_vmparm(char *dest)
size_t append_ipl_vmparm(char *dest, size_t size)
{
size_t rc;

rc = 0;
if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
reipl_get_ascii_vmparm(dest, &ipl_block);
rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
else
dest[0] = 0;
return rc;
}

static ssize_t ipl_vm_parm_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
char parm[DIAG308_VMPARM_SIZE + 1] = {};

get_ipl_vmparm(parm);
append_ipl_vmparm(parm, sizeof(parm));
return sprintf(page, "%s\n", parm);
}

static size_t scpdata_length(const char* buf, size_t count)
{
while (count) {
if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
break;
count--;
}
return count;
}

size_t reipl_append_ascii_scpdata(char *dest, size_t size,
const struct ipl_parameter_block *ipb)
{
size_t count;
size_t i;

count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
ipb->ipl_info.fcp.scp_data_len));
if (!count)
goto out;

for (i = 0; i < count; i++)
if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
count = 0;
goto out;
}

memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
out:
dest[count] = '\0';
return count;
}

size_t append_ipl_scpdata(char *dest, size_t len)
{
size_t rc;

rc = 0;
if (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
else
dest[0] = 0;
return rc;
}


static struct kobj_attribute sys_ipl_vm_parm_attr =
__ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);

Expand Down Expand Up @@ -553,7 +606,7 @@ static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
{
char vmparm[DIAG308_VMPARM_SIZE + 1] = {};

reipl_get_ascii_vmparm(vmparm, ipb);
reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
return sprintf(page, "%s\n", vmparm);
}

Expand Down Expand Up @@ -626,6 +679,59 @@ static struct kobj_attribute sys_reipl_ccw_vmparm_attr =

/* FCP reipl device attributes */

static ssize_t reipl_fcp_scpdata_read(struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
size_t size = reipl_block_fcp->ipl_info.fcp.scp_data_len;
void *scp_data = reipl_block_fcp->ipl_info.fcp.scp_data;

return memory_read_from_buffer(buf, count, &off, scp_data, size);
}

static ssize_t reipl_fcp_scpdata_write(struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
size_t padding;
size_t scpdata_len;

if (off < 0)
return -EINVAL;

if (off >= DIAG308_SCPDATA_SIZE)
return -ENOSPC;

if (count > DIAG308_SCPDATA_SIZE - off)
count = DIAG308_SCPDATA_SIZE - off;

memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf + off, count);
scpdata_len = off + count;

if (scpdata_len % 8) {
padding = 8 - (scpdata_len % 8);
memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
0, padding);
scpdata_len += padding;
}

reipl_block_fcp->ipl_info.fcp.scp_data_len = scpdata_len;
reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len;
reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len;

return count;
}

static struct bin_attribute sys_reipl_fcp_scp_data_attr = {
.attr = {
.name = "scp_data",
.mode = S_IRUGO | S_IWUSR,
},
.size = PAGE_SIZE,
.read = reipl_fcp_scpdata_read,
.write = reipl_fcp_scpdata_write,
};

DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
reipl_block_fcp->ipl_info.fcp.wwpn);
DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
Expand All @@ -647,7 +753,6 @@ static struct attribute *reipl_fcp_attrs[] = {
};

static struct attribute_group reipl_fcp_attr_group = {
.name = IPL_FCP_STR,
.attrs = reipl_fcp_attrs,
};

Expand Down Expand Up @@ -895,6 +1000,7 @@ static struct kobj_attribute reipl_type_attr =
__ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);

static struct kset *reipl_kset;
static struct kset *reipl_fcp_kset;

static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
const enum ipl_method m)
Expand All @@ -906,7 +1012,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,

reipl_get_ascii_loadparm(loadparm, ipb);
reipl_get_ascii_nss_name(nss_name, ipb);
reipl_get_ascii_vmparm(vmparm, ipb);
reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);

switch (m) {
case REIPL_METHOD_CCW_VM:
Expand Down Expand Up @@ -1076,23 +1182,44 @@ static int __init reipl_fcp_init(void)
int rc;

if (!diag308_set_works) {
if (ipl_info.type == IPL_TYPE_FCP)
if (ipl_info.type == IPL_TYPE_FCP) {
make_attrs_ro(reipl_fcp_attrs);
else
sys_reipl_fcp_scp_data_attr.attr.mode = S_IRUGO;
} else
return 0;
}

reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
if (!reipl_block_fcp)
return -ENOMEM;
rc = sysfs_create_group(&reipl_kset->kobj, &reipl_fcp_attr_group);

/* sysfs: create fcp kset for mixing attr group and bin attrs */
reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL,
&reipl_kset->kobj);
if (!reipl_kset) {
free_page((unsigned long) reipl_block_fcp);
return -ENOMEM;
}

rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
if (rc) {
free_page((unsigned long)reipl_block_fcp);
kset_unregister(reipl_fcp_kset);
free_page((unsigned long) reipl_block_fcp);
return rc;
}
if (ipl_info.type == IPL_TYPE_FCP) {

rc = sysfs_create_bin_file(&reipl_fcp_kset->kobj,
&sys_reipl_fcp_scp_data_attr);
if (rc) {
sysfs_remove_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
kset_unregister(reipl_fcp_kset);
free_page((unsigned long) reipl_block_fcp);
return rc;
}

if (ipl_info.type == IPL_TYPE_FCP)
memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
} else {
else {
reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
Expand Down

0 comments on commit aeb8aaa

Please sign in to comment.