Example #1
0
/**
 * Write to PCI configuration space
 *
 * @v pci		PCI device
 * @v location		Encoded offset and width
 * @v value		Value
 * @ret rc		Return status code
 */
int efipci_write ( struct pci_device *pci, unsigned long location,
		   unsigned long value ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
	EFI_HANDLE handle;
	EFI_STATUS efirc;
	int rc;

	/* Identify root bridge */
	if ( ( rc = efipci_root ( pci, &handle, &root ) ) != 0 )
		goto err_root;

	/* Read from configuration space */
	if ( ( efirc = root->Pci.Write ( root, EFIPCI_WIDTH ( location ),
					 efipci_address ( pci, location ), 1,
					 &value ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( pci, "EFIPCI " PCI_FMT " config write to offset %02lx "
		       "failed: %s\n", PCI_ARGS ( pci ),
		       EFIPCI_OFFSET ( location ), strerror ( rc ) );
		goto err_write;
	}

 err_write:
	bs->CloseProtocol ( handle, &efi_pci_root_bridge_io_protocol_guid,
			    efi_image_handle, handle );
 err_root:
	return rc;
}
Example #2
0
/**
 * Handle fatal errors
 *
 * @v fmt	Error message format string
 * @v ...	Arguments
 */
void die ( const char *fmt, ... ) {
	EFI_BOOT_SERVICES *bs;
	EFI_RUNTIME_SERVICES *rs;
	va_list args;

	/* Print message */
	va_start ( args, fmt );
	vprintf ( fmt, args );
	va_end ( args );

	/* Reboot or exit as applicable */
	if ( efi_systab ) {

		/* Exit */
		bs = efi_systab->BootServices;
		bs->Exit ( efi_image_handle, EFI_LOAD_ERROR, 0, NULL );
		printf ( "Failed to exit\n" );
		rs = efi_systab->RuntimeServices;
		rs->ResetSystem ( EfiResetWarm, 0, 0, NULL );
		printf ( "Failed to reboot\n" );

	} else {

		/* Wait for keypress */
		printf ( "Press a key to reboot..." );
		getchar();
		printf ( "\n" );

		/* Reboot system */
		reboot();
	}

	/* Should be impossible to reach this */
	__builtin_unreachable();
}
Example #3
0
/**
 * Probe SNP root bus
 *
 * @v rootdev		SNP bus root device
 *
 * Look at the loaded image's device handle and see if the simple network
 * protocol exists. If so, register a driver for it.
 */
static int snpbus_probe ( struct root_device *rootdev ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_STATUS efirc;
	int rc;
	void *snp;

	efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
				   &efi_simple_network_protocol_guid,
				   &snp, efi_image_handle, NULL,
				   EFI_OPEN_PROTOCOL_GET_PROTOCOL );
	if ( efirc ) {
		DBG ( "Could not find Simple Network Protocol!\n" );
		return -ENODEV;
	}
	snponly_dev.snp = snp;

	/* Add to device hierarchy */
	strncpy ( snponly_dev.dev.name, "EFI SNP",
		  ( sizeof ( snponly_dev.dev.name ) - 1 ) );
	snponly_dev.dev.parent = &rootdev->dev;
	list_add ( &snponly_dev.dev.siblings, &rootdev->dev.children);
	INIT_LIST_HEAD ( &snponly_dev.dev.children );

	/* Create network device */
	if ( ( rc = snpnet_probe ( &snponly_dev ) ) != 0 )
		goto err;

	return 0;

err:
	list_del ( &snponly_dev.dev.siblings );
	return rc;
}
/**
 * Identify autoboot device
 *
 */
void efi_set_autoboot ( void ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	union {
		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
		void *interface;
	} snp;
	EFI_SIMPLE_NETWORK_MODE *mode;
	EFI_STATUS efirc;

	/* Look for an SNP instance on the image's device handle */
	if ( ( efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
					  &efi_simple_network_protocol_guid,
					  &snp.interface, efi_image_handle,
					  NULL,
					  EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
		DBGC ( efi_loaded_image, "EFI found no autoboot device\n" );
		return;
	}

	/* Record autoboot device */
	mode = snp.snp->Mode;
	set_autoboot_ll_addr ( &mode->CurrentAddress, mode->HwAddressSize );
	DBGC ( efi_loaded_image, "EFI found autoboot link-layer address:\n" );
	DBGC_HDA ( efi_loaded_image, 0, &mode->CurrentAddress,
		   mode->HwAddressSize );

	/* Close protocol */
	bs->CloseProtocol ( efi_loaded_image->DeviceHandle,
			    &efi_simple_network_protocol_guid,
			    efi_image_handle, NULL );
}
Example #5
0
/**
 * Detach driver from device
 *
 * @v efidev		EFI device
  */
void snpnet_stop ( struct efi_device *efidev ) {
    EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
    struct net_device *netdev = efidev_get_drvdata ( efidev );
    struct snp_nic *snp = netdev->priv;
    EFI_HANDLE device = efidev->device;
    EFI_STATUS efirc;
    int rc;

    /* Unregister network device */
    unregister_netdev ( netdev );

    /* Stop SNP protocol */
    if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
        rc = -EEFI ( efirc );
        DBGC ( device, "SNP %s could not stop: %s\n",
               efi_handle_name ( device ), strerror ( rc ) );
        /* Nothing we can do about this */
    }

    /* Free network device */
    list_del ( &snp->dev.siblings );
    netdev_nullify ( netdev );
    netdev_put ( netdev );

    /* Close SNP protocol */
    bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
                        efi_image_handle, device );
}
Example #6
0
/**
 * Initialise EFI environment
 *
 * @v image_handle	Image handle
 * @v systab		System table
 * @ret efirc		EFI return status code
 */
EFI_STATUS efi_init ( EFI_HANDLE image_handle,
		      EFI_SYSTEM_TABLE *systab ) {
	EFI_BOOT_SERVICES *bs;
	struct efi_protocol *prot;
	struct efi_config_table *tab;
	EFI_STATUS efirc;

	/* Store image handle and system table pointer for future use */
	efi_image_handle = image_handle;
	efi_systab = systab;

	/* Sanity checks */
	if ( ! systab )
		return EFI_NOT_AVAILABLE_YET;
	if ( ! systab->ConOut )
		return EFI_NOT_AVAILABLE_YET;
	if ( ! systab->BootServices ) {
		DBGC ( systab, "EFI provided no BootServices entry point\n" );
		return EFI_NOT_AVAILABLE_YET;
	}
	if ( ! systab->RuntimeServices ) {
		DBGC ( systab, "EFI provided no RuntimeServices entry "
		       "point\n" );
		return EFI_NOT_AVAILABLE_YET;
	}
	DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );

	/* Look up used protocols */
	bs = systab->BootServices;
	for_each_table_entry ( prot, EFI_PROTOCOLS ) {
		if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL,
						    prot->protocol ) ) == 0 ) {
			DBGC ( systab, "EFI protocol %s is at %p\n",
			       uuid_ntoa ( &prot->u.uuid ), *(prot->protocol));
		} else {
			DBGC ( systab, "EFI does not provide protocol %s\n",
			       uuid_ntoa ( &prot->u.uuid ) );
			/* All protocols are required */
			return efirc;
		}
	}

	/* Look up used configuration tables */
	for_each_table_entry ( tab, EFI_CONFIG_TABLES ) {
		if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) {
			DBGC ( systab, "EFI configuration table %s is at %p\n",
			       uuid_ntoa ( &tab->u.uuid ), *(tab->table) );
		} else {
			DBGC ( systab, "EFI does not provide configuration "
			       "table %s\n", uuid_ntoa ( &tab->u.uuid ) );
			if ( tab->required )
				return EFI_NOT_AVAILABLE_YET;
		}
	}

	return 0;
}
Example #7
0
/**
 * Reallocate external memory
 *
 * @v old_ptr		Memory previously allocated by umalloc(), or UNULL
 * @v new_size		Requested size
 * @ret new_ptr		Allocated memory, or UNULL
 *
 * Calling realloc() with a new size of zero is a valid way to free a
 * memory block.
 */
static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_PHYSICAL_ADDRESS phys_addr;
	unsigned int new_pages, old_pages;
	userptr_t new_ptr = UNOWHERE;
	size_t old_size;
	EFI_STATUS efirc;
	int rc;

	/* Allocate new memory if necessary.  If allocation fails,
	 * return without touching the old block.
	 */
	if ( new_size ) {
		new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 );
		if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
						   EfiBootServicesData,
						   new_pages,
						   &phys_addr ) ) != 0 ) {
			rc = -EEFI ( efirc );
			DBG ( "EFI could not allocate %d pages: %s\n",
			      new_pages, strerror ( rc ) );
			return UNULL;
		}
		assert ( phys_addr != 0 );
		new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE );
		copy_to_user ( new_ptr, -EFI_PAGE_SIZE,
			       &new_size, sizeof ( new_size ) );
		DBG ( "EFI allocated %d pages at %llx\n",
		      new_pages, phys_addr );
	}

	/* Copy across relevant part of the old data region (if any),
	 * then free it.  Note that at this point either (a) new_ptr
	 * is valid, or (b) new_size is 0; either way, the memcpy() is
	 * valid.
	 */
	if ( old_ptr && ( old_ptr != UNOWHERE ) ) {
		copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE,
				 sizeof ( old_size ) );
		memcpy_user ( new_ptr, 0, old_ptr, 0,
			      ( (old_size < new_size) ? old_size : new_size ));
		old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 );
		phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE );
		if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){
			rc = -EEFI ( efirc );
			DBG ( "EFI could not free %d pages at %llx: %s\n",
			      old_pages, phys_addr, strerror ( rc ) );
			/* Not fatal; we have leaked memory but successfully
			 * allocated (if asked to do so).
			 */
		}
		DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr );
	}

	return new_ptr;
}
Example #8
0
/**
 * Delay for a fixed number of microseconds
 *
 * @v usecs		Number of microseconds for which to delay
 */
static void efi_udelay ( unsigned long usecs ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_STATUS efirc;

	if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) {
		DBG ( "EFI could not delay for %ldus: %s\n",
		      usecs, efi_strerror ( efirc ) );
		/* Probably screwed */
	}
}
Example #9
0
File: nii.c Project: baloo/ipxe
/**
 * Block callback
 *
 * @v unique_id		NII NIC
 * @v acquire		Acquire lock
 */
static EFIAPI VOID nii_block ( UINT64 unique_id, UINT32 acquire ) {
	struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;

	/* This functionality (which is copied verbatim from the
	 * SnpDxe implementation of this function) appears to be
	 * totally brain-dead, since it produces no actual blocking
	 * behaviour.
	 */
	if ( acquire ) {
		nii->saved_tpl = bs->RaiseTPL ( TPL_NOTIFY );
	} else {
		bs->RestoreTPL ( nii->saved_tpl );
	}
}
Example #10
0
VOID EFIAPI
OvrRestoreTPL(IN EFI_TPL OldTpl)
{
	gOrgBS.RestoreTPL(OldTpl);
	// do not print - it's called by UEFI events and timers (from timer interrupts) many times
	//PRINT("->RestoreTPL(OldTpl=%d)\n", OldTpl);
	return;
}
Example #11
0
EFI_TPL EFIAPI
OvrRaiseTPL(IN EFI_TPL NewTpl)
{
	EFI_TPL				Status;
	
	Status = gOrgBS.RaiseTPL(NewTpl);
	// do not print - it's called by UEFI events and timers (from timer interrupts) many times
	//PRINT("->RaiseTPL(NewTpl=%d) = %d\n", NewTpl, Status);
	return Status;
}
Example #12
0
EFI_STATUS EFIAPI
OvrCheckEvent(
	IN EFI_EVENT		Event
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.CheckEvent(Event);
	//PRINT("->CheckEvent(%p) = %r\n", Event, Status);
	return Status;
}
Example #13
0
VOID EFIAPI
OvrSetMem(
	IN VOID				*Buffer,
	IN UINTN			Size,
	IN UINT8			Value
)
{
	gOrgBS.SetMem(Buffer, Size, Value);
	//PRINT("->SetMem(%p, 0x%x, 0x%x)\n", Buffer, Size, Value);
	return;
}
Example #14
0
EFI_STATUS EFIAPI
OvrUnloadImage(
	IN EFI_HANDLE				ImageHandle
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.UnloadImage(ImageHandle);
	PRINT("->UnloadImage(%p) = %r\n", ImageHandle, Status);
	return Status;
}
Example #15
0
VOID EFIAPI
OvrCopyMem(
	IN VOID				*Destination,
	IN VOID				*Source,
	IN UINTN			Length
)
{
	gOrgBS.CopyMem(Destination, Source, Length);
	//PRINT("->CopyMem(%p, %p, 0x%x)\n", Destination, Source, Length);
	return;
}
Example #16
0
EFI_STATUS EFIAPI
OvrGetNextMonotonicCount(
	OUT UINT64					*Count
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.GetNextMonotonicCount(Count);
	PRINT("->GetNextMonotonicCount(0x%x) = %r\n", *Count, Status);
	return Status;
}
Example #17
0
EFI_STATUS EFIAPI
OvrStall(
	IN UINTN					Microseconds
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.Stall(Microseconds);
	// do not print - too many calls
	//PRINT("->Stall(%d) = %r\n", Microseconds, Status);
	return Status;
}
Example #18
0
EFI_STATUS EFIAPI
OvrFreePages(
	IN EFI_PHYSICAL_ADDRESS Memory,
	IN UINTN Pages
)  
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.FreePages(Memory, Pages);
//	PRINT("->FreePages(0x%lx, 0x%x) = %r\n", Memory, Pages, Status);
	return Status;
}
Example #19
0
EFI_STATUS EFIAPI
OvrHandleProtocol(
	IN EFI_HANDLE		Handle,
	IN EFI_GUID			*Protocol,
	OUT VOID			**Interface
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.HandleProtocol(Handle, Protocol, Interface);
	PRINT("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, Status);
	return Status;
}
Example #20
0
/**
 * Probe EFI image
 *
 * @v image		EFI file
 * @ret rc		Return status code
 */
static int efi_image_probe ( struct image *image ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_HANDLE handle;
	EFI_STATUS efirc;

	/* Attempt loading image */
	if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
				       user_to_virt ( image->data, 0 ),
				       image->len, &handle ) ) != 0 ) {
		/* Not an EFI image */
		DBGC ( image, "EFIIMAGE %p could not load: %s\n",
		       image, efi_strerror ( efirc ) );
		return -ENOEXEC;
	}

	/* Unload the image.  We can't leave it loaded, because we
	 * have no "unload" operation.
	 */
	bs->UnloadImage ( handle );

	return 0;
}
/**
 * Hold off watchdog timer
 *
 * @v retry		Retry timer
 * @v over		Failure indicator
 */
static void efi_watchdog_expired ( struct retry_timer *timer,
				   int over __unused ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	static CHAR16 data[] = WATCHDOG_DATA;
	EFI_STATUS efirc;
	int rc;

	DBGC2 ( timer, "EFI holding off watchdog timer\n" );

	/* Restart this holdoff timer */
	start_timer_fixed ( timer, ( WATCHDOG_HOLDOFF_SECS * TICKS_PER_SEC ) );

	/* Reset watchdog timer */
	if ( ( efirc = bs->SetWatchdogTimer ( WATCHDOG_TIMEOUT_SECS,
					      WATCHDOG_CODE, sizeof ( data ),
					      data ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( timer, "EFI could not set watchdog timer: %s\n",
		       strerror ( rc ) );
		return;
	}
}
Example #22
0
EFI_STATUS EFIAPI
OvrDisconnectController(
	IN EFI_HANDLE				ControllerHandle,
	IN EFI_HANDLE				DriverImageHandle,
	IN EFI_HANDLE				ChildHandle
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.DisconnectController(ControllerHandle, DriverImageHandle, ChildHandle);
	PRINT("->DisconnectController(%p, %p, %p) = %r\n", ControllerHandle, DriverImageHandle, ChildHandle, Status);
	return Status;
}
Example #23
0
EFI_STATUS EFIAPI
OvrFreePool(
	IN VOID				*Buffer
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.FreePool(Buffer);
	// do not print to console - requires FreePool - recursion
	// do not print to serial - too many calls from UEFI
	//DebugPrint(1, "->FreePool(%p) = %r\n", Buffer, Status);
	return Status;
}
Example #24
0
EFI_STATUS EFIAPI
OvrStartImage(
	IN EFI_HANDLE				ImageHandle,
	OUT UINTN					*ExitDataSize,
	OUT CHAR16					**ExitData
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.StartImage(ImageHandle, ExitDataSize, ExitData);
	PRINT("->StartImage(%p, 0x%x, %p) = %r\n", ImageHandle, *ExitDataSize, *ExitData, Status);
	return Status;
}
Example #25
0
EFI_STATUS EFIAPI
OvrSetTimer(
	IN EFI_EVENT		Event,
	IN EFI_TIMER_DELAY	Type,
	IN UINT64			TriggerTime
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.SetTimer(Event, Type, TriggerTime);
	PRINT("->SetTimer(%p, %d, 0x%x) = %r\n", Event, Type, TriggerTime, Status);
	return Status;
}
Example #26
0
EFI_STATUS EFIAPI
OvrWaitForEvent(
	IN UINTN		NumberOfEvents,
	IN EFI_EVENT	*Event,
	OUT UINTN		*Index
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.WaitForEvent(NumberOfEvents, Event, Index);
//	PRINT("->WaitForEvent(%d, %p, %d) = %r\n", NumberOfEvents, *Event, *Index, Status);
	return Status;
}
Example #27
0
EFI_STATUS EFIAPI
OvrUninstallProtocolInterface(
	IN EFI_HANDLE		Handle,
	IN EFI_GUID			*Protocol,
	IN VOID				*Interface
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.UninstallProtocolInterface(Handle, Protocol, Interface);
	PRINT("->UninstallProtocolInterface(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), Interface, Status);
	return Status;
}
Example #28
0
EFI_STATUS EFIAPI
OvrRegisterProtocolNotify(
	IN EFI_GUID			*Protocol,
	IN EFI_EVENT		Event,
	OUT VOID			**Registration
)
{
	EFI_STATUS			Status;
	
	Status = gOrgBS.RegisterProtocolNotify(Protocol, Event, Registration);
	PRINT("->RegisterProtocolNotify(%s, %p, %p) = %r\n", GuidStr(Protocol), Event, *Registration, Status);
	return Status;
}
Example #29
0
EFI_STATUS EFIAPI
OvrInstallConfigurationTable(
	IN EFI_GUID					*Guid,
	IN VOID						*Table
)
{
	EFI_STATUS					Status;
	
	Status = gOrgBS.InstallConfigurationTable(Guid, Table);
	// TODO: table guids to Lib.c
	PRINT("->InstallConfigurationTable(%s, %p) = %r\n", GuidStr(Guid), Table, Status);
	return Status;
}
Example #30
0
EFI_STATUS EFIAPI
OvrLocateProtocol(
	IN EFI_GUID			*Protocol,
	IN VOID				*Registration,
	OUT VOID			**Interface
)
{
	EFI_STATUS			Status;
	VOID				*InterfaceIn = *Interface;
	
	Status = gOrgBS.LocateProtocol(Protocol, Registration, Interface);
	PRINT("->LocateProtocol(%s, %p, %p/%p) = %r\n", GuidStr(Protocol), Registration, InterfaceIn, *Interface, Status);
	return Status;
}