mirror of
https://github.com/ipxe/ipxe.git
synced 2025-01-07 14:33:10 -06:00
Add Xen console support
Add a Xen console driver so iPXE CLI can be accessed from the Xen PV console (hvc0). (This applies when iPXE is run as an HVM guest in Xen)
This commit is contained in:
parent
6ba671acd9
commit
df93cabcc6
@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <ipxe/xenstore.h>
|
||||
#include <ipxe/xenbus.h>
|
||||
#include <ipxe/xengrant.h>
|
||||
#include <interface/xen/xencon.h>
|
||||
#include "hvm.h"
|
||||
|
||||
/** @file
|
||||
@ -405,6 +406,69 @@ static void hvm_unmap_xenstore ( struct hvm_device *hvm ) {
|
||||
iounmap ( hvm->xen.store.intf );
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Xen Console
|
||||
*
|
||||
* @v hvm HVM device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int hvm_map_console ( struct hvm_device *hvm ) {
|
||||
uint64_t console_evtchn=0;
|
||||
uint64_t console_pfn=0;
|
||||
physaddr_t console_phys;
|
||||
int xenrc;
|
||||
int rc;
|
||||
|
||||
/* Get Console event channel */
|
||||
if ( ( xenrc = xen_hvm_get_param ( &hvm->xen, HVM_PARAM_CONSOLE_EVTCHN,
|
||||
&console_evtchn ) ) != 0 ) {
|
||||
rc = -EXEN ( xenrc );
|
||||
DBGC ( hvm, "HVM could not get Console event channel: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
hvm->xen.console.port = console_evtchn;
|
||||
|
||||
/* Get Console PFN */
|
||||
if ( ( xenrc = xen_hvm_get_param ( &hvm->xen, HVM_PARAM_CONSOLE_PFN,
|
||||
&console_pfn ) ) != 0 ) {
|
||||
rc = -EXEN ( xenrc );
|
||||
DBGC ( hvm, "HVM could not get Console PFN: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
console_phys = ( console_pfn * PAGE_SIZE );
|
||||
|
||||
/* Map Xen Console */
|
||||
hvm->xen.console.intf = pci_ioremap ( hvm->pci, console_phys, PAGE_SIZE );
|
||||
if ( ! hvm->xen.console.intf ) {
|
||||
DBGC ( hvm, "HVM could not map Xen Console at [%08lx,%08lx)\n",
|
||||
console_phys, ( console_phys + PAGE_SIZE ) );
|
||||
return -ENODEV;
|
||||
}
|
||||
DBGC2 ( hvm, "HVM mapped Xen Console at [%08lx,%08lx) with event port "
|
||||
"%d\n", console_phys, ( console_phys + PAGE_SIZE ),
|
||||
hvm->xen.console.port );
|
||||
|
||||
xencon_late_init(&hvm->xen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmap Xen Console
|
||||
*
|
||||
* @v hvm HVM device
|
||||
*/
|
||||
static void hvm_unmap_console ( struct hvm_device *hvm ) {
|
||||
|
||||
xencon_uninit();
|
||||
|
||||
/* Unmap Xen Console */
|
||||
iounmap ( hvm->xen.console.intf );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Probe PCI device
|
||||
*
|
||||
@ -439,6 +503,8 @@ static int hvm_probe ( struct pci_device *pci ) {
|
||||
goto err_map_shared_info;
|
||||
if ( ( rc = hvm_map_grant ( hvm ) ) != 0 )
|
||||
goto err_map_grant;
|
||||
if ( ( rc = hvm_map_console ( hvm ) ) != 0 )
|
||||
goto err_map_console;
|
||||
if ( ( rc = hvm_map_xenstore ( hvm ) ) != 0 )
|
||||
goto err_map_xenstore;
|
||||
|
||||
@ -455,6 +521,8 @@ static int hvm_probe ( struct pci_device *pci ) {
|
||||
xenbus_remove ( &hvm->xen, &pci->dev );
|
||||
err_xenbus_probe:
|
||||
hvm_unmap_xenstore ( hvm );
|
||||
err_map_console:
|
||||
hvm_unmap_console ( hvm );
|
||||
err_map_xenstore:
|
||||
hvm_unmap_grant ( hvm );
|
||||
err_map_grant:
|
||||
@ -478,6 +546,7 @@ static void hvm_remove ( struct pci_device *pci ) {
|
||||
|
||||
xenbus_remove ( &hvm->xen, &pci->dev );
|
||||
hvm_unmap_xenstore ( hvm );
|
||||
hvm_unmap_console ( hvm );
|
||||
hvm_unmap_grant ( hvm );
|
||||
hvm_unmap_shared_info ( hvm );
|
||||
hvm_unmap_hypercall ( hvm );
|
||||
|
@ -78,6 +78,9 @@ REQUIRE_OBJECT ( vmconsole );
|
||||
#ifdef CONSOLE_DEBUGCON
|
||||
REQUIRE_OBJECT ( debugcon );
|
||||
#endif
|
||||
#ifdef CONSOLE_XENCON
|
||||
REQUIRE_OBJECT ( xencon );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Drag in all requested network protocols
|
||||
|
@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
//#define CONSOLE_VMWARE /* VMware logfile console */
|
||||
//#define CONSOLE_DEBUGCON /* Bochs/QEMU/KVM debug port console */
|
||||
//#define CONSOLE_INT13 /* INT13 disk log console */
|
||||
//#define CONSOLE_XENCON /* XEN Console */
|
||||
|
||||
/*
|
||||
* Very obscure console types
|
||||
|
@ -10,6 +10,7 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#define CONSOLE_LINUX
|
||||
#define CONSOLE_XENCON
|
||||
#define TIMER_LINUX
|
||||
#define UACCESS_LINUX
|
||||
#define UMALLOC_LINUX
|
||||
|
@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <ipxe/bitops.h>
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/event_channel.h>
|
||||
|
||||
/* Memory barrier macros used by ring.h */
|
||||
@ -47,6 +48,16 @@ struct xen_store {
|
||||
evtchn_port_t port;
|
||||
};
|
||||
|
||||
/** A Xen Console */
|
||||
struct xencons_info {
|
||||
|
||||
/** Event Channel */
|
||||
evtchn_port_t port;
|
||||
|
||||
/* Console interface */
|
||||
volatile struct xencons_interface *intf;
|
||||
};
|
||||
|
||||
/** A Xen hypervisor */
|
||||
struct xen_hypervisor {
|
||||
/** Hypercall table */
|
||||
@ -57,6 +68,8 @@ struct xen_hypervisor {
|
||||
struct xen_grant grant;
|
||||
/** XenStore */
|
||||
struct xen_store store;
|
||||
/** Console */
|
||||
struct xencons_info console;
|
||||
};
|
||||
|
||||
/**
|
||||
|
51
src/include/xen/console.h
Normal file
51
src/include/xen/console.h
Normal file
@ -0,0 +1,51 @@
|
||||
/******************************************************************************
|
||||
* console.h
|
||||
*
|
||||
* Console I/O interface for Xen guest OSes.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright (c) 2005, Keir Fraser
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
|
||||
#define __XEN_PUBLIC_IO_CONSOLE_H__
|
||||
|
||||
typedef uint32_t XENCONS_RING_IDX;
|
||||
|
||||
#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
|
||||
|
||||
struct xencons_interface {
|
||||
char in[1024];
|
||||
char out[2048];
|
||||
XENCONS_RING_IDX in_cons, in_prod;
|
||||
XENCONS_RING_IDX out_cons, out_prod;
|
||||
};
|
||||
|
||||
#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
149
src/interface/xen/xencon.c
Normal file
149
src/interface/xen/xencon.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Xen console
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <ipxe/io.h>
|
||||
#include <ipxe/console.h>
|
||||
#include <ipxe/init.h>
|
||||
#include <ipxe/xen.h>
|
||||
#include <ipxe/xenevent.h>
|
||||
#include <config/console.h>
|
||||
#include <interface/xen/xencon.h>
|
||||
|
||||
/* Set default console usage if applicable */
|
||||
#if ! ( defined ( CONSOLE_XENCON ) && CONSOLE_EXPLICIT ( CONSOLE_XENCON ) )
|
||||
#undef CONSOLE_XENCON
|
||||
#define CONSOLE_XENCON ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_DEBUG)
|
||||
#endif
|
||||
|
||||
static struct xen_hypervisor *g_xen = NULL;
|
||||
|
||||
static inline void notify_daemon(struct xencons_info *cons)
|
||||
{
|
||||
struct evtchn_send event = { .port = cons->port };
|
||||
xenevent_send(g_xen, &event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a character to debug port console
|
||||
*
|
||||
* @v character Character to be printed
|
||||
*/
|
||||
static void xencon_putchar ( int character ) {
|
||||
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
volatile struct xencons_interface *intf = g_xen->console.intf;
|
||||
|
||||
|
||||
prod = intf->out_prod;
|
||||
do
|
||||
{
|
||||
cons = intf->out_cons;
|
||||
}while(MASK_XENCONS_IDX(prod-cons+1, intf->out) == 0);
|
||||
|
||||
intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = character;
|
||||
|
||||
wmb(); /* write ring before updating pointer */
|
||||
intf->out_prod = prod;
|
||||
|
||||
notify_daemon(&g_xen->console);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get character from console
|
||||
*
|
||||
* @ret character Character read from console
|
||||
*/
|
||||
static int xencon_getchar ( void ) {
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
volatile struct xencons_interface *intf = g_xen->console.intf;
|
||||
uint8_t data;
|
||||
|
||||
cons = intf->in_cons;
|
||||
|
||||
/* Wait for data to be ready */
|
||||
do {
|
||||
prod = intf->in_prod;
|
||||
} while(cons == prod);
|
||||
|
||||
/* Receive data */
|
||||
data = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
|
||||
|
||||
intf->in_cons = cons;
|
||||
|
||||
/* convert DEL to backspace */
|
||||
if ( data == 0x7f )
|
||||
data = 0x08;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for character ready to read from console
|
||||
*
|
||||
* @ret True Character available to read
|
||||
* @ret False No character available to read
|
||||
*/
|
||||
static int xencon_iskey ( void ) {
|
||||
volatile struct xencons_interface *intf = g_xen->console.intf;
|
||||
return intf->in_cons != intf->in_prod;
|
||||
}
|
||||
|
||||
/** Xen port console driver */
|
||||
struct console_driver xencon_console __console_driver = {
|
||||
.putchar = xencon_putchar,
|
||||
.getchar = xencon_getchar,
|
||||
.iskey = xencon_iskey,
|
||||
.usage = CONSOLE_XENCON,
|
||||
.disabled = CONSOLE_DISABLED,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize xen console
|
||||
*/
|
||||
void xencon_late_init(struct xen_hypervisor *xen)
|
||||
{
|
||||
g_xen = xen;
|
||||
xencon_console.disabled = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown xen console
|
||||
*/
|
||||
void xencon_uninit(void)
|
||||
{
|
||||
xencon_console.disabled = CONSOLE_DISABLED;
|
||||
g_xen = NULL;
|
||||
}
|
||||
|
||||
|
14
src/interface/xen/xencon.h
Normal file
14
src/interface/xen/xencon.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _XENCON_H
|
||||
#define _XENCON_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Xen Console driver
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
void xencon_late_init(struct xen_hypervisor *xen);
|
||||
void xencon_uninit(void);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user