mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
pc-bios/s390-ccw/net: Add support for .INS config files
The .INS config files can normally be found on CD-ROM ISO images, so by supporting these files, it is now possible to boot directly when the TFTP server is set up with the contents of such an CD-ROM image. Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
9a848adf45
commit
c4942ee942
1 changed files with 95 additions and 5 deletions
|
@ -39,8 +39,12 @@
|
||||||
|
|
||||||
extern char _start[];
|
extern char _start[];
|
||||||
|
|
||||||
|
#define KERNEL_ADDR ((void *)0L)
|
||||||
|
#define KERNEL_MAX_SIZE ((long)_start)
|
||||||
|
|
||||||
char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE)));
|
char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE)));
|
||||||
IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE)));
|
IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
static char cfgbuf[2048];
|
||||||
|
|
||||||
static SubChannelId net_schid = { .one = 1 };
|
static SubChannelId net_schid = { .one = 1 };
|
||||||
static int ip_version = 4;
|
static int ip_version = 4;
|
||||||
|
@ -136,9 +140,15 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len)
|
||||||
rc = tftp(fnip, buffer, len, DEFAULT_TFTP_RETRIES, &tftp_err, 1, 1428,
|
rc = tftp(fnip, buffer, len, DEFAULT_TFTP_RETRIES, &tftp_err, 1, 1428,
|
||||||
ip_version);
|
ip_version);
|
||||||
|
|
||||||
if (rc > 0) {
|
if (rc < 0) {
|
||||||
printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename,
|
/* Make sure that error messages are put into a new line */
|
||||||
rc / 1024);
|
printf("\n ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc > 1024) {
|
||||||
|
printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, rc / 1024);
|
||||||
|
} else if (rc > 0) {
|
||||||
|
printf(" TFTP: Received %s (%d Bytes)\n", fnip->filename, rc);
|
||||||
} else if (rc == -1) {
|
} else if (rc == -1) {
|
||||||
puts("unknown TFTP error");
|
puts("unknown TFTP error");
|
||||||
} else if (rc == -2) {
|
} else if (rc == -2) {
|
||||||
|
@ -275,6 +285,83 @@ static void net_release(filename_ip_t *fn_ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load via information from a .INS file (which can be found on CD-ROMs
|
||||||
|
* for example)
|
||||||
|
*/
|
||||||
|
static int handle_ins_cfg(filename_ip_t *fn_ip, char *cfg, int cfgsize)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int rc = -1, llen;
|
||||||
|
void *destaddr;
|
||||||
|
char *insbuf = cfg;
|
||||||
|
|
||||||
|
ptr = strchr(insbuf, '\n');
|
||||||
|
if (!ptr) {
|
||||||
|
puts("Does not seem to be a valid .INS file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = 0;
|
||||||
|
printf("\nParsing .INS file:\n %s\n", &insbuf[2]);
|
||||||
|
|
||||||
|
insbuf = ptr + 1;
|
||||||
|
while (*insbuf && insbuf < cfg + cfgsize) {
|
||||||
|
ptr = strchr(insbuf, '\n');
|
||||||
|
if (ptr) {
|
||||||
|
*ptr = 0;
|
||||||
|
}
|
||||||
|
llen = strlen(insbuf);
|
||||||
|
if (!llen) {
|
||||||
|
insbuf = ptr + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ptr = strchr(insbuf, ' ');
|
||||||
|
if (!ptr) {
|
||||||
|
puts("Missing space separator in .INS file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ptr = 0;
|
||||||
|
strncpy((char *)fn_ip->filename, insbuf, sizeof(fn_ip->filename));
|
||||||
|
destaddr = (char *)atol(ptr + 1);
|
||||||
|
rc = tftp_load(fn_ip, destaddr, (long)_start - (long)destaddr);
|
||||||
|
if (rc <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
insbuf += llen + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
void *loadaddr = (void *)0x2000; /* Load right after the low-core */
|
||||||
|
|
||||||
|
rc = tftp_load(fn_ip, loadaddr, KERNEL_MAX_SIZE - (long)loadaddr);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
} else if (rc < 8) {
|
||||||
|
printf("'%s' is too small (%i bytes only).\n", fn_ip->filename, rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether it is a configuration file instead of a kernel */
|
||||||
|
if (rc < sizeof(cfgbuf) - 1) {
|
||||||
|
memcpy(cfgbuf, loadaddr, rc);
|
||||||
|
cfgbuf[rc] = 0; /* Make sure that it is NUL-terminated */
|
||||||
|
if (!strncmp("* ", cfgbuf, 2)) {
|
||||||
|
return handle_ins_cfg(fn_ip, cfgbuf, rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move kernel to right location */
|
||||||
|
memmove(KERNEL_ADDR, loadaddr, rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void panic(const char *string)
|
void panic(const char *string)
|
||||||
{
|
{
|
||||||
sclp_print(string);
|
sclp_print(string);
|
||||||
|
@ -356,7 +443,7 @@ static void virtio_setup(void)
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
filename_ip_t fn_ip;
|
filename_ip_t fn_ip;
|
||||||
int rc;
|
int rc, fnlen;
|
||||||
|
|
||||||
sclp_setup();
|
sclp_setup();
|
||||||
sclp_print("Network boot starting...\n");
|
sclp_print("Network boot starting...\n");
|
||||||
|
@ -368,7 +455,10 @@ void main(void)
|
||||||
panic("Network initialization failed. Halting.\n");
|
panic("Network initialization failed. Halting.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = tftp_load(&fn_ip, NULL, (long)_start);
|
fnlen = strlen((char *)fn_ip.filename);
|
||||||
|
if (fnlen > 0 && fn_ip.filename[fnlen - 1] != '/') {
|
||||||
|
rc = net_try_direct_tftp_load(&fn_ip);
|
||||||
|
}
|
||||||
|
|
||||||
net_release(&fn_ip);
|
net_release(&fn_ip);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue