mirror of
https://github.com/ipxe/ipxe.git
synced 2025-01-06 14:03:09 -06:00
[sbi] Add support for running as a RISC-V SBI payload
Add basic support for running directly on top of SBI, with no UEFI firmware present. Build as e.g.: make CROSS=riscv64-linux-gnu- bin-riscv64/ipxe.sbi The resulting binary can be tested in QEMU using e.g.: qemu-system-riscv64 -M virt -cpu max -serial stdio \ -kernel bin-riscv64/ipxe.sbi No drivers or executable binary formats are supported yet, but the unit test suite may be run successfully. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
7ccd08dbf4
commit
e0e102ee24
@ -352,6 +352,8 @@ arch :
|
||||
# Determine build platform
|
||||
DEFAULT_PLATFORM_i386 := pcbios
|
||||
DEFAULT_PLATFORM_x86_64 := pcbios
|
||||
DEFAULT_PLATFORM_riscv32 := sbi
|
||||
DEFAULT_PLATFORM_riscv64 := sbi
|
||||
DEFAULT_PLATFORM := $(DEFAULT_PLATFORM_$(ARCH))
|
||||
PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM) none)
|
||||
CFLAGS += -DPLATFORM=$(PLATFORM) -DPLATFORM_$(PLATFORM)
|
||||
|
@ -11,6 +11,7 @@ INCDIRS := arch/$(ARCH)/include arch/riscv/include $(INCDIRS)
|
||||
#
|
||||
SRCDIRS += arch/riscv/core
|
||||
SRCDIRS += arch/riscv/interface/sbi
|
||||
SRCDIRS += arch/riscv/prefix
|
||||
|
||||
# RISCV-specific flags
|
||||
#
|
||||
|
16
src/arch/riscv/Makefile.sbi
Normal file
16
src/arch/riscv/Makefile.sbi
Normal file
@ -0,0 +1,16 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Build a position-independent executable, with relocations required
|
||||
# only for data values. Runtime relocations are applied by the
|
||||
# prefix code.
|
||||
#
|
||||
CFLAGS += -mcmodel=medany -fpie
|
||||
LDFLAGS += -pie --no-dynamic-linker
|
||||
|
||||
# Linker script
|
||||
#
|
||||
LDSCRIPT = arch/riscv/scripts/sbi.lds
|
||||
|
||||
# Media types
|
||||
#
|
||||
MEDIA += sbi
|
45
src/arch/riscv/core/stack.S
Normal file
45
src/arch/riscv/core/stack.S
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 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
|
||||
*
|
||||
* Internal stack
|
||||
*
|
||||
*/
|
||||
|
||||
.section ".note.GNU-stack", "", @progbits
|
||||
.text
|
||||
|
||||
#define STACK_ALIGN 16
|
||||
|
||||
#define STACK_SIZE 8192
|
||||
|
||||
.section ".stack", "aw", @nobits
|
||||
.balign STACK_ALIGN
|
||||
.globl _stack
|
||||
_stack:
|
||||
.space STACK_SIZE
|
||||
.globl _estack
|
||||
_estack:
|
14
src/arch/riscv/include/bits/umalloc.h
Normal file
14
src/arch/riscv/include/bits/umalloc.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _BITS_UMALLOC_H
|
||||
#define _BITS_UMALLOC_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* RISCV-specific user memory allocation API implementations
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/sbi_umalloc.h>
|
||||
|
||||
#endif /* _BITS_UMALLOC_H */
|
19
src/arch/riscv/include/ipxe/errno/sbi.h
Normal file
19
src/arch/riscv/include/ipxe/errno/sbi.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _IPXE_ERRNO_SBI_H
|
||||
#define _IPXE_ERRNO_SBI_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* RISC-V SBI platform error codes
|
||||
*
|
||||
* We never need to return SBI error codes ourselves, so we
|
||||
* arbitrarily choose to use the Linux error codes as platform error
|
||||
* codes.
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/errno/linux.h>
|
||||
|
||||
#endif /* _IPXE_ERRNO_SBI_H */
|
18
src/arch/riscv/include/ipxe/sbi_umalloc.h
Normal file
18
src/arch/riscv/include/ipxe/sbi_umalloc.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _IPXE_SBI_UMALLOC_H
|
||||
#define _IPXE_SBI_UMALLOC_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* External memory allocation
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifdef UMALLOC_SBI
|
||||
#define UMALLOC_PREFIX_sbi
|
||||
#else
|
||||
#define UMALLOC_PREFIX_sbi __sbi_
|
||||
#endif
|
||||
|
||||
#endif /* _IPXE_SBI_UMALLOC_H */
|
54
src/arch/riscv/interface/sbi/sbi_umalloc.c
Normal file
54
src/arch/riscv/interface/sbi/sbi_umalloc.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 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 );
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ipxe/umalloc.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* iPXE user memory allocation API for SBI
|
||||
*
|
||||
*/
|
||||
|
||||
/** Equivalent of NOWHERE for user pointers */
|
||||
#define UNOWHERE ( ~UNULL )
|
||||
|
||||
/**
|
||||
* 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 sbi_urealloc ( userptr_t old_ptr, size_t new_size ) {
|
||||
|
||||
/* External allocation not yet implemented: allocate from heap */
|
||||
return ( ( userptr_t ) realloc ( ( ( void * ) old_ptr ), new_size ) );
|
||||
}
|
||||
|
||||
PROVIDE_UMALLOC ( sbi, urealloc, sbi_urealloc );
|
156
src/arch/riscv/prefix/sbiprefix.S
Normal file
156
src/arch/riscv/prefix/sbiprefix.S
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* 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 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
|
||||
*
|
||||
* SBI position-independent executable prefix
|
||||
*
|
||||
*/
|
||||
|
||||
.section ".note.GNU-stack", "", @progbits
|
||||
.text
|
||||
|
||||
/* SBI debug console extension */
|
||||
#define SBI_DBCN ( ( 'D' << 24 ) | ( 'B' << 16 ) | ( 'C' << 8 ) | 'N' )
|
||||
#define SBI_DBCN_WRITE 0x00
|
||||
|
||||
/* SBI system reset extension */
|
||||
#define SBI_SRST ( ( 'S' << 24 ) | ( 'R' << 16 ) | ( 'S' << 8 ) | 'T' )
|
||||
#define SBI_SRST_SYSTEM_RESET 0x00
|
||||
#define SBI_RESET_COLD 0x00000001
|
||||
|
||||
/* Relative relocation type */
|
||||
#define R_RISCV_RELATIVE 3
|
||||
|
||||
/* Layout of a relocation record */
|
||||
.struct 0
|
||||
rela_offset: .space ( __riscv_xlen / 8 )
|
||||
rela_type: .space ( __riscv_xlen / 8 )
|
||||
rela_addend: .space ( __riscv_xlen / 8 )
|
||||
rela_len:
|
||||
.previous
|
||||
|
||||
/*
|
||||
* Display progress message via debug console
|
||||
*/
|
||||
.macro progress message
|
||||
#ifndef NDEBUG
|
||||
.section ".prefix.data", "aw", @progbits
|
||||
progress_\@:
|
||||
.ascii "\message"
|
||||
.equ progress_\@_len, . - progress_\@
|
||||
.size progress_\@, . - progress_\@
|
||||
.previous
|
||||
li a7, SBI_DBCN
|
||||
li a6, SBI_DBCN_WRITE
|
||||
li a0, progress_\@_len
|
||||
la a1, progress_\@
|
||||
mv a2, zero
|
||||
ecall
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* SBI entry point
|
||||
*/
|
||||
.section ".prefix", "ax", @progbits
|
||||
.org 0
|
||||
.globl _sbi_start
|
||||
_sbi_start:
|
||||
/* Preserve arguments */
|
||||
mv s0, a0
|
||||
mv s1, a1
|
||||
progress "\nSBI->iPXE"
|
||||
|
||||
/* Apply dynamic relocations */
|
||||
la t0, _reloc
|
||||
la t1, _ereloc
|
||||
la t2, _sbi_start
|
||||
1: /* Read relocation record */
|
||||
LOADN t3, rela_offset(t0)
|
||||
LOADN t4, rela_type(t0)
|
||||
LOADN t5, rela_addend(t0)
|
||||
/* Check relocation type */
|
||||
addi t4, t4, -R_RISCV_RELATIVE
|
||||
bnez t4, 2f
|
||||
/* Apply relocation */
|
||||
add t3, t3, t2
|
||||
add t5, t5, t2
|
||||
STOREN t5, (t3)
|
||||
2: /* Loop */
|
||||
addi t0, t0, rela_len
|
||||
blt t0, t1, 1b
|
||||
progress " .reloc"
|
||||
|
||||
/* Zero the bss */
|
||||
la t0, _bss
|
||||
la t1, _ebss
|
||||
1: STOREN zero, (t0)
|
||||
addi t0, t0, ( __riscv_xlen / 8 )
|
||||
blt t0, t1, 1b
|
||||
progress " .bss"
|
||||
|
||||
/* Set up stack */
|
||||
la sp, _estack
|
||||
progress " .stack"
|
||||
|
||||
/* Store boot hart */
|
||||
la t0, boot_hart
|
||||
STOREN s0, (t0)
|
||||
|
||||
/* Register device tree */
|
||||
mv a0, s1
|
||||
call register_fdt
|
||||
|
||||
/* Call main program */
|
||||
progress "\n\n"
|
||||
call main
|
||||
|
||||
/* We have no return path, since the M-mode SBI implementation
|
||||
* will have jumped to us by setting our start address in MEPC
|
||||
* and issuing an MRET instruction.
|
||||
*
|
||||
* Attempt a system reset, since there is nothing else we can
|
||||
* viably do at this point.
|
||||
*/
|
||||
progress "\niPXE->SBI reset\n"
|
||||
li a7, SBI_SRST
|
||||
li a6, SBI_SRST_SYSTEM_RESET
|
||||
li a0, SBI_RESET_COLD
|
||||
mv a1, zero
|
||||
ecall
|
||||
|
||||
/* If reset failed, lock the system */
|
||||
progress "(reset failed)\n"
|
||||
1: wfi
|
||||
j 1b
|
||||
.size _sbi_start, . - _sbi_start
|
||||
|
||||
/* File split information for the compressor */
|
||||
.section ".zinfo", "a", @progbits
|
||||
.ascii "COPY"
|
||||
.word 0
|
||||
.word _sbi_filesz
|
||||
.word 1
|
119
src/arch/riscv/scripts/sbi.lds
Normal file
119
src/arch/riscv/scripts/sbi.lds
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Linker script for RISC-V SBI images
|
||||
*
|
||||
*/
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* Start at virtual address zero */
|
||||
. = 0;
|
||||
|
||||
/* Weak symbols that need zero values if not otherwise defined */
|
||||
.weak 0x0 : {
|
||||
_weak = .;
|
||||
*(.weak)
|
||||
*(.weak.*)
|
||||
_eweak = .;
|
||||
}
|
||||
_assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
|
||||
|
||||
/* Prefix code */
|
||||
.prefix : {
|
||||
_prefix = .;
|
||||
*(.prefix)
|
||||
*(.prefix.*)
|
||||
_eprefix = .;
|
||||
}
|
||||
|
||||
/* Program code */
|
||||
.text : {
|
||||
_text = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
/* Align to page size to allow linker to generate W^X segments */
|
||||
. = ALIGN ( 4096 );
|
||||
|
||||
/* Read-only data */
|
||||
.rodata : {
|
||||
_rodata = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
_erodata = .;
|
||||
}
|
||||
|
||||
/* Writable data */
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
|
||||
KEEP(*(.provided))
|
||||
KEEP(*(.provided.*))
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
/* Uninitialised and discardable data */
|
||||
OVERLAY : {
|
||||
|
||||
/* Runtime relocations (discarded after use) */
|
||||
.rela.dyn {
|
||||
_reloc = .;
|
||||
*(.rela)
|
||||
*(.rela.dyn)
|
||||
}
|
||||
|
||||
/* Compressor information block */
|
||||
.zinfo {
|
||||
_zinfo = .;
|
||||
KEEP(*(.zinfo))
|
||||
KEEP(*(.zinfo.*))
|
||||
_ezinfo = .;
|
||||
}
|
||||
|
||||
/* Uninitialised data */
|
||||
.bss {
|
||||
_bss = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
*(.stack)
|
||||
*(.stack.*)
|
||||
/* Align to allow for easy zeroing by prefix code */
|
||||
. = ALIGN ( 16 );
|
||||
_ebss = .;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate end of relocations
|
||||
*
|
||||
* This cannot be done by placing "_ereloc = .;" inside the
|
||||
* .rela.dyn section, since the dynamic relocations are not
|
||||
* present in the input sections but are instead generated during
|
||||
* linking.
|
||||
*/
|
||||
_ereloc = ( _reloc + __load_stop_reladyn - __load_start_reladyn );
|
||||
|
||||
/* Length of initialised data */
|
||||
_sbi_filesz = ABSOLUTE ( _ereloc );
|
||||
|
||||
/* Unwanted sections */
|
||||
/DISCARD/ : {
|
||||
*(.comment)
|
||||
*(.comment.*)
|
||||
*(.note)
|
||||
*(.note.*)
|
||||
*(.eh_frame)
|
||||
*(.eh_frame.*)
|
||||
*(.dynamic)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.einfo)
|
||||
*(.einfo.*)
|
||||
*(.discard)
|
||||
*(.discard.*)
|
||||
*(.pci_devlist.*)
|
||||
}
|
||||
}
|
6
src/arch/riscv32/Makefile.sbi
Normal file
6
src/arch/riscv32/Makefile.sbi
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Include generic SBI Makefile
|
||||
#
|
||||
MAKEDEPS += arch/riscv/Makefile.sbi
|
||||
include arch/riscv/Makefile.sbi
|
20
src/arch/riscv32/include/ipxe/sbi/dhcparch.h
Normal file
20
src/arch/riscv32/include/ipxe/sbi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_SBI_DHCPARCH_H
|
||||
#define _IPXE_SBI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_RISCV32
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_SBI_DHCPARCH_H */
|
6
src/arch/riscv64/Makefile.sbi
Normal file
6
src/arch/riscv64/Makefile.sbi
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# Include generic SBI Makefile
|
||||
#
|
||||
MAKEDEPS += arch/riscv/Makefile.sbi
|
||||
include arch/riscv/Makefile.sbi
|
20
src/arch/riscv64/include/ipxe/sbi/dhcparch.h
Normal file
20
src/arch/riscv64/include/ipxe/sbi/dhcparch.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _IPXE_SBI_DHCPARCH_H
|
||||
#define _IPXE_SBI_DHCPARCH_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* DHCP client architecture definitions
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/dhcp.h>
|
||||
|
||||
/** DHCP client architecture */
|
||||
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_RISCV64
|
||||
|
||||
/** DHCP client network device interface */
|
||||
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
|
||||
|
||||
#endif /* _IPXE_SBI_DHCPARCH_H */
|
0
src/config/config_sbi.c
Normal file
0
src/config/config_sbi.c
Normal file
36
src/config/defaults/sbi.h
Normal file
36
src/config/defaults/sbi.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef CONFIG_DEFAULTS_SBI_H
|
||||
#define CONFIG_DEFAULTS_SBI_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Configuration defaults for RISC-V SBI
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#define IOAPI_RISCV
|
||||
#define IOMAP_VIRT
|
||||
#define DMAAPI_FLAT
|
||||
#define UACCESS_FLAT
|
||||
#define TIMER_ZICNTR
|
||||
#define ENTROPY_ZKR
|
||||
|
||||
#define CONSOLE_SBI
|
||||
#define REBOOT_SBI
|
||||
#define UMALLOC_SBI
|
||||
|
||||
#define ACPI_NULL
|
||||
#define MPAPI_NULL
|
||||
#define NAP_NULL
|
||||
#define PCIAPI_NULL
|
||||
#define SANBOOT_NULL
|
||||
#define SMBIOS_NULL
|
||||
#define TIME_NULL
|
||||
|
||||
#define IMAGE_SCRIPT
|
||||
|
||||
#define REBOOT_CMD
|
||||
#define POWEROFF_CMD
|
||||
|
||||
#endif /* CONFIG_DEFAULTS_SBI_H */
|
Loading…
Reference in New Issue
Block a user