mirror of https://github.com/red-prig/fpPS4.git
202 lines
3.3 KiB
Plaintext
202 lines
3.3 KiB
Plaintext
unit dev_null;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
sys_conf;
|
|
|
|
const
|
|
ZERO_REGION_SIZE=(2 * 1024 * 1024); // 2MB
|
|
|
|
var
|
|
zero_region:Pointer;
|
|
|
|
procedure init_zero_region;
|
|
procedure free_zero_region;
|
|
|
|
Function null_modevent(_mod,_type:Integer):Integer; //DEV_MODULE(nil, null_modevent, nil);
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
vuio,
|
|
vdisk,
|
|
vfilio,
|
|
subr_uio;
|
|
|
|
var
|
|
{ For use with destroy_dev(9). }
|
|
null_dev:p_cdev;
|
|
zero_dev:p_cdev;
|
|
|
|
Function null_write(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer; forward;
|
|
Function null_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer; forward;
|
|
Function zero_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer; forward;
|
|
Function zero_read(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer; forward;
|
|
|
|
const
|
|
null_cdevsw:t_cdevsw=(
|
|
d_version :D_VERSION;
|
|
d_flags :0;
|
|
d_name :'null';
|
|
d_read :d_read_t(@_nullop);
|
|
d_write :@null_write;
|
|
d_ioctl :@null_ioctl;
|
|
);
|
|
|
|
zero_cdevsw:t_cdevsw=(
|
|
d_version :D_VERSION;
|
|
d_flags :D_MMAP_ANON;
|
|
d_name :'zero';
|
|
d_read :@zero_read;
|
|
d_write :@null_write;
|
|
d_ioctl :@zero_ioctl;
|
|
);
|
|
|
|
{ ARGSUSED }
|
|
Function null_write(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
|
|
begin
|
|
uio^.uio_resid:=0;
|
|
|
|
Exit(0);
|
|
end;
|
|
|
|
{ ARGSUSED }
|
|
Function null_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
|
|
var
|
|
error:Integer;
|
|
begin
|
|
error:=0;
|
|
|
|
case (cmd) of
|
|
DIOCSKERNELDUMP:
|
|
begin
|
|
error:=EPERM;
|
|
//error:=priv_check(td, PRIV_SETDUMPER);
|
|
//if (error=0)
|
|
// error:=set_dumper(nil);
|
|
end;
|
|
FIONBIO:;
|
|
FIOASYNC:
|
|
begin
|
|
if (PInteger(data)^<>0) then
|
|
begin
|
|
error:=EINVAL;
|
|
end;
|
|
end;
|
|
else
|
|
begin
|
|
error:=ENOIOCTL;
|
|
end;
|
|
end;
|
|
|
|
Exit(error);
|
|
end;
|
|
|
|
{ ARGSUSED }
|
|
Function zero_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
|
|
var
|
|
error:Integer;
|
|
begin
|
|
error:=0;
|
|
|
|
case (cmd) of
|
|
FIONBIO:;
|
|
FIOASYNC:
|
|
begin
|
|
if (PInteger(data)^<>0) then
|
|
begin
|
|
error:=EINVAL;
|
|
end;
|
|
end;
|
|
else
|
|
begin
|
|
error:=ENOIOCTL;
|
|
end;
|
|
end;
|
|
|
|
Exit(error);
|
|
end;
|
|
|
|
procedure init_zero_region;
|
|
var
|
|
buf:Pointer;
|
|
begin
|
|
if (zero_region=nil) then
|
|
begin
|
|
buf:=AllocMem(ZERO_REGION_SIZE);
|
|
if (System.InterlockedCompareExchange(zero_region,buf,nil)<>nil) then
|
|
begin
|
|
FreeMem(buf);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure free_zero_region;
|
|
var
|
|
buf:Pointer;
|
|
begin
|
|
buf:=System.InterlockedExchange(zero_region,nil);
|
|
FreeMem(buf);
|
|
end;
|
|
|
|
{ ARGSUSED }
|
|
Function zero_read(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
|
|
var
|
|
zbuf:Pointer;
|
|
len:QWORD;
|
|
error:Integer;
|
|
begin
|
|
error:=0;
|
|
|
|
Assert(uio^.uio_rw=UIO_READ,'Cant be in %s for write');
|
|
|
|
init_zero_region;
|
|
|
|
zbuf:=zero_region;
|
|
while (uio^.uio_resid > 0) and (error=0) do
|
|
begin
|
|
len:=uio^.uio_resid;
|
|
if (len > ZERO_REGION_SIZE) then
|
|
begin
|
|
len:=ZERO_REGION_SIZE;
|
|
end;
|
|
error:=uiomove(zbuf, len, uio);
|
|
end;
|
|
|
|
Exit(error);
|
|
end;
|
|
|
|
{ ARGSUSED }
|
|
Function null_modevent(_mod,_type:Integer):Integer;
|
|
begin
|
|
case (_type) of
|
|
MOD_LOAD:
|
|
begin
|
|
null_dev:=make_dev_credf(0, @null_cdevsw, 0, UID_ROOT, GID_WHEEL, &666, 'null',[]);
|
|
zero_dev:=make_dev_credf(0, @zero_cdevsw, 0, UID_ROOT, GID_WHEEL, &666, 'zero',[]);
|
|
end;
|
|
|
|
MOD_UNLOAD:
|
|
begin
|
|
destroy_dev(null_dev);
|
|
destroy_dev(zero_dev);
|
|
free_zero_region;
|
|
end;
|
|
|
|
MOD_SHUTDOWN:;
|
|
|
|
else
|
|
Exit(EOPNOTSUPP);
|
|
end;
|
|
|
|
Exit(0);
|
|
end;
|
|
|
|
end.
|
|
|