From dc976f76e73b04420d3fd07be10204c697d8719e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:37 +0000 Subject: [PATCH 001/402] sys/lib/dist/pc/inst: add Venti Bloom filter configuration --- sys/lib/dist/pc/inst/fmtventi | 72 +++++++++++++++++++++++++++++-- sys/lib/dist/pc/inst/isventibloom | 13 ++++++ sys/lib/dist/pc/inst/prepdisk | 2 +- 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 sys/lib/dist/pc/inst/isventibloom diff --git a/sys/lib/dist/pc/inst/fmtventi b/sys/lib/dist/pc/inst/fmtventi index db79440acf..add5b88051 100755 --- a/sys/lib/dist/pc/inst/fmtventi +++ b/sys/lib/dist/pc/inst/fmtventi @@ -10,9 +10,9 @@ case checkready checkdone export fmtventi exit } - if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex){ + if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex || ! test -e /bin/venti/fmtbloom){ bind -a /n/dist/386/bin/venti /bin/venti - if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex){ + if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex || ! test -e /bin/venti/fmtbloom){ fmtventi=notdone export fmtventi exit @@ -105,6 +105,38 @@ case go ventiindex=$aa export ventiindex + hh=`{ls /dev/sd*/bloom* /dev/fs/bloom* >[2]/dev/null} + if(~ $#hh 0){ + echo 'You need to create a partition or partitions to hold the Venti bloom.' + echo 'The bloom partition names must begin with "bloom".' + echo + fmtventi=notdone + export fmtventi + exit + } + default=(-d $"hh) + if(! ~ $#ventibloom 0){ + default=(-d $"ventibloom) + } + + echo You have the following Venti bloom partitions. + ls -l $hh + echo + + prompt $default 'Venti bloom partitions to use' + aa=`{echo $rd} + bad=no + for(a in $aa){ + if(! ~ $a $hh){ + echo 'Bad venti bloom partition' $a + fmtventi=notdone + export fmtventi + exit + } + } + ventibloom=$aa + export ventibloom + n=-1 fmta=() for(a in $ventiarena){ @@ -133,11 +165,25 @@ case go fmti=($fmti isect$n:$a) } + n=-1 + fmtb=() + for(a in $ventibloom){ + do=yes + n=`{hoc -e 1+$n} + if(isventibloom $a){ + echo File $a is already formatted as a Venti bloom section. + prompt -d no 'Reformat '$a yes no + do=$rd + } + if(~ $do yes) + fmtb=($fmtb bloom$n:$a) + } + echo Formatting Venti arenas and indices (this takes a while). # do each disk in parallel echo good >/tmp/fmt dd=() - for(a in $fmta $fmti){ + for(a in $fmta $fmti $fmtb){ d=`{echo $a | sed 's!.*:(/.*/).*!\1!'} if(! ~ $d $dd) dd=($dd $d) @@ -160,6 +206,24 @@ case go echo done with $i(3) } } + for(a in $fmtb){ + i=`{echo $a | sed 's!(.*):(/.*/)(.*)!\1 \2 \2\3!'} + pgsize=`{grep pagesize /dev/swap | sed 's/^([0-9]+) .*$/\1/'} + userused=`{grep user /dev/swap | sed 's/^([0-9]+)\/([0-9]+) .*$/\1/'} + userpgs=`{grep user /dev/swap | sed 's/^([0-9]+)\/([0-9]+) .*$/\2/'} + userfree=`{hoc -e '('$userpgs-$userused')'*$pgsize} + bloomsize=`{hoc -e 2'^(int(log('$userfree/1024/1024*20/100*1/3')/log(2)))'} + partsize=`{ls -l $i(3) | awk '{print int($6/1024/1024)}' | hoc} + if(test $bloomsize -gt $partsize) + bloomsize=$partsize + if(test $bloomsize -lt 1) + bloomsize=1 + if(~ $i(2) $d){ + echo $i(3) ... + venti/fmtbloom -s $bloomsize^m $i(3) || echo bad >/tmp/fmt + echo done with $i(3) + } + } } & } wait @@ -178,6 +242,8 @@ case go echo index main for(i in $ventiindex) echo isect $i + for(b in $ventibloom) + echo bloom $b for(a in $ventiarena) echo arenas $a } | venti/conf -w $v diff --git a/sys/lib/dist/pc/inst/isventibloom b/sys/lib/dist/pc/inst/isventibloom new file mode 100644 index 0000000000..bc62af5218 --- /dev/null +++ b/sys/lib/dist/pc/inst/isventibloom @@ -0,0 +1,13 @@ +#!/bin/rc + +if(! ~ $#* 1){ + echo 'usage: isventibloom /dev/sdC0/part' >[1=2] + exit usage +} + +arg=$1 +if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 | + dd -quiet 1 -bs 4 -count 1 | xd -b | sed 1q} <{echo '0000000 b1 00 4e ad'}) + exit notbloom +exit 0 + diff --git a/sys/lib/dist/pc/inst/prepdisk b/sys/lib/dist/pc/inst/prepdisk index 6ef4a92f8a..b31dae9a04 100755 --- a/sys/lib/dist/pc/inst/prepdisk +++ b/sys/lib/dist/pc/inst/prepdisk @@ -7,7 +7,7 @@ fn autotype { if(~ $fstype fossil) echo -a 9fat -a nvram -a fossil -a swap if(~ $fstype fossil+venti) - echo -a 9fat -a nvram -a arenas -a isect -a fossil -a swap # -a other + echo -a 9fat -a nvram -a arenas -a isect -a bloom -a fossil -a swap # -a other } switch($1) { From 9f48c182887ebb40f902aa06b4ca0d3db45a5d60 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 27 Feb 2016 18:30:35 +0000 Subject: [PATCH 002/402] sys/lib/dist/pc/inst: fix network installation option --- sys/lib/dist/pc/inst/download | 2 +- sys/lib/dist/pc/inst/main | 2 +- sys/lib/dist/pc/plan9.ini.cd | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/lib/dist/pc/inst/download b/sys/lib/dist/pc/inst/download index 70d7f5ba75..70a2aa5396 100755 --- a/sys/lib/dist/pc/inst/download +++ b/sys/lib/dist/pc/inst/download @@ -1,6 +1,6 @@ #!/bin/rc -# prereq: mountfs +# prereq: mountfs confignet # desc: download or continue to download the distribution archives switch($1) { diff --git a/sys/lib/dist/pc/inst/main b/sys/lib/dist/pc/inst/main index 25ac0d1683..742d0e4678 100755 --- a/sys/lib/dist/pc/inst/main +++ b/sys/lib/dist/pc/inst/main @@ -18,9 +18,9 @@ tasks=(\ mountfs\ configdist\ confignet\ + download\ mountdist\ fmtventi\ - download\ copydist\ bootsetup finish stop\ stopether stopppp\ diff --git a/sys/lib/dist/pc/plan9.ini.cd b/sys/lib/dist/pc/plan9.ini.cd index 828a1f856b..f3631adefd 100644 --- a/sys/lib/dist/pc/plan9.ini.cd +++ b/sys/lib/dist/pc/plan9.ini.cd @@ -24,6 +24,7 @@ vgasize=ask dmamode=ask adisk=/dev/sdD0/cdboot cdboot=yes +installurl=http://148.251.6.120/plan9/download # console=0 # baud=9600 From 0b57185b04147dcd38b7b0a3ca5dab83cecc8fa0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 003/402] sys/lib/dist/pc/inst: use pbslba instead of pbs when formatting 9fat --- sys/lib/dist/pc/inst/bootsetup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/lib/dist/pc/inst/bootsetup b/sys/lib/dist/pc/inst/bootsetup index cc22fe6ee9..d44cfa89cd 100755 --- a/sys/lib/dist/pc/inst/bootsetup +++ b/sys/lib/dist/pc/inst/bootsetup @@ -59,7 +59,7 @@ case go bind /n/newfs/386/9loadnousb /n/newfs/386/9load # cater to old bioses if(~ $need9fatformat yes){ log Initializing Plan 9 FAT partition. - disk/format -r 2 -d -b /386/pbs \ + disk/format -r 2 -d -b /386/pbslba \ /dev/$disk/9fat /n/newfs/386/9load # silently install pbslba if the partition is way into the disk. # it''s our only hope. only need this for >8.5GB into the disk. From c023df535a46565359ac4df9f1d681c86d312e8b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 004/402] sys/lib/dist/pc/inst: define nobootprompt and user in default plan9.ini --- sys/lib/dist/pc/inst/bootsetup | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/lib/dist/pc/inst/bootsetup b/sys/lib/dist/pc/inst/bootsetup index d44cfa89cd..a22a50f050 100755 --- a/sys/lib/dist/pc/inst/bootsetup +++ b/sys/lib/dist/pc/inst/bootsetup @@ -24,6 +24,7 @@ case go sfs=`{echo $fs | sed 's;/dev;#S;'} if(~ $fstype fossil fossil+venti){ echo bootfile'='$bootfat!9pcf + echo 'nobootprompt=local!'^$sfs echo 'bootargs=local!'^$sfs echo 'bootdisk=local!'^$sfs } @@ -42,6 +43,7 @@ case go echo 'mouseport='^$mouseport echo 'monitor='^$monitor echo 'vgasize='^$vgasize + echo 'user=glenda' } >/tmp/plan9.ini } if(! test -f /tmp/plan9ini.bak) From 1028c369391b7cf39b2dd9e5530b9fb0236d1a5f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 005/402] sys/lib/dist/pc: enable serial console in installer --- sys/lib/dist/pc/plan9.ini.cd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/lib/dist/pc/plan9.ini.cd b/sys/lib/dist/pc/plan9.ini.cd index f3631adefd..0633ed7523 100644 --- a/sys/lib/dist/pc/plan9.ini.cd +++ b/sys/lib/dist/pc/plan9.ini.cd @@ -25,7 +25,7 @@ dmamode=ask adisk=/dev/sdD0/cdboot cdboot=yes installurl=http://148.251.6.120/plan9/download -# console=0 +console=0 b115200 # baud=9600 [install] From fe67742a4c022771d3d15ea1b6001d45ad8e1454 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 20 May 2021 19:20:58 +0000 Subject: [PATCH 006/402] sys/lib/dist/cmd/multi: fix mkfile --- sys/lib/dist/cmd/multi/mkmulti | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/lib/dist/cmd/multi/mkmulti b/sys/lib/dist/cmd/multi/mkmulti index 2317e51e8a..5511893d47 100755 --- a/sys/lib/dist/cmd/multi/mkmulti +++ b/sys/lib/dist/cmd/multi/mkmulti @@ -43,7 +43,7 @@ echo $i... } if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.$b}){ cd /sys/src/cmd/$i - rm 8.out + rm 8.$b files=`{mk 8.$b | getfiles} } if not if(test -d /sys/src/cmd/$d && @{cd /sys/src/cmd/$d && mk 8.$b}){ From 5d383dfdd6ffca11ef19421fe2052ea3f6cecada Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 007/402] sys/src/9/pc: add sdiahci to pcflop kernel configuration --- sys/src/9/pc/pcflop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index 6fa886aca3..2eba49ddb9 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -75,7 +75,7 @@ misc sdata pci sdscsi sd53c8xx pci sdscsi sdmylex pci sdscsi -# sdiahci pci sdscsi + sdiahci pci sdscsi uarti8250 From 3eea29777d6733088030f3fc2898dbb25f7b7a29 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 008/402] sys/src/9/pc: add ether82563 to pcflop kernel configuration --- sys/src/9/pc/pcflop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index 2eba49ddb9..c7c83e44f0 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -47,7 +47,7 @@ link ether8169 pci ethermii # ether82543gc pci ether82557 pci -# ether82563 pci + ether82563 pci ether83815 pci # etherdp83820 pci etherec2t ether8390 From ffca9dfe6a70ecd29e9355094cab3f3087e1f7e4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 14 Aug 2017 09:09:20 +0000 Subject: [PATCH 009/402] sys/src/9: use SCSI commands enumeration (thanks Geoff Collyer) --- sys/include/disk.h | 67 ++------------------------------------- sys/include/diskcmd.h | 66 ++++++++++++++++++++++++++++++++++++++ sys/src/9/pc/sdata.c | 30 +++++++++--------- sys/src/9/pc/sdiahci.c | 14 ++++---- sys/src/9/pcboot/sdbios.c | 1 - sys/src/9/port/devsd.c | 28 ++++++++-------- sys/src/9/port/sd.h | 2 ++ sys/src/9/port/sdaoe.c | 11 +++---- sys/src/9/port/sdscsi.c | 10 +++--- 9 files changed, 116 insertions(+), 113 deletions(-) create mode 100644 sys/include/diskcmd.h mode change 100644 => 100755 sys/src/9/port/sdaoe.c diff --git a/sys/include/disk.h b/sys/include/disk.h index b8fdb49094..bf6fa73d7a 100644 --- a/sys/include/disk.h +++ b/sys/include/disk.h @@ -1,6 +1,8 @@ #pragma src "/sys/src/libdisk" #pragma lib "libdisk.a" +#include + /* SCSI interface */ typedef struct Scsi Scsi; struct Scsi { @@ -59,71 +61,6 @@ enum { Gdisk, Gguess, }; -enum { /* SCSI command codes */ - ScmdTur = 0x00, /* test unit ready */ - ScmdRewind = 0x01, /* rezero/rewind */ - ScmdRsense = 0x03, /* request sense */ - ScmdFormat = 0x04, /* format unit */ - ScmdRblimits = 0x05, /* read block limits */ - ScmdRead = 0x08, /* read */ - ScmdWrite = 0x0A, /* write */ - ScmdSeek = 0x0B, /* seek */ - ScmdFmark = 0x10, /* write filemarks */ - ScmdSpace = 0x11, /* space forward/backward */ - ScmdInq = 0x12, /* inquiry */ - ScmdMselect6 = 0x15, /* mode select */ - ScmdMselect10 = 0x55, /* mode select */ - ScmdMsense6 = 0x1A, /* mode sense */ - ScmdMsense10 = 0x5A, /* mode sense */ - ScmdStart = 0x1B, /* start/stop unit */ - ScmdRcapacity = 0x25, /* read capacity */ - ScmdRcapacity16 = 0x9e, /* long read capacity */ - ScmdRformatcap = 0x23, /* read format capacity */ - ScmdExtread = 0x28, /* extended read (10 bytes) */ - ScmdRead16 = 0x88, /* long read (16 bytes) */ - ScmdExtwrite = 0x2A, /* extended write (10 bytes) */ - ScmdExtwritever = 0x2E, /* extended write and verify (10) */ - ScmdWrite16 = 0x8A, /* long write (16 bytes) */ - ScmdExtseek = 0x2B, /* extended seek */ - - ScmdSynccache = 0x35, /* flush cache */ - ScmdRTOC = 0x43, /* read TOC data */ - ScmdRdiscinfo = 0x51, /* read disc information */ - ScmdRtrackinfo = 0x52, /* read track information */ - ScmdReserve = 0x53, /* reserve track */ - ScmdBlank = 0xA1, /* blank *-RW media */ - - ScmdCDpause = 0x4B, /* pause/resume */ - ScmdCDstop = 0x4E, /* stop play/scan */ - ScmdCDplay = 0xA5, /* play audio */ - ScmdCDload = 0xA6, /* load/unload */ - ScmdCDscan = 0xBA, /* fast forward/reverse */ - ScmdCDstatus = 0xBD, /* mechanism status */ - Scmdgetconf = 0x46, /* get configuration */ - - ScmdEInitialise = 0x07, /* initialise element status */ - ScmdMMove = 0xA5, /* move medium */ - ScmdEStatus = 0xB8, /* read element status */ - ScmdMExchange = 0xA6, /* exchange medium */ - ScmdEposition = 0x2B, /* position to element */ - - ScmdReadDVD = 0xAD, /* read dvd structure */ - ScmdReportKey = 0xA4, /* read dvd key */ - ScmdSendKey = 0xA3, /* write dvd key */ - - ScmdClosetracksess= 0x5B, - ScmdRead12 = 0xA8, - ScmdSetcdspeed = 0xBB, - ScmdReadcd = 0xBE, - - /* vendor-specific */ - ScmdFwaddr = 0xE2, /* first writeable address */ - ScmdTreserve = 0xE4, /* reserve track */ - ScmdTinfo = 0xE5, /* read track info */ - ScmdTwrite = 0xE6, /* write track */ - ScmdMload = 0xE7, /* medium load/unload */ - ScmdFixation = 0xE9, /* fixation */ -}; /* proto file parsing */ typedef void Protoenum(char *new, char *old, Dir *d, void *a); diff --git a/sys/include/diskcmd.h b/sys/include/diskcmd.h new file mode 100644 index 0000000000..0c0fbe050f --- /dev/null +++ b/sys/include/diskcmd.h @@ -0,0 +1,66 @@ +enum { /* SCSI command codes */ + ScmdTur = 0x00, /* test unit ready */ + ScmdRewind = 0x01, /* rezero/rewind */ + ScmdRsense = 0x03, /* request sense */ + ScmdFormat = 0x04, /* format unit */ + ScmdRblimits = 0x05, /* read block limits */ + ScmdRead = 0x08, /* read */ + ScmdWrite = 0x0A, /* write */ + ScmdSeek = 0x0B, /* seek */ + ScmdFmark = 0x10, /* write filemarks */ + ScmdSpace = 0x11, /* space forward/backward */ + ScmdInq = 0x12, /* inquiry */ + ScmdMselect6 = 0x15, /* mode select */ + ScmdMselect10 = 0x55, /* mode select */ + ScmdMsense6 = 0x1A, /* mode sense */ + ScmdMsense10 = 0x5A, /* mode sense */ + ScmdStart = 0x1B, /* start/stop unit */ + ScmdRcapacity = 0x25, /* read capacity */ + ScmdRcapacity16 = 0x9e, /* long read capacity */ + ScmdRformatcap = 0x23, /* read format capacity */ + ScmdExtread = 0x28, /* extended read (10 bytes) */ + ScmdRead16 = 0x88, /* long read (16 bytes) */ + ScmdExtwrite = 0x2A, /* extended write (10 bytes) */ + ScmdExtwritever = 0x2E, /* extended write and verify (10) */ + ScmdWrite16 = 0x8A, /* long write (16 bytes) */ + ScmdExtseek = 0x2B, /* extended seek */ + + ScmdSynccache = 0x35, /* flush cache */ + ScmdSynccache16 = 0x91, /* flush cache (16) */ + ScmdRTOC = 0x43, /* read TOC data */ + ScmdRdiscinfo = 0x51, /* read disc information */ + ScmdRtrackinfo = 0x52, /* read track information */ + ScmdReserve = 0x53, /* reserve track */ + ScmdBlank = 0xA1, /* blank *-RW media */ + + ScmdCDpause = 0x4B, /* pause/resume */ + ScmdCDstop = 0x4E, /* stop play/scan */ + ScmdCDplay = 0xA5, /* play audio */ + ScmdCDload = 0xA6, /* load/unload */ + ScmdCDscan = 0xBA, /* fast forward/reverse */ + ScmdCDstatus = 0xBD, /* mechanism status */ + Scmdgetconf = 0x46, /* get configuration */ + + ScmdEInitialise = 0x07, /* initialise element status */ + ScmdMMove = 0xA5, /* move medium */ + ScmdEStatus = 0xB8, /* read element status */ + ScmdMExchange = 0xA6, /* exchange medium */ + ScmdEposition = 0x2B, /* position to element */ + + ScmdReadDVD = 0xAD, /* read dvd structure */ + ScmdReportKey = 0xA4, /* read dvd key */ + ScmdSendKey = 0xA3, /* write dvd key */ + + ScmdClosetracksess= 0x5B, + ScmdRead12 = 0xA8, + ScmdSetcdspeed = 0xBB, + ScmdReadcd = 0xBE, + + /* vendor-specific */ + ScmdFwaddr = 0xE2, /* first writeable address */ + ScmdTreserve = 0xE4, /* reserve track */ + ScmdTinfo = 0xE5, /* read track info */ + ScmdTwrite = 0xE6, /* write track */ + ScmdMload = 0xE7, /* medium load/unload */ + ScmdFixation = 0xE9, /* fixation */ +}; diff --git a/sys/src/9/pc/sdata.c b/sys/src/9/pc/sdata.c index f821f20bac..aaf2de7887 100644 --- a/sys/src/9/pc/sdata.c +++ b/sys/src/9/pc/sdata.c @@ -1503,17 +1503,17 @@ atagenio(Drive* drive, uchar* cmd, int clen) * Fail any command with a LUN except INQUIRY which * will return 'logical unit not supported'. */ - if((cmd[1]>>5) && cmd[0] != 0x12) + if((cmd[1]>>5) && cmd[0] != ScmdInq) return atasetsense(drive, SDcheck, 0x05, 0x25, 0); switch(cmd[0]){ default: return atasetsense(drive, SDcheck, 0x05, 0x20, 0); - case 0x00: /* test unit ready */ + case ScmdTur: /* test unit ready */ return SDok; - case 0x03: /* request sense */ + case ScmdRsense: /* request sense */ if(cmd[4] < sizeof(drive->sense)) len = cmd[4]; else @@ -1524,7 +1524,7 @@ atagenio(Drive* drive, uchar* cmd, int clen) } return SDok; - case 0x12: /* inquiry */ + case ScmdInq: /* inquiry */ if(cmd[4] < sizeof(drive->inquiry)) len = cmd[4]; else @@ -1535,14 +1535,14 @@ atagenio(Drive* drive, uchar* cmd, int clen) } return SDok; - case 0x1B: /* start/stop unit */ + case ScmdStart: /* start/stop unit */ /* * NOP for now, can use the power management feature * set later. */ return SDok; - case 0x25: /* read capacity */ + case ScmdRcapacity: /* read capacity */ if((cmd[1] & 0x01) || cmd[2] || cmd[3]) return atasetsense(drive, SDcheck, 0x05, 0x24, 0); if(drive->data == nil || drive->dlen < 8) @@ -1564,7 +1564,7 @@ atagenio(Drive* drive, uchar* cmd, int clen) drive->data += 8; return SDok; - case 0x9E: /* long read capacity */ + case ScmdRcapacity16: if((cmd[1] & 0x01) || cmd[2] || cmd[3]) return atasetsense(drive, SDcheck, 0x05, 0x24, 0); if(drive->data == nil || drive->dlen < 8) @@ -1590,14 +1590,14 @@ atagenio(Drive* drive, uchar* cmd, int clen) drive->data += 12; return SDok; - case 0x28: /* read (10) */ - case 0x88: /* long read (16) */ - case 0x2a: /* write (10) */ - case 0x8a: /* long write (16) */ - case 0x2e: /* write and verify (10) */ + case ScmdExtread: + case ScmdExtwrite: + case ScmdExtwritever: + case ScmdRead16: + case ScmdWrite16: break; - case 0x5A: + case ScmdMsense10: return atamodesense(drive, cmd); } @@ -1690,8 +1690,8 @@ atario(SDreq* r) * effort. Read/write(6) are easy. */ switch(r->cmd[0]){ - case 0x08: /* read */ - case 0x0A: /* write */ + case ScmdRead: + case ScmdWrite: cmdp = cmd10; memset(cmdp, 0, sizeof(cmd10)); cmdp[0] = r->cmd[0]|0x20; diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 224d9b72dd..dfbd401041 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1526,7 +1526,7 @@ ahcibuild(Drive *d, uchar *cmd, void *data, int n, vlong lba) static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35, }; pm = &d->portm; - dir = *cmd != 0x28; + dir = *cmd != ScmdExtread; llba = pm->feat&Dllba? 1: 0; acmd = tab[dir][llba]; qlock(pm); @@ -1772,10 +1772,10 @@ iariopkt(SDreq *r, Drive *d) case SDperworm: case SDpercd: switch(cmd[0]){ - case 0x0a: /* write (6?) */ - case 0x2a: /* write (10) */ - case 0x8a: /* long write (16) */ - case 0x2e: /* write and verify (10) */ + case ScmdWrite: + case ScmdExtwrite: + case ScmdExtwritever: + case ScmdWrite16: wormwrite = 1; break; } @@ -1822,7 +1822,7 @@ iario(SDreq *r) name = d->unit->name; p = d->port; - if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ + if(*cmd == ScmdSynccache || *cmd == ScmdSynccache16){ if(flushcache(d) == 0) return sdsetsense(r, SDok, 0, 0, 0); return sdsetsense(r, SDcheck, 3, 0xc, 2); @@ -1833,7 +1833,7 @@ iario(SDreq *r) return i; } - if(*cmd != 0x28 && *cmd != 0x2a){ + if(*cmd != ScmdExtread && *cmd != ScmdExtwrite){ print("%s: bad cmd %.2#ux\n", name, cmd[0]); r->status = SDcheck; return SDcheck; diff --git a/sys/src/9/pcboot/sdbios.c b/sys/src/9/pcboot/sdbios.c index f1a738fecc..4c76cf7bc7 100644 --- a/sys/src/9/pcboot/sdbios.c +++ b/sys/src/9/pcboot/sdbios.c @@ -20,7 +20,6 @@ #include "../port/netif.h" #include "../port/sd.h" #include "dosfs.h" -#include long biosread0(Bootfs *, void *, long); vlong biosseek(Bootfs *fs, vlong off); diff --git a/sys/src/9/port/devsd.c b/sys/src/9/port/devsd.c index 58de1a88b8..c7edd3fb6f 100644 --- a/sys/src/9/port/devsd.c +++ b/sys/src/9/port/devsd.c @@ -964,8 +964,8 @@ sdfakescsi(SDreq *r, void *info, int ilen) * Rewrite read(6)/write(6) into read(10)/write(10). */ switch(cmd[0]){ - case 0x08: /* read */ - case 0x0A: /* write */ + case ScmdRead: + case ScmdWrite: cmd[9] = 0; cmd[8] = cmd[4]; cmd[7] = 0; @@ -984,17 +984,17 @@ sdfakescsi(SDreq *r, void *info, int ilen) * Fail any command with a LUN except INQUIRY which * will return 'logical unit not supported'. */ - if((cmd[1]>>5) && cmd[0] != 0x12) + if((cmd[1]>>5) && cmd[0] != ScmdInq) return sdsetsense(r, SDcheck, 0x05, 0x25, 0); switch(cmd[0]){ default: return sdsetsense(r, SDcheck, 0x05, 0x20, 0); - case 0x00: /* test unit ready */ + case ScmdTur: /* test unit ready */ return sdsetsense(r, SDok, 0, 0, 0); - case 0x03: /* request sense */ + case ScmdRsense: /* request sense */ if(cmd[4] < sizeof unit->sense) len = cmd[4]; else @@ -1005,7 +1005,7 @@ sdfakescsi(SDreq *r, void *info, int ilen) } return sdsetsense(r, SDok, 0, 0, 0); - case 0x12: /* inquiry */ + case ScmdInq: /* inquiry */ if(cmd[4] < sizeof unit->inquiry) len = cmd[4]; else @@ -1016,13 +1016,13 @@ sdfakescsi(SDreq *r, void *info, int ilen) } return sdsetsense(r, SDok, 0, 0, 0); - case 0x1B: /* start/stop unit */ + case ScmdStart: /* start/stop unit */ /* * nop for now, can use power management later. */ return sdsetsense(r, SDok, 0, 0, 0); - case 0x25: /* read capacity */ + case ScmdRcapacity: /* read capacity */ if((cmd[1] & 0x01) || cmd[2] || cmd[3]) return sdsetsense(r, SDcheck, 0x05, 0x24, 0); if(r->data == nil || r->dlen < 8) @@ -1045,7 +1045,7 @@ sdfakescsi(SDreq *r, void *info, int ilen) r->rlen = p - (uchar*)r->data; return sdsetsense(r, SDok, 0, 0, 0); - case 0x9E: /* long read capacity */ + case ScmdRcapacity16: /* long read capacity */ if((cmd[1] & 0x01) || cmd[2] || cmd[3]) return sdsetsense(r, SDcheck, 0x05, 0x24, 0); if(r->data == nil || r->dlen < 8) @@ -1071,13 +1071,13 @@ sdfakescsi(SDreq *r, void *info, int ilen) r->rlen = p - (uchar*)r->data; return sdsetsense(r, SDok, 0, 0, 0); - case 0x5A: /* mode sense */ + case ScmdMsense10: /* mode sense */ return sdmodesense(r, cmd, info, ilen); - case 0x28: /* read */ - case 0x2A: /* write */ - case 0x88: /* read16 */ - case 0x8a: /* write16 */ + case ScmdExtread: + case ScmdExtwrite: + case ScmdRead16: + case ScmdWrite16: return SDnostatus; } } diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index 2c8659c879..51e0eabd8e 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -1,6 +1,8 @@ /* * Storage Device. */ +#include + typedef struct SDev SDev; typedef struct SDifc SDifc; typedef struct SDio SDio; diff --git a/sys/src/9/port/sdaoe.c b/sys/src/9/port/sdaoe.c old mode 100644 new mode 100755 index 8a8ecdbe11..6bd7916dc5 --- a/sys/src/9/port/sdaoe.c +++ b/sys/src/9/port/sdaoe.c @@ -447,14 +447,13 @@ aoerio(SDreq *r) cmd = r->cmd; name = unit->name; - if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ + if(*cmd == ScmdSynccache || *cmd == ScmdSynccache16) // qlock(c); // i = flushcache(); // qunlock(c); // if(i == 0) // return sdsetsense(r, SDok, 0, 0, 0); return sdsetsense(r, SDcheck, 3, 0xc, 2); - } if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){ r->status = i; @@ -462,12 +461,12 @@ aoerio(SDreq *r) } switch(*cmd){ - case 0x88: - case 0x28: + case ScmdRead16: + case ScmdExtread: rio = devtab[c->c->type]->read; break; - case 0x8a: - case 0x2a: + case ScmdWrite16: + case ScmdExtwrite: rio = devtab[c->c->type]->write; break; default: diff --git a/sys/src/9/port/sdscsi.c b/sys/src/9/port/sdscsi.c index 3bacbe6f55..28807fad25 100644 --- a/sys/src/9/port/sdscsi.c +++ b/sys/src/9/port/sdscsi.c @@ -202,7 +202,7 @@ scsionline(SDunit* unit) */ r->write = 0; memset(r->cmd, 0, sizeof(r->cmd)); - r->cmd[0] = 0x25; + r->cmd[0] = ScmdRcapacity; r->cmd[1] = r->lun<<5; r->clen = 10; r->data = p; @@ -310,9 +310,9 @@ scsifmt10(SDreq *r, int write, int lun, ulong nb, uvlong bno) c = r->cmd; if(write == 0) - c[0] = 0x28; + c[0] = ScmdExtread; else - c[0] = 0x2A; + c[0] = ScmdExtwrite; c[1] = lun<<5; c[2] = bno>>24; c[3] = bno>>16; @@ -333,9 +333,9 @@ scsifmt16(SDreq *r, int write, int lun, ulong nb, uvlong bno) c = r->cmd; if(write == 0) - c[0] = 0x88; + c[0] = ScmdRead16; else - c[0] = 0x8A; + c[0] = ScmdWrite16; c[1] = lun<<5; /* so wrong */ c[2] = bno>>56; c[3] = bno>>48; From d9da46845402a19caeca4870e6d3934e8a1517e0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 21:17:04 +0000 Subject: [PATCH 010/402] sys/src/9/pc: enable DMA in sdata --- sys/src/9/pc/sdata.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/src/9/pc/sdata.c b/sys/src/9/pc/sdata.c index aaf2de7887..00e6f358b8 100644 --- a/sys/src/9/pc/sdata.c +++ b/sys/src/9/pc/sdata.c @@ -577,6 +577,7 @@ atadmamode(Drive* drive) drive->dma = (dma>>8) & dma; if(drive->dma) drive->dma |= 'U'<<16; + drive->dmactl = drive->dma; } return dma; From cf0d74120f041a06fb12b528458e4b7acd3016aa Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 011/402] sys/src/9/pc: move Intel 82801FBM (ICH6-M) DID from sdata to sdiahci --- sys/src/9/pc/sdata.c | 1 - sys/src/9/pc/sdiahci.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/sdata.c b/sys/src/9/pc/sdata.c index 00e6f358b8..de1006943a 100644 --- a/sys/src/9/pc/sdata.c +++ b/sys/src/9/pc/sdata.c @@ -2091,7 +2091,6 @@ atapnp(void) case (0x24D1<<16)|0x8086: /* 82801EB/ER (ICH5 High-End) */ case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */ case (0x25A3<<16)|0x8086: /* 6300ESB (E7210) */ - case (0x2653<<16)|0x8086: /* 82801FBM (ICH6M) */ case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */ case (0x27DF<<16)|0x8086: /* 82801G SATA (ICH7) */ case (0x27C0<<16)|0x8086: /* 82801GB SATA AHCI (ICH7) */ diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index dfbd401041..f1d2b7ecaf 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1964,6 +1964,7 @@ didtype(Pcidev *p) */ if (p->did == 0x1e02 || /* c210 */ p->did == 0x24d1 || /* 82801eb/er */ + p->did == 0x2653 || /* 82801fbm */ (p->did & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */ p->did == 0x2821 || /* 82801h[roh] */ (p->did & 0xfffe) == 0x2824 || /* 82801h[b] */ From a46fa8ba06082aa8a27b5d8da760587c71362c40 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 012/402] sys/src/9/pc: increase Nrb back to 1024 (as before 2014-03-18) in some Ethernet drivers (thanks Geoff Collyer) --- sys/src/9/pc/ether82563.c | 8 ++++++-- sys/src/9/pc/ether82598.c | 10 +++++++--- sys/src/9/pc/etherigbe.c | 8 ++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index 7ff6438724..35b8cb8cd3 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -414,9 +414,13 @@ enum { }; enum { - /* were 512, 1024 & 64, but 52, 253 and 9 are ample. */ + /* + * these were 512, 1024 & 64, but 52, 253 & 9 are usually ample; + * however cpu servers and terminals can need more receive buffers + * due to bursts of traffic. + */ Nrd = 128, /* power of two */ - Nrb = 512, /* private receive buffers per Ctlr */ + Nrb = 1024, /* private receive buffers per Ctlr */ Ntd = 32, /* power of two */ }; diff --git a/sys/src/9/pc/ether82598.c b/sys/src/9/pc/ether82598.c index e24e30a211..c6c133ae2e 100644 --- a/sys/src/9/pc/ether82598.c +++ b/sys/src/9/pc/ether82598.c @@ -23,9 +23,13 @@ enum { /* tunable parameters */ Goslow = 0, /* flag: go slow by throttling intrs, etc. */ - /* were 256, 1024 & 64, but 30, 47 and 1 are ample. */ - Nrd = 64, /* multiple of 8, power of 2 for NEXTPOW2 */ - Nrb = 128, + /* + * these were 256, 1024 & 128, but 30, 47 and 1 are usually ample; + * however cpu servers and terminals can need more receive buffers + * due to bursts of traffic. + */ + Nrd = 128, /* multiple of 8, power of 2 for NEXTPOW2 */ + Nrb = 1024, Ntd = 32, /* multiple of 8, power of 2 for NEXTPOW2 */ }; diff --git a/sys/src/9/pc/etherigbe.c b/sys/src/9/pc/etherigbe.c index a5cd7a3764..070ec7a17e 100644 --- a/sys/src/9/pc/etherigbe.c +++ b/sys/src/9/pc/etherigbe.c @@ -444,9 +444,13 @@ enum { /* Td status */ enum { Rbsz = 2048, - /* were 256, 1024 & 64, but 52, 253 and 9 are ample. */ + /* + * these were 256, 1024 & 64, but 52, 253 & 9 are usually ample; + * however cpu servers and terminals can need more receive buffers + * due to bursts of traffic. + */ Nrd = 128, /* multiple of 8 */ - Nrb = 512, /* private receive buffers per Ctlr */ + Nrb = 1024, /* private receive buffers per Ctlr */ Ntd = 32, /* multiple of 8 */ }; From c8b694fceb7adf0e62690506421b789eb7593e92 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Oct 2016 22:55:28 +0000 Subject: [PATCH 013/402] sys/src/9/pc: add i210, i217 and i218 support in ether82563 (thanks Geoff Collyer) --- sys/src/9/pc/ether82563.c | 972 ++++++++++++++++++++++++-------------- 1 file changed, 628 insertions(+), 344 deletions(-) diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index 35b8cb8cd3..d77bf6bd5b 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -1,11 +1,14 @@ /* * Intel Gigabit Ethernet PCI-Express Controllers. - * 8256[36], 8257[1-79] + * 8256[367], 8257[1-79], 21[078] * Pretty basic, does not use many of the chip smarts. * The interrupt mitigation tuning for each chip variant * is probably different. The reset/initialisation * sequence needs straightened out. Doubt the PHY code * for the 82575eb is right. + * + * on the assumption that allowing jumbo packets makes the controller + * much slower (as is true of the 82579), never allow jumbos. */ #include "u.h" #include "../port/lib.h" @@ -15,9 +18,10 @@ #include "io.h" #include "../port/error.h" #include "../port/netif.h" - #include "etherif.h" +#define now() TK2MS(MACHP(0)->ticks) + /* * these are in the order they appear in the manual, not numeric order. * It was too hard to find them in the book. Ref 21489, rev 2.6 @@ -25,10 +29,10 @@ enum { /* General */ - Ctrl = 0x0000, /* Device Control */ Status = 0x0008, /* Device Status */ Eec = 0x0010, /* EEPROM/Flash Control/Data */ + Fextnvm6 = 0x0010, /* Future Extended NVM 6 */ Eerd = 0x0014, /* EEPROM Read */ Ctrlext = 0x0018, /* Extended Device Control */ Fla = 0x001c, /* Flash Access */ @@ -47,7 +51,6 @@ enum { Pbs = 0x1008, /* Packet Buffer Size */ /* Interrupt */ - Icr = 0x00C0, /* Interrupt Cause Read */ Itr = 0x00c4, /* Interrupt Throttling Rate */ Ics = 0x00C8, /* Interrupt Cause Set */ @@ -56,7 +59,6 @@ enum { Iam = 0x00E0, /* Interrupt acknowledge Auto Mask */ /* Receive */ - Rctl = 0x0100, /* Control */ Ert = 0x2008, /* Early Receive Threshold (573[EVL], 579 only) */ Fcrtl = 0x2160, /* Flow Control RX Threshold Low */ @@ -92,7 +94,6 @@ enum { Rssrk = 0x5c80, /* RSS Random Key */ /* Transmit */ - Tctl = 0x0400, /* Transmit Control */ Tipg = 0x0410, /* Transmit IPG */ Tkabgtxd = 0x3004, /* glci afe band gap transmit ref data, or something */ @@ -114,7 +115,6 @@ enum { Tarc1 = 0x3940, /* Arbitration Counter Queue 1 */ /* Statistics */ - Statistics = 0x4000, /* Start of Statistics Area */ Gorcl = 0x88/4, /* Good Octets Received Count */ Gotcl = 0x90/4, /* Good Octets Transmitted Count */ @@ -196,6 +196,10 @@ enum { /* phy interface registers */ Phyier = 18, /* 82573 phy interrupt enable */ Phyisr = 19, /* 82563 phy interrupt status */ Phylhr = 19, /* 8257[12] link health */ + Phyier218 = 24, /* 218 (phy79?) phy interrupt enable */ + Phyisr218 = 25, /* 218 (phy79?) phy interrupt status */ + Phystat = 26, /* 82580 (phy79?) phy status */ + Phypage = 31, /* page number */ Rtlink = 1<<10, /* realtime link status */ Phyan = 1<<11, /* phy has auto-negotiated */ @@ -204,15 +208,28 @@ enum { /* phy interface registers */ Ran = 1<<9, /* restart auto-negotiation */ Ean = 1<<12, /* enable auto-negotiation */ - /* 82573 Phyier bits */ - Lscie = 1<<10, /* link status changed ie */ - Ancie = 1<<11, /* auto-negotiation complete ie */ - Spdie = 1<<14, /* speed changed ie */ - Panie = 1<<15, /* phy auto-negotiation error ie */ + /* 82573 Phyier interrupt enable bits */ + Lscie = 1<<10, /* link status changed */ + Ancie = 1<<11, /* auto-negotiation complete */ + Spdie = 1<<14, /* speed changed */ + Panie = 1<<15, /* phy auto-negotiation error */ /* Phylhr/Phyisr bits */ Anf = 1<<6, /* lhr: auto-negotiation fault */ Ane = 1<<15, /* isr: auto-negotiation error */ + + /* 82580 Phystat bits */ + Ans = 3<<14, /* 82580 autoneg. status */ + Link = 1<<6, /* 82580 link */ + + /* 218 Phystat bits */ + Anfs = 3<<13, /* fault status */ + Ans218 = 1<<12, /* autoneg complete */ + + /* 218 Phyier218 interrupt enable bits */ + Spdie218 = 1<<1, /* speed changed */ + Lscie218 = 1<<2, /* link status changed */ + Ancie218 = 1<<8, /* auto-negotiation changed */ }; enum { /* Icr, Ics, Ims, Imc */ @@ -286,8 +303,8 @@ enum { /* Tctl */ Ten = 0x00000002, /* Transmit Enable */ Psp = 0x00000008, /* Pad Short Packets */ Mulr = 0x10000000, /* Allow multiple concurrent requests */ - CtMASK = 0x00000FF0, /* Collision Threshold */ - CtSHIFT = 4, + Ctmask = 0x00000FF0, /* Collision Threshold */ + Ctshift = 4, ColdMASK = 0x003FF000, /* Collision Distance */ ColdSHIFT = 12, Swxoff = 0x00400000, /* Sofware XOFF Transmission */ @@ -303,7 +320,7 @@ enum { /* [RT]xdctl */ HthreshSHIFT = 8, WthreshMASK = 0x003F0000, /* Writeback Threshold */ WthreshSHIFT = 16, - Gran = 0x01000000, /* Granularity */ + Gran = 0x01000000, /* Granularity (descriptors, not cls) */ Qenable = 0x02000000, /* Queue Enable (82575) */ }; @@ -413,15 +430,43 @@ enum { Fdbc = 1<<8, /* bytes to read; 5 bits */ }; +/* + * the kumeran interface is mac-to-phy for external gigabit ethernet on + * intel's esb2 ich8 (io controller hub), it carries mii bits. can be used + * to reset the phy. intel proprietary, see "kumeran specification". + */ +enum { + I217inbandctlpage = 770, /* phy page */ + I217inbandctlreg = 18, /* phy register */ + I217inbandctllnkststxtmoutmask = 0x3F00, + I217inbandctllnkststxtmoutshift = 8, + + Fextnvm6reqpllclk = 0x100, + Fextnvm6enak1entrycond = 0x200, /* extend K1 entry latency */ + + Nvmk1cfg = 0x1B, /* NVM K1 Config Word */ + Nvmk1enable = 0x1, /* NVM Enable K1 bit */ + + Kumctrlstaoff = 0x1F0000, + Kumctrlstaoffshift = 16, + Kumctrlstaren = 0x200000, /* read enable */ + Kumctrlstak1cfg = 0x7, + Kumctrlstak1enable = 0x2, +}; + enum { /* * these were 512, 1024 & 64, but 52, 253 & 9 are usually ample; * however cpu servers and terminals can need more receive buffers * due to bursts of traffic. + * + * Tdlen and Rdlen have to be multiples of 128. Rd and Td are both + * 16 bytes long, so Nrd and Ntd must be multiples of 8. */ - Nrd = 128, /* power of two */ + Ntd = 32, /* power of two >= 8 */ + Nrd = 128, /* power of two >= 8 */ Nrb = 1024, /* private receive buffers per Ctlr */ - Ntd = 32, /* power of two */ + Slop = 32, /* for vlan headers, crcs, etc. */ }; enum { @@ -437,36 +482,27 @@ enum { i82576, i82577, i82579, -}; - -static int rbtab[] = { - 0, - 9014, - ETHERMAXTU, - ETHERMAXTU, - 9234, - 9234, - 8192, /* terrible performance above 8k */ - ETHERMAXTU, - ETHERMAXTU, - ETHERMAXTU, - ETHERMAXTU, - 9018, + i210, + i217, + i218, }; static char *tname[] = { - "any", - "i82563", - "i82566", - "i82567", - "i82571", - "i82572", - "i82573", - "i82574", - "i82575", - "i82576", - "i82577", - "i82579", +[Iany] "any", +[i82563] "i82563", +[i82566] "i82566", +[i82567] "i82567", +[i82571] "i82571", +[i82572] "i82572", +[i82573] "i82573", +[i82574] "i82574", +[i82575] "i82575", +[i82576] "i82576", +[i82577] "i82577", +[i82579] "i82579", +[i210] "i210", +[i217] "i217", +[i218] "i218", }; struct Ctlr { @@ -480,10 +516,6 @@ struct Ctlr { QLock alock; /* attach */ int attached; - int nrd; - int ntd; - int nrb; /* # rcv bufs this Ctlr has in the pool */ - unsigned rbsz; /* unsigned for % and / by 1024 */ int *nic; Lock imlock; @@ -491,6 +523,8 @@ struct Ctlr { Rendez lrendez; int lim; + int phynum; + int didk1fix; Watermark wmrb; Watermark wmrd; @@ -510,7 +544,7 @@ struct Ctlr { uint speeds[4]; uchar ra[Eaddrlen]; /* receive address */ - ulong mta[128]; /* multicast table array */ + ulong mta[128]; /* maximal multicast table array */ Rendez rrendez; int rim; @@ -519,8 +553,6 @@ struct Ctlr { Block **rb; /* receive buffers */ int rdh; /* receive descriptor head */ int rdt; /* receive descriptor tail */ - int rdtr; /* receive delay timer ring value */ - int radv; /* receive interrupt absolute delay timer */ Rendez trendez; QLock tlock; @@ -532,6 +564,7 @@ struct Ctlr { int fcrtl; int fcrth; + uint pbs; /* packet buffer size */ uint pba; /* packet buffer allocation */ }; @@ -545,6 +578,10 @@ static Lock i82563rblock; /* free receive Blocks */ static Block* i82563rbpool; static int nrbfull; /* # of rcv Blocks with data awaiting processing */ +static int speedtab[] = { + 10, 100, 1000, 0 +}; + static char* statistics[] = { "CRC Error", "Alignment Error", @@ -621,6 +658,8 @@ static char* statistics[] = { "Interrupt Rx Overrun", }; +static int i82563reset(Ctlr *); + static long i82563ifstat(Ether* edev, void* a, long n, ulong offset) { @@ -674,14 +713,13 @@ i82563ifstat(Ether* edev, void* a, long n, ulong offset) p = seprint(p, e, "rintr: %ud %ud\n", ctlr->rintr, ctlr->rsleep); p = seprint(p, e, "tintr: %ud %ud\n", ctlr->tintr, ctlr->txdw); p = seprint(p, e, "ixcs: %ud %ud %ud\n", ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs); - p = seprint(p, e, "rdtr: %ud\n", ctlr->rdtr); - p = seprint(p, e, "radv: %ud\n", ctlr->radv); p = seprint(p, e, "ctrl: %.8ux\n", csr32r(ctlr, Ctrl)); p = seprint(p, e, "ctrlext: %.8ux\n", csr32r(ctlr, Ctrlext)); p = seprint(p, e, "status: %.8ux\n", csr32r(ctlr, Status)); p = seprint(p, e, "txcw: %.8ux\n", csr32r(ctlr, Txcw)); p = seprint(p, e, "txdctl: %.8ux\n", csr32r(ctlr, Txdctl)); - p = seprint(p, e, "pba: %.8ux\n", ctlr->pba); + p = seprint(p, e, "pbs: %dKB\n", ctlr->pbs); + p = seprint(p, e, "pba: %#.8ux\n", ctlr->pba); p = seprint(p, e, "speeds: 10:%ud 100:%ud 1000:%ud ?:%ud\n", ctlr->speeds[0], ctlr->speeds[1], ctlr->speeds[2], ctlr->speeds[3]); @@ -708,54 +746,11 @@ i82563ifstat(Ether* edev, void* a, long n, ulong offset) return n; } -enum { - CMrdtr, - CMradv, -}; - -static Cmdtab i82563ctlmsg[] = { - CMrdtr, "rdtr", 2, - CMradv, "radv", 2, -}; - static long -i82563ctl(Ether* edev, void* buf, long n) +i82563ctl(Ether*, void*, long) { - ulong v; - char *p; - Ctlr *ctlr; - Cmdbuf *cb; - Cmdtab *ct; - - if((ctlr = edev->ctlr) == nil) - error(Enonexist); - - cb = parsecmd(buf, n); - if(waserror()){ - free(cb); - nexterror(); - } - - ct = lookupcmd(cb, i82563ctlmsg, nelem(i82563ctlmsg)); - switch(ct->index){ - case CMrdtr: - v = strtoul(cb->f[1], &p, 0); - if(p == cb->f[1] || v > 0xFFFF) - error(Ebadarg); - ctlr->rdtr = v; - csr32w(ctlr, Rdtr, v); - break; - case CMradv: - v = strtoul(cb->f[1], &p, 0); - if(p == cb->f[1] || v > 0xFFFF) - error(Ebadarg); - ctlr->radv = v; - csr32w(ctlr, Radv, v); - } - free(cb); - poperror(); - - return n; + error(Enonexist); + return 0; } static void @@ -768,8 +763,7 @@ i82563promiscuous(void* arg, int on) edev = arg; ctlr = edev->ctlr; - rctl = csr32r(ctlr, Rctl); - rctl &= ~MoMASK; + rctl = csr32r(ctlr, Rctl) & ~MoMASK; if(on) rctl |= Upe|Mpe; else @@ -777,20 +771,73 @@ i82563promiscuous(void* arg, int on) csr32w(ctlr, Rctl, rctl); } +/* + * Returns the number of bits of mac address used in multicast hash, + * thus the number of longs of ctlr->mta (2^(bits-5)). + * This must be right for multicast (thus ipv6) to work reliably. + * + * The default multicast hash for mta is based on 12 bits of MAC address; + * the rightmost bit is a function of Rctl's Multicast Offset: 0=>36, + * 1=>35, 2=>34, 3=>32. Exceptions include the 578, 579, 217, 218, 219; + * they use only 10 bits, ignoring the rightmost 2 of the 12. + */ +static int +mcastbits(Ctlr *ctlr) +{ + switch (ctlr->type) { + /* + * openbsd says all `ich8' versions (ich8, ich9, ich10, pch, pch2 and + * pch_lpt) have 32 longs (use 10 bits of mac address for hash). + */ + case i82566: + case i82567: +// case i82578: + case i82579: + case i217: + case i218: +// case i219: + return 10; /* 32 longs */ + case i82563: + case i82571: + case i82572: + case i82573: + case i82574: +// case i82575: +// case i82583: + case i210: /* includes i211 */ + return 12; /* 128 longs */ + default: + print("82563: unsure of multicast bits in mac addresses; " + "enabling promiscuous multicast reception\n"); + csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Mpe); + return 10; /* be conservative (for mta size) */ + } +} + +static int +mcbitstolongs(int nmcbits) +{ + return 1 << (nmcbits - 5); /* 2^5 = 32 */ +} + static void i82563multicast(void* arg, uchar* addr, int on) { - int bit, x; + ulong nbits, tblsz, hash, word, bit; Ctlr *ctlr; Ether *edev; edev = arg; ctlr = edev->ctlr; - x = addr[5]>>1; - if(ctlr->type == i82566 || ctlr->type == i82567) - x &= 31; - bit = ((addr[5] & 1)<<4)|(addr[4]>>4); + nbits = mcastbits(ctlr); + tblsz = mcbitstolongs(nbits); + /* assume multicast offset in Rctl is 0 (we clear it above) */ + hash = addr[5] << 4 | addr[4] >> 4; /* bits 47:36 of mac */ + if (nbits == 10) + hash >>= 2; /* discard 37:36 of mac */ + word = (hash / 32) & (tblsz - 1); + bit = 1UL << (hash % 32); /* * multiple ether addresses can hash to the same filter bit, * so it's never safe to clear a filter bit. @@ -799,11 +846,10 @@ i82563multicast(void* arg, uchar* addr, int on) * then set the ones corresponding to in-use addresses. */ if(on) - ctlr->mta[x] |= 1<mta[word] |= bit; // else -// ctlr->mta[x] &= ~(1<mta[x]); +// ctlr->mta[word] &= ~bit; + csr32w(ctlr, Mta+word*4, ctlr->mta[word]); } static Block* @@ -846,60 +892,64 @@ i82563im(Ctlr* ctlr, int im) static void i82563txinit(Ctlr* ctlr) { - int i, r; + int i, r, tctl; Block *bp; - csr32w(ctlr, Tctl, 0x0F<type) { + case i210: + break; + default: + tctl |= Mulr; + /* fall through */ + case i217: + case i218: + tctl |= 66<tb[i]) != nil) { + ctlr->tb[i] = nil; + freeb(bp); + } + memset(ctlr->tdba, 0, Ntd * sizeof(Td)); + coherence(); csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba)); - csr32w(ctlr, Tdbah, 0); - csr32w(ctlr, Tdlen, ctlr->ntd * sizeof(Td)); - ctlr->tdh = PREV(0, ctlr->ntd); + csr32w(ctlr, Tdbah, 0); /* 32-bit system */ + csr32w(ctlr, Tdlen, Ntd * sizeof(Td)); + ctlr->tdh = PREV(0, Ntd); csr32w(ctlr, Tdh, 0); ctlr->tdt = 0; csr32w(ctlr, Tdt, 0); - for(i = 0; i < ctlr->ntd; i++){ - if((bp = ctlr->tb[i]) != nil){ - ctlr->tb[i] = nil; - freeb(bp); - } - memset(&ctlr->tdba[i], 0, sizeof(Td)); - } - csr32w(ctlr, Tidv, 128); - r = csr32r(ctlr, Txdctl); - r &= ~(WthreshMASK|PthreshMASK); + csr32w(ctlr, Tidv, 0); /* don't coalesce interrupts */ + csr32w(ctlr, Tadv, 0); + r = csr32r(ctlr, Txdctl) & ~(WthreshMASK|PthreshMASK); r |= 4<type == i82575 || ctlr->type == i82576) + if(ctlr->type == i82575 || ctlr->type == i82576 || ctlr->type == i210) r |= Qenable; - csr32w(ctlr, Tadv, 64); csr32w(ctlr, Txdctl, r); - r = csr32r(ctlr, Tctl); - r |= Ten; - csr32w(ctlr, Tctl, r); -// if(ctlr->type == i82671) -// csr32w(ctlr, Tarc0, csr32r(ctlr, Tarc0) | 7<<24); /* yb sez? */ + coherence(); + csr32w(ctlr, Tctl, csr32r(ctlr, Tctl) | Ten); } -#define Next(x, m) (((x)+1) & (m)) - static int i82563cleanup(Ctlr *ctlr) { - Block *b; - int tdh, m, n; + Block *bp; + int tdh, n; tdh = ctlr->tdh; - m = ctlr->ntd-1; - while(ctlr->tdba[n = Next(tdh, m)].status & Tdd){ + while(ctlr->tdba[n = NEXT(tdh, Ntd)].status & Tdd){ tdh = n; - if((b = ctlr->tb[tdh]) != nil){ + if((bp = ctlr->tb[tdh]) != nil){ ctlr->tb[tdh] = nil; - freeb(b); + freeb(bp); }else iprint("82563 tx underrun!\n"); ctlr->tdba[tdh].status = 0; } - return ctlr->tdh = tdh; } @@ -909,10 +959,9 @@ i82563transmit(Ether* edev) Td *td; Block *bp; Ctlr *ctlr; - int tdh, tdt, m; + int tdh, tdt; ctlr = edev->ctlr; - qlock(&ctlr->tlock); /* @@ -920,13 +969,18 @@ i82563transmit(Ether* edev) */ tdh = i82563cleanup(ctlr); + /* if link down on 218, don't try since we need k1fix to run first */ + if (!edev->link && ctlr->type == i218 && !ctlr->didk1fix) { + qunlock(&ctlr->tlock); + return; + } + /* * Try to fill the ring back up. */ tdt = ctlr->tdt; - m = ctlr->ntd-1; for(;;){ - if(Next(tdt, m) == tdh){ + if(NEXT(tdt, Ntd) == tdh){ /* ring full? */ ctlr->txdw++; i82563im(ctlr, Txdw); break; @@ -939,12 +993,14 @@ i82563transmit(Ether* edev) ctlr->tb[tdt] = bp; /* note size of queue of tds awaiting transmission */ notemark(&ctlr->wmtd, (tdt + Ntd - tdh) % Ntd); - tdt = Next(tdt, m); + tdt = NEXT(tdt, Ntd); } if(ctlr->tdt != tdt){ ctlr->tdt = tdt; + coherence(); csr32w(ctlr, Tdt, tdt); } + /* else may not be any new ones, but could be some still in flight */ qunlock(&ctlr->tlock); } @@ -952,12 +1008,11 @@ static void i82563replenish(Ctlr* ctlr) { Rd *rd; - int rdt, m; + int rdt; Block *bp; rdt = ctlr->rdt; - m = ctlr->nrd-1; - while(Next(rdt, m) != ctlr->rdh){ + while(NEXT(rdt, Nrd) != ctlr->rdh){ rd = &ctlr->rdba[rdt]; if(ctlr->rb[rdt] != nil){ print("#l%d: 82563: rx overrun\n", ctlr->edev->ctlrno); @@ -971,15 +1026,16 @@ i82563replenish(Ctlr* ctlr) * receive Block. */ panic("#l%d: 82563: all %d rx buffers in use, nrbfull %d", - ctlr->edev->ctlrno, ctlr->nrb, nrbfull); + ctlr->edev->ctlrno, Nrb, nrbfull); ctlr->rb[rdt] = bp; rd->addr[0] = PCIWADDR(bp->rp); // rd->addr[1] = 0; rd->status = 0; ctlr->rdfree++; - rdt = Next(rdt, m); + rdt = NEXT(rdt, Nrd); } ctlr->rdt = rdt; + coherence(); csr32w(ctlr, Rdt, rdt); } @@ -987,77 +1043,63 @@ static void i82563rxinit(Ctlr* ctlr) { Block *bp; - int i, r, rctl; - - if(ctlr->rbsz <= 2048) - rctl = Dpf|Bsize2048|Bam|RdtmsHALF; - else if(ctlr->rbsz <= 8192) - rctl = Lpe|Dpf|Bsize8192|Bsex|Bam|RdtmsHALF|Secrc; - else if(ctlr->rbsz <= 12*1024){ - i = ctlr->rbsz / 1024; - if(ctlr->rbsz % 1024) - i++; - rctl = Lpe|Dpf|BsizeFlex*i|Bam|RdtmsHALF|Secrc; - } - else - rctl = Lpe|Dpf|Bsize16384|Bsex|Bam|RdtmsHALF|Secrc; + int i, r, rctl, type; - if(ctlr->type == i82575 || ctlr->type == i82576){ + rctl = Dpf|Bsize2048|Bam|RdtmsHALF; + type = ctlr->type; + if(type == i82575 || type == i82576 || type == i210){ /* * Setting Qenable in Rxdctl does not * appear to stick unless Ren is on. */ csr32w(ctlr, Rctl, Ren|rctl); - r = csr32r(ctlr, Rxdctl); - r |= Qenable; - csr32w(ctlr, Rxdctl, r); + csr32w(ctlr, Rxdctl, csr32r(ctlr, Rxdctl) | Qenable); } csr32w(ctlr, Rctl, rctl); - if(ctlr->type == i82573 || ctlr->type == i82577 || ctlr->type == i82579) - csr32w(ctlr, Ert, 1024/8); - - if(ctlr->type == i82566 || ctlr->type == i82567) - csr32w(ctlr, Pbs, 16); + switch (type) { + case i82573: + case i82577: +// case i82577: /* not yet implemented */ + case i82579: + case i210: + case i217: + case i218: + csr32w(ctlr, Ert, 1024/8); /* early rx threshold */ + break; + } csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba)); - csr32w(ctlr, Rdbah, 0); - csr32w(ctlr, Rdlen, ctlr->nrd * sizeof(Rd)); - ctlr->rdh = 0; + csr32w(ctlr, Rdbah, 0); /* 32-bit system */ + csr32w(ctlr, Rdlen, Nrd * sizeof(Rd)); + ctlr->rdh = ctlr->rdt = 0; csr32w(ctlr, Rdh, 0); - ctlr->rdt = 0; csr32w(ctlr, Rdt, 0); - /* to hell with interrupt moderation, we've got fast cpus */ -// ctlr->rdtr = 25; /* µs units? */ -// ctlr->radv = 500; /* µs units? */ - ctlr->radv = ctlr->rdtr = 0; - csr32w(ctlr, Rdtr, ctlr->rdtr); - csr32w(ctlr, Radv, ctlr->radv); - - for(i = 0; i < ctlr->nrd; i++){ + + /* to hell with interrupt moderation, we want low latency */ + csr32w(ctlr, Rdtr, 0); + csr32w(ctlr, Radv, 0); + + for(i = 0; i < Nrd; i++) if((bp = ctlr->rb[i]) != nil){ ctlr->rb[i] = nil; freeb(bp); } - } i82563replenish(ctlr); - if(ctlr->type != i82575 || ctlr->type == i82576){ + if(type == i82575 || type == i82576 || type == i210){ /* * See comment above for Qenable. * Could shuffle the code? */ - r = csr32r(ctlr, Rxdctl); - r &= ~(WthreshMASK|PthreshMASK); - r |= (2<rim != 0; } +/* + * With no errors and the Ixsm bit set, + * the descriptor status Tpcs and Ipcs bits give + * an indication of whether the checksums were + * calculated and valid. + * + * Must be called with rd->errors == 0. + */ +static void +ckcksums(Ctlr *ctlr, Rd *rd, Block *bp) +{ +if (0) { + if(rd->status & Ixsm) + return; + ctlr->ixsm++; + if(rd->status & Ipcs){ + /* + * IP checksum calculated (and valid as errors == 0). + */ + ctlr->ipcs++; + bp->flag |= Bipck; + } + if(rd->status & Tcpcs){ + /* + * TCP/UDP checksum calculated (and valid as errors == 0). + */ + ctlr->tcpcs++; + bp->flag |= Btcpck|Budpck; + } + bp->checksum = rd->checksum; + bp->flag |= Bpktck; +} +} + static void i82563rproc(void* arg) { Rd *rd; Block *bp; Ctlr *ctlr; - int r, m, rdh, rim, passed; + int rdh, rim, passed; Ether *edev; edev = arg; ctlr = edev->ctlr; - i82563rxinit(ctlr); - r = csr32r(ctlr, Rctl); - r |= Ren; - csr32w(ctlr, Rctl, r); - m = ctlr->nrd-1; + coherence(); + csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Ren); + + if(ctlr->type == i210) + csr32w(ctlr, Rxdctl, csr32r(ctlr, Rxdctl) | Qenable); for(;;){ i82563replenish(ctlr); @@ -1102,41 +1178,18 @@ i82563rproc(void* arg) /* * Accept eop packets with no errors. - * With no errors and the Ixsm bit set, - * the descriptor status Tpcs and Ipcs bits give - * an indication of whether the checksums were - * calculated and valid. */ bp = ctlr->rb[rdh]; if((rd->status & Reop) && rd->errors == 0){ bp->wp += rd->length; bp->lim = bp->wp; /* lie like a dog. */ - if(!(rd->status & Ixsm)){ - ctlr->ixsm++; - if(rd->status & Ipcs){ - /* - * IP checksum calculated - * (and valid as errors == 0). - */ - ctlr->ipcs++; - bp->flag |= Bipck; - } - if(rd->status & Tcpcs){ - /* - * TCP/UDP checksum calculated - * (and valid as errors == 0). - */ - ctlr->tcpcs++; - bp->flag |= Btcpck|Budpck; - } - bp->checksum = rd->checksum; - bp->flag |= Bpktck; - } + if(0) + ckcksums(ctlr, rd, bp); ilock(&i82563rblock); nrbfull++; iunlock(&i82563rblock); notemark(&ctlr->wmrb, nrbfull); - etheriq(edev, bp, 1); + etheriq(edev, bp, 1); /* pass pkt upstream */ passed++; } else { if (rd->status & Reop && rd->errors) @@ -1149,12 +1202,12 @@ i82563rproc(void* arg) /* rd needs to be replenished to accept another pkt */ rd->status = 0; ctlr->rdfree--; - ctlr->rdh = rdh = Next(rdh, m); + ctlr->rdh = rdh = NEXT(rdh, Nrd); /* * if number of rds ready for packets is too low, * set up the unready ones. */ - if(ctlr->rdfree <= ctlr->nrd - 32 || (rim & Rxdmt0)) + if(ctlr->rdfree <= Nrd - 32 || (rim & Rxdmt0)) i82563replenish(ctlr); } /* note how many rds had full buffers */ @@ -1168,16 +1221,33 @@ i82563lim(void* ctlr) return ((Ctlr*)ctlr)->lim != 0; } -static int speedtab[] = { - 10, 100, 1000, 0 -}; +static int +phynum(Ctlr *ctlr) +{ + if (ctlr->phynum < 0) + switch (ctlr->type) { + case i82577: +// case i82578: /* not yet implemented */ + case i82579: + case i217: + case i218: + ctlr->phynum = 2; /* pcie phy */ + break; + default: + ctlr->phynum = 1; /* gbe phy */ + break; + } + return ctlr->phynum; +} static uint phyread(Ctlr *ctlr, int reg) { uint phy, i; - csr32w(ctlr, Mdic, MDIrop | 1<= 32) + iprint("phyread: reg %d >= 32\n", reg); + csr32w(ctlr, Mdic, MDIrop | phynum(ctlr)<= 32) + iprint("phyread: reg %d >= 32\n", reg); + csr32w(ctlr, Mdic, MDIwop | phynum(ctlr)<edev; + fextnvm6 = csr32r(ctlr, Fextnvm6); + status = csr32r(ctlr, Status); + /* status speed bits are different on 21[78] than earlier ctlrs */ + if (edev->link && status & (Sspeed1000>>2)) { + reg = kmrnread(ctlr, Kumctrlstak1cfg); + kmrnwrite(ctlr, Kumctrlstak1cfg, reg & ~Kumctrlstak1enable); + microdelay(10); + csr32w(ctlr, Fextnvm6, fextnvm6 | Fextnvm6reqpllclk); + kmrnwrite(ctlr, Kumctrlstak1cfg, reg); + ctlr->didk1fix = 1; + return; + } + /* else uncommon cases */ + + fextnvm6 &= ~Fextnvm6reqpllclk; + /* + * 217 manual claims not to have Frcdplx bit in status; + * 218 manual just omits the non-phy registers. + */ + if (!edev->link || + (status & (Sspeed100>>2|Frcdplx)) == (Sspeed100>>2|Frcdplx)) { + csr32w(ctlr, Fextnvm6, fextnvm6); + ctlr->didk1fix = 1; + return; + } + + /* access other page via phy addr 1 reg 31, then access reg 16-30 */ + phywrite(ctlr, Phypage, I217inbandctlpage<<5); + reg = phyread(ctlr, I217inbandctlreg) & ~I217inbandctllnkststxtmoutmask; + if (status & (Sspeed100>>2)) { /* 100Mb/s half-duplex? */ + txtmout = 5; + fextnvm6 &= ~Fextnvm6enak1entrycond; + } else { /* 10Mb/s */ + txtmout = 50; + fextnvm6 |= Fextnvm6enak1entrycond; + } + phywrite(ctlr, I217inbandctlreg, reg | + txtmout << I217inbandctllnkststxtmoutshift); + csr32w(ctlr, Fextnvm6, fextnvm6); + phywrite(ctlr, Phypage, 0<<5); /* reset page to usual 0 */ + ctlr->didk1fix = 1; +} + /* * watch for changes of link state */ static void i82563lproc(void *v) { - uint phy, i, a; + uint phy, sp, a, phy79, prevlink; Ctlr *ctlr; - Ether *e; - - e = v; - ctlr = e->ctlr; + Ether *edev; + edev = v; + ctlr = edev->ctlr; + phy79 = 0; + switch (ctlr->type) { + case i82579: +// case i82580: + case i217: + case i218: +// case i219: +// case i350: +// case i354: + phy79 = 1; + break; + } if(ctlr->type == i82573 && (phy = phyread(ctlr, Phyier)) != ~0) phywrite(ctlr, Phyier, phy | Lscie | Ancie | Spdie | Panie); + else if(phy79 && (phy = phyread(ctlr, Phyier218)) != ~0) + phywrite(ctlr, Phyier218, phy | Lscie218 | Ancie218 | Spdie218); + prevlink = 0; for(;;){ - phy = phyread(ctlr, Physsr); + a = 0; + phy = phyread(ctlr, phy79? Phystat: Physsr); if(phy == ~0) goto next; - i = (phy>>14) & 3; - - switch(ctlr->type){ - case i82563: - a = phyread(ctlr, Phyisr) & Ane; - break; - case i82571: - case i82572: - case i82575: - case i82576: - a = phyread(ctlr, Phylhr) & Anf; - i = (i-1) & 3; - break; - default: - a = 0; - break; + if (phy79) { + sp = (phy>>8) & 3; + // a = phy & (ctlr->type == i218? Anfs: Ans); + a = phy & Anfs; + } else { + sp = (phy>>14) & 3; + switch(ctlr->type){ + case i82563: + case i210: + a = phyread(ctlr, Phyisr) & Ane; /* a-n error */ + break; + case i82571: + case i82572: + case i82575: + case i82576: + a = phyread(ctlr, Phylhr) & Anf; /* a-n fault */ + sp = (sp-1) & 3; + break; + } } if(a) - phywrite(ctlr, Phyctl, phyread(ctlr, Phyctl) | Ran | Ean); - e->link = (phy & Rtlink) != 0; - if(e->link){ - ctlr->speeds[i]++; - if (speedtab[i]) - e->mbps = speedtab[i]; - } + phywrite(ctlr, Phyctl, phyread(ctlr, Phyctl) | + Ran | Ean); /* enable & restart autoneg */ + edev->link = (phy & (phy79? Link: Rtlink)) != 0; + if(edev->link){ + ctlr->speeds[sp]++; + if (speedtab[sp]) + edev->mbps = speedtab[sp]; + if (prevlink == 0 && ctlr->type == i218) + k1fix(ctlr); /* link newly up: kludge away */ + } else + ctlr->didk1fix = 0; /* force fix at next link up */ + prevlink = edev->link; next: ctlr->lim = 0; i82563im(ctlr, Lsc); @@ -1263,61 +1451,99 @@ i82563lproc(void *v) static void i82563tproc(void *v) { - Ether *e; + Ether *edev; Ctlr *ctlr; - e = v; - ctlr = e->ctlr; + edev = v; + ctlr = edev->ctlr; for(;;){ sleep(&ctlr->trendez, return0, 0); - i82563transmit(e); + i82563transmit(edev); } } +/* + * controller is buggered; shock it back to life. + */ +static void +restart(Ctlr *ctlr) +{ +if (0) { + static Lock rstlock; + + qlock(&ctlr->tlock); + ilock(&rstlock); + iprint("#l%d: resetting...", ctlr->edev->ctlrno); + i82563reset(ctlr); + /* [rt]xinit reset the ring indices */ + i82563txinit(ctlr); + i82563rxinit(ctlr); + coherence(); + csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Ren); + iunlock(&rstlock); + qunlock(&ctlr->tlock); + iprint("reset\n"); +} +} + +static void +freerbs(Ctlr *) +{ + int i; + Block *bp; + + for(i = Nrb; i > 0; i--){ + bp = i82563rballoc(); + bp->free = nil; + freeb(bp); + } +} + +static void +freemem(Ctlr *ctlr) +{ + freerbs(ctlr); + free(ctlr->tb); + ctlr->tb = nil; + free(ctlr->rb); + ctlr->rb = nil; + free(ctlr->tdba); + ctlr->tdba = nil; + free(ctlr->rdba); + ctlr->rdba = nil; +} + static void i82563attach(Ether* edev) { + int i; Block *bp; Ctlr *ctlr; char name[KNAMELEN]; ctlr = edev->ctlr; qlock(&ctlr->alock); + if(ctlr->attached){ qunlock(&ctlr->alock); return; } - ctlr->nrd = Nrd; - ctlr->ntd = Ntd; - if(waserror()){ - while(ctlr->nrb > 0){ - bp = i82563rballoc(); - bp->free = nil; - freeb(bp); - ctlr->nrb--; - } - free(ctlr->tb); - ctlr->tb = nil; - free(ctlr->rb); - ctlr->rb = nil; - free(ctlr->tdba); - ctlr->tdba = nil; - free(ctlr->rdba); - ctlr->rdba = nil; + freemem(ctlr); qunlock(&ctlr->alock); nexterror(); } - if((ctlr->rdba = mallocalign(ctlr->nrd*sizeof(Rd), 128, 0, 0)) == nil || - (ctlr->tdba = mallocalign(ctlr->ntd*sizeof(Td), 128, 0, 0)) == nil || - (ctlr->rb = malloc(ctlr->nrd*sizeof(Block*))) == nil || - (ctlr->tb = malloc(ctlr->ntd*sizeof(Block*))) == nil) + ctlr->rdba = mallocalign(Nrd * sizeof(Rd), 128, 0, 0); + ctlr->tdba = mallocalign(Ntd * sizeof(Td), 128, 0, 0); + if(ctlr->rdba == nil || ctlr->tdba == nil || + (ctlr->rb = malloc(Nrd*sizeof(Block*))) == nil || + (ctlr->tb = malloc(Ntd*sizeof(Block*))) == nil) error(Enomem); - for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ - if((bp = allocb(ctlr->rbsz + BY2PG)) == nil) + for(i = 0; i < Nrb; i++){ + if((bp = allocb(ETHERMAXTU + Slop + BY2PG)) == nil) error(Enomem); bp->free = i82563rbfree; freeb(bp); @@ -1354,7 +1580,6 @@ i82563interrupt(Ureg*, void* arg) edev = arg; ctlr = edev->ctlr; - ilock(&ctlr->imlock); csr32w(ctlr, Imc, ~0); im = ctlr->im; @@ -1411,6 +1636,29 @@ i82563detach0(Ctlr* ctlr) delay(10); + /* + * Balance Rx/Tx packet buffer. + * No need to set PBA register unless using jumbo, defaults to 32KB + * for receive. If it is changed, then have to do a MAC reset, + * and need to do that at the the right time as it will wipe stuff. + */ + ctlr->pba = csr32r(ctlr, Pba); + + /* set packet buffer size if present. no effect until soft reset. */ + switch (ctlr->type) { + case i82566: + case i82567: + case i217: + ctlr->pbs = 16; /* in KB */ + csr32w(ctlr, Pbs, ctlr->pbs); + break; + case i218: + // after pxe or 9fat boot, pba is always 0xe0012 on i218 => 32K + ctlr->pbs = (ctlr->pba >> 16) + (ushort)ctlr->pba; + csr32w(ctlr, Pbs, ctlr->pbs); + break; + } + r = csr32r(ctlr, Ctrl); if(ctlr->type == i82566 || ctlr->type == i82567 || ctlr->type == i82579) r |= Phyrst; @@ -1445,26 +1693,7 @@ i82563detach0(Ctlr* ctlr) if(csr32r(ctlr, Icr)) return -1; - /* - * Balance Rx/Tx packet buffer. - * No need to set PBA register unless using jumbo, defaults to 32KB - * for receive. If it is changed, then have to do a MAC reset, - * and need to do that at the the right time as it will wipe stuff. - */ - if(ctlr->rbsz > 8192 && (ctlr->type == i82563 || ctlr->type == i82571 || - ctlr->type == i82572)){ - ctlr->pba = csr32r(ctlr, Pba); - r = ctlr->pba >> 16; - r += ctlr->pba & 0xffff; - r >>= 1; - csr32w(ctlr, Pba, r); - } else if(ctlr->type == i82573 && ctlr->rbsz > ETHERMAXTU) - csr32w(ctlr, Pba, 14); - ctlr->pba = csr32r(ctlr, Pba); - - r = csr32r(ctlr, Ctrl); - csr32w(ctlr, Ctrl, Slu|r); - + csr32w(ctlr, Ctrl, Slu | csr32r(ctlr, Ctrl)); return 0; } @@ -1499,6 +1728,7 @@ eeread(Ctlr *ctlr, int adr) return csr32r(ctlr, Eerd) >> 16; } +/* load eeprom into ctlr */ static int eeload(Ctlr *ctlr) { @@ -1524,7 +1754,7 @@ fcycle(Ctlr *, Flash *f) return -1; f->reg[Fsts] |= Fcerr | Ael; for(i = 0; i < 10; i++){ - if((s&Scip) == 0) + if((s&Scip) == 0) /* spi cycle done? */ return 0; delay(1); s = f->reg[Fsts]; @@ -1545,8 +1775,7 @@ fread(Ctlr *ctlr, Flash *f, int ladr) f->reg32[Faddr] = ladr; /* setup flash control register */ - s = f->reg[Fctl]; - s &= ~(0x1f << 8); + s = f->reg[Fctl] & ~(0x1f << 8); s |= (2-1) << 8; /* 2 bytes */ s &= ~(2*Flcycle); /* read */ f->reg[Fctl] = s | Fgo; @@ -1560,6 +1789,7 @@ fread(Ctlr *ctlr, Flash *f, int ladr) return f->reg32[Fdata] & 0xffff; } +/* load flash into ctlr */ static int fload(Ctlr *ctlr) { @@ -1593,58 +1823,80 @@ fload(Ctlr *ctlr) static int i82563reset(Ctlr *ctlr) { - int i, r; + int i, r, type; - if(i82563detach(ctlr)) + if(i82563detach(ctlr)) { + iprint("82563 reset: detach failed\n"); return -1; - if(ctlr->type == i82566 || ctlr->type == i82567 || - ctlr->type == i82577 || ctlr->type == i82579) + } + type = ctlr->type; + if (ctlr->ra[Eaddrlen - 1] != 0) + goto macset; + switch (type) { + case i82566: + case i82567: + case i82577: +// case i82578: /* not yet implemented */ + case i82579: + case i217: + case i218: r = fload(ctlr); - else + break; + default: r = eeload(ctlr); + break; + } if (r != 0 && r != 0xBABA){ print("%s: bad EEPROM checksum - %#.4ux\n", - tname[ctlr->type], r); + tname[type], r); return -1; } + /* set mac addr */ for(i = 0; i < Eaddrlen/2; i++){ ctlr->ra[2*i] = ctlr->eeprom[Ea+i]; ctlr->ra[2*i+1] = ctlr->eeprom[Ea+i] >> 8; } - r = (csr32r(ctlr, Status) & Lanid) >> 2; - ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */ - - r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0]; - csr32w(ctlr, Ral, r); - r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4]; - csr32w(ctlr, Rah, r); - for(i = 1; i < 16; i++){ + /* ea ctlr[1] = ea ctlr[0]+1 */ + ctlr->ra[5] += (csr32r(ctlr, Status) & Lanid) >> 2; + /* + * zero other mac addresses. + * AV bits should be zeroed by master reset & there may only be 11 + * other registers on e.g., the i217. + */ + for(i = 1; i < 12; i++){ /* `12' used to be `16' here */ csr32w(ctlr, Ral+i*8, 0); csr32w(ctlr, Rah+i*8, 0); } memset(ctlr->mta, 0, sizeof(ctlr->mta)); - for(i = 0; i < 128; i++) - csr32w(ctlr, Mta + i*4, 0); +macset: + csr32w(ctlr, Ral, ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | + ctlr->ra[0]); /* low mac addr */ + /* address valid | high mac addr */ + csr32w(ctlr, Rah, 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4]); + + /* populate multicast table */ + for(i = 0; i < mcbitstolongs(mcastbits(ctlr)); i++) + csr32w(ctlr, Mta + i*4, ctlr->mta[i]); /* * Does autonegotiation affect this manual setting? * The correct values here should depend on the PBA value * and maximum frame length, no? - * ctlr->fcrt[lh] are never set, so default to 0. */ + /* fixed flow control ethernet address 0x0180c2000001 */ csr32w(ctlr, Fcal, 0x00C28001); csr32w(ctlr, Fcah, 0x0100); - if(ctlr->type != i82579) + if (type != i82579 && type != i210 && type != i217 && type != i218) + /* flow control type, dictated by Intel */ csr32w(ctlr, Fct, 0x8808); - csr32w(ctlr, Fcttv, 0x0100); - - ctlr->fcrtl = ctlr->fcrth = 0; - // ctlr->fcrtl = 0x00002000; + csr32w(ctlr, Fcttv, 0x0100); /* for XOFF frame */ + // ctlr->fcrtl = 0x00002000; /* rcv low water mark: 8KB */ + /* rcv high water mark: 16KB, < rcv buffer in PBA & RXA */ // ctlr->fcrth = 0x00004000; + ctlr->fcrtl = ctlr->fcrth = 0; csr32w(ctlr, Fcrtl, ctlr->fcrtl); csr32w(ctlr, Fcrth, ctlr->fcrth); - return 0; } @@ -1713,6 +1965,23 @@ i82563pci(void) case 0x1503: /* 82579v */ type = i82579; break; + case 0x1533: /* i210-t1 */ + case 0x1534: /* i210 */ + case 0x1536: /* i210-fiber */ + case 0x1537: /* i210-backplane */ + case 0x1538: + case 0x1539: /* i211 */ + case 0x157b: /* i210 */ + case 0x157c: /* i210 */ + type = i210; + break; + case 0x153a: /* i217-lm */ + case 0x153b: /* i217-v */ + type = i217; + break; + case 0x15a3: /* i218 */ + type = i218; + break; } io = p->mem[0].bar & ~0x0F; @@ -1729,14 +1998,8 @@ i82563pci(void) ctlr->port = io; ctlr->pcidev = p; ctlr->type = type; - /* - * on the assumption that allowing jumbo packets makes - * the controller much slower (as is true of the 82579), - * never allow jumbos. - */ - // ctlr->rbsz = rbtab[type]; - ctlr->rbsz = ETHERMAXTU; ctlr->nic = mem; + ctlr->phynum = -1; /* not yet known */ if(i82563reset(ctlr)){ vunmap(mem, p->mem[0].size); @@ -1787,7 +2050,7 @@ pnp(Ether* edev, int type) edev->irq = ctlr->pcidev->intl; edev->tbdf = ctlr->pcidev->tbdf; edev->mbps = 1000; - edev->maxmtu = ctlr->rbsz; + edev->maxmtu = ETHERMAXTU; memmove(edev->ea, ctlr->ra, Eaddrlen); /* @@ -1856,6 +2119,24 @@ i82579pnp(Ether *e) return pnp(e, i82579); } +static int +i210pnp(Ether *e) +{ + return pnp(e, i210); +} + +static int +i217pnp(Ether *e) +{ + return pnp(e, i217); +} + +static int +i218pnp(Ether *e) +{ + return pnp(e, i218); +} + void ether82563link(void) { @@ -1867,5 +2148,8 @@ ether82563link(void) addethercard("i82573", i82573pnp); addethercard("i82575", i82575pnp); addethercard("i82579", i82579pnp); + addethercard("i210", i210pnp); + addethercard("i217", i217pnp); + addethercard("i218", i218pnp); addethercard("igbepcie", anypnp); } From 27bac30b05b57397bb4f102a8c49565af2793445 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 19:48:16 +0000 Subject: [PATCH 014/402] sys/src/9/port: set mach in lock (thanks Yoann Padioleau) --- sys/src/9/port/taslock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/9/port/taslock.c b/sys/src/9/port/taslock.c index 5ff68ff400..ae3445dd09 100644 --- a/sys/src/9/port/taslock.c +++ b/sys/src/9/port/taslock.c @@ -80,6 +80,7 @@ lock(Lock *l) l->pc = pc; l->p = up; l->isilock = 0; + l->m = MACHP(m->machno); #ifdef LOCKCYCLES l->lockcycles = -lcycles(); #endif @@ -115,6 +116,7 @@ lock(Lock *l) l->pc = pc; l->p = up; l->isilock = 0; + l->m = MACHP(m->machno); #ifdef LOCKCYCLES l->lockcycles = -lcycles(); #endif From 9b50b39a1267d6f67447980e1903e67102c7021c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 20:20:09 +0000 Subject: [PATCH 015/402] sys/src/9/port: fix mapsize in newseg (thanks Yoann Padioleau) --- sys/src/9/port/segment.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c index 94267ae85e..92432a4f50 100644 --- a/sys/src/9/port/segment.c +++ b/sys/src/9/port/segment.c @@ -76,8 +76,8 @@ newseg(int type, ulong base, ulong size) mapsize = ROUND(size, PTEPERTAB)/PTEPERTAB; if(mapsize > nelem(s->ssegmap)){ mapsize *= 2; - if(mapsize > (SEGMAPSIZE*PTEPERTAB)) - mapsize = (SEGMAPSIZE*PTEPERTAB); + if(mapsize > SEGMAPSIZE) + mapsize = SEGMAPSIZE; s->map = smalloc(mapsize*sizeof(Pte*)); s->mapsize = mapsize; } From d14d24ab18367936719728729e4602e0e4234cc1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 19:33:27 +0000 Subject: [PATCH 016/402] sys/src/9: fix kmem in confinit (thanks Yoann Padioleau) --- sys/src/9/bcm/main.c | 2 +- sys/src/9/kw/main.c | 2 +- sys/src/9/mtx/main.c | 2 +- sys/src/9/omap/main.c | 2 +- sys/src/9/pc/main.c | 2 +- sys/src/9/pcboot/main.c | 2 +- sys/src/9/ppc/main.c | 2 +- sys/src/9/rb/main.c | 2 +- sys/src/9/teg2/main.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c index 3fcf05f202..69e9a37a28 100644 --- a/sys/src/9/bcm/main.c +++ b/sys/src/9/bcm/main.c @@ -487,7 +487,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver) /* diff --git a/sys/src/9/kw/main.c b/sys/src/9/kw/main.c index 3a060dc850..e5054fb352 100644 --- a/sys/src/9/kw/main.c +++ b/sys/src/9/kw/main.c @@ -713,7 +713,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver) /* diff --git a/sys/src/9/mtx/main.c b/sys/src/9/mtx/main.c index eebad4444f..e7e37e2dc5 100644 --- a/sys/src/9/mtx/main.c +++ b/sys/src/9/mtx/main.c @@ -350,7 +350,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver){ /* diff --git a/sys/src/9/omap/main.c b/sys/src/9/omap/main.c index c11b0f238a..9a2fda56cf 100644 --- a/sys/src/9/omap/main.c +++ b/sys/src/9/omap/main.c @@ -683,7 +683,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver) /* diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 2a59eb6619..34786f62b8 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -489,7 +489,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver){ /* diff --git a/sys/src/9/pcboot/main.c b/sys/src/9/pcboot/main.c index 356371b96e..5f3cae9666 100644 --- a/sys/src/9/pcboot/main.c +++ b/sys/src/9/pcboot/main.c @@ -379,7 +379,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver){ /* diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c index 380d6fd6fd..dc350bb904 100644 --- a/sys/src/9/ppc/main.c +++ b/sys/src/9/ppc/main.c @@ -396,7 +396,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver){ /* diff --git a/sys/src/9/rb/main.c b/sys/src/9/rb/main.c index 8ad5a20b3b..60f7f826bc 100644 --- a/sys/src/9/rb/main.c +++ b/sys/src/9/rb/main.c @@ -605,7 +605,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; /* diff --git a/sys/src/9/teg2/main.c b/sys/src/9/teg2/main.c index ac1c79f4bc..d75cb274c8 100644 --- a/sys/src/9/teg2/main.c +++ b/sys/src/9/teg2/main.c @@ -911,7 +911,7 @@ confinit(void) + conf.nproc*sizeof(Proc) + conf.nimage*sizeof(Image) + conf.nswap - + conf.nswppo*sizeof(Page); + + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; if(!cpuserver) /* From dbbe43ed1a5b13b495ce73e626aeb71449794eab Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 20:03:46 +0000 Subject: [PATCH 017/402] sys/src/9/port: fix buffer flow in kbdputc (thanks Yoann Padioleau) --- sys/src/9/port/devcons.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/devcons.c b/sys/src/9/port/devcons.c index 884d2e33e8..a7b27423aa 100644 --- a/sys/src/9/port/devcons.c +++ b/sys/src/9/port/devcons.c @@ -523,7 +523,7 @@ int kbdputc(Queue*, int ch) { int i, n; - char buf[3]; + char buf[UTFmax]; Rune r; char *next; From 57f3136685c5d3788ba96dd9692d58d04bf6e63f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 16:09:09 +0000 Subject: [PATCH 018/402] sys/src/9/ip: cleanup spaces in indentation (thanks Geoff Collyer) --- sys/src/9/ip/arp.c | 10 +++++----- sys/src/9/ip/devip.c | 12 ++++++------ sys/src/9/ip/esp.c | 2 +- sys/src/9/ip/ethermedium.c | 18 +++++++++--------- sys/src/9/ip/icmp.c | 8 ++++---- sys/src/9/ip/icmp6.c | 6 +++--- sys/src/9/ip/ip.c | 2 +- sys/src/9/ip/ip.h | 30 +++++++++++++++--------------- sys/src/9/ip/ipifc.c | 4 ++-- sys/src/9/ip/ipmux.c | 2 +- sys/src/9/ip/ipv6.c | 2 +- sys/src/9/ip/rudp.c | 2 +- sys/src/9/ip/tcp.c | 14 +++++++------- sys/src/9/ip/udp.c | 2 +- 14 files changed, 57 insertions(+), 57 deletions(-) diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index 8def094621..aa2b55c74f 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -40,16 +40,16 @@ struct Arp Arpent *rxmt; Proc *rxmitp; /* neib sol re-transmit proc */ Rendez rxmtq; - Block *dropf, *dropl; + Block *dropf, *dropl; }; char *Ebadarp = "bad arp"; #define haship(s) ((s)[IPaddrlen-1]%NHASH) -extern int ReTransTimer = RETRANS_TIMER; +extern int ReTransTimer = RETRANS_TIMER; -static void rxmitproc(void *v); +static void rxmitproc(void *v); void arpinit(Fs *f) @@ -578,11 +578,11 @@ rxmitsols(Arp *arp) a = arp->rxmt; if(a==nil){ nrxt = 0; - goto dodrops; /* return nrxt; */ + goto dodrops; /* return nrxt; */ } nrxt = a->rtime - NOW; if(nrxt > 3*ReTransTimer/4) - goto dodrops; /* return nrxt; */ + goto dodrops; /* return nrxt; */ for(; a; a = a->nextrxt){ ifc = a->ifc; diff --git a/sys/src/9/ip/devip.c b/sys/src/9/ip/devip.c index 888c9d9116..823cacc6d8 100644 --- a/sys/src/9/ip/devip.c +++ b/sys/src/9/ip/devip.c @@ -44,10 +44,10 @@ enum Nfs= 128, }; -#define TYPE(x) ( ((ulong)(x).path) & Masktype ) -#define CONV(x) ( (((ulong)(x).path) >> Shiftconv) & Maskconv ) -#define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto ) -#define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<> Shiftconv) & Maskconv ) +#define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto ) +#define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<perm>>6)) != perm) { if(strcmp(ATTACHER(c), cv->owner) != 0) error(Eperm); - if((perm & cv->perm) != perm) + if((perm & cv->perm) != perm) error(Eperm); } @@ -453,7 +453,7 @@ ipopen(Chan* c, int omode) if((perm & (cv->perm>>6)) != perm) { if(strcmp(ATTACHER(c), cv->owner) != 0) error(Eperm); - if((perm & cv->perm) != perm) + if((perm & cv->perm) != perm) error(Eperm); } diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c index fb3ab23389..3f7d28e3da 100644 --- a/sys/src/9/ip/esp.c +++ b/sys/src/9/ip/esp.c @@ -145,7 +145,7 @@ struct Espcb struct Algorithm { - char *name; + char *name; int keylen; /* in bits */ void (*init)(Espcb*, char* name, uchar *key, unsigned keylen); }; diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index 18cf8942ae..cd767630eb 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -196,7 +196,7 @@ etherbind(Ipifc *ifc, int argc, char **argv) ifc->mbps = 100; /* - * open arp conversation + * open arp conversation */ snprint(addr, sizeof(addr), "%s!0x806", argv[2]); /* ETARP */ achan = chandial(addr, nil, nil, nil); @@ -308,7 +308,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) memmove(eh->s, ifc->mac, sizeof(eh->s)); memmove(eh->d, mac, sizeof(eh->d)); - switch(version){ + switch(version){ case V4: eh->t[0] = 0x08; eh->t[1] = 0x00; @@ -701,14 +701,14 @@ multicastea(uchar *ea, uchar *ip) ea[4] = ip[14]; ea[5] = ip[15]; break; - case V6: - ea[0] = 0x33; - ea[1] = 0x33; - ea[2] = ip[12]; + case V6: + ea[0] = 0x33; + ea[1] = 0x33; + ea[2] = ip[12]; ea[3] = ip[13]; - ea[4] = ip[14]; - ea[5] = ip[15]; - break; + ea[4] = ip[14]; + ea[5] = ip[15]; + break; } return x; } diff --git a/sys/src/9/ip/icmp.c b/sys/src/9/ip/icmp.c index 2ff9f8a58b..23dd6beb04 100644 --- a/sys/src/9/ip/icmp.c +++ b/sys/src/9/ip/icmp.c @@ -38,8 +38,8 @@ enum { /* Packet Types */ TimestampReply = 14, InfoRequest = 15, InfoReply = 16, - AddrMaskRequest = 17, - AddrMaskReply = 18, + AddrMaskRequest = 17, + AddrMaskReply = 18, Maxtype = 18, }; @@ -63,7 +63,7 @@ char *icmpnames[Maxtype+1] = [InfoRequest] "InfoRequest", [InfoReply] "InfoReply", [AddrMaskRequest] "AddrMaskRequest", -[AddrMaskReply ] "AddrMaskReply ", +[AddrMaskReply] "AddrMaskReply", }; enum { @@ -302,7 +302,7 @@ mkechoreply(Block *bp) q->vihl = IP_VER4; memmove(ip, q->src, sizeof(q->dst)); memmove(q->src, q->dst, sizeof(q->src)); - memmove(q->dst, ip, sizeof(q->dst)); + memmove(q->dst, ip, sizeof(q->dst)); q->type = EchoReply; memset(q->cksum, 0, sizeof(q->cksum)); hnputs(q->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE)); diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c index 4d4c7540c3..078058a5dc 100644 --- a/sys/src/9/ip/icmp6.c +++ b/sys/src/9/ip/icmp6.c @@ -191,7 +191,7 @@ set_cksum(Block *bp) { IPICMP *p = (IPICMP *)(bp->rp); - hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */ + hnputl(p->vcf, 0); /* borrow IP header as pseudoheader */ hnputs(p->ploadlen, blocklen(bp) - IP6HDR); p->proto = 0; p->ttl = ICMPv6; /* ttl gets set later */ @@ -339,9 +339,9 @@ mkechoreply6(Block *bp, Ipifc *ifc) /* * sends out an ICMPv6 neighbor solicitation - * suni == SRC_UNSPEC or SRC_UNI, + * suni == SRC_UNSPEC or SRC_UNI, * tuni == TARG_MULTI => multicast for address resolution, - * and tuni == TARG_UNI => neighbor reachability. + * and tuni == TARG_UNI => neighbor reachability. */ extern void icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac) diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 098e46f56c..14951238e2 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -63,7 +63,7 @@ ip_init_6(Fs *f) v6p->hp.rxmithost = 1000; /* v6 RETRANS_TIMER */ - v6p->cdrouter = -1; + v6p->cdrouter = -1; f->v6p = v6p; } diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 661ea76464..287f24b67b 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -23,8 +23,8 @@ typedef struct Arp Arp; typedef struct Route Route; typedef struct Routerparams Routerparams; -typedef struct Hostparams Hostparams; -typedef struct v6router v6router; +typedef struct Hostparams Hostparams; +typedef struct v6router v6router; typedef struct v6params v6params; #pragma incomplete Arp @@ -53,7 +53,7 @@ enum /* ip versions */ V4= 4, V6= 6, - IP_VER4= 0x40, + IP_VER4= 0x40, IP_VER6= 0x60, IP_HLEN4= 5, /* v4: Header length in words */ IP_DF= 0x4000, /* v4: Don't fragment */ @@ -106,20 +106,20 @@ struct Fragment4 { Block* blist; Fragment4* next; - ulong src; - ulong dst; + ulong src; + ulong dst; ushort id; - ulong age; + ulong age; }; struct Fragment6 { Block* blist; Fragment6* next; - uchar src[IPaddrlen]; - uchar dst[IPaddrlen]; + uchar src[IPaddrlen]; + uchar dst[IPaddrlen]; uint id; - ulong age; + ulong age; }; struct Ipfrag @@ -158,7 +158,7 @@ struct Ip4hdr uchar length[2]; /* packet length */ uchar id[2]; /* ip->identification */ uchar frag[2]; /* Fragment information */ - uchar ttl; /* Time to live */ + uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar cksum[2]; /* Header checksum */ uchar src[4]; /* IP source */ @@ -228,7 +228,7 @@ struct Medium int hsize; /* medium header size */ int mintu; /* default min mtu */ int maxtu; /* default max mtu */ - int maclen; /* mac address length */ + int maclen; /* mac address length */ void (*bind)(Ipifc*, int, char**); void (*unbind)(Ipifc*); void (*bwrite)(Ipifc *ifc, Block *b, int version, uchar *ip); @@ -269,8 +269,8 @@ struct Iplifc uchar tentative; /* =1 => v6 dup disc on, =0 => confirmed unique */ uchar onlink; /* =1 => onlink, =0 offlink. */ uchar autoflag; /* v6 autonomous flag */ - long validlt; /* v6 valid lifetime */ - long preflt; /* v6 preferred lifetime */ + long validlt; /* v6 valid lifetime */ + long preflt; /* v6 preferred lifetime */ long origint; /* time when addr was added */ Iplink *link; /* addresses linked to this lifc */ Iplifc *next; @@ -294,7 +294,7 @@ struct Iplink struct Routerparams { int mflag; /* flag: managed address configuration */ int oflag; /* flag: other stateful configuration */ - int maxraint; /* max. router adv interval (ms) */ + int maxraint; /* max. router adv interval (ms) */ int minraint; /* min. router adv interval (ms) */ int linkmtu; /* mtu options */ int reachtime; /* reachable time */ @@ -460,7 +460,7 @@ struct v6params Routerparams rp; /* v6 params, one copy per node now */ Hostparams hp; v6router v6rlist[3]; /* max 3 default routers, currently */ - int cdrouter; /* uses only v6rlist[cdrouter] if */ + int cdrouter; /* uses only v6rlist[cdrouter] if */ /* cdrouter >= 0. */ }; diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index 8bce90fe0f..f7f4df323d 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -1236,7 +1236,7 @@ findlocalip(Fs *f, uchar *local, uchar *remote) USED(atypel); qlock(f->ipifc); r = v6lookup(f, remote, nil); - version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6; + version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6; if(r != nil){ ifc = r->ifc; @@ -1481,7 +1481,7 @@ ipifcremmulti(Conv *c, uchar *ma, uchar *ia) multi = *l; if(multi == nil) - return; /* we don't have it open */ + return; /* we don't have it open */ *l = multi->next; diff --git a/sys/src/9/ip/ipmux.c b/sys/src/9/ip/ipmux.c index c2707fe58a..39292aaffb 100644 --- a/sys/src/9/ip/ipmux.c +++ b/sys/src/9/ip/ipmux.c @@ -56,7 +56,7 @@ char *ftname[] = { [Tproto] "proto", [Tdata] "data", -[Tiph] "iph", +[Tiph] "iph", [Tdst] "dst", [Tsrc] "src", [Tifc] "ifc", diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c index 8dca669103..2c9eb31125 100644 --- a/sys/src/9/ip/ipv6.c +++ b/sys/src/9/ip/ipv6.c @@ -10,7 +10,7 @@ enum { - IP6FHDR = 8, /* sizeof(Fraghdr6) */ + IP6FHDR = 8, /* sizeof(Fraghdr6) */ }; #define IPV6CLASS(hdr) (((hdr)->vcf[0]&0x0F)<<2 | ((hdr)->vcf[1]&0xF0)>>2) diff --git a/sys/src/9/ip/rudp.c b/sys/src/9/ip/rudp.c index 6d87d56f1b..816b85e53a 100644 --- a/sys/src/9/ip/rudp.c +++ b/sys/src/9/ip/rudp.c @@ -564,7 +564,7 @@ rudpiput(Proto *rudp, Ipifc *ifc, Block *bp) /* connection oriented rudp */ if(ipcmp(c->raddr, IPnoaddr) == 0){ /* save the src address in the conversation */ - ipmove(c->raddr, raddr); + ipmove(c->raddr, raddr); c->rport = rport; /* reply with the same ip address (if not broadcast) */ diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c index 629718aef1..8d4b40050f 100644 --- a/sys/src/9/ip/tcp.c +++ b/sys/src/9/ip/tcp.c @@ -27,7 +27,7 @@ enum TcptimerOFF = 0, TcptimerON = 1, TcptimerDONE = 2, - MAX_TIME = (1<<20), /* Forever */ + MAX_TIME = (1<<20), /* Forever */ TCP_ACK = 50, /* Timed ack sequence in ms */ MAXBACKMS = 9*60*1000, /* longest backoff time (ms) before hangup */ @@ -93,9 +93,9 @@ enum /* Must correspond to the enumeration above */ char *tcpstates[] = { - "Closed", "Listen", "Syn_sent", "Syn_received", - "Established", "Finwait1", "Finwait2", "Close_wait", - "Closing", "Last_ack", "Time_wait" + "Closed", "Listen", "Syn_sent", "Syn_received", + "Established", "Finwait1", "Finwait2", "Close_wait", + "Closing", "Last_ack", "Time_wait" }; typedef struct Tcptimer Tcptimer; @@ -383,7 +383,7 @@ typedef struct Tcppriv Tcppriv; struct Tcppriv { /* List of active timers */ - QLock tl; + QLock tl; Tcptimer *timers; /* hash table for matching conversations */ @@ -764,7 +764,7 @@ tcpackproc(void *a) if(loop++ > 10000) panic("tcpackproc1"); tp = t->next; - if(t->state == TcptimerON) { + if(t->state == TcptimerON) { t->count--; if(t->count == 0) { timerstate(priv, t, TcptimerDONE); @@ -1719,7 +1719,7 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version) src, segp->source, lp->raddr, lp->rport, dst, segp->dest, lp->laddr, lp->lport, version, lp->version - ); + ); if(lp->lport != segp->dest || lp->rport != segp->source || lp->version != version) continue; diff --git a/sys/src/9/ip/udp.c b/sys/src/9/ip/udp.c index 0f79b413fd..7dd03b6048 100644 --- a/sys/src/9/ip/udp.c +++ b/sys/src/9/ip/udp.c @@ -555,7 +555,7 @@ udpadvise(Proto *udp, Block *bp, char *msg) break; default: panic("udpadvise: version %d", version); - return; /* to avoid a warning */ + return; /* to avoid a warning */ } /* Look for a connection */ From 77f680673c9d62ad9b41701a16f6276ddea64934 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 16:00:32 +0000 Subject: [PATCH 019/402] sys/src/9/ip: rename m variables to medium (thanks Geoff Collyer) --- sys/src/9/ip/arp.c | 28 +++++------ sys/src/9/ip/ethermedium.c | 12 ++--- sys/src/9/ip/icmp6.c | 2 +- sys/src/9/ip/igmp.c | 8 ++-- sys/src/9/ip/ip.c | 10 ++-- sys/src/9/ip/ip.h | 2 +- sys/src/9/ip/ipifc.c | 98 +++++++++++++++++++------------------- sys/src/9/ip/ipv6.c | 8 ++-- sys/src/9/ip/tcp.c | 4 +- 9 files changed, 86 insertions(+), 86 deletions(-) diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index aa2b55c74f..9dcb52ebed 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -70,7 +70,6 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt) uint t; Block *next, *xp; Arpent *a, *e, *f, **l; - Medium *m = ifc->m; int empty; /* find oldest entry */ @@ -127,7 +126,7 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt) memmove(a->ip, ip, sizeof(a->ip)); a->utime = NOW; a->ctime = 0; - a->type = m; + a->type = ifc->medium; a->rtime = NOW + ReTransTimer; a->rxtsrem = MAX_MULTICAST_SOLICIT; @@ -208,7 +207,7 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac) { int hash; Arpent *a; - Medium *type = ifc->m; + Medium *type; uchar v6ip[IPaddrlen]; if(version == V4){ @@ -218,6 +217,7 @@ arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac) qlock(arp); hash = haship(ip); + type = ifc->medium; for(a = arp->hash[hash]; a; a = a->hash){ if(memcmp(ip, a->ip, sizeof(a->ip)) == 0) if(type == a->type) @@ -332,7 +332,7 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh) } ifc = r->ifc; - type = ifc->m; + type = ifc->medium; qlock(arp); for(a = arp->hash[haship(ip)]; a; a = a->hash){ @@ -373,8 +373,8 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh) nexterror(); } rlock(ifc); - if(ifc->m != nil) - ifc->m->bwrite(ifc, bp, version, ip); + if(ifc->medium != nil) + ifc->medium->bwrite(ifc, bp, version, ip); else freeb(bp); runlock(ifc); @@ -406,7 +406,7 @@ arpwrite(Fs *fs, char *s, int len) Arp *arp; Block *bp; Arpent *a, *fl, **l; - Medium *m; + Medium *type; char *f[4], buf[256]; uchar ip[IPaddrlen], mac[MAClen]; @@ -455,23 +455,23 @@ arpwrite(Fs *fs, char *s, int len) r = v6lookup(fs, ip, nil); if(r == nil) error("Destination unreachable"); - m = r->ifc->m; - n = parsemac(mac, f[2], m->maclen); + type = r->ifc->medium; + n = parsemac(mac, f[2], type->maclen); break; case 4: - m = ipfindmedium(f[1]); - if(m == nil) + type = ipfindmedium(f[1]); + if(type == nil) error(Ebadarp); if (parseip(ip, f[2]) == -1) error(Ebadip); - n = parsemac(mac, f[3], m->maclen); + n = parsemac(mac, f[3], type->maclen); break; } - if(m->ares == nil) + if(type->ares == nil) error(Ebadarp); - m->ares(fs, V6, ip, mac, n, 0); + type->ares(fs, V6, ip, mac, n, 0); } else if(strcmp(f[0], "del") == 0){ if(n != 2) error(Ebadarg); diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index cd767630eb..67abda0d92 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -280,7 +280,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) a = arpget(er->f->arp, bp, version, ifc, ip, mac); if(a){ /* check for broadcast or multicast */ - bp = multicastarp(er->f, a, ifc->m, mac); + bp = multicastarp(er->f, a, ifc->medium, mac); if(bp==nil){ switch(version){ case V4: @@ -297,7 +297,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) } /* make it a single block with space for the ether header */ - bp = padblock(bp, ifc->m->hsize); + bp = padblock(bp, ifc->medium->hsize); if(bp->next) bp = concatblock(bp); if(BLEN(bp) < ifc->mintu) @@ -354,7 +354,7 @@ etherread4(void *a) nexterror(); } ifc->in++; - bp->rp += ifc->m->hsize; + bp->rp += ifc->medium->hsize; if(ifc->lifc == nil) freeb(bp); else @@ -393,7 +393,7 @@ etherread6(void *a) nexterror(); } ifc->in++; - bp->rp += ifc->m->hsize; + bp->rp += ifc->medium->hsize; if(ifc->lifc == nil) freeb(bp); else @@ -553,8 +553,8 @@ sendgarp(Ipifc *ifc, uchar *ip) return; n = sizeof(Etherarp); - if(n < ifc->m->mintu) - n = ifc->m->mintu; + if(n < ifc->medium->mintu) + n = ifc->medium->mintu; bp = allocb(n); memset(bp->rp, 0, n); e = (Etherarp*)bp->rp; diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c index 078058a5dc..af85e3f2c0 100644 --- a/sys/src/9/ip/icmp6.c +++ b/sys/src/9/ip/icmp6.c @@ -534,7 +534,7 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp) memmove(np->dst, p->src, IPaddrlen); np->type = PacketTooBigV6; np->code = 0; - hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize); + hnputl(np->icmpid, ifc->maxtu - ifc->medium->hsize); memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ); set_cksum(nbp); np->ttl = HOP_LIMIT; diff --git a/sys/src/9/ip/igmp.c b/sys/src/9/ip/igmp.c index ee5241ff4f..2299b46e48 100644 --- a/sys/src/9/ip/igmp.c +++ b/sys/src/9/ip/igmp.c @@ -161,7 +161,7 @@ igmpproc(void *a) if(mp){ /* do a single report and try again */ hnputl(ip, mp->addr); - igmpsendreport(rp->m, ip); + igmpsendreport(rp->medium, ip); free(mp); continue; } @@ -209,7 +209,7 @@ igmpiput(Medium *m, Ipifc *, Block *bp) */ stats.inqueries++; for(rp = igmpalloc.reports; rp; rp = rp->next) - if(rp->m == m) + if(rp->medium == m) break; if(rp != nil) break; /* already reporting */ @@ -222,7 +222,7 @@ igmpiput(Medium *m, Ipifc *, Block *bp) if(rp == nil) break; - rp->m = m; + rp->medium = m; rp->multi = mp; rp->ticks = 0; for(; mp; mp = mp->next) @@ -240,7 +240,7 @@ igmpiput(Medium *m, Ipifc *, Block *bp) stats.inreports++; lrp = &igmpalloc.reports; for(rp = *lrp; rp; rp = *lrp){ - if(rp->m == m) + if(rp->medium == m) break; lrp = &rp->next; } diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 14951238e2..9bf520a58f 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -189,14 +189,14 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) runlock(ifc); nexterror(); } - if(ifc->m == nil) + if(ifc->medium == nil) goto raise; /* If we dont need to fragment just send it */ if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu) - medialen = c->maxfragsize - ifc->m->hsize; + medialen = c->maxfragsize - ifc->medium->hsize; else - medialen = ifc->maxtu - ifc->m->hsize; + medialen = ifc->maxtu - ifc->medium->hsize; if(len <= medialen) { if(!gating) hnputs(eh->id, incref(&ip->id4)); @@ -209,7 +209,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) eh->cksum[1] = 0; hnputs(eh->cksum, ipcsum(&eh->vihl)); assert(bp->next == nil); - ifc->m->bwrite(ifc, bp, V4, gate); + ifc->medium->bwrite(ifc, bp, V4, gate); runlock(ifc); poperror(); return 0; @@ -294,7 +294,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) feh->cksum[0] = 0; feh->cksum[1] = 0; hnputs(feh->cksum, ipcsum(&feh->vihl)); - ifc->m->bwrite(ifc, nb, V4, gate); + ifc->medium->bwrite(ifc, nb, V4, gate); ip->stats[FragCreates]++; } ip->stats[FragOKs]++; diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 287f24b67b..ad3b7582eb 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -313,7 +313,7 @@ struct Ipifc Conv *conv; /* link to its conversation structure */ char dev[64]; /* device we're attached to */ - Medium *m; /* Media pointer */ + Medium *medium; /* Media pointer */ int maxtu; /* Maximum transfer unit */ int mintu; /* Minumum tranfer unit */ int mbps; /* megabits per second */ diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index f7f4df323d..812bc9d48c 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -104,7 +104,7 @@ static char* ipifcbind(Conv *c, char **argv, int argc) { Ipifc *ifc; - Medium *m; + Medium *medium; if(argc < 2) return Ebadarg; @@ -112,12 +112,12 @@ ipifcbind(Conv *c, char **argv, int argc) ifc = (Ipifc*)c->ptcl; /* bind the device to the interface */ - m = ipfindmedium(argv[1]); - if(m == nil) + medium = ipfindmedium(argv[1]); + if(medium == nil) return "unknown interface type"; wlock(ifc); - if(ifc->m != nil){ + if(ifc->medium != nil){ wunlock(ifc); return "interface already bound"; } @@ -127,20 +127,20 @@ ipifcbind(Conv *c, char **argv, int argc) } /* do medium specific binding */ - (*m->bind)(ifc, argc, argv); + (*medium->bind)(ifc, argc, argv); /* set the bound device name */ if(argc > 2) strncpy(ifc->dev, argv[2], sizeof(ifc->dev)); else - snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x); + snprint(ifc->dev, sizeof ifc->dev, "%s%d", medium->name, c->x); ifc->dev[sizeof(ifc->dev)-1] = 0; /* set up parameters */ - ifc->m = m; - ifc->mintu = ifc->m->mintu; - ifc->maxtu = ifc->m->maxtu; - if(ifc->m->unbindonclose == 0) + ifc->medium = medium; + ifc->mintu = ifc->medium->mintu; + ifc->maxtu = ifc->medium->maxtu; + if(ifc->medium->unbindonclose == 0) ifc->conv->inuse++; ifc->rp.mflag = 0; /* default not managed */ ifc->rp.oflag = 0; @@ -182,7 +182,7 @@ ipifcunbind(Ipifc *ifc) wlock(ifc); /* dissociate routes */ - if(ifc->m != nil && ifc->m->unbindonclose == 0) + if(ifc->medium != nil && ifc->medium->unbindonclose == 0) ifc->conv->inuse--; ifc->ifcid++; @@ -198,8 +198,8 @@ ipifcunbind(Ipifc *ifc) } /* disassociate device */ - if(ifc->m && ifc->m->unbind) - (*ifc->m->unbind)(ifc); + if(ifc->medium && ifc->medium->unbind) + (*ifc->medium->unbind)(ifc); memset(ifc->dev, 0, sizeof(ifc->dev)); ifc->arg = nil; ifc->reassemble = 0; @@ -209,7 +209,7 @@ ipifcunbind(Ipifc *ifc) qclose(ifc->conv->wq); qclose(ifc->conv->sq); - ifc->m = nil; + ifc->medium = nil; wunlock(ifc); poperror(); return nil; @@ -274,7 +274,7 @@ ipifcinuse(Conv *c) Ipifc *ifc; ifc = (Ipifc*)c->ptcl; - return ifc->m != nil; + return ifc->medium != nil; } /* @@ -300,10 +300,10 @@ ipifckick(void *x) runlock(ifc); nexterror(); } - if(ifc->m == nil || ifc->m->pktin == nil) + if(ifc->medium == nil || ifc->medium->pktin == nil) freeb(bp); else - (*ifc->m->pktin)(c->p->f, ifc, bp); + (*ifc->medium->pktin)(c->p->f, ifc, bp); runlock(ifc); poperror(); } @@ -322,7 +322,7 @@ ipifccreate(Conv *c) ifc = (Ipifc*)c->ptcl; ifc->conv = c; ifc->unbinding = 0; - ifc->m = nil; + ifc->medium = nil; ifc->reassemble = 0; } @@ -334,11 +334,11 @@ static void ipifcclose(Conv *c) { Ipifc *ifc; - Medium *m; + Medium *medium; ifc = (Ipifc*)c->ptcl; - m = ifc->m; - if(m && m->unbindonclose) + medium = ifc->medium; + if(medium != nil && medium->unbindonclose) ipifcunbind(ifc); } @@ -350,10 +350,10 @@ ipifcsetmtu(Ipifc *ifc, char **argv, int argc) { int mtu; - if(argc < 2 || ifc->m == nil) + if(argc < 2 || ifc->medium == nil) return Ebadarg; mtu = strtoul(argv[1], 0, 0); - if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu) + if(mtu < ifc->medium->mintu || mtu > ifc->medium->maxtu) return Ebadarg; ifc->maxtu = mtu; return nil; @@ -371,7 +371,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) Iplifc *lifc, **l; Fs *f; - if(ifc->m == nil) + if(ifc->medium == nil) return "ipifc not yet bound to device"; f = ifc->conv->p->f; @@ -387,7 +387,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); - if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu) + if(mtu >= ifc->medium->mintu && mtu <= ifc->medium->maxtu) ifc->maxtu = mtu; /* fall through */ case 4: @@ -525,8 +525,8 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) } /* register the address on this network for address resolution */ - if(isv4(ip) && ifc->m->areg != nil) - (*ifc->m->areg)(ifc, ip); + if(isv4(ip) && ifc->medium->areg != nil) + (*ifc->medium->areg)(ifc, ip); out: wunlock(ifc); @@ -628,7 +628,7 @@ ipifcrem(Ipifc *ifc, char **argv, int argc) void ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type) { - Medium *m; + Medium *medium; Conv **cp, **e; Ipifc *ifc; @@ -636,9 +636,9 @@ ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type) for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; - m = ifc->m; - if(m && m->addroute) - m->addroute(ifc, vers, addr, mask, gate, type); + medium = ifc->medium; + if(medium != nil && medium->addroute != nil) + medium->addroute(ifc, vers, addr, mask, gate, type); } } } @@ -646,7 +646,7 @@ ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type) void ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask) { - Medium *m; + Medium *medium; Conv **cp, **e; Ipifc *ifc; @@ -654,9 +654,9 @@ ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask) for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; - m = ifc->m; - if(m && m->remroute) - m->remroute(ifc, vers, addr, mask); + medium = ifc->medium; + if(medium != nil && medium->remroute != nil) + medium->remroute(ifc, vers, addr, mask); } } } @@ -674,7 +674,7 @@ ipifcconnect(Conv* c, char **argv, int argc) ifc = (Ipifc*)c->ptcl; - if(ifc->m == nil) + if(ifc->medium == nil) return "ipifc not yet bound to device"; if(waserror()){ @@ -881,8 +881,8 @@ addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type) else v6addroute(f, tifc, a, IPallbits, a, type); - if((type & Rmulti) && ifc->m->addmulti != nil) - (*ifc->m->addmulti)(ifc, a, lifc->local); + if((type & Rmulti) && ifc->medium->addmulti != nil) + (*ifc->medium->addmulti)(ifc, a, lifc->local); } else lp->ref++; @@ -993,8 +993,8 @@ remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a) if(--(link->ref) != 0) goto out; - if((p->type & Rmulti) && ifc->m->remmulti != nil) - (*ifc->m->remmulti)(ifc, a, lifc->local); + if((p->type & Rmulti) && ifc->medium->remmulti != nil) + (*ifc->medium->remmulti)(ifc, a, lifc->local); /* ref == 0, remove from both chains and free the link */ *l_lifc = link->lifclink; @@ -1528,7 +1528,7 @@ ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) Conv **cp, **e; Ipifc *nifc; Iplifc *lifc; - Medium *m; + Medium *medium; uchar net[IPaddrlen]; /* register the address on any network that will proxy for us */ @@ -1539,8 +1539,8 @@ ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) continue; rlock(nifc); - m = nifc->m; - if(m == nil || m->addmulti == nil) { + medium = nifc->medium; + if(medium == nil || medium->addmulti == nil) { runlock(nifc); continue; } @@ -1551,7 +1551,7 @@ ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) ipv62smcast(net, ip); addselfcache(f, nifc, lifc, net, Rmulti); arpenter(f, V6, ip, nifc->mac, 6, 0); - // (*m->addmulti)(nifc, net, ip); + // (*medium->addmulti)(nifc, net, ip); break; } } @@ -1563,15 +1563,15 @@ ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) continue; rlock(nifc); - m = nifc->m; - if(m == nil || m->areg == nil){ + medium = nifc->medium; + if(medium == nil || medium->areg == nil){ runlock(nifc); continue; } for(lifc = nifc->lifc; lifc; lifc = lifc->next){ maskip(ip, lifc->mask, net); if(ipcmp(net, lifc->remote) == 0){ - (*m->areg)(nifc, ip); + (*medium->areg)(nifc, ip); /* e.g., send garp */ break; } } @@ -1656,9 +1656,9 @@ ipifcadd6(Ipifc *ifc, char**argv, int argc) lifc->origint = origint; /* issue "add" ctl msg for v6 link-local addr and prefix len */ - if(!ifc->m->pref2addr) + if(!ifc->medium->pref2addr) return "no pref2addr on interface"; - ifc->m->pref2addr(prefix, ifc->mac); /* mac → v6 link-local addr */ + ifc->medium->pref2addr(prefix, ifc->mac); /* mac → v6 link-local addr */ snprint(addr, sizeof addr, "%I", prefix); snprint(preflen, sizeof preflen, "/%d", plen); params[0] = "add"; diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c index 2c9eb31125..f0a8d21443 100644 --- a/sys/src/9/ip/ipv6.c +++ b/sys/src/9/ip/ipv6.c @@ -111,14 +111,14 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) nexterror(); } - if(ifc->m == nil) + if(ifc->medium == nil) goto raise; /* If we dont need to fragment just send it */ - medialen = ifc->maxtu - ifc->m->hsize; + medialen = ifc->maxtu - ifc->medium->hsize; if(len <= medialen) { hnputs(eh->ploadlen, len - IP6HDR); - ifc->m->bwrite(ifc, bp, V6, gate); + ifc->medium->bwrite(ifc, bp, V6, gate); runlock(ifc); poperror(); return 0; @@ -209,7 +209,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) xp = xp->next; } - ifc->m->bwrite(ifc, nb, V6, gate); + ifc->medium->bwrite(ifc, nb, V6, gate); ip->stats[FragCreates]++; } ip->stats[FragOKs]++; diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c index 8d4b40050f..eb88a719a2 100644 --- a/sys/src/9/ip/tcp.c +++ b/sys/src/9/ip/tcp.c @@ -861,12 +861,12 @@ tcpmtu(Proto *tcp, uchar *addr, int version, uint *scale) case V4: mtu = DEF_MSS; if(ifc != nil) - mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE); + mtu = ifc->maxtu - ifc->medium->hsize - (TCP4_PKT + TCP4_HDRSIZE); break; case V6: mtu = DEF_MSS6; if(ifc != nil) - mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE); + mtu = ifc->maxtu - ifc->medium->hsize - (TCP6_PKT + TCP6_HDRSIZE); break; } /* From 19a55dbe04e764c034e211776752034436e91726 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 7 Jun 2021 16:44:42 +0000 Subject: [PATCH 020/402] sys/src/9/ip: use named constants (thanks Geoff Collyer) --- sys/src/9/ip/ethermedium.c | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index 67abda0d92..f75cbf6b39 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -12,8 +12,8 @@ typedef struct Etherhdr Etherhdr; struct Etherhdr { - uchar d[6]; - uchar s[6]; + uchar d[Eaddrlen]; + uchar s[Eaddrlen]; uchar t[2]; }; @@ -44,10 +44,10 @@ static void etherpref2addr(uchar *pref, uchar *ea); Medium ethermedium = { .name= "ether", -.hsize= 14, -.mintu= 60, -.maxtu= 1514, -.maclen= 6, +.hsize= ETHERHDRSIZE, +.mintu= ETHERMINTU, +.maxtu= ETHERMAXTU, +.maclen= Eaddrlen, .bind= etherbind, .unbind= etherunbind, .bwrite= etherbwrite, @@ -61,10 +61,10 @@ Medium ethermedium = Medium gbemedium = { .name= "gbe", -.hsize= 14, -.mintu= 60, +.hsize= ETHERHDRSIZE, +.mintu= ETHERMINTU, .maxtu= 9014, -.maclen= 6, +.maclen= Eaddrlen, .bind= etherbind, .unbind= etherunbind, .bwrite= etherbwrite, @@ -101,18 +101,18 @@ enum typedef struct Etherarp Etherarp; struct Etherarp { - uchar d[6]; - uchar s[6]; + uchar d[Eaddrlen]; + uchar s[Eaddrlen]; uchar type[2]; uchar hrd[2]; uchar pro[2]; uchar hln; uchar pln; uchar op[2]; - uchar sha[6]; - uchar spa[4]; - uchar tha[6]; - uchar tpa[4]; + uchar sha[Eaddrlen]; + uchar spa[IPv4addrlen]; + uchar tha[Eaddrlen]; + uchar tpa[IPv4addrlen]; }; static char *nbmsg = "nonblocking"; @@ -273,7 +273,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) { Etherhdr *eh; Arpent *a; - uchar mac[6]; + uchar mac[Eaddrlen]; Etherrock *er = ifc->arg; /* get mac address of destination */ @@ -310,13 +310,13 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) switch(version){ case V4: - eh->t[0] = 0x08; - eh->t[1] = 0x00; + eh->t[0] = ETIP4>>8; + eh->t[1] = ETIP4; devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0); break; case V6: - eh->t[0] = 0x86; - eh->t[1] = 0xDD; + eh->t[0] = ETIP6>>8; + eh->t[1] = ETIP6; devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0); break; default: @@ -406,7 +406,7 @@ etherread6(void *a) static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *) { - uchar mac[6]; + uchar mac[Eaddrlen]; char buf[64]; Etherrock *er = ifc->arg; int version; @@ -428,7 +428,7 @@ etheraddmulti(Ipifc *ifc, uchar *a, uchar *) static void etherremmulti(Ipifc *ifc, uchar *a, uchar *) { - uchar mac[6]; + uchar mac[Eaddrlen]; char buf[64]; Etherrock *er = ifc->arg; int version; From ecddda76e278323645debc5e01ebeec00b580336 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 16:00:32 +0000 Subject: [PATCH 021/402] sys/src/9/ip: add del1route function (thanks Geoff Collyer) --- sys/src/9/ip/iproute.c | 77 +++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/sys/src/9/ip/iproute.c b/sys/src/9/ip/iproute.c index 9bc2c2a1b2..0f415a2cb2 100644 --- a/sys/src/9/ip/iproute.c +++ b/sys/src/9/ip/iproute.c @@ -396,10 +396,36 @@ looknode(Route **cur, Route *r) } } +static void +del1route(Fs *f, Route **root, Route *rtp, int h, int dolock) +{ + Route **r, *p; + + if(dolock) + wlock(&routelock); + r = looknode(&root[h], rtp); + if(r) { + p = *r; + if(--(p->ref) == 0){ + *r = 0; + addqueue(&f->queue, p->left); + addqueue(&f->queue, p->mid); + addqueue(&f->queue, p->right); + freeroute(p); + while(p = f->queue) { + f->queue = p->mid; + walkadd(f, &root[h], p->left); + freeroute(p); + } + } + } + if(dolock) + wunlock(&routelock); +} + void v4delroute(Fs *f, uchar *a, uchar *mask, int dolock) { - Route **r, *p; Route rt; int h, eh; ulong m; @@ -410,28 +436,8 @@ v4delroute(Fs *f, uchar *a, uchar *mask, int dolock) rt.type = Rv4; eh = V4H(rt.v4.endaddress); - for(h=V4H(rt.v4.address); h<=eh; h++) { - if(dolock) - wlock(&routelock); - r = looknode(&f->v4root[h], &rt); - if(r) { - p = *r; - if(--(p->ref) == 0){ - *r = 0; - addqueue(&f->queue, p->left); - addqueue(&f->queue, p->mid); - addqueue(&f->queue, p->right); - freeroute(p); - while(p = f->queue) { - f->queue = p->mid; - walkadd(f, &f->v4root[h], p->left); - freeroute(p); - } - } - } - if(dolock) - wunlock(&routelock); - } + for(h=V4H(rt.v4.address); h<=eh; h++) + del1route(f, f->v4root, &rt, h, dolock); v4routegeneration++; ipifcremroute(f, Rv4, a, mask); @@ -440,7 +446,6 @@ v4delroute(Fs *f, uchar *a, uchar *mask, int dolock) void v6delroute(Fs *f, uchar *a, uchar *mask, int dolock) { - Route **r, *p; Route rt; int h, eh; ulong x, y; @@ -454,28 +459,8 @@ v6delroute(Fs *f, uchar *a, uchar *mask, int dolock) rt.type = 0; eh = V6H(rt.v6.endaddress); - for(h=V6H(rt.v6.address); h<=eh; h++) { - if(dolock) - wlock(&routelock); - r = looknode(&f->v6root[h], &rt); - if(r) { - p = *r; - if(--(p->ref) == 0){ - *r = 0; - addqueue(&f->queue, p->left); - addqueue(&f->queue, p->mid); - addqueue(&f->queue, p->right); - freeroute(p); - while(p = f->queue) { - f->queue = p->mid; - walkadd(f, &f->v6root[h], p->left); - freeroute(p); - } - } - } - if(dolock) - wunlock(&routelock); - } + for(h=V6H(rt.v6.address); h<=eh; h++) + del1route(f, f->v6root, &rt, h, dolock); v6routegeneration++; ipifcremroute(f, 0, a, mask); From f54ff42efcdf109856e01bcfeaa334b1a417e326 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 20:03:27 +0000 Subject: [PATCH 022/402] sys/src/9/ip: fix number of entries in iphash (thanks Yoann Padioleau) --- sys/src/9/ip/ip.h | 1 - sys/src/9/ip/ipaux.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index ad3b7582eb..b605c0d459 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -37,7 +37,6 @@ enum { Addrlen= 64, Maxproto= 20, - Nhash= 64, Maxincall= 64, /* max. conn.s in listen q not accepted yet */ Nchans= 1024, MAClen= 16, /* longest mac address */ diff --git a/sys/src/9/ip/ipaux.c b/sys/src/9/ip/ipaux.c index 75a4fd4f2e..fd253dafef 100644 --- a/sys/src/9/ip/ipaux.c +++ b/sys/src/9/ip/ipaux.c @@ -238,7 +238,7 @@ parsemac(uchar *to, char *from, int len) ulong iphash(uchar *sa, ushort sp, uchar *da, ushort dp) { - return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash; + return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nipht; } void From 6e3bb7d700870b0906736c15b4ed2f6fabba167e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 21 Oct 2020 09:20:47 +0000 Subject: [PATCH 023/402] sys/src/9/ip: implement direct attached routes (thanks Kyohei Kadota) --- sys/src/9/ip/ip.c | 7 ++++++- sys/src/9/ip/iproute.c | 19 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 9bf520a58f..dfb1313746 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -129,6 +129,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) Route *r, *sr; IP *ip; int rv = 0; + uchar v4dst[IPv4addrlen]; ip = f->ip; @@ -169,7 +170,11 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) gate = eh->dst; else if(r->type & (Rbcast|Rmulti)) { - gate = eh->dst; + if(nhgetl(r->v4.gate) == 0){ + hnputl(v4dst, r->v4.address); + gate = v4dst; + }else + gate = eh->dst; sr = v4lookup(f, eh->src, nil); if(sr != nil && (sr->type & Runi)) ifc = sr->ifc; diff --git a/sys/src/9/ip/iproute.c b/sys/src/9/ip/iproute.c index 0f415a2cb2..6055374a80 100644 --- a/sys/src/9/ip/iproute.c +++ b/sys/src/9/ip/iproute.c @@ -478,6 +478,7 @@ v4lookup(Fs *f, uchar *a, Conv *c) return c->r; la = nhgetl(a); +again: q = nil; for(p=f->v4root[V4H(la)]; p;) if(la >= p->v4.address) { @@ -496,8 +497,14 @@ v4lookup(Fs *f, uchar *a, Conv *c) } else v4tov6(gate, q->v4.gate); ifc = findipifc(f, gate, q->type); - if(ifc == nil) + if(ifc == nil){ + /* find a direct attached route */ + if(q->v4.address == 0 && q->v4.endaddress == ~0){ + la = nhgetl(q->v4.gate); + goto again; + } return nil; + } q->ifc = ifc; q->ifcid = ifc->ifcid; } @@ -802,6 +809,7 @@ routewrite(Fs *f, Chan *c, char *p, int n) uchar gate[IPaddrlen]; IPaux *a, *na; Route *q; + uchar type; cb = parsecmd(p, n); if(waserror()){ @@ -845,9 +853,12 @@ routewrite(Fs *f, Chan *c, char *p, int n) a = c->aux; tag = a->tag; } - if(memcmp(addr, v4prefix, IPv4off) == 0) - v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); - else + if(memcmp(addr, v4prefix, IPv4off) == 0){ + type = 0; + if(ipcmp(mask, IPallbits) == 0) + type = Rbcast; + v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, type); + }else v6addroute(f, tag, addr, mask, gate, 0); } else if(strcmp(cb->f[0], "tag") == 0) { if(cb->nf < 2) From 6dc43b7fe64e57881c223730c8dede01b876f3ac Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 23 Aug 2017 05:30:12 +0000 Subject: [PATCH 024/402] sys/src/9: use MACHP(m->machno) instead of m on 386 (thanks Geoff Collyer) --- sys/src/9/pc/mmu.c | 21 ++++++++++++--------- sys/src/9/port/proc.c | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index 8a7da9cc4c..ee5a22076f 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -671,18 +671,21 @@ vunmap(void *v, int size) if(p != up) p->newtlb = 1; } - for(i=0; iflushmmu = 1; - } + /* + * since the 386 is short of registers, m always contains the constant + * MACHADDR, not MACHP(m->machno); see ../pc/dat.h. so we can't just + * compare addresses with m. + */ + for(i=0; imachno) + MACHP(i)->flushmmu = 1; flushmmu(); - for(i=0; imachno) { + nm = MACHP(i); while((active.machs&(1<machno)) && nm->flushmmu) ; - } + } } /* diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index b3f5195559..8acf65c902 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -419,7 +419,12 @@ ready(Proc *p) return; } - if(up != p && (p->wired == nil || p->wired == m)) + /* + * since the 386 is short of registers, m always contains the constant + * MACHADDR, not MACHP(m->machno); see ../pc/dat.h. so we can't just + * compare addresses with m. + */ + if(up != p && (p->wired == nil || p->wired == MACHP(m->machno))) m->readied = p; /* group scheduling */ updatecpu(p); @@ -504,8 +509,13 @@ runproc(void) start = perfticks(); /* cooperative scheduling until the clock ticks */ + /* + * since the 386 is short of registers, m always contains the constant + * MACHADDR, not MACHP(m->machno); see ../pc/dat.h. so we can't just + * compare addresses with m. + */ if((p=m->readied) && p->mach==0 && p->state==Ready - && (p->wired == nil || p->wired == m) + && (p->wired == nil || p->wired == MACHP(m->machno)) && runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){ skipscheds++; rq = &runq[p->priority]; From 5732203f6314029a111e50bf67f4318ae51e5ca6 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Aug 2017 08:31:10 +0000 Subject: [PATCH 025/402] sys/src/9/port: implement scsilbacount function in sdscsi (thanks Geoff Collyer) --- sys/src/9/port/sd.h | 1 + sys/src/9/port/sdscsi.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index 51e0eabd8e..0acec6d039 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -178,3 +178,4 @@ extern int scsiverify(SDunit*); extern int scsionline(SDunit*); extern long scsibio(SDunit*, int, int, void*, long, uvlong); extern SDev* scsiid(SDev*, SDifc*); +extern void scsilbacount(uchar *, int, uvlong*, ulong*); diff --git a/sys/src/9/port/sdscsi.c b/sys/src/9/port/sdscsi.c index 28807fad25..1ee5156cd8 100644 --- a/sys/src/9/port/sdscsi.c +++ b/sys/src/9/port/sdscsi.c @@ -303,6 +303,21 @@ scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen) return status; } +/* extract lba and count from scsi command block cmd of clen bytes */ +void +scsilbacount(uchar *cmd, int clen, uvlong *lbap, ulong *countp) +{ + if (clen == 16) { + *lbap = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32 | + cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9]; + *countp = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13]; + } else if (clen == 10) { + *lbap = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; + *countp = cmd[7]<<8 | cmd[8]; + } else + panic("scsilbacount: command len %d unexpected", clen); +} + static void scsifmt10(SDreq *r, int write, int lun, ulong nb, uvlong bno) { From 1809a4d61d0736714c2d47ae4f5de8b9529435dc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Aug 2017 09:27:59 +0000 Subject: [PATCH 026/402] sys/src/9/port: use scsilbacount in sdaoe (thanks Geoff Collyer) --- sys/src/9/port/sdaoe.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sys/src/9/port/sdaoe.c b/sys/src/9/port/sdaoe.c index 6bd7916dc5..a0138bce70 100755 --- a/sys/src/9/port/sdaoe.c +++ b/sys/src/9/port/sdaoe.c @@ -431,7 +431,8 @@ aoeonline(SDunit *u) static int aoerio(SDreq *r) { - int i, count; + int i; + ulong count; uvlong lba; char *name; uchar *cmd; @@ -479,16 +480,11 @@ aoerio(SDreq *r) return SDok; if(r->clen == 16){ + /* ata commands only go to 48-bit lba */ if(cmd[2] || cmd[3]) return sdsetsense(r, SDcheck, 3, 0xc, 2); - lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32; - lba |= cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9]; - count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13]; - }else{ - lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; - count = cmd[7]<<8 | cmd[8]; } - + scsilbacount(cmd, r->clen, &lba, &count); count *= Aoesectsz; if(r->dlen < count) From a1525e067714eb47123ea3f66a163e42977cc976 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Aug 2017 09:26:54 +0000 Subject: [PATCH 027/402] sys/src/9/pc: use scsilbacount in sdata (thanks Geoff Collyer) --- sys/src/9/pc/sdata.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sys/src/9/pc/sdata.c b/sys/src/9/pc/sdata.c index de1006943a..a71c72bfba 100644 --- a/sys/src/9/pc/sdata.c +++ b/sys/src/9/pc/sdata.c @@ -1496,8 +1496,10 @@ atagenio(Drive* drive, uchar* cmd, int clen) { uchar *p; Ctlr *ctlr; - vlong lba, len; - int count, maxio; + int maxio; + ulong count; + vlong len; + uvlong lba; /* * Map SCSI commands into ATA commands for discs. @@ -1603,17 +1605,11 @@ atagenio(Drive* drive, uchar* cmd, int clen) } ctlr = drive->ctlr; - if(clen == 16){ + if(clen == 16) /* ata commands only go to 48-bit lba */ if(cmd[2] || cmd[3]) return atasetsense(drive, SDcheck, 3, 0xc, 2); - lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32; - lba |= cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9]; - count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13]; - }else{ - lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; - count = cmd[7]<<8 | cmd[8]; - } + scsilbacount(cmd, clen, &lba, &count); if(drive->data == nil) return SDok; if(drive->dlen < count*drive->secsize) From a1f9b97dd58e63175c855bbfd3219711a089d215 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Aug 2017 08:30:39 +0000 Subject: [PATCH 028/402] sys/src/9/pc: use scsilbacount in sdiahci (fix READ(16) and WRITE(16) commands) (thanks Geoff Collyer) --- sys/src/9/pc/sdiahci.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index f1d2b7ecaf..830365e197 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1803,8 +1803,9 @@ iariopkt(SDreq *r, Drive *d) static int iario(SDreq *r) { - int i, n, count, try, max, flag, task; - vlong lba; + int i, n, try, max, flag, task; + ulong count; + uvlong lba; char *name; uchar *cmd, *data; Aport *p; @@ -1833,14 +1834,17 @@ iario(SDreq *r) return i; } - if(*cmd != ScmdExtread && *cmd != ScmdExtwrite){ + if(*cmd == ScmdRead16 || *cmd == ScmdWrite16){ + /* ata commands only go to 48-bit lba */ + if(cmd[2] || cmd[3]) + return sdsetsense(r, SDcheck, 3, 0xc, 2); + }else if(*cmd != ScmdExtread && *cmd != ScmdExtwrite){ print("%s: bad cmd %.2#ux\n", name, cmd[0]); r->status = SDcheck; return SDcheck; } + scsilbacount(cmd, r->clen, &lba, &count); - lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; - count = cmd[7]<<8 | cmd[8]; if(r->data == nil) return SDok; if(r->dlen < count * unit->secsize) From fbc5d166d34594730372c32edab0ad56a40565a9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Aug 2017 18:42:46 +0000 Subject: [PATCH 029/402] sys/src/9/pc: fix READ(16) command in sdiahci (thanks Geoff Collyer) --- sys/src/9/pc/sdiahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index 830365e197..a1fb44ccd0 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1526,7 +1526,7 @@ ahcibuild(Drive *d, uchar *cmd, void *data, int n, vlong lba) static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35, }; pm = &d->portm; - dir = *cmd != ScmdExtread; + dir = *cmd == ScmdExtwrite || *cmd == ScmdWrite16; llba = pm->feat&Dllba? 1: 0; acmd = tab[dir][llba]; qlock(pm); From 229718e7c07ac5dd34bc1e7eec96a10f4735cef8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 22 Aug 2017 19:06:54 +0000 Subject: [PATCH 030/402] sys/src/9/pc: fix issue when block numbers pass 2^40 in sdiahci (thanks Geoff Collyer) --- sys/src/9/pc/sdiahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/sdiahci.c b/sys/src/9/pc/sdiahci.c index a1fb44ccd0..780b0cf94a 100644 --- a/sys/src/9/pc/sdiahci.c +++ b/sys/src/9/pc/sdiahci.c @@ -1548,7 +1548,7 @@ ahcibuild(Drive *d, uchar *cmd, void *data, int n, vlong lba) c[8] = lba >> 24; /* sector (exp) lba 31:24 */ c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */ - c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */ + c[10] = lba >> 40; /* cylinder hi (exp) lba 47:40 */ c[11] = 0; /* features (exp); */ c[12] = n; /* sector count */ From b2094fe2cdffc0ead5089062d3e8d2fae556c025 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 031/402] sys/src/9/port: fix okaddr integer overflow (thanks Geoff Collyer) --- sys/src/9/port/fault.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index 136355fed8..50a870c62f 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -290,21 +290,17 @@ okaddr(ulong addr, ulong len, int write) { Segment *s; - if((long)len >= 0) { - for(;;) { - s = seg(up, addr, 0); - if(s == 0 || (write && (s->type&SG_RONLY))) - break; - - if(addr+len > s->top) { - len -= s->top - addr; - addr = s->top; - continue; - } - return 1; + /* second test is paranoia only needed on 64-bit systems */ + if((long)len >= 0 && addr+len >= addr) + while ((s = seg(up, addr, 0)) != nil && + (!write || !(s->type&SG_RONLY))) { + if((uvlong)addr+len <= s->top) + return 1; + len -= s->top - addr; + addr = s->top; } - } - pprint("suicide: invalid address %#lux/%lud in sys call pc=%#lux\n", addr, len, userpc()); + pprint("suicide: invalid address %#lux/%lud in sys call pc=%#lux\n", + addr, len, userpc()); return 0; } From 116daa49a485052c43a95cdcfd1bb076f18f094c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 22 Aug 2017 18:52:57 +0000 Subject: [PATCH 032/402] sys/src/9/pc: fix read past end of array in screenputc --- sys/src/9/pc/vga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/vga.c b/sys/src/9/pc/vga.c index 587d8c185d..0279f6a977 100644 --- a/sys/src/9/pc/vga.c +++ b/sys/src/9/pc/vga.c @@ -70,7 +70,7 @@ vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) Rectangle r; // drawdebug = 1; - if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) + if(xp < xbuf || xp >= &xbuf[nelem(xbuf)]) xp = xbuf; h = scr->memdefont->height; From 7db7b3700b7dbb04751fdf00304e28c87bcc3390 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 24 Sep 2017 16:40:37 +0000 Subject: [PATCH 033/402] sys/src/cmd/unix/drawterm: fix read past end of array in screenputc --- sys/src/cmd/unix/drawterm/kern/term.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/unix/drawterm/kern/term.c b/sys/src/cmd/unix/drawterm/kern/term.c index f8fa9cbbf3..6a53bb8632 100644 --- a/sys/src/cmd/unix/drawterm/kern/term.c +++ b/sys/src/cmd/unix/drawterm/kern/term.c @@ -126,7 +126,7 @@ screenputc(char *buf) static int *xp; static int xbuf[256]; - if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) + if(xp < xbuf || xp >= &xbuf[nelem(xbuf)]) xp = xbuf; switch(buf[0]) { From ee52e0de412c2f72ca9666783785769300cbb939 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 29 Apr 2016 23:00:33 +0000 Subject: [PATCH 034/402] sys/src/9/port: increase number of wait records to 2000 (thanks Charles Forsyth) --- sys/src/9/port/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 8acf65c902..af0b4bacbf 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1152,13 +1152,13 @@ pexit(char *exitstr, int freemem) p->time[TCUser] += utime; p->time[TCSys] += stime; /* - * If there would be more than 128 wait records + * If there would be more than 2000 wait records * processes for my parent, then don't leave a wait * record behind. This helps prevent badly written * daemon processes from accumulating lots of wait * records. */ - if(p->nwait < 128) { + if(p->nwait < 2000) { wq->next = p->waitq; p->waitq = wq; p->nwait++; From 59360758d0822812a06fdbbf34a38b782e88df99 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 29 Apr 2016 23:52:10 +0000 Subject: [PATCH 035/402] sys/src/9/port: fix warning in packoldstat (thanks Charles Forsyth) --- sys/src/9/port/sysfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c index 4b8597649e..18fdeeb1b1 100644 --- a/sys/src/9/port/sysfile.c +++ b/sys/src/9/port/sysfile.c @@ -1233,7 +1233,7 @@ packoldstat(uchar *buf, Dir *d) strncpy((char*)p, d->gid, 28); p += 28; q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */ - if(d->qid.type & QTDIR) /* this is the real test of a new directory */ + if((ulong)d->qid.type & QTDIR) /* this is the real test of a new directory */ q |= DMDIR; PBIT32(p, q); p += BIT32SZ; From 8bd50f6ad81288c74562caf259ac44a0f34c7e3f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 14 Nov 2016 15:14:07 +0000 Subject: [PATCH 036/402] sys/src/9/port: increase MAXRPC to 16 KB (thanks Geoff Collyer) --- sys/src/9/port/devmnt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c index ae2a99a0ed..920a7addd3 100644 --- a/sys/src/9/port/devmnt.c +++ b/sys/src/9/port/devmnt.c @@ -16,7 +16,9 @@ * connection. */ -#define MAXRPC (IOHDRSZ+8192) +#define MAXRPC (IOHDRSZ+16*1024) /* maybe a larger size will be faster */ +/* use a known-good common size for initial negotiation */ +#define MAXCMNRPC (IOHDRSZ+8192) struct Mntrpc { @@ -150,14 +152,14 @@ mntversion(Chan *c, char *version, int msize, int returnlen) f.tag = NOTAG; f.msize = msize; f.version = v; - msg = malloc(8192+IOHDRSZ); + msg = malloc(MAXCMNRPC); if(msg == nil) exhausted("version memory"); if(waserror()){ free(msg); nexterror(); } - k = convS2M(&f, msg, 8192+IOHDRSZ); + k = convS2M(&f, msg, MAXCMNRPC); if(k == 0) error("bad fversion conversion on send"); @@ -176,7 +178,7 @@ mntversion(Chan *c, char *version, int msize, int returnlen) } /* message sent; receive and decode reply */ - k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); + k = devtab[c->type]->read(c, msg, MAXCMNRPC, c->offset); if(k <= 0) error("EOF receiving fversion reply"); From aeaf4d03b916729280c365c6c6a9a005f41098d0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 037/402] sys/src/9/pc: implement /dev/cputemp (thanks Erik Quanstrom) --- sys/man/3/arch | 6 ++ sys/src/9/pc/dat.h | 1 + sys/src/9/pc/devarch.c | 165 +++++++++++++++++++++++++++++++++++++++++ sys/src/9/pcboot/dat.h | 1 + 4 files changed, 173 insertions(+) diff --git a/sys/man/3/arch b/sys/man/3/arch index 123766f9d9..d2f18090d5 100644 --- a/sys/man/3/arch +++ b/sys/man/3/arch @@ -7,6 +7,7 @@ arch \- architecture-specific information and control .sp 0.3v .B /dev/archctl .B /dev/cputype +.B /dev/cputemp .B /dev/ioalloc .B /dev/iob .B /dev/iol @@ -20,6 +21,11 @@ Reads from .I cputype recover the processor type and clock rate in MHz. Reads from +.I cputemp +recover one line containing per processor containing +two fields: the processor temperature and precision +in degrees Celsius. +Reads from .I archctl yield at least data of this form: .IP diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index d9041cb710..068e5b9e02 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -330,6 +330,7 @@ enum { Pge = 1<<13, /* page global extension */ Pse2 = 1<<17, /* more page size extensions */ Clflush = 1<<19, + Acpif = 1<<22, Mmx = 1<<23, Fxsr = 1<<24, /* have SSE FXSAVE/FXRSTOR */ Sse = 1<<25, /* thus sfence instr. */ diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 9d25c47d54..5958d6e909 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -870,6 +870,159 @@ cputyperead(Chan*, void *a, long n, vlong offset) return readstr(offset, a, n, str); } +static int +intelcputempok(void) +{ + ulong regs[4]; + + if(m->cpuiddx & Acpif) + if(strcmp(m->cpuidid, "GenuineIntel") == 0){ + cpuid(6, regs); + return regs[0] & 1; + } + return 0; +} + +static char Notemp[] = "-1 -1 unsupported\n"; + +static long +cputemprd0(Chan*, void *a, long n, vlong offset) +{ + char buf[32], *s; + ulong msr, t, res, d; + vlong emsr; + ulong regs[4]; + static ulong tj; + + cpuid(6, regs); + if((regs[0] & 1) == 0) + return readstr(offset, a, n, Notemp); + if(tj == 0){ + /* + * magic undocumented msr. tj(max) is 100 or 85. + */ + tj = 100; + d = X86MODEL(m->cpuidax); + d |= (m->cpuidax>>12) & 0xf0; + if((d == 0xf && (m->cpuidax & 0xf)>1) || d == 0xe){ + rdmsr(0xee, &emsr); + msr = emsr; + if(msr & 1<<30) + tj = 85; + } + } + rdmsr(0x19c, &emsr); + msr = emsr; + t = -1; + if(msr & 1<<31){ + t = (msr>>16) & 127; + t = tj - t; + } + res = (msr>>27) & 15; + s = ""; + if((msr & 0x30) == 0x30) + s = " alarm"; + snprint(buf, sizeof buf, "%ld %lud%s\n", t, res, s); + return readstr(offset, a, n, buf); +} + +static long +intelcputemprd(Chan *c, void *va, long n, vlong offset) +{ + char *a; + long i, r, t; + Mach *w; + + w = up->wired; + a = va; + t = 0; + for(i = 0; i < conf.nmach; i++){ + procwired(up, i); + sched(); + r = cputemprd0(c, a, n, offset); + if(r == 0) + break; + offset -= r; + if(offset < 0) + offset = 0; + n -= r; + a = a + r; + t += r; + } + up->wired = w; + sched(); + return t; +} + +static long +amd0ftemprd(Chan*, void *a, long n, vlong offset) +{ + char *s, *e, buf[64]; + long i, t, j, max; + Pcidev *p; + + p = pcimatch(0, 0x1022, 0x1103); + if(p == nil) + return readstr(offset, a, n, Notemp); + max = 2; + if(max > conf.nmach) + max = conf.nmach; + s = buf; + e = buf + sizeof buf; + for(j = 0; j < max; j++){ + pcicfgw32(p, 0xe4, pcicfgr32(p, 0xe4) & ~4 | j<<2); + i = pcicfgr32(p, 0xe4); + if(X86STEPPING(m->cpuidax) == 2) + t = i>>16 & 0xff; + else{ + t = i>>14 & 0x3ff; + t *= 3; + t /= 4; + } + t += -49; + s = seprint(s, e, "%ld %lud%s\n", t, 1l, ""); + } + return readstr(offset, a, n, buf); +} + +static long +amd10temprd(Chan*, void *a, long n, vlong offset) +{ + char *s, *e, *r, *buf; + long i, t, c, nb, cores[MAXMACH]; + Pcidev *p; + + nb = 0; + for(p = 0; p = pcimatch(p, 0x1022, 0x1203); ){ + cores[nb++] = 1 + ((pcicfgr32(p, 0xe8) & 0x3000)>>12); + if(nb == nelem(cores)) + break; + } + if(nb == 0) + return readstr(offset, a, n, Notemp); + buf = smalloc(MAXMACH*4*32); + s = buf; + e = buf + MAXMACH*4*32; + nb = 0; + c = 0; + for(p = 0; p = pcimatch(p, 0x1022, 0x1203); nb++){ + i = pcicfgr32(p, 0xa4) & 0x7fffffff; + i >>= 21; + t = i/8; + r = ".0"; + if(i % 8 >= 4) + r = "0.5"; + /* + * only one value per nb; repeat per core + */ + while(c++ < conf.nmach && cores[nb]--) + s = seprint(s, e, "%ld%s 0.5%s\n", t, r, ""); + } + i = readstr(offset, a, n, buf); + free(buf); + return i; +} + static long archctlread(Chan*, void *a, long nn, vlong offset) { @@ -1042,6 +1195,18 @@ archinit(void) if(m->cpuiddx & Sse2) coherence = mfence; + if(intelcputempok()) + addarchfile("cputemp", 0444, intelcputemprd, nil); + if(strcmp(m->cpuidid, "AuthenticAMD") == 0) + switch(X86FAMILY(m->cpuidax)){ + case 0xf: + addarchfile("cputemp", 0444, amd0ftemprd, nil); + break; + case 0x10: + case 0x1f: + addarchfile("cputemp", 0444, amd10temprd, nil); + break; + } addarchfile("cputype", 0444, cputyperead, nil); addarchfile("archctl", 0664, archctlread, archctlwrite); } diff --git a/sys/src/9/pcboot/dat.h b/sys/src/9/pcboot/dat.h index 8b8b5cb35c..f7d911c25d 100644 --- a/sys/src/9/pcboot/dat.h +++ b/sys/src/9/pcboot/dat.h @@ -329,6 +329,7 @@ enum { Pge = 1<<13, /* page global extension */ Pse2 = 1<<17, /* more page size extensions */ Clflush = 1<<19, + Acpif = 1<<22, Mmx = 1<<23, Fxsr = 1<<24, /* have SSE FXSAVE/FXRSTOR */ Sse = 1<<25, /* thus sfence instr. */ From 83b7d2993f13f4b25cd3956757e301dd5b9db9bd Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 22 Aug 2017 05:32:05 +0000 Subject: [PATCH 038/402] sys/src/9/pc: add VT8235 and VT8251 devices to PCI (thanks Jerome Ibanes) --- sys/src/9/pc/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index b9c5b35880..afee0f12ef 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -673,7 +673,9 @@ static Bridge southbridges[] = { { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */ { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */ { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */ + { 0x1106, 0x3177, viaget, viaset }, /* Viatech VT8235 */ { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */ + { 0x1106, 0x3287, viaget, viaset }, /* Viatech VT8251 */ { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */ { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */ { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */ From e94dd55fc31c0123593f660d25b080a27ff6e926 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 27 Sep 2021 06:50:53 +0000 Subject: [PATCH 039/402] sys/src/9/pc: increase MaxEther to 64 (thanks Dan Cross) --- sys/src/9/pc/etherif.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/pc/etherif.h b/sys/src/9/pc/etherif.h index 4beebe88dc..3b9485e5d1 100644 --- a/sys/src/9/pc/etherif.h +++ b/sys/src/9/pc/etherif.h @@ -1,5 +1,5 @@ enum { - MaxEther = 48, + MaxEther = 64, Ntypes = 8, }; From 73af93ac47d0dd900d70999584d403d0ade0790b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 040/402] sys/src/9/port: import sdfakescsirw from 9atom (thanks Erik Quanstrom) --- sys/src/9/port/devsd.c | 52 ++++++++++++++++++++++++++++++++++++++++++ sys/src/9/port/sd.h | 1 + 2 files changed, 53 insertions(+) diff --git a/sys/src/9/port/devsd.c b/sys/src/9/port/devsd.c index c7edd3fb6f..8984b3c1d0 100644 --- a/sys/src/9/port/devsd.c +++ b/sys/src/9/port/devsd.c @@ -1082,6 +1082,58 @@ sdfakescsi(SDreq *r, void *info, int ilen) } } +int +sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp) +{ + uchar *c; + int rw, count; + uvlong lba; + + c = r->cmd; + rw = 0; + if((c[0] & 0xf) == 0xa) + rw = 1; + switch(c[0]){ + case 0x08: /* read6 */ + case 0x0a: + lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3]; + count = c[4]; + break; + case 0x28: /* read10 */ + case 0x2a: + lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5]; + count = c[7]<<8 | c[8]; + break; + case 0xa8: /* read12 */ + case 0xaa: + lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5]; + count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9]; + break; + case 0x88: /* read16 */ + case 0x8a: + /* ata commands only go to 48-bit lba */ + if(c[2] || c[3]) + return sdsetsense(r, SDcheck, 3, 0xc, 2); + lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32; + lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9]; + count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13]; + break; + default: + print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]); + r->status = sdsetsense(r, SDcheck, 0x05, 0x20, 0); + return SDcheck; + } + if(r->data == nil) + return SDok; + if(r->dlen < count * r->unit->secsize) + count = r->dlen/r->unit->secsize; + if(rwp) + *rwp = rw; + *llba = lba; + *nsec = count; + return SDnostatus; +} + static long sdread(Chan *c, void *a, long n, vlong off) { diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index 0acec6d039..bb158cf2d4 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -172,6 +172,7 @@ extern void sdaddpart(SDunit*, char*, uvlong, uvlong); extern int sdsetsense(SDreq*, int, int, int, int); extern int sdmodesense(SDreq*, uchar*, void*, int); extern int sdfakescsi(SDreq*, void*, int); +extern int sdfakescsirw(SDreq*, uvlong*, int*, int*); /* sdscsi.c */ extern int scsiverify(SDunit*); From d12594b09281be542804dd153e01dc7d9b9c905a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 20:17:22 +0000 Subject: [PATCH 041/402] sys/src/9/pc: import sdvirtio from 9front (thanks Cinap Lenrek) --- sys/src/9/pc/sdvirtio.c | 709 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 709 insertions(+) create mode 100644 sys/src/9/pc/sdvirtio.c diff --git a/sys/src/9/pc/sdvirtio.c b/sys/src/9/pc/sdvirtio.c new file mode 100644 index 0000000000..03e3cd112e --- /dev/null +++ b/sys/src/9/pc/sdvirtio.c @@ -0,0 +1,709 @@ +/* + * virtio ethernet driver implementing the legacy interface: + * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +#include "../port/sd.h" + +typedef struct Vring Vring; +typedef struct Vdesc Vdesc; +typedef struct Vused Vused; +typedef struct Vqueue Vqueue; +typedef struct Vdev Vdev; + +typedef struct ScsiCfg ScsiCfg; + +/* device types */ +enum { + TypBlk = 2, + TypSCSI = 8, +}; + +/* status flags */ +enum { + Acknowledge = 1, + Driver = 2, + DriverOk = 4, + Failed = 0x80, +}; + +/* virtio ports */ +enum { + Devfeat = 0, + Drvfeat = 4, + Qaddr = 8, + Qsize = 12, + Qselect = 14, + Qnotify = 16, + Status = 18, + Isr = 19, + + Devspec = 20, +}; + +/* descriptor flags */ +enum { + Next = 1, + Write = 2, + Indirect = 4, +}; + +/* struct sizes */ +enum { + VringSize = 4, +}; + +struct Vring +{ + u16int flags; + u16int idx; +}; + +struct Vdesc +{ + u64int addr; + u32int len; + u16int flags; + u16int next; +}; + +struct Vused +{ + u32int id; + u32int len; +}; + +struct Vqueue +{ + Lock; + + Vdev *dev; + int idx; + + int size; + + int free; + int nfree; + + Vdesc *desc; + + Vring *avail; + u16int *availent; + u16int *availevent; + + Vring *used; + Vused *usedent; + u16int *usedevent; + u16int lastused; + + void *rock[]; +}; + +struct Vdev +{ + int typ; + + Pcidev *pci; + + ulong port; + ulong feat; + + int nqueue; + Vqueue *queue[16]; + + void *cfg; /* device specific config (for scsi) */ + + Vdev *next; +}; + +enum { + CDBSIZE = 32, + SENSESIZE = 96, +}; + +struct ScsiCfg +{ + u32int num_queues; + u32int seg_max; + u32int max_sectors; + u32int cmd_per_lun; + u32int event_info_size; + u32int sense_size; + u32int cdb_size; + u16int max_channel; + u16int max_target; + u32int max_lun; +}; + +static Vqueue* +mkvqueue(int size) +{ + Vqueue *q; + uchar *p; + int i; + + q = malloc(sizeof(*q) + sizeof(void*)*size); + p = mallocalign( + PGROUND(sizeof(Vdesc)*size + + VringSize + + sizeof(u16int)*size + + sizeof(u16int)) + + PGROUND(VringSize + + sizeof(Vused)*size + + sizeof(u16int)), + BY2PG, 0, 0); + if(p == nil || q == nil){ + print("virtio: no memory for Vqueue\n"); + free(p); + free(q); + return nil; + } + + q->desc = (void*)p; + p += sizeof(Vdesc)*size; + q->avail = (void*)p; + p += VringSize; + q->availent = (void*)p; + p += sizeof(u16int)*size; + q->availevent = (void*)p; + p += sizeof(u16int); + + p = (uchar*)PGROUND((uintptr)p); + q->used = (void*)p; + p += VringSize; + q->usedent = (void*)p; + p += sizeof(Vused)*size; + q->usedevent = (void*)p; + + q->free = -1; + q->nfree = q->size = size; + for(i=0; idesc[i].next = q->free; + q->free = i; + } + + return q; +} + +static Vdev* +viopnpdevs(int typ) +{ + Vdev *vd, *h, *t; + Vqueue *q; + Pcidev *p; + int n, i, size; + + h = t = nil; + for(p = nil; p = pcimatch(p, 0x1AF4, 0);){ + if((p->did < 0x1000) || (p->did > 0x103F)) + continue; + if(p->rid != 0) + continue; + //if((p->mem[0].bar & 1) == 0) /* zero on gce */ + // continue; + if(pcicfgr16(p, 0x2E) != typ) + continue; + if((vd = malloc(sizeof(*vd))) == nil){ + print("virtio: no memory for Vdev\n"); + break; + } + vd->port = p->mem[0].bar & ~3; + size = p->mem[0].size; + if(vd->port == 0){ /* gce */ + vd->port = 0xc000; + size = 0x40; + } + if(ioalloc(vd->port, size, 0, "virtio") < 0){ + print("virtio: port %lux in use\n", vd->port); + free(vd); + continue; + } + vd->typ = typ; + vd->pci = p; + + /* reset */ + outb(vd->port+Status, 0); + + vd->feat = inl(vd->port+Devfeat); + outb(vd->port+Status, Acknowledge|Driver); + for(i=0; iqueue); i++){ + outs(vd->port+Qselect, i); + n = ins(vd->port+Qsize); + if(n == 0 || (n & (n-1)) != 0) + break; + if((q = mkvqueue(n)) == nil) + break; + q->dev = vd; + q->idx = i; + vd->queue[i] = q; + coherence(); + outl(vd->port+Qaddr, PADDR(vd->queue[i]->desc)/BY2PG); + } + vd->nqueue = i; + + if(h == nil) + h = vd; + else + t->next = vd; + t = vd; + } + + return h; +} + +struct Rock { + int done; + Rendez *sleep; +}; + +static void +vqinterrupt(Vqueue *q) +{ + int id, free, m; + struct Rock *r; + Rendez *z; + + m = q->size-1; + + ilock(q); + while((q->lastused ^ q->used->idx) & m){ + id = q->usedent[q->lastused++ & m].id; + if(r = q->rock[id]){ + q->rock[id] = nil; + z = r->sleep; + r->done = 1; /* hands off */ + if(z != nil) + wakeup(z); + } + do { + free = id; + id = q->desc[free].next; + q->desc[free].next = q->free; + q->free = free; + q->nfree++; + } while(q->desc[free].flags & Next); + } + iunlock(q); +} + +static void +viointerrupt(Ureg *, void *arg) +{ + Vdev *vd = arg; + + if(inb(vd->port+Isr) & 1) + vqinterrupt(vd->queue[vd->typ == TypSCSI ? 2 : 0]); +} + +static int +viodone(void *arg) +{ + return ((struct Rock*)arg)->done; +} + +static void +vqio(Vqueue *q, int head) +{ + struct Rock rock; + + rock.done = 0; + rock.sleep = &up->sleep; + q->rock[head] = &rock; + q->availent[q->avail->idx & (q->size-1)] = head; + coherence(); + q->avail->idx++; + iunlock(q); + if((q->used->flags & 1) == 0) + outs(q->dev->port+Qnotify, q->idx); + while(!rock.done){ + while(waserror()) + ; + tsleep(rock.sleep, viodone, &rock, 1000); + poperror(); + + if(!rock.done) + vqinterrupt(q); + } +} + +static int +vioblkreq(Vdev *vd, int typ, void *a, long count, long secsize, uvlong lba) +{ + int need, free, head; + Vqueue *q; + Vdesc *d; + + u8int status; + struct Vioblkreqhdr { + u32int typ; + u32int prio; + u64int lba; + } req; + + need = 2; + if(a != nil) + need = 3; + + status = -1; + req.typ = typ; + req.prio = 0; + req.lba = lba; + + q = vd->queue[0]; + ilock(q); + while(q->nfree < need){ + iunlock(q); + + if(!waserror()) + tsleep(&up->sleep, return0, 0, 500); + poperror(); + + ilock(q); + } + + head = free = q->free; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(&req); + d->len = sizeof(req); + d->flags = Next; + + if(a != nil){ + d = &q->desc[free]; free = d->next; + d->addr = PADDR(a); + d->len = secsize*count; + d->flags = typ ? Next : (Write|Next); + } + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(&status); + d->len = sizeof(status); + d->flags = Write; + + q->free = free; + q->nfree -= need; + + /* queue io, unlock and wait for completion */ + vqio(q, head); + + return status; +} + +static int +vioscsireq(SDreq *r) +{ + u8int resp[4+4+2+2+SENSESIZE]; + u8int req[8+8+3+CDBSIZE]; + int free, head; + u32int len; + Vqueue *q; + Vdesc *d; + Vdev *vd; + SDunit *u; + ScsiCfg *cfg; + + u = r->unit; + vd = u->dev->ctlr; + cfg = vd->cfg; + + memset(resp, 0, sizeof(resp)); + memset(req, 0, sizeof(req)); + req[0] = 1; + req[1] = u->subno; + req[2] = r->lun>>8; + req[3] = r->lun&0xFF; + *(u64int*)(&req[8]) = (uintptr)r; + + memmove(&req[8+8+3], r->cmd, r->clen); + + q = vd->queue[2]; + ilock(q); + while(q->nfree < 3){ + iunlock(q); + + if(!waserror()) + tsleep(&up->sleep, return0, 0, 500); + poperror(); + + ilock(q); + } + + head = free = q->free; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(req); + d->len = 8+8+3+cfg->cdb_size; + d->flags = Next; + + if(r->write && r->dlen > 0){ + d = &q->desc[free]; free = d->next; + d->addr = PADDR(r->data); + d->len = r->dlen; + d->flags = Next; + } + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(resp); + d->len = 4+4+2+2+cfg->sense_size; + d->flags = Write; + + if(!r->write && r->dlen > 0){ + d->flags |= Next; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(r->data); + d->len = r->dlen; + d->flags = Write; + } + + q->free = free; + q->nfree -= 2 + (r->dlen > 0); + + /* queue io, unlock and wait for completion */ + vqio(q, head); + + /* response+status */ + r->status = resp[10]; + if(resp[11] != 0) + r->status = SDcheck; + + /* sense_len */ + len = *((u32int*)&resp[0]); + if(len > 0){ + if(len > sizeof(r->sense)) + len = sizeof(r->sense); + memmove(r->sense, &resp[4+4+2+2], len); + r->flags |= SDvalidsense; + } + + /* data residue */ + len = *((u32int*)&resp[4]); + if(len > r->dlen) + r->rlen = 0; + else + r->rlen = r->dlen - len; + + return r->status; + +} + +static long +viobio(SDunit *u, int lun, int write, void *a, long count, uvlong lba) +{ + long ss, cc, max, ret; + Vdev *vd; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsibio(u, lun, write, a, count, lba); + + max = 32; + ss = u->secsize; + ret = 0; + while(count > 0){ + if((cc = count) > max) + cc = max; + if(vioblkreq(vd, write != 0, (uchar*)a + ret, cc, ss, lba) != 0) + error(Eio); + ret += cc*ss; + count -= cc; + lba += cc; + } + return ret; +} + +enum { + SDread, + SDwrite, +}; + +static int +viorio(SDreq *r) +{ + int i, count, rw; + uvlong lba; + SDunit *u; + Vdev *vd; + + u = r->unit; + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return vioscsireq(r); + if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ + if(vioblkreq(vd, 4, nil, 0, 0, 0) != 0) + return sdsetsense(r, SDcheck, 3, 0xc, 2); + return sdsetsense(r, SDok, 0, 0, 0); + } + if((i = sdfakescsi(r, nil, 0)) != SDnostatus) + return r->status = i; + if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus) + return i; + r->rlen = viobio(u, r->lun, rw == SDwrite, r->data, count, lba); + return r->status = SDok; +} + +static int +vioonline(SDunit *u) +{ + uvlong cap; + Vdev *vd; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsionline(u); + + cap = inl(vd->port+Devspec+4); + cap <<= 32; + cap |= inl(vd->port+Devspec); + if(u->sectors != cap){ + u->sectors = cap; + u->secsize = 512; + return 2; + } + return 1; +} + +static int +vioverify(SDunit *u) +{ + Vdev *vd; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsiverify(u); + + return 1; +} + +SDifc sdvirtioifc; + +static int +vioenable(SDev *sd) +{ + char name[32]; + Vdev *vd; + + vd = sd->ctlr; + pcisetbme(vd->pci); + snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name); + intrenable(vd->pci->intl, viointerrupt, vd, vd->pci->tbdf, name); + outb(vd->port+Status, inb(vd->port+Status) | DriverOk); + return 1; +} + +static int +viodisable(SDev *sd) +{ + char name[32]; + Vdev *vd; + + vd = sd->ctlr; + snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name); + intrdisable(vd->pci->intl, viointerrupt, vd, vd->pci->tbdf, name); + pciclrbme(vd->pci); + return 1; +} + +static SDev* +viopnp(void) +{ + SDev *s, *h, *t; + Vdev *vd; + int id; + + h = t = nil; + + id = 'F'; + for(vd = viopnpdevs(TypBlk); vd; vd = vd->next){ + if(vd->nqueue != 1) + continue; + + if((s = malloc(sizeof(*s))) == nil) + break; + s->ctlr = vd; + s->idno = id++; + s->ifc = &sdvirtioifc; + s->nunit = 1; + if(h) + t->next = s; + else + h = s; + t = s; + } + + id = '0'; + for(vd = viopnpdevs(TypSCSI); vd; vd = vd->next){ + ScsiCfg *cfg; + + if(vd->nqueue < 3) + continue; + + if((cfg = malloc(sizeof(*cfg))) == nil) + break; + cfg->num_queues = inl(vd->port+Devspec+4*0); + cfg->seg_max = inl(vd->port+Devspec+4*1); + cfg->max_sectors = inl(vd->port+Devspec+4*2); + cfg->cmd_per_lun = inl(vd->port+Devspec+4*3); + cfg->event_info_size = inl(vd->port+Devspec+4*4); + cfg->sense_size = inl(vd->port+Devspec+4*5); + cfg->cdb_size = inl(vd->port+Devspec+4*6); + cfg->max_channel = ins(vd->port+Devspec+4*7); + cfg->max_target = ins(vd->port+Devspec+4*7+2); + cfg->max_lun = inl(vd->port+Devspec+4*8); + + if(cfg->max_target == 0){ + free(cfg); + continue; + } + if((cfg->cdb_size > CDBSIZE) || (cfg->sense_size > SENSESIZE)){ + print("sdvirtio: cdb %ud or sense size %ud too big\n", + cfg->cdb_size, cfg->sense_size); + free(cfg); + continue; + } + vd->cfg = cfg; + + if((s = malloc(sizeof(*s))) == nil) + break; + s->ctlr = vd; + s->idno = id++; + s->ifc = &sdvirtioifc; + s->nunit = cfg->max_target; + if(h) + t->next = s; + else + h = s; + t = s; + } + + return h; +} + +SDifc sdvirtioifc = { + "virtio", /* name */ + + viopnp, /* pnp */ + nil, /* legacy */ + vioenable, /* enable */ + viodisable, /* disable */ + + vioverify, /* verify */ + vioonline, /* online */ + viorio, /* rio */ + nil, /* rctl */ + nil, /* wctl */ + + viobio, /* bio */ + nil, /* probe */ + nil, /* clear */ + nil, /* rtopctl */ + nil, /* wtopctl */ +}; From 2058c894bc2ab82415d81a6b1f85b1a988282e45 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 042/402] sys/src/9/pc: add sdvirtio in kernel configurations --- sys/src/9/pc/pc | 1 + sys/src/9/pc/pcauth | 1 + sys/src/9/pc/pccd | 1 + sys/src/9/pc/pccpu | 1 + sys/src/9/pc/pccpuf | 1 + sys/src/9/pc/pcdisk | 1 + sys/src/9/pc/pcf | 1 + sys/src/9/pc/pcflop | 1 + sys/src/9/pc/pcfs | 1 + sys/src/9/pcboot/load | 1 + 10 files changed, 10 insertions(+) diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index e26f68abd9..edb91f18dc 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -91,6 +91,7 @@ misc sd53c8xx pci sdscsi sdmylex pci sdscsi sdiahci pci sdscsi + sdvirtio pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcauth b/sys/src/9/pc/pcauth index 221740e4e4..a44a9b7b9f 100644 --- a/sys/src/9/pc/pcauth +++ b/sys/src/9/pc/pcauth @@ -48,6 +48,7 @@ misc realmode mtrr sdata pci sdscsi + sdvirtio pci sdscsi uarti8250 uartpci diff --git a/sys/src/9/pc/pccd b/sys/src/9/pc/pccd index 50b25774c9..9d8a82cead 100644 --- a/sys/src/9/pc/pccd +++ b/sys/src/9/pc/pccd @@ -87,6 +87,7 @@ misc sd53c8xx pci sdscsi sdmylex pci sdscsi sdiahci pci sdscsi + sdvirtio pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu index 3b7963f706..e3a7adb223 100644 --- a/sys/src/9/pc/pccpu +++ b/sys/src/9/pc/pccpu @@ -90,6 +90,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdaoe sdscsi + sdvirtio pci sdscsi ip tcp diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index f6fcbfd128..3ad5afacdf 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -88,6 +88,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdaoe + sdvirtio pci sdscsi vga3dfx +cur vgaark2000pv +cur diff --git a/sys/src/9/pc/pcdisk b/sys/src/9/pc/pcdisk index 10e46750d0..1e964cfa64 100644 --- a/sys/src/9/pc/pcdisk +++ b/sys/src/9/pc/pcdisk @@ -87,6 +87,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdaoe + sdvirtio pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 4e9c9c06f5..fe824477a4 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -87,6 +87,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdaoe + sdvirtio pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index c7c83e44f0..5ab025d238 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -76,6 +76,7 @@ misc sd53c8xx pci sdscsi sdmylex pci sdscsi sdiahci pci sdscsi + sdvirtio pci sdscsi uarti8250 diff --git a/sys/src/9/pc/pcfs b/sys/src/9/pc/pcfs index 70d06deb98..eb6aec6d0b 100644 --- a/sys/src/9/pc/pcfs +++ b/sys/src/9/pc/pcfs @@ -59,6 +59,7 @@ misc sdiahci pci sdscsi sd53c8xx pci sdscsi sdmylex pci sdscsi + sdvirtio pci sdscsi ip tcp diff --git a/sys/src/9/pcboot/load b/sys/src/9/pcboot/load index 9c853731eb..8044e17b58 100644 --- a/sys/src/9/pcboot/load +++ b/sys/src/9/pcboot/load @@ -31,6 +31,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi # sdflop + sdvirtio pci sdscsi port int cpuserver = 1; From c1f3dae3468713111b4254b3bc4ad716c35098d8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 20:16:59 +0000 Subject: [PATCH 043/402] sys/src/9/pc: import ethervirtio from 9front (thanks Nick Owens) --- sys/src/9/pc/ethervirtio.c | 688 +++++++++++++++++++++++++++++++++++++ 1 file changed, 688 insertions(+) create mode 100644 sys/src/9/pc/ethervirtio.c diff --git a/sys/src/9/pc/ethervirtio.c b/sys/src/9/pc/ethervirtio.c new file mode 100644 index 0000000000..b414e3bd2d --- /dev/null +++ b/sys/src/9/pc/ethervirtio.c @@ -0,0 +1,688 @@ +/* + * virtio ethernet driver implementing the legacy interface: + * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" +#include "etherif.h" + +typedef struct Vring Vring; +typedef struct Vdesc Vdesc; +typedef struct Vused Vused; +typedef struct Vheader Vheader; +typedef struct Vqueue Vqueue; +typedef struct Ctlr Ctlr; + +enum { + /* §2.1 Device Status Field */ + Sacknowledge = 1, + Sdriver = 2, + Sdriverok = 4, + Sfeatureok = 8, + Sfailed = 128, + + /* §4.1.4.8 Legacy Interfaces: A Note on PCI Device Layout */ + Qdevfeat = 0, + Qdrvfeat = 4, + Qaddr = 8, + Qsize = 12, + Qselect = 14, + Qnotify = 16, + Qstatus = 18, + Qisr = 19, + Qmac = 20, + Qnetstatus = 26, + + /* flags in Qnetstatus */ + Nlinkup = (1<<0), + Nannounce = (1<<1), + + /* feature bits */ + Fmac = (1<<5), + Fstatus = (1<<16), + Fctrlvq = (1<<17), + Fctrlrx = (1<<18), + + /* vring used flags */ + Unonotify = 1, + /* vring avail flags */ + Rnointerrupt = 1, + + /* descriptor flags */ + Dnext = 1, + Dwrite = 2, + Dindirect = 4, + + /* struct sizes */ + VringSize = 4, + VdescSize = 16, + VusedSize = 8, + VheaderSize = 10, + + /* §4.1.5.1.4.1 says pages are 4096 bytes + * for the purposes of the driver. + */ + VBY2PG = 4096, +#define VPGROUND(s) ROUND(s, VBY2PG) + + Vrxq = 0, + Vtxq = 1, + Vctlq = 2, + + /* class/cmd for Vctlq */ + CtrlRx = 0x00, + CmdPromisc = 0x00, + CmdAllmulti = 0x01, + CtrlMac = 0x01, + CmdMacTableSet = 0x00, + CtrlVlan= 0x02, + CmdVlanAdd = 0x00, + CmdVlanDel = 0x01, +}; + +struct Vring +{ + u16int flags; + u16int idx; +}; + +struct Vdesc +{ + u64int addr; + u32int len; + u16int flags; + u16int next; +}; + +struct Vused +{ + u32int id; + u32int len; +}; + +struct Vheader +{ + u8int flags; + u8int segtype; + u16int hlen; + u16int seglen; + u16int csumstart; + u16int csumend; +}; + +/* §2.4 Virtqueues */ +struct Vqueue +{ + Rendez; + + uint qsize; + uint qmask; + + Vdesc *desc; + + Vring *avail; + u16int *availent; + u16int *availevent; + + Vring *used; + Vused *usedent; + u16int *usedevent; + u16int lastused; + + uint nintr; + uint nnote; +}; + +struct Ctlr { + Lock; + + QLock ctllock; + + int attached; + + int port; + Pcidev *pcidev; + Ctlr *next; + int active; + int id; + int typ; + ulong feat; + int nqueue; + + /* virtioether has 3 queues: rx, tx and ctl */ + Vqueue queue[3]; +}; + +static Ctlr *ctlrhead; + +static int +vhasroom(void *v) +{ + Vqueue *q = v; + return q->lastused != q->used->idx; +} + +static void +vqnotify(Ctlr *ctlr, int x) +{ + Vqueue *q; + + coherence(); + q = &ctlr->queue[x]; + if(q->used->flags & Unonotify) + return; + q->nnote++; + outs(ctlr->port+Qnotify, x); +} + +static void +txproc(void *v) +{ + Vheader *header; + Block **blocks; + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + Vused *u; + Block *b; + int i, j; + + edev = v; + ctlr = edev->ctlr; + q = &ctlr->queue[Vtxq]; + + header = smalloc(VheaderSize); + blocks = smalloc(sizeof(Block*) * (q->qsize/2)); + + for(i = 0; i < q->qsize/2; i++){ + j = i << 1; + q->desc[j].addr = PADDR(header); + q->desc[j].len = VheaderSize; + q->desc[j].next = j | 1; + q->desc[j].flags = Dnext; + + q->availent[i] = q->availent[i + q->qsize/2] = j; + + j |= 1; + q->desc[j].next = 0; + q->desc[j].flags = 0; + } + + q->avail->flags &= ~Rnointerrupt; + + while(waserror()) + ; + + while((b = qbread(edev->oq, 1000000)) != nil){ + for(;;){ + /* retire completed packets */ + while((i = q->lastused) != q->used->idx){ + u = &q->usedent[i & q->qmask]; + i = (u->id & q->qmask) >> 1; + if(blocks[i] == nil) + break; + freeb(blocks[i]); + blocks[i] = nil; + q->lastused++; + } + + /* have free slot? */ + i = q->avail->idx & (q->qmask >> 1); + if(blocks[i] == nil) + break; + + /* ring full, wait and retry */ + if(!vhasroom(q)) + sleep(q, vhasroom, q); + } + + /* slot is free, fill in descriptor */ + blocks[i] = b; + j = (i << 1) | 1; + q->desc[j].addr = PADDR(b->rp); + q->desc[j].len = BLEN(b); + coherence(); + q->avail->idx++; + vqnotify(ctlr, Vtxq); + } + + pexit("ether out queue closed", 1); +} + +static void +rxproc(void *v) +{ + Vheader *header; + Block **blocks; + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + Vused *u; + Block *b; + int i, j; + + edev = v; + ctlr = edev->ctlr; + q = &ctlr->queue[Vrxq]; + + header = smalloc(VheaderSize); + blocks = smalloc(sizeof(Block*) * (q->qsize/2)); + + for(i = 0; i < q->qsize/2; i++){ + j = i << 1; + q->desc[j].addr = PADDR(header); + q->desc[j].len = VheaderSize; + q->desc[j].next = j | 1; + q->desc[j].flags = Dwrite|Dnext; + + q->availent[i] = q->availent[i + q->qsize/2] = j; + + j |= 1; + q->desc[j].next = 0; + q->desc[j].flags = Dwrite; + } + + q->avail->flags &= ~Rnointerrupt; + + while(waserror()) + ; + + for(;;){ + /* replenish receive ring */ + do { + i = q->avail->idx & (q->qmask >> 1); + if(blocks[i] != nil) + break; + if((b = iallocb(ETHERMAXTU)) == nil) + break; + blocks[i] = b; + j = (i << 1) | 1; + q->desc[j].addr = PADDR(b->rp); + q->desc[j].len = BALLOC(b); + coherence(); + q->avail->idx++; + } while(q->avail->idx != q->used->idx); + vqnotify(ctlr, Vrxq); + + /* wait for any packets to complete */ + if(!vhasroom(q)) + sleep(q, vhasroom, q); + + /* retire completed packets */ + while((i = q->lastused) != q->used->idx) { + u = &q->usedent[i & q->qmask]; + i = (u->id & q->qmask) >> 1; + if((b = blocks[i]) == nil) + break; + + blocks[i] = nil; + + b->wp = b->rp + u->len - VheaderSize; + etheriq(edev, b, 1); + q->lastused++; + } + } +} + +static int +vctlcmd(Ether *edev, uchar class, uchar cmd, uchar *data, int ndata) +{ + uchar hdr[2], ack[1]; + Ctlr *ctlr; + Vqueue *q; + Vdesc *d; + int i; + + ctlr = edev->ctlr; + q = &ctlr->queue[Vctlq]; + if(q->qsize < 3) + return -1; + + qlock(&ctlr->ctllock); + while(waserror()) + ; + + ack[0] = 0x55; + hdr[0] = class; + hdr[1] = cmd; + + d = &q->desc[0]; + d->addr = PADDR(hdr); + d->len = sizeof(hdr); + d->next = 1; + d->flags = Dnext; + d++; + d->addr = PADDR(data); + d->len = ndata; + d->next = 2; + d->flags = Dnext; + d++; + d->addr = PADDR(ack); + d->len = sizeof(ack); + d->next = 0; + d->flags = Dwrite; + + i = q->avail->idx & q->qmask; + q->availent[i] = 0; + coherence(); + + q->avail->flags &= ~Rnointerrupt; + q->avail->idx++; + vqnotify(ctlr, Vctlq); + while(!vhasroom(q)) + sleep(q, vhasroom, q); + q->lastused = q->used->idx; + q->avail->flags |= Rnointerrupt; + + qunlock(&ctlr->ctllock); + poperror(); + + if(ack[0] != 0) + print("#l%d: vctlcmd: %ux.%ux -> %ux\n", edev->ctlrno, class, cmd, ack[0]); + + return ack[0]; +} + +static void +interrupt(Ureg*, void* arg) +{ + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + int i; + + edev = arg; + ctlr = edev->ctlr; + if(inb(ctlr->port+Qisr) & 1){ + for(i = 0; i < ctlr->nqueue; i++){ + q = &ctlr->queue[i]; + if(vhasroom(q)){ + q->nintr++; + wakeup(q); + } + } + } +} + +static void +attach(Ether* edev) +{ + char name[KNAMELEN]; + Ctlr* ctlr; + + ctlr = edev->ctlr; + lock(ctlr); + if(ctlr->attached){ + unlock(ctlr); + return; + } + ctlr->attached = 1; + unlock(ctlr); + + /* ready to go */ + outb(ctlr->port+Qstatus, inb(ctlr->port+Qstatus) | Sdriverok); + + /* start kprocs */ + snprint(name, sizeof name, "#l%drx", edev->ctlrno); + kproc(name, rxproc, edev); + snprint(name, sizeof name, "#l%dtx", edev->ctlrno); + kproc(name, txproc, edev); +} + +static long +ifstat(Ether *edev, void *a, long n, ulong offset) +{ + int i, l; + char *p; + Ctlr *ctlr; + Vqueue *q; + + ctlr = edev->ctlr; + + p = smalloc(READSTR); + + l = snprint(p, READSTR, "devfeat %4.4luX\n", ctlr->feat); + l += snprint(p+l, READSTR-l, "drvfeat %4.4luX\n", inl(ctlr->port+Qdrvfeat)); + l += snprint(p+l, READSTR-l, "devstatus %uX\n", inb(ctlr->port+Qstatus)); + if(ctlr->feat & Fstatus) + l += snprint(p+l, READSTR-l, "netstatus %uX\n", inb(ctlr->port+Qnetstatus)); + + for(i = 0; i < ctlr->nqueue; i++){ + q = &ctlr->queue[i]; + l += snprint(p+l, READSTR-l, + "vq%d %#p size %d avail->idx %d used->idx %d lastused %hud nintr %ud nnote %ud\n", + i, q, q->qsize, q->avail->idx, q->used->idx, q->lastused, q->nintr, q->nnote); + } + + n = readstr(offset, a, n, p); + free(p); + + return n; +} + +static void +shutdown(Ether* edev) +{ + Ctlr *ctlr = edev->ctlr; + outb(ctlr->port+Qstatus, 0); + pciclrbme(ctlr->pcidev); +} + +static void +promiscuous(void *arg, int on) +{ + Ether *edev = arg; + uchar b[1]; + + b[0] = on != 0; + vctlcmd(edev, CtrlRx, CmdPromisc, b, sizeof(b)); +} + +static void +multicast(void *arg, uchar*, int) +{ + Ether *edev = arg; + uchar b[1]; + + b[0] = edev->nmaddr > 0; + vctlcmd(edev, CtrlRx, CmdAllmulti, b, sizeof(b)); +} + +/* §2.4.2 Legacy Interfaces: A Note on Virtqueue Layout */ +static ulong +queuesize(ulong size) +{ + return VPGROUND(VdescSize*size + sizeof(u16int)*(3+size)) + + VPGROUND(sizeof(u16int)*3 + VusedSize*size); +} + +static int +initqueue(Vqueue *q, int size) +{ + uchar *p; + + /* §2.4: Queue Size value is always a power of 2 and <= 32768 */ + assert(!(size & (size - 1)) && size <= 32768); + + p = mallocalign(queuesize(size), VBY2PG, 0, 0); + if(p == nil){ + print("ethervirtio: no memory for Vqueue\n"); + free(p); + return -1; + } + + q->desc = (void*)p; + p += VdescSize*size; + q->avail = (void*)p; + p += VringSize; + q->availent = (void*)p; + p += sizeof(u16int)*size; + q->availevent = (void*)p; + p += sizeof(u16int); + + p = (uchar*)VPGROUND((uintptr)p); + q->used = (void*)p; + p += VringSize; + q->usedent = (void*)p; + p += VusedSize*size; + q->usedevent = (void*)p; + + q->qsize = size; + q->qmask = q->qsize - 1; + + q->lastused = q->avail->idx = q->used->idx = 0; + + q->avail->flags |= Rnointerrupt; + + return 0; +} + +static Ctlr* +pciprobe(int typ) +{ + Ctlr *c, *h, *t; + Pcidev *p; + int n, i; + + h = t = nil; + + /* §4.1.2 PCI Device Discovery */ + for(p = nil; p = pcimatch(p, 0x1AF4, 0);){ + /* the two possible DIDs for virtio-net */ + if(p->did != 0x1000 && p->did != 0x1041) + continue; + /* + * non-transitional devices will have a revision > 0, + * these are handled by ethervirtio10 driver. + */ + if(p->rid != 0) + continue; + /* first membar needs to be I/O */ + if((p->mem[0].bar & 1) == 0) + continue; + /* non-transitional device will have typ+0x40 */ + if(pcicfgr16(p, 0x2E) != typ) + continue; + if((c = mallocz(sizeof(Ctlr), 1)) == nil){ + print("ethervirtio: no memory for Ctlr\n"); + break; + } + c->port = p->mem[0].bar & ~3; + if(ioalloc(c->port, p->mem[0].size, 0, "ethervirtio") < 0){ + print("ethervirtio: port %ux in use\n", c->port); + free(c); + continue; + } + + c->typ = typ; + c->pcidev = p; + c->id = (p->did<<16)|p->vid; + + /* §3.1.2 Legacy Device Initialization */ + outb(c->port+Qstatus, 0); + while(inb(c->port+Qstatus) != 0) + delay(1); + outb(c->port+Qstatus, Sacknowledge|Sdriver); + + /* negotiate feature bits */ + c->feat = inl(c->port+Qdevfeat); + outl(c->port+Qdrvfeat, c->feat & (Fmac|Fstatus|Fctrlvq|Fctrlrx)); + + /* §4.1.5.1.4 Virtqueue Configuration */ + for(i=0; iqueue); i++){ + outs(c->port+Qselect, i); + n = ins(c->port+Qsize); + if(n == 0 || (n & (n-1)) != 0){ + if(i < 2) + print("ethervirtio: queue %d has invalid size %d\n", i, n); + break; + } + if(initqueue(&c->queue[i], n) < 0) + break; + coherence(); + outl(c->port+Qaddr, PADDR(c->queue[i].desc)/VBY2PG); + } + if(i < 2){ + print("ethervirtio: no queues\n"); + free(c); + continue; + } + c->nqueue = i; + + if(h == nil) + h = c; + else + t->next = c; + t = c; + } + + return h; +} + + +static int +reset(Ether* edev) +{ + static uchar zeros[Eaddrlen]; + Ctlr *ctlr; + int i; + + if(ctlrhead == nil) + ctlrhead = pciprobe(1); + + for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ + if(ctlr->active) + continue; + if(edev->port == 0 || edev->port == ctlr->port){ + ctlr->active = 1; + break; + } + } + + if(ctlr == nil) + return -1; + + edev->ctlr = ctlr; + edev->port = ctlr->port; + edev->irq = ctlr->pcidev->intl; + edev->tbdf = ctlr->pcidev->tbdf; + edev->mbps = 1000; + edev->link = 1; + + if((ctlr->feat & Fmac) != 0 && memcmp(edev->ea, zeros, Eaddrlen) == 0){ + for(i = 0; i < Eaddrlen; i++) + edev->ea[i] = inb(ctlr->port+Qmac+i); + } else { + for(i = 0; i < Eaddrlen; i++) + outb(ctlr->port+Qmac+i, edev->ea[i]); + } + + edev->arg = edev; + + edev->attach = attach; + edev->shutdown = shutdown; + edev->ifstat = ifstat; + + if((ctlr->feat & (Fctrlvq|Fctrlrx)) == (Fctrlvq|Fctrlrx)){ + edev->multicast = multicast; + edev->promiscuous = promiscuous; + } + + pcisetbme(ctlr->pcidev); + intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name); + + return 0; +} + +void +ethervirtiolink(void) +{ + addethercard("virtio", reset); +} + From a6aa2842697aad70b46371be062dcc14d2ee8f48 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 044/402] sys/src/9/pc: add ethervirtio in kernel configurations --- sys/src/9/pc/pc | 1 + sys/src/9/pc/pcauth | 1 + sys/src/9/pc/pccd | 1 + sys/src/9/pc/pccpu | 1 + sys/src/9/pc/pccpuf | 1 + sys/src/9/pc/pcdisk | 1 + sys/src/9/pc/pcf | 1 + sys/src/9/pc/pcflop | 1 + sys/src/9/pc/pcfs | 1 + sys/src/9/pcboot/boot | 1 + 10 files changed, 10 insertions(+) diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index edb91f18dc..cd46dae1ed 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -71,6 +71,7 @@ link etherwavelan wavelan devi82365 cis pci # etherm10g pci ethermii # vast firmware # ether82598 pci + ethervirtio pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcauth b/sys/src/9/pc/pcauth index a44a9b7b9f..b52e542180 100644 --- a/sys/src/9/pc/pcauth +++ b/sys/src/9/pc/pcauth @@ -37,6 +37,7 @@ link ether82557 pci ethervt6102 pci ethermii ethervt6105m pci ethermii + ethervirtio pci ethermedium netdevmedium loopbackmedium diff --git a/sys/src/9/pc/pccd b/sys/src/9/pc/pccd index 9d8a82cead..ea9edaa9c5 100644 --- a/sys/src/9/pc/pccd +++ b/sys/src/9/pc/pccd @@ -70,6 +70,7 @@ link etherwavelan wavelan devi82365 cis pci # etherm10g pci ethermii # vast firmware # ether82598 pci + ethervirtio pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu index e3a7adb223..b13210365d 100644 --- a/sys/src/9/pc/pccpu +++ b/sys/src/9/pc/pccpu @@ -65,6 +65,7 @@ link etherwavelan wavelan devi82365 cis pci etherm10g pci ethermii ether82598 pci + ethervirtio pci ethermedium netdevmedium diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index 3ad5afacdf..9b53684f85 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -67,6 +67,7 @@ link etherwavelan wavelan devi82365 cis pci etherm10g pci ethermii ether82598 pci + ethervirtio pci ethermedium netdevmedium diff --git a/sys/src/9/pc/pcdisk b/sys/src/9/pc/pcdisk index 1e964cfa64..77ea4fccd1 100644 --- a/sys/src/9/pc/pcdisk +++ b/sys/src/9/pc/pcdisk @@ -68,6 +68,7 @@ link ethersink ethersmc devi82365 cis etherwavelan wavelan devi82365 cis pci + ethervirtio pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index fe824477a4..27d197d96c 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -68,6 +68,7 @@ link ethersink ethersmc devi82365 cis etherwavelan wavelan devi82365 cis pci + ethervirtio pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index 5ab025d238..a4ecd37660 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -63,6 +63,7 @@ link etherwavelan wavelan devi82365 cis pci # etherm10g pci ethermii # vast firmware # ether82598 pci + ethervirtio pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcfs b/sys/src/9/pc/pcfs index eb6aec6d0b..58b8656601 100644 --- a/sys/src/9/pc/pcfs +++ b/sys/src/9/pc/pcfs @@ -40,6 +40,7 @@ link etherigbe pci ethermii ethervt6105m pci ethermii ethersink + ethervirtio pci ethermedium netdevmedium loopbackmedium diff --git a/sys/src/9/pcboot/boot b/sys/src/9/pcboot/boot index 439f52a9b5..6adfaa3b29 100644 --- a/sys/src/9/pcboot/boot +++ b/sys/src/9/pcboot/boot @@ -39,6 +39,7 @@ link etherwavelan wavelan devi82365 cis pci etherm10g ether82598 pci + ethervirtio pci ethermedium From f43fa13b9e2fc66725543f9da4ca2521893418c8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 14:49:52 +0000 Subject: [PATCH 045/402] sys/src/9/pc: import sdvirtio10 from 9front (thanks Cinap Lenrek) --- sys/src/9/pc/sdvirtio10.c | 812 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 812 insertions(+) create mode 100644 sys/src/9/pc/sdvirtio10.c diff --git a/sys/src/9/pc/sdvirtio10.c b/sys/src/9/pc/sdvirtio10.c new file mode 100644 index 0000000000..e19d06afb7 --- /dev/null +++ b/sys/src/9/pc/sdvirtio10.c @@ -0,0 +1,812 @@ +/* + * virtio 1.0 disk driver + * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html + * + * In contrast to sdvirtio.c, this driver handles the non-legacy + * interface for virtio disk which uses mmio for all register accesses + * and requires a laborate pci capability structure dance to get working. + * + * It is kind of pointless as it is most likely slower than + * port i/o (harder to emulate on the pc platform). + * + * The reason why this driver is needed it is that vultr set the + * disable-legacy=on option in the -device parameter for qemu + * on their hypervisor. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +#include "../port/sd.h" + +typedef struct Vscsidev Vscsidev; +typedef struct Vblkdev Vblkdev; + +typedef struct Vconfig Vconfig; +typedef struct Vring Vring; +typedef struct Vdesc Vdesc; +typedef struct Vused Vused; +typedef struct Vqueue Vqueue; +typedef struct Vdev Vdev; + + +/* device types */ +enum { + TypBlk = 2, + TypSCSI = 8, +}; + +/* status flags */ +enum { + Acknowledge = 1, + Driver = 2, + FeaturesOk = 8, + DriverOk = 4, + Failed = 0x80, +}; + +/* descriptor flags */ +enum { + Next = 1, + Write = 2, + Indirect = 4, +}; + +/* struct sizes */ +enum { + VringSize = 4, +}; + +enum { + CDBSIZE = 32, + SENSESIZE = 96, +}; + + +struct Vscsidev +{ + u32int num_queues; + u32int seg_max; + u32int max_sectors; + u32int cmd_per_lun; + u32int event_info_size; + u32int sense_size; + u32int cdb_size; + u16int max_channel; + u16int max_target; + u32int max_lun; +}; + +struct Vblkdev +{ + u64int capacity; +}; + +struct Vconfig { + u32int devfeatsel; + u32int devfeat; + u32int drvfeatsel; + u32int drvfeat; + + u16int msixcfg; + u16int nqueues; + + u8int status; + u8int cfggen; + u16int queuesel; + + u16int queuesize; + u16int queuemsixvect; + + u16int queueenable; + u16int queuenotifyoff; + + u64int queuedesc; + u64int queueavail; + u64int queueused; +}; + +struct Vring +{ + u16int flags; + u16int idx; +}; + +struct Vdesc +{ + u64int addr; + u32int len; + u16int flags; + u16int next; +}; + +struct Vused +{ + u32int id; + u32int len; +}; + +struct Vqueue +{ + Lock; + + Vdev *dev; + void *notify; + int idx; + + int size; + + int free; + int nfree; + + Vdesc *desc; + + Vring *avail; + u16int *availent; + u16int *availevent; + + Vring *used; + Vused *usedent; + u16int *usedevent; + u16int lastused; + + void *rock[]; +}; + +struct Vdev +{ + int typ; + + Pcidev *pci; + + uvlong port; + ulong feat[2]; + + int nqueue; + Vqueue *queue[16]; + + void *dev; /* device specific config (for scsi) */ + + /* registers */ + Vconfig *cfg; + u8int *isr; + u8int *notify; + u32int notifyoffmult; + + Vdev *next; +}; + +static Vqueue* +mkvqueue(int size) +{ + Vqueue *q; + uchar *p; + int i; + + q = malloc(sizeof(*q) + sizeof(void*)*size); + p = mallocalign( + PGROUND(sizeof(Vdesc)*size + + VringSize + + sizeof(u16int)*size + + sizeof(u16int)) + + PGROUND(VringSize + + sizeof(Vused)*size + + sizeof(u16int)), + BY2PG, 0, 0); + if(p == nil || q == nil){ + print("virtio: no memory for Vqueue\n"); + free(p); + free(q); + return nil; + } + + q->desc = (void*)p; + p += sizeof(Vdesc)*size; + q->avail = (void*)p; + p += VringSize; + q->availent = (void*)p; + p += sizeof(u16int)*size; + q->availevent = (void*)p; + p += sizeof(u16int); + + p = (uchar*)PGROUND((uintptr)p); + q->used = (void*)p; + p += VringSize; + q->usedent = (void*)p; + p += sizeof(Vused)*size; + q->usedevent = (void*)p; + + q->free = -1; + q->nfree = q->size = size; + for(i=0; idesc[i].next = q->free; + q->free = i; + } + + return q; +} + +static int +matchvirtiocfgcap(Pcidev *p, int cap, int off, int typ) +{ + int bar; + + if(cap != 9 || pcicfgr8(p, off+3) != typ) + return 1; + + /* skip invalid or non memory bars */ + bar = pcicfgr8(p, off+4); + if(bar < 0 || bar >= nelem(p->mem) + || p->mem[bar].size == 0 + || (p->mem[bar].bar & 3) != 0) + return 1; + + return 0; +} + +static int +virtiocap(Pcidev *p, int typ) +{ + return pcienumcaps(p, matchvirtiocfgcap, typ); +} + +static void* +virtiomapregs(Pcidev *p, int cap, int size) +{ + int bar, len; + uvlong addr; + + if(cap < 0) + return nil; + bar = pcicfgr8(p, cap+4) % nelem(p->mem); + addr = pcicfgr32(p, cap+8); + len = pcicfgr32(p, cap+12); + if(size <= 0) + size = len; + else if(len < size) + return nil; + if(addr+len > p->mem[bar].size) + return nil; + addr += p->mem[bar].bar & ~0xFULL; + return vmap(addr, size); +} + +static Vdev* +viopnpdevs(int typ) +{ + Vdev *vd, *h, *t; + Vconfig *cfg; + Vqueue *q; + Pcidev *p; + int cap, bar; + int n, i; + + h = t = nil; + for(p = nil; p = pcimatch(p, 0x1AF4, 0x1040+typ);){ + if(p->rid == 0) + continue; + if((cap = virtiocap(p, 1)) < 0) + continue; + bar = pcicfgr8(p, cap+4) % nelem(p->mem); + cfg = virtiomapregs(p, cap, sizeof(Vconfig)); + if(cfg == nil) + continue; + if((vd = malloc(sizeof(*vd))) == nil){ + print("virtio: no memory for Vdev\n"); + break; + } + vd->port = p->mem[bar].bar & ~0xFULL; + vd->typ = typ; + vd->pci = p; + vd->cfg = cfg; + + vd->isr = virtiomapregs(p, virtiocap(p, 3), 0); + if(vd->isr == nil){ +Baddev: + /* TODO: vunmap */ + free(vd); + continue; + } + cap = virtiocap(p, 2); + vd->notify = virtiomapregs(p, cap, 0); + if(vd->notify == nil) + goto Baddev; + vd->notifyoffmult = pcicfgr32(p, cap+16); + + /* reset */ + cfg->status = 0; + while(cfg->status != 0) + delay(1); + cfg->status = Acknowledge|Driver; + + /* negotiate feature bits */ + cfg->devfeatsel = 1; + vd->feat[1] = cfg->devfeat; + cfg->devfeatsel = 0; + vd->feat[0] = cfg->devfeat; + cfg->drvfeatsel = 1; + cfg->drvfeat = vd->feat[1] & 1; + cfg->drvfeatsel = 0; + cfg->drvfeat = 0; + cfg->status |= FeaturesOk; + + for(i=0; iqueue); i++){ + cfg->queuesel = i; + n = cfg->queuesize; + if(n == 0 || (n & (n-1)) != 0) + break; + if((q = mkvqueue(n)) == nil) + break; + q->notify = vd->notify + vd->notifyoffmult * cfg->queuenotifyoff; + q->dev = vd; + q->idx = i; + vd->queue[i] = q; + coherence(); + cfg->queuedesc = PADDR(q->desc); + cfg->queueavail = PADDR(q->avail); + cfg->queueused = PADDR(q->used); + } + vd->nqueue = i; + + if(h == nil) + h = vd; + else + t->next = vd; + t = vd; + } + + return h; +} + +struct Rock { + int done; + Rendez *sleep; +}; + +static void +vqinterrupt(Vqueue *q) +{ + int id, free, m; + struct Rock *r; + Rendez *z; + + m = q->size-1; + + ilock(q); + while((q->lastused ^ q->used->idx) & m){ + id = q->usedent[q->lastused++ & m].id; + if(r = q->rock[id]){ + q->rock[id] = nil; + z = r->sleep; + r->done = 1; /* hands off */ + if(z != nil) + wakeup(z); + } + do { + free = id; + id = q->desc[free].next; + q->desc[free].next = q->free; + q->free = free; + q->nfree++; + } while(q->desc[free].flags & Next); + } + iunlock(q); +} + +static void +viointerrupt(Ureg *, void *arg) +{ + Vdev *vd = arg; + + if(vd->isr[0] & 1) + vqinterrupt(vd->queue[vd->typ == TypSCSI ? 2 : 0]); +} + +static int +viodone(void *arg) +{ + return ((struct Rock*)arg)->done; +} + +static void +vqio(Vqueue *q, int head) +{ + struct Rock rock; + + rock.done = 0; + rock.sleep = &up->sleep; + q->rock[head] = &rock; + q->availent[q->avail->idx & (q->size-1)] = head; + coherence(); + q->avail->idx++; + iunlock(q); + if((q->used->flags & 1) == 0) + *((u16int*)q->notify) = q->idx; + while(!rock.done){ + while(waserror()) + ; + tsleep(rock.sleep, viodone, &rock, 1000); + poperror(); + + if(!rock.done) + vqinterrupt(q); + } +} + +static int +vioblkreq(Vdev *vd, int typ, void *a, long count, long secsize, uvlong lba) +{ + int need, free, head; + Vqueue *q; + Vdesc *d; + + u8int status; + struct Vioblkreqhdr { + u32int typ; + u32int prio; + u64int lba; + } req; + + need = 2; + if(a != nil) + need = 3; + + status = -1; + req.typ = typ; + req.prio = 0; + req.lba = lba; + + q = vd->queue[0]; + ilock(q); + while(q->nfree < need){ + iunlock(q); + + if(!waserror()) + tsleep(&up->sleep, return0, 0, 500); + poperror(); + + ilock(q); + } + + head = free = q->free; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(&req); + d->len = sizeof(req); + d->flags = Next; + + if(a != nil){ + d = &q->desc[free]; free = d->next; + d->addr = PADDR(a); + d->len = secsize*count; + d->flags = typ ? Next : (Write|Next); + } + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(&status); + d->len = sizeof(status); + d->flags = Write; + + q->free = free; + q->nfree -= need; + + /* queue io, unlock and wait for completion */ + vqio(q, head); + + return status; +} + +static int +vioscsireq(SDreq *r) +{ + u8int resp[4+4+2+2+SENSESIZE]; + u8int req[8+8+3+CDBSIZE]; + int free, head; + u32int len; + Vqueue *q; + Vdesc *d; + Vdev *vd; + SDunit *u; + Vscsidev *scsi; + + u = r->unit; + vd = u->dev->ctlr; + scsi = vd->dev; + + memset(resp, 0, sizeof(resp)); + memset(req, 0, sizeof(req)); + req[0] = 1; + req[1] = u->subno; + req[2] = r->lun>>8; + req[3] = r->lun&0xFF; + *(u64int*)(&req[8]) = (uintptr)r; + + memmove(&req[8+8+3], r->cmd, r->clen); + + q = vd->queue[2]; + ilock(q); + while(q->nfree < 3){ + iunlock(q); + + if(!waserror()) + tsleep(&up->sleep, return0, 0, 500); + poperror(); + + ilock(q); + } + + head = free = q->free; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(req); + d->len = 8+8+3+scsi->cdb_size; + d->flags = Next; + + if(r->write && r->dlen > 0){ + d = &q->desc[free]; free = d->next; + d->addr = PADDR(r->data); + d->len = r->dlen; + d->flags = Next; + } + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(resp); + d->len = 4+4+2+2+scsi->sense_size; + d->flags = Write; + + if(!r->write && r->dlen > 0){ + d->flags |= Next; + + d = &q->desc[free]; free = d->next; + d->addr = PADDR(r->data); + d->len = r->dlen; + d->flags = Write; + } + + q->free = free; + q->nfree -= 2 + (r->dlen > 0); + + /* queue io, unlock and wait for completion */ + vqio(q, head); + + /* response+status */ + r->status = resp[10]; + if(resp[11] != 0) + r->status = SDcheck; + + /* sense_len */ + len = *((u32int*)&resp[0]); + if(len > 0){ + if(len > sizeof(r->sense)) + len = sizeof(r->sense); + memmove(r->sense, &resp[4+4+2+2], len); + r->flags |= SDvalidsense; + } + + /* data residue */ + len = *((u32int*)&resp[4]); + if(len > r->dlen) + r->rlen = 0; + else + r->rlen = r->dlen - len; + + return r->status; + +} + +static long +viobio(SDunit *u, int lun, int write, void *a, long count, uvlong lba) +{ + long ss, cc, max, ret; + Vdev *vd; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsibio(u, lun, write, a, count, lba); + + max = 32; + ss = u->secsize; + ret = 0; + while(count > 0){ + if((cc = count) > max) + cc = max; + if(vioblkreq(vd, write != 0, (uchar*)a + ret, cc, ss, lba) != 0) + error(Eio); + ret += cc*ss; + count -= cc; + lba += cc; + } + return ret; +} + +enum { + SDread, + SDwrite, +}; + +static int +viorio(SDreq *r) +{ + int i, count, rw; + uvlong lba; + SDunit *u; + Vdev *vd; + + u = r->unit; + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return vioscsireq(r); + if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ + if(vioblkreq(vd, 4, nil, 0, 0, 0) != 0) + return sdsetsense(r, SDcheck, 3, 0xc, 2); + return sdsetsense(r, SDok, 0, 0, 0); + } + if((i = sdfakescsi(r, nil, 0)) != SDnostatus) + return r->status = i; + if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus) + return i; + r->rlen = viobio(u, r->lun, rw == SDwrite, r->data, count, lba); + return r->status = SDok; +} + +static int +vioonline(SDunit *u) +{ + Vdev *vd; + Vblkdev *blk; + uvlong cap; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsionline(u); + + blk = vd->dev; + cap = blk->capacity; + if(u->sectors != cap){ + u->sectors = cap; + u->secsize = 512; + return 2; + } + return 1; +} + +static int +vioverify(SDunit *u) +{ + Vdev *vd; + + vd = u->dev->ctlr; + if(vd->typ == TypSCSI) + return scsiverify(u); + + return 1; +} + +SDifc sdvirtio10ifc; + +static int +vioenable(SDev *sd) +{ + char name[32]; + Vdev *vd; + int i; + + vd = sd->ctlr; + pcisetbme(vd->pci); + snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name); + intrenable(vd->pci->intl, viointerrupt, vd, vd->pci->tbdf, name); + coherence(); + + for(i = 0; i < vd->nqueue; i++){ + vd->cfg->queuesel = i; + vd->cfg->queueenable = 1; + } + vd->cfg->status |= DriverOk; + + return 1; +} + +static int +viodisable(SDev *sd) +{ + char name[32]; + Vdev *vd; + + vd = sd->ctlr; + snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name); + intrdisable(vd->pci->intl, viointerrupt, vd, vd->pci->tbdf, name); + pciclrbme(vd->pci); + return 1; +} + +static SDev* +viopnp(void) +{ + SDev *s, *h, *t; + Vdev *vd; + int id; + + h = t = nil; + + id = 'F'; + for(vd = viopnpdevs(TypBlk); vd; vd = vd->next){ + if(vd->nqueue == 0) + continue; + + if((vd->dev = virtiomapregs(vd->pci, virtiocap(vd->pci, 4), sizeof(Vblkdev))) == nil) + break; + if((s = malloc(sizeof(*s))) == nil) + break; + s->ctlr = vd; + s->idno = id++; + s->ifc = &sdvirtio10ifc; + s->nunit = 1; + if(h) + t->next = s; + else + h = s; + t = s; + } + + id = '0'; + for(vd = viopnpdevs(TypSCSI); vd; vd = vd->next){ + Vscsidev *scsi; + + if(vd->nqueue < 3) + continue; + + if((scsi = virtiomapregs(vd->pci, virtiocap(vd->pci, 4), sizeof(Vscsidev))) == nil) + break; + if(scsi->max_target == 0){ + vunmap(scsi, sizeof(Vscsidev)); + continue; + } + if((scsi->cdb_size > CDBSIZE) || (scsi->sense_size > SENSESIZE)){ + print("sdvirtio: cdb %ud or sense size %ud too big\n", + scsi->cdb_size, scsi->sense_size); + vunmap(scsi, sizeof(Vscsidev)); + continue; + } + vd->dev = scsi; + + if((s = malloc(sizeof(*s))) == nil) + break; + s->ctlr = vd; + s->idno = id++; + s->ifc = &sdvirtio10ifc; + s->nunit = scsi->max_target; + + if(h) + t->next = s; + else + h = s; + t = s; + } + return h; +} + +SDifc sdvirtio10ifc = { + "virtio10", /* name */ + + viopnp, /* pnp */ + nil, /* legacy */ + vioenable, /* enable */ + viodisable, /* disable */ + + vioverify, /* verify */ + vioonline, /* online */ + viorio, /* rio */ + nil, /* rctl */ + nil, /* wctl */ + + viobio, /* bio */ + nil, /* probe */ + nil, /* clear */ + nil, /* rtopctl */ + nil, /* wtopctl */ +}; From d1d1102d1677d26fbeab2ee5b7d33328517a81d1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 14:30:41 +0000 Subject: [PATCH 046/402] sys/src/9/pc: add sdvirtio10 in kernel configurations --- sys/src/9/pc/pc | 1 + sys/src/9/pc/pcauth | 1 + sys/src/9/pc/pccd | 1 + sys/src/9/pc/pccpu | 1 + sys/src/9/pc/pccpuf | 1 + sys/src/9/pc/pcdisk | 1 + sys/src/9/pc/pcf | 1 + sys/src/9/pc/pcflop | 1 + sys/src/9/pc/pcfs | 1 + sys/src/9/pcboot/load | 1 + 10 files changed, 10 insertions(+) diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index cd46dae1ed..092d9008b6 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -93,6 +93,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcauth b/sys/src/9/pc/pcauth index b52e542180..bd8d44e530 100644 --- a/sys/src/9/pc/pcauth +++ b/sys/src/9/pc/pcauth @@ -50,6 +50,7 @@ misc mtrr sdata pci sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 uartpci diff --git a/sys/src/9/pc/pccd b/sys/src/9/pc/pccd index ea9edaa9c5..82f574b8f1 100644 --- a/sys/src/9/pc/pccd +++ b/sys/src/9/pc/pccd @@ -89,6 +89,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu index b13210365d..3d5cf51ddd 100644 --- a/sys/src/9/pc/pccpu +++ b/sys/src/9/pc/pccpu @@ -92,6 +92,7 @@ misc sdiahci pci sdscsi sdaoe sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi ip tcp diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index 9b53684f85..e15c339479 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -90,6 +90,7 @@ misc sdiahci pci sdscsi sdaoe sdvirtio pci sdscsi + sdvirtio10 pci sdscsi vga3dfx +cur vgaark2000pv +cur diff --git a/sys/src/9/pc/pcdisk b/sys/src/9/pc/pcdisk index 77ea4fccd1..09dae2fa4c 100644 --- a/sys/src/9/pc/pcdisk +++ b/sys/src/9/pc/pcdisk @@ -89,6 +89,7 @@ misc sdiahci pci sdscsi sdaoe sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 27d197d96c..c8837996a8 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -89,6 +89,7 @@ misc sdiahci pci sdscsi sdaoe sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 uartpci pci diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index a4ecd37660..60a5960300 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -78,6 +78,7 @@ misc sdmylex pci sdscsi sdiahci pci sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi uarti8250 diff --git a/sys/src/9/pc/pcfs b/sys/src/9/pc/pcfs index 58b8656601..851290cbb9 100644 --- a/sys/src/9/pc/pcfs +++ b/sys/src/9/pc/pcfs @@ -61,6 +61,7 @@ misc sd53c8xx pci sdscsi sdmylex pci sdscsi sdvirtio pci sdscsi + sdvirtio10 pci sdscsi ip tcp diff --git a/sys/src/9/pcboot/load b/sys/src/9/pcboot/load index 8044e17b58..999a9ac371 100644 --- a/sys/src/9/pcboot/load +++ b/sys/src/9/pcboot/load @@ -32,6 +32,7 @@ misc sdiahci pci sdscsi # sdflop sdvirtio pci sdscsi + sdvirtio10 pci sdscsi port int cpuserver = 1; From 720ead3df2e91562ae0b335cedc622e460670e8c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 14:51:56 +0000 Subject: [PATCH 047/402] sys/src/9/pc: import ethervirtio10 from 9front (thanks Cinap Lenrek) --- sys/src/9/pc/ethervirtio10.c | 790 +++++++++++++++++++++++++++++++++++ 1 file changed, 790 insertions(+) create mode 100644 sys/src/9/pc/ethervirtio10.c diff --git a/sys/src/9/pc/ethervirtio10.c b/sys/src/9/pc/ethervirtio10.c new file mode 100644 index 0000000000..f444406306 --- /dev/null +++ b/sys/src/9/pc/ethervirtio10.c @@ -0,0 +1,790 @@ +/* + * virtio 1.0 ethernet driver + * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html + * + * In contrast to ethervirtio.c, this driver handles the non-legacy + * interface for virtio ethernet which uses mmio for all register accesses + * and requires a laborate pci capability structure dance to get working. + * + * It is kind of pointless as it is most likely slower than + * port i/o (harder to emulate on the pc platform). + * + * The reason why this driver is needed it is that vultr set the + * disable-legacy=on option in the -device parameter for qemu + * on their hypervisor. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" +#include "etherif.h" + +typedef struct Vconfig Vconfig; +typedef struct Vnetcfg Vnetcfg; + +typedef struct Vring Vring; +typedef struct Vdesc Vdesc; +typedef struct Vused Vused; +typedef struct Vheader Vheader; +typedef struct Vqueue Vqueue; + +typedef struct Ctlr Ctlr; + +enum { + /* §2.1 Device Status Field */ + Sacknowledge = 1, + Sdriver = 2, + Sdriverok = 4, + Sfeaturesok = 8, + Sfailed = 128, + + /* flags in Qnetstatus */ + Nlinkup = (1<<0), + Nannounce = (1<<1), + + /* feat[0] bits */ + Fmac = 1<<5, + Fstatus = 1<<16, + Fctrlvq = 1<<17, + Fctrlrx = 1<<18, + + /* feat[1] bits */ + Fversion1 = 1<<(32-32), + + /* vring used flags */ + Unonotify = 1, + /* vring avail flags */ + Rnointerrupt = 1, + + /* descriptor flags */ + Dnext = 1, + Dwrite = 2, + Dindirect = 4, + + /* struct sizes */ + VringSize = 4, + VdescSize = 16, + VusedSize = 8, + VheaderSize = 12, + + Vrxq = 0, + Vtxq = 1, + Vctlq = 2, + + /* class/cmd for Vctlq */ + CtrlRx = 0x00, + CmdPromisc = 0x00, + CmdAllmulti = 0x01, + CtrlMac = 0x01, + CmdMacTableSet = 0x00, + CtrlVlan= 0x02, + CmdVlanAdd = 0x00, + CmdVlanDel = 0x01, +}; + +struct Vconfig { + u32int devfeatsel; + u32int devfeat; + u32int drvfeatsel; + u32int drvfeat; + + u16int msixcfg; + u16int nqueues; + + u8int status; + u8int cfggen; + u16int queuesel; + + u16int queuesize; + u16int queuemsixvect; + + u16int queueenable; + u16int queuenotifyoff; + + u64int queuedesc; + u64int queueavail; + u64int queueused; +}; + +struct Vnetcfg +{ + u16int mac0; + u16int mac1; + u16int mac2; + u16int status; + u16int maxqueuepairs; + u16int mtu; +}; + +struct Vring +{ + u16int flags; + u16int idx; +}; + +struct Vdesc +{ + u64int addr; + u32int len; + u16int flags; + u16int next; +}; + +struct Vused +{ + u32int id; + u32int len; +}; + +struct Vheader +{ + u8int flags; + u8int segtype; + u16int hlen; + u16int seglen; + u16int csumstart; + u16int csumend; +}; + +struct Vqueue +{ + Rendez; + + uint qsize; + uint qmask; + + Vdesc *desc; + + Vring *avail; + u16int *availent; + u16int *availevent; + + Vring *used; + Vused *usedent; + u16int *usedevent; + u16int lastused; + + uint nintr; + uint nnote; + + /* notify register */ + void *notify; +}; + +struct Ctlr { + Lock; + + QLock ctllock; + + int attached; + + /* registers */ + Vconfig *cfg; + Vnetcfg *dev; + u8int *isr; + u8int *notify; + u32int notifyoffmult; + + uvlong port; + Pcidev *pcidev; + Ctlr *next; + int active; + ulong feat[2]; + int nqueue; + + /* virtioether has 3 queues: rx, tx and ctl */ + Vqueue queue[3]; +}; + +static Ctlr *ctlrhead; + +static int +vhasroom(void *v) +{ + Vqueue *q = v; + return q->lastused != q->used->idx; +} + +static void +vqnotify(Ctlr *ctlr, int x) +{ + Vqueue *q; + + coherence(); + q = &ctlr->queue[x]; + if(q->used->flags & Unonotify) + return; + q->nnote++; + *((u16int*)q->notify) = x; +} + +static void +txproc(void *v) +{ + Vheader *header; + Block **blocks; + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + Vused *u; + Block *b; + int i, j; + + edev = v; + ctlr = edev->ctlr; + q = &ctlr->queue[Vtxq]; + + header = smalloc(VheaderSize); + blocks = smalloc(sizeof(Block*) * (q->qsize/2)); + + for(i = 0; i < q->qsize/2; i++){ + j = i << 1; + q->desc[j].addr = PADDR(header); + q->desc[j].len = VheaderSize; + q->desc[j].next = j | 1; + q->desc[j].flags = Dnext; + + q->availent[i] = q->availent[i + q->qsize/2] = j; + + j |= 1; + q->desc[j].next = 0; + q->desc[j].flags = 0; + } + + q->avail->flags &= ~Rnointerrupt; + + while(waserror()) + ; + + while((b = qbread(edev->oq, 1000000)) != nil){ + for(;;){ + /* retire completed packets */ + while((i = q->lastused) != q->used->idx){ + u = &q->usedent[i & q->qmask]; + i = (u->id & q->qmask) >> 1; + if(blocks[i] == nil) + break; + freeb(blocks[i]); + blocks[i] = nil; + q->lastused++; + } + + /* have free slot? */ + i = q->avail->idx & (q->qmask >> 1); + if(blocks[i] == nil) + break; + + /* ring full, wait and retry */ + if(!vhasroom(q)) + sleep(q, vhasroom, q); + } + + /* slot is free, fill in descriptor */ + blocks[i] = b; + j = (i << 1) | 1; + q->desc[j].addr = PADDR(b->rp); + q->desc[j].len = BLEN(b); + coherence(); + q->avail->idx++; + vqnotify(ctlr, Vtxq); + } + + pexit("ether out queue closed", 1); +} + +static void +rxproc(void *v) +{ + Vheader *header; + Block **blocks; + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + Vused *u; + Block *b; + int i, j; + + edev = v; + ctlr = edev->ctlr; + q = &ctlr->queue[Vrxq]; + + header = smalloc(VheaderSize); + blocks = smalloc(sizeof(Block*) * (q->qsize/2)); + + for(i = 0; i < q->qsize/2; i++){ + j = i << 1; + q->desc[j].addr = PADDR(header); + q->desc[j].len = VheaderSize; + q->desc[j].next = j | 1; + q->desc[j].flags = Dwrite|Dnext; + + q->availent[i] = q->availent[i + q->qsize/2] = j; + + j |= 1; + q->desc[j].next = 0; + q->desc[j].flags = Dwrite; + } + + q->avail->flags &= ~Rnointerrupt; + + while(waserror()) + ; + + for(;;){ + /* replenish receive ring */ + do { + i = q->avail->idx & (q->qmask >> 1); + if(blocks[i] != nil) + break; + if((b = iallocb(ETHERMAXTU)) == nil) + break; + blocks[i] = b; + j = (i << 1) | 1; + q->desc[j].addr = PADDR(b->rp); + q->desc[j].len = BALLOC(b); + coherence(); + q->avail->idx++; + } while(q->avail->idx != q->used->idx); + vqnotify(ctlr, Vrxq); + + /* wait for any packets to complete */ + if(!vhasroom(q)) + sleep(q, vhasroom, q); + + /* retire completed packets */ + while((i = q->lastused) != q->used->idx) { + u = &q->usedent[i & q->qmask]; + i = (u->id & q->qmask) >> 1; + if((b = blocks[i]) == nil) + break; + + blocks[i] = nil; + b->wp = b->rp + u->len - VheaderSize; + etheriq(edev, b, 1); + q->lastused++; + } + } +} + +static int +vctlcmd(Ether *edev, uchar class, uchar cmd, uchar *data, int ndata) +{ + uchar hdr[2], ack[1]; + Ctlr *ctlr; + Vqueue *q; + Vdesc *d; + int i; + + ctlr = edev->ctlr; + q = &ctlr->queue[Vctlq]; + if(q->qsize < 3) + return -1; + + qlock(&ctlr->ctllock); + while(waserror()) + ; + + ack[0] = 0x55; + hdr[0] = class; + hdr[1] = cmd; + + d = &q->desc[0]; + d->addr = PADDR(hdr); + d->len = sizeof(hdr); + d->next = 1; + d->flags = Dnext; + d++; + d->addr = PADDR(data); + d->len = ndata; + d->next = 2; + d->flags = Dnext; + d++; + d->addr = PADDR(ack); + d->len = sizeof(ack); + d->next = 0; + d->flags = Dwrite; + + i = q->avail->idx & q->qmask; + q->availent[i] = 0; + coherence(); + + q->avail->flags &= ~Rnointerrupt; + q->avail->idx++; + vqnotify(ctlr, Vctlq); + while(!vhasroom(q)) + sleep(q, vhasroom, q); + q->lastused = q->used->idx; + q->avail->flags |= Rnointerrupt; + + qunlock(&ctlr->ctllock); + poperror(); + + if(ack[0] != 0) + print("#l%d: vctlcmd: %ux.%ux -> %ux\n", edev->ctlrno, class, cmd, ack[0]); + + return ack[0]; +} + +static void +interrupt(Ureg*, void* arg) +{ + Ether *edev; + Ctlr *ctlr; + Vqueue *q; + int i; + + edev = arg; + ctlr = edev->ctlr; + if(*ctlr->isr & 1){ + for(i = 0; i < ctlr->nqueue; i++){ + q = &ctlr->queue[i]; + if(vhasroom(q)){ + q->nintr++; + wakeup(q); + } + } + } +} + +static void +attach(Ether* edev) +{ + char name[KNAMELEN]; + Ctlr* ctlr; + int i; + + ctlr = edev->ctlr; + ilock(ctlr); + if(ctlr->attached){ + iunlock(ctlr); + return; + } + ctlr->attached = 1; + + /* enable the queues */ + for(i = 0; i < ctlr->nqueue; i++){ + ctlr->cfg->queuesel = i; + ctlr->cfg->queueenable = 1; + } + + /* driver is ready */ + ctlr->cfg->status |= Sdriverok; + + iunlock(ctlr); + + /* start kprocs */ + snprint(name, sizeof name, "#l%drx", edev->ctlrno); + kproc(name, rxproc, edev); + snprint(name, sizeof name, "#l%dtx", edev->ctlrno); + kproc(name, txproc, edev); +} + +static long +ifstat(Ether *edev, void *a, long n, ulong offset) +{ + int i, l; + char *p; + Ctlr *ctlr; + Vqueue *q; + + ctlr = edev->ctlr; + + p = smalloc(READSTR); + + l = snprint(p, READSTR, "devfeat %32.32luX %32.32luX\n", ctlr->feat[1], ctlr->feat[0]); + l += snprint(p+l, READSTR-l, "devstatus %8.8uX\n", ctlr->cfg->status); + + for(i = 0; i < ctlr->nqueue; i++){ + q = &ctlr->queue[i]; + l += snprint(p+l, READSTR-l, + "vq%d %#p size %d avail->idx %d used->idx %d lastused %hud nintr %ud nnote %ud\n", + i, q, q->qsize, q->avail->idx, q->used->idx, q->lastused, q->nintr, q->nnote); + } + + n = readstr(offset, a, n, p); + free(p); + + return n; +} + +static void +shutdown(Ether* edev) +{ + Ctlr *ctlr = edev->ctlr; + + coherence(); + ctlr->cfg->status = 0; + coherence(); + + pciclrbme(ctlr->pcidev); +} + +static void +promiscuous(void *arg, int on) +{ + Ether *edev = arg; + uchar b[1]; + + b[0] = on != 0; + vctlcmd(edev, CtrlRx, CmdPromisc, b, sizeof(b)); +} + +static void +multicast(void *arg, uchar*, int) +{ + Ether *edev = arg; + uchar b[1]; + + b[0] = edev->nmaddr > 0; + vctlcmd(edev, CtrlRx, CmdAllmulti, b, sizeof(b)); +} + +static int +initqueue(Vqueue *q, int size) +{ + uchar *p; + + q->desc = mallocalign(VdescSize*size, 16, 0, 0); + if(q->desc == nil) + return -1; + p = mallocalign(VringSize + 2*size + 2, 2, 0, 0); + if(p == nil){ +FreeDesc: + free(q->desc); + q->desc = nil; + return -1; + } + q->avail = (void*)p; + p += VringSize; + q->availent = (void*)p; + p += sizeof(u16int)*size; + q->availevent = (void*)p; + p = mallocalign(VringSize + VusedSize*size + 2, 4, 0, 0); + if(p == nil){ + free(q->avail); + q->avail = nil; + goto FreeDesc; + } + q->used = (void*)p; + p += VringSize; + q->usedent = (void*)p; + p += VusedSize*size; + q->usedevent = (void*)p; + + q->qsize = size; + q->qmask = q->qsize - 1; + + q->lastused = q->avail->idx = q->used->idx = 0; + + q->avail->flags |= Rnointerrupt; + + return 0; +} + +static int +matchvirtiocfgcap(Pcidev *p, int cap, int off, int typ) +{ + int bar; + + if(cap != 9 || pcicfgr8(p, off+3) != typ) + return 1; + + /* skip invalid or non memory bars */ + bar = pcicfgr8(p, off+4); + if(bar < 0 || bar >= nelem(p->mem) + || p->mem[bar].size == 0 + || (p->mem[bar].bar & 3) != 0) + return 1; + + return 0; +} + +static int +virtiocap(Pcidev *p, int typ) +{ + return pcienumcaps(p, matchvirtiocfgcap, typ); +} + +static void* +virtiomapregs(Pcidev *p, int cap, int size) +{ + int bar, len; + uvlong addr; + + if(cap < 0) + return nil; + bar = pcicfgr8(p, cap+4) % nelem(p->mem); + addr = pcicfgr32(p, cap+8); + len = pcicfgr32(p, cap+12); + if(size <= 0) + size = len; + else if(len < size) + return nil; + if(addr+len > p->mem[bar].size) + return nil; + addr += p->mem[bar].bar & ~0xFULL; + return vmap(addr, size); +} + +static Ctlr* +pciprobe(void) +{ + Ctlr *c, *h, *t; + Pcidev *p; + Vconfig *cfg; + int bar, cap, n, i; + + h = t = nil; + + /* §4.1.2 PCI Device Discovery */ + for(p = nil; p = pcimatch(p, 0x1AF4, 0x1041);){ + /* non-transitional devices will have a revision > 0 */ + if(p->rid == 0) + continue; + if((cap = virtiocap(p, 1)) < 0) + continue; + bar = pcicfgr8(p, cap+4) % nelem(p->mem); + cfg = virtiomapregs(p, cap, sizeof(Vconfig)); + if(cfg == nil) + continue; + if((c = mallocz(sizeof(Ctlr), 1)) == nil){ + print("ethervirtio: no memory for Ctlr\n"); + break; + } + c->cfg = cfg; + c->pcidev = p; + c->port = p->mem[bar].bar & ~0xFULL; + + c->dev = virtiomapregs(p, virtiocap(p, 4), sizeof(Vnetcfg)); + if(c->dev == nil) + goto Baddev; + c->isr = virtiomapregs(p, virtiocap(p, 3), 0); + if(c->isr == nil) + goto Baddev; + cap = virtiocap(p, 2); + c->notify = virtiomapregs(p, cap, 0); + if(c->notify == nil) + goto Baddev; + c->notifyoffmult = pcicfgr32(p, cap+16); + + /* device reset */ + coherence(); + cfg->status = 0; + while(cfg->status != 0) + delay(1); + cfg->status = Sacknowledge|Sdriver; + + /* negotiate feature bits */ + cfg->devfeatsel = 1; + c->feat[1] = cfg->devfeat; + + cfg->devfeatsel = 0; + c->feat[0] = cfg->devfeat; + + cfg->drvfeatsel = 1; + cfg->drvfeat = c->feat[1] & Fversion1; + + cfg->drvfeatsel = 0; + cfg->drvfeat = c->feat[0] & (Fmac|Fctrlvq|Fctrlrx); + + cfg->status |= Sfeaturesok; + + for(i=0; iqueue); i++){ + cfg->queuesel = i; + n = cfg->queuesize; + if(n == 0 || (n & (n-1)) != 0){ + if(i < 2) + print("ethervirtio: queue %d has invalid size %d\n", i, n); + break; + } + if(initqueue(&c->queue[i], n) < 0) + break; + c->queue[i].notify = c->notify + c->notifyoffmult * cfg->queuenotifyoff; + coherence(); + cfg->queuedesc = PADDR(c->queue[i].desc); + cfg->queueavail = PADDR(c->queue[i].avail); + cfg->queueused = PADDR(c->queue[i].used); + } + if(i < 2){ + print("ethervirtio: no queues\n"); +Baddev: + /* TODO, vunmap */ + free(c); + continue; + } + c->nqueue = i; + + if(h == nil) + h = c; + else + t->next = c; + t = c; + } + + return h; +} + + +static int +reset(Ether* edev) +{ + static uchar zeros[Eaddrlen]; + Ctlr *ctlr; + int i; + + if(ctlrhead == nil) + ctlrhead = pciprobe(); + + for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ + if(ctlr->active) + continue; + if(edev->port == 0 || edev->port == ctlr->port){ + ctlr->active = 1; + break; + } + } + + if(ctlr == nil) + return -1; + + edev->ctlr = ctlr; + edev->port = ctlr->port; + edev->irq = ctlr->pcidev->intl; + edev->tbdf = ctlr->pcidev->tbdf; + edev->mbps = 1000; + edev->link = 1; + + if((ctlr->feat[0] & Fmac) != 0 && memcmp(edev->ea, zeros, Eaddrlen) == 0){ + for(i = 0; i < Eaddrlen; i++) + edev->ea[i] = ((uchar*)ctlr->dev)[i]; + } else { + for(i = 0; i < Eaddrlen; i++) + ((uchar*)ctlr->dev)[i] = edev->ea[i]; + } + + edev->arg = edev; + + edev->attach = attach; + edev->shutdown = shutdown; + edev->ifstat = ifstat; + + if((ctlr->feat[0] & (Fctrlvq|Fctrlrx)) == (Fctrlvq|Fctrlrx)){ + edev->multicast = multicast; + edev->promiscuous = promiscuous; + } + + pcisetbme(ctlr->pcidev); + intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name); + + return 0; +} + +void +ethervirtio10link(void) +{ + addethercard("virtio10", reset); +} From 714ed94df0fad6cc77fd1dbd2fbf7fdaf6f4ffc8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 14:51:57 +0000 Subject: [PATCH 048/402] sys/src/9/pc: add ethervirtio10 in kernel configurations --- sys/src/9/pc/pc | 1 + sys/src/9/pc/pcauth | 1 + sys/src/9/pc/pccd | 1 + sys/src/9/pc/pccpu | 1 + sys/src/9/pc/pccpuf | 1 + sys/src/9/pc/pcdisk | 1 + sys/src/9/pc/pcf | 1 + sys/src/9/pc/pcflop | 1 + sys/src/9/pc/pcfs | 1 + sys/src/9/pcboot/boot | 1 + 10 files changed, 10 insertions(+) diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 092d9008b6..b5e68a1b39 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -72,6 +72,7 @@ link # etherm10g pci ethermii # vast firmware # ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcauth b/sys/src/9/pc/pcauth index bd8d44e530..5d8f4cc813 100644 --- a/sys/src/9/pc/pcauth +++ b/sys/src/9/pc/pcauth @@ -38,6 +38,7 @@ link ethervt6102 pci ethermii ethervt6105m pci ethermii ethervirtio pci + ethervirtio10 pci ethermedium netdevmedium loopbackmedium diff --git a/sys/src/9/pc/pccd b/sys/src/9/pc/pccd index 82f574b8f1..9cf122d490 100644 --- a/sys/src/9/pc/pccd +++ b/sys/src/9/pc/pccd @@ -71,6 +71,7 @@ link # etherm10g pci ethermii # vast firmware # ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pccpu b/sys/src/9/pc/pccpu index 3d5cf51ddd..0ca22b788b 100644 --- a/sys/src/9/pc/pccpu +++ b/sys/src/9/pc/pccpu @@ -66,6 +66,7 @@ link etherm10g pci ethermii ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium netdevmedium diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf index e15c339479..68476e175e 100644 --- a/sys/src/9/pc/pccpuf +++ b/sys/src/9/pc/pccpuf @@ -68,6 +68,7 @@ link etherm10g pci ethermii ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium netdevmedium diff --git a/sys/src/9/pc/pcdisk b/sys/src/9/pc/pcdisk index 09dae2fa4c..716a6aaf31 100644 --- a/sys/src/9/pc/pcdisk +++ b/sys/src/9/pc/pcdisk @@ -69,6 +69,7 @@ link ethersmc devi82365 cis etherwavelan wavelan devi82365 cis pci ethervirtio pci + ethervirtio10 pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index c8837996a8..9915b575bf 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -69,6 +69,7 @@ link ethersmc devi82365 cis etherwavelan wavelan devi82365 cis pci ethervirtio pci + ethervirtio10 pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcflop b/sys/src/9/pc/pcflop index 60a5960300..f7cca07cbb 100644 --- a/sys/src/9/pc/pcflop +++ b/sys/src/9/pc/pcflop @@ -64,6 +64,7 @@ link # etherm10g pci ethermii # vast firmware # ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium pcmciamodem diff --git a/sys/src/9/pc/pcfs b/sys/src/9/pc/pcfs index 851290cbb9..10181c9cb4 100644 --- a/sys/src/9/pc/pcfs +++ b/sys/src/9/pc/pcfs @@ -41,6 +41,7 @@ link ethervt6105m pci ethermii ethersink ethervirtio pci + ethervirtio10 pci ethermedium netdevmedium loopbackmedium diff --git a/sys/src/9/pcboot/boot b/sys/src/9/pcboot/boot index 6adfaa3b29..473f91c0d5 100644 --- a/sys/src/9/pcboot/boot +++ b/sys/src/9/pcboot/boot @@ -40,6 +40,7 @@ link etherm10g ether82598 pci ethervirtio pci + ethervirtio10 pci ethermedium From 6d3ccaec37ac9cc3743ce83ef4a9c29be7ddd24f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 20:38:17 +0000 Subject: [PATCH 049/402] sys/src/9/port: fix imagereclaim (thanks Richard Miller) --- sys/src/9/port/page.c | 2 +- sys/src/9/port/portfns.h | 1 + sys/src/9/port/segment.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c index b99e3588bb..86895ed299 100644 --- a/sys/src/9/port/page.c +++ b/sys/src/9/port/page.c @@ -64,7 +64,7 @@ pageinit(void) print("%ldM swap\n", vkb/1024); } -static void +void pageunchain(Page *p) { if(canlock(&palloc)) diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 5894c8f268..af68b0889a 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -215,6 +215,7 @@ void pagechainhead(Page*); void pageinit(void); ulong pagenumber(Page*); void pagersummary(void); +void pageunchain(Page *p); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); void pathclose(Path*); diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c index 92432a4f50..a42303922f 100644 --- a/sys/src/9/port/segment.c +++ b/sys/src/9/port/segment.c @@ -344,6 +344,8 @@ imagereclaim(void) if(p->ref == 0) { n++; uncachepage(p); + pageunchain(p); + pagechainhead(p); } unlock(p); } From a5d34f490b05fb0171af08016df06e42af112569 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 20:35:02 +0000 Subject: [PATCH 050/402] sys/src/9/port: fix test for overlapping segments in ibrk and isoverlap (thanks Richard Miller) --- sys/src/9/port/segment.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/src/9/port/segment.c b/sys/src/9/port/segment.c index a42303922f..74d6c3e433 100644 --- a/sys/src/9/port/segment.c +++ b/sys/src/9/port/segment.c @@ -486,7 +486,7 @@ ibrk(ulong addr, int seg) ns = up->seg[i]; if(ns == 0 || ns == s) continue; - if(newtop >= ns->base && newtop < ns->top) { + if(newtop > ns->base && s->base < ns->top) { qunlock(&s->lk); error(Esoverlap); } @@ -588,8 +588,7 @@ isoverlap(Proc *p, ulong va, int len) ns = p->seg[i]; if(ns == 0) continue; - if((newtop > ns->base && newtop <= ns->top) || - (va >= ns->base && va < ns->top)) + if(newtop > ns->base && va < ns->top) return ns; } return nil; From ddfb3cb8b49d0b5e3a3cdce9356a48d12015da8e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 20:37:13 +0000 Subject: [PATCH 051/402] sys/src/9/port: fix livelock in rebalance (thanks Richard Miller) --- sys/src/9/port/proc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index af0b4bacbf..398a89c79b 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -476,8 +476,6 @@ rebalance(void) p = rq->head; if(p == nil) continue; - if(p->mp != MACHP(m->machno)) - continue; if(pri == p->basepri) continue; updatecpu(p); From ed8fedb507d4a74b4ab2186fc3f828c5db84253f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 20:37:43 +0000 Subject: [PATCH 052/402] sys/src/9/port: fix logic error in procflushseg (thanks Richard Miller) --- sys/src/9/port/proc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 398a89c79b..7b95ee7b0e 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1307,7 +1307,7 @@ procdump(void) /* * wait till all processes have flushed their mmu - * state about segement s + * state about segment s */ void procflushseg(Segment *s) @@ -1344,10 +1344,13 @@ procflushseg(Segment *s) * wait for all processors to take a clock interrupt * and flush their mmu's */ - for(nm = 0; nm < conf.nmach; nm++) - if(MACHP(nm) != m) - while(MACHP(nm)->flushmmu) - sched(); +again: + for(nm = 0; nm < conf.nmach; nm++){ + if(nm != m->machno && MACHP(nm)->flushmmu){ + sched(); + goto again; + } + } } void From 86f7352683ff391372176d0e53f2465cbb5a6a60 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 16:16:11 +0000 Subject: [PATCH 053/402] sys/src/9/port: fix "no living children" issue (thanks Richard Miller) --- sys/src/9/port/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 7b95ee7b0e..711fe167d1 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1116,7 +1116,7 @@ pexit(char *exitstr, int freemem) * if not a kernel process and have a parent, * do some housekeeping. */ - if(up->kp == 0) { + if(up->kp == 0 && up->parentpid != 0) { p = up->parent; if(p == 0) { if(exitstr == 0) From e9afa8c40c3187b8e301a68fd1b44ed41e1c0518 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 8 Mar 2016 20:58:45 +0000 Subject: [PATCH 054/402] sys/src/9/port: fix coherence in unlock and iunlock (multicore ARM) (thanks Richard Miller) --- sys/src/9/port/taslock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/9/port/taslock.c b/sys/src/9/port/taslock.c index ae3445dd09..6296b16802 100644 --- a/sys/src/9/port/taslock.c +++ b/sys/src/9/port/taslock.c @@ -209,6 +209,7 @@ unlock(Lock *l) if(l->p != up) print("unlock: up changed: pc %#p, acquired at pc %lux, lock p %#p, unlock up %#p\n", getcallerpc(&l), l->pc, l->p, up); l->m = nil; + coherence(); l->key = 0; coherence(); @@ -248,6 +249,7 @@ iunlock(Lock *l) sr = l->sr; l->m = nil; + coherence(); l->key = 0; coherence(); m->ilockdepth--; From 7215c7da99a5bdc79502823f95d9ae457abbe49a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 16:23:08 +0000 Subject: [PATCH 055/402] sys/src/9/port: move close-on-exec after up->nnote is cleared (thanks Richard Miller) --- sys/src/9/port/sysproc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index d8098d8ee3..36196774d4 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -421,13 +421,6 @@ sysexec(ulong *arg) } } - /* - * Close on exec - */ - f = up->fgrp; - for(i=0; i<=f->maxfd; i++) - fdclose(i, CCEXEC); - /* Text. Shared. Attaches to cache image if possible */ /* attachimage returns a locked cache image */ img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); @@ -480,6 +473,7 @@ sysexec(ulong *arg) flushmmu(); qlock(&up->debug); up->nnote = 0; + up->notepending = 0; up->notify = 0; up->notified = 0; up->privatemem = 0; @@ -488,6 +482,13 @@ sysexec(ulong *arg) if(up->hang) up->procctl = Proc_stopme; + /* + * Close on exec + */ + f = up->fgrp; + for(i=0; i<=f->maxfd; i++) + fdclose(i, CCEXEC); + return execregs(entry, ssize, nargs); } From 6207e22e5d67edf651f4750b644cdd675314b729 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 21:13:45 +0000 Subject: [PATCH 056/402] sys/src/9/ip: set MSS on incoming TCP connections --- sys/src/9/ip/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c index eb88a719a2..f472284c61 100644 --- a/sys/src/9/ip/tcp.c +++ b/sys/src/9/ip/tcp.c @@ -1774,11 +1774,13 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version) tcb->flgcnt = 0; tcb->flags |= SYNACK; + /* set desired mss and scale */ + tcb->mss = tcpmtu(s->p, dst, s->ipversion, &tcb->scale); + /* our sending max segment size cannot be bigger than what he asked for */ - if(lp->mss != 0 && lp->mss < tcb->mss) { + if(lp->mss != 0 && lp->mss < tcb->mss) tcb->mss = lp->mss; - tpriv->stats[Mss] = tcb->mss; - } + tpriv->stats[Mss] = tcb->mss; /* window scaling */ tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale); From 5a9f5b72cdfe02e7c03302b7d596becfb9e272dd Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 5 May 2016 20:42:02 +0000 Subject: [PATCH 057/402] sys/src/9/ip: fix cb->f[0] nil dereference due to short control request (thanks Cinap Lenrek) --- sys/src/9/ip/iproute.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/src/9/ip/iproute.c b/sys/src/9/ip/iproute.c index 6055374a80..12ec16ee76 100644 --- a/sys/src/9/ip/iproute.c +++ b/sys/src/9/ip/iproute.c @@ -817,6 +817,9 @@ routewrite(Fs *f, Chan *c, char *p, int n) nexterror(); } + if(cb->nf < 1) + error("short control request"); + if(strcmp(cb->f[0], "flush") == 0){ tag = cb->f[1]; for(h = 0; h < nelem(f->v4root); h++) @@ -880,7 +883,8 @@ routewrite(Fs *f, Chan *c, char *p, int n) print("no route\n"); else printroute(q); - } + } else + error(Ebadctl); poperror(); free(cb); From 35616d48a8a9ae73e1cc55cad56a816612b1fc52 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 07:50:32 +0000 Subject: [PATCH 058/402] sys/src/9/port: don't update the channel offset in pread --- sys/src/9/port/sysfile.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c index 18fdeeb1b1..84eaeb0b08 100644 --- a/sys/src/9/port/sysfile.c +++ b/sys/src/9/port/sysfile.c @@ -680,10 +680,12 @@ read(ulong *arg, vlong *offp) }else nnn = nn = devtab[c->type]->read(c, p, n, off); - lock(c); - c->devoffset += nn; - c->offset += nnn; - unlock(c); + if(c->qid.type & QTDIR || offp == nil){ + lock(c); + c->devoffset += nn; + c->offset += nnn; + unlock(c); + } poperror(); cclose(c); From fd174e763b3613a7941945fde8175e6f522a124e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 20:43:44 +0000 Subject: [PATCH 059/402] sys/src/9/port: fix 32-bit unsigned complement zero-extended to 64 bits (thanks Geoff Collyer) --- sys/src/9/port/sysfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c index 84eaeb0b08..68b9bb56f4 100644 --- a/sys/src/9/port/sysfile.c +++ b/sys/src/9/port/sysfile.c @@ -1234,8 +1234,8 @@ packoldstat(uchar *buf, Dir *d) p += 28; strncpy((char*)p, d->gid, 28); p += 28; - q = d->qid.path & ~DMDIR; /* make sure doesn't accidentally look like directory */ - if((ulong)d->qid.type & QTDIR) /* this is the real test of a new directory */ + q = d->qid.path & ~(uvlong)DMDIR; /* make sure doesn't accidentally look like directory */ + if(d->qid.type & QTDIR) /* this is the real test of a new directory */ q |= DMDIR; PBIT32(p, q); p += BIT32SZ; From 850d06b0e48e987f2ad555eed0f0aa92f247afbb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 13 Feb 2021 19:48:37 +0000 Subject: [PATCH 060/402] sys/man: import i2c, gpio and spi manuals (thanks Brian L. Stuart) --- sys/man/3/gpio | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ sys/man/3/i2c | 85 +++++++++++++++++++++++++++++++++++++++++++ sys/man/3/spi | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 sys/man/3/gpio create mode 100644 sys/man/3/i2c create mode 100644 sys/man/3/spi diff --git a/sys/man/3/gpio b/sys/man/3/gpio new file mode 100644 index 0000000000..ad41986bee --- /dev/null +++ b/sys/man/3/gpio @@ -0,0 +1,99 @@ +.TH GPIO 3 +.SH NAME +gpio \- access to Raspberry Pi GPIO pins +.SH SYNOPSIS +.B bind -a #G /dev +.PP +.B /dev/gpio +.fi +.SH DESCRIPTION +.I Gpio +serves a single file that provides access to the GPIO pins on the +Raspberry Pi. +Reads from the file receive a 16-character hexadecimal string +representing a +.B vlong +giving the values of up to 64 GPIO lines. +(The processor on both the first and second generation Pis provides +54 actual GPIO lines.) +The proper method for sampling GPIO 27 is as follows: +.IP +.B read(gfd, buf, 16); +.br +.B buf[16] = 0; +.br +.B gvals = strtoull(buf, nil, 16); +.br +.B "pin27 = gvals & (1 << 27);" +.PP +Writes to +.B gpio +control the characteristics and output values of GPIO lines. +The exact operation is specified by one of the following commands: +.TP +.BI function " pin f" +Set the function of GPIO +.I pin +to +.I f. +The valid values for +.I f +are: +.BR in , +.BR out , +.BR alt0 , +.BR alt1 , +.BR alt2 , +.BR alt3 , +.BR alt4 , +.BR atl5 , +and +.BR pulse . +The functions +.B in +and +.B out +set the specified GPIO line to be a general purpose input +and output, respectively. +The various +.BI alt n +functions are as specified in the Broadcom documentation and +differ on a per-pin basis. +The +.B pulse +function is somewhat specialized. +It causes the pin to be set to an output for +2μS and then to be set to a input. +With the value of the line set to 0 and a pullup resistor on the +line, this operation provides a short low pulse suitable for bit-banging +a 1-wire interface. +.TP +.BI pullup " pin" +Enables the internal pullup resistor for the specified GPIO pin. +.TP +.BI pulldown " pin" +Enables the internal pulldown resistor for the specified GPIO pin. +.TP +.BI float " pin" +Disables both internal pullup and pulldown resistors for the specified +GPIO pin. +.TP +.BI set " pin value" +For GPIO pins set to the output function, this command sets the output +value for the pin. +The +.I value +should be either 0 or 1. +.SH NOTES +All pin number references are according to the SoC documentation. +These GPIO signal numbers do +.I not +match the pin numbers on the header on the Pi board. +Reads sample the external signal values. +As a result, the values read for output pins might not match +the value written to them if externally they are driven harder +than the SoC drives them. +.SH SOURCE +.B /sys/src/9/bcm/devgpio.c +.br +.B /sys/src/9/bcm/gpio.c diff --git a/sys/man/3/i2c b/sys/man/3/i2c new file mode 100644 index 0000000000..8f394df140 --- /dev/null +++ b/sys/man/3/i2c @@ -0,0 +1,85 @@ +.TH I2C 3 +.SH NAME +i2c \- basic I2C interface +.SH SYNOPSIS +.B bind -a +.BI #J n +.B /dev +.PP +.BI /dev/i2c. n .ctl +. br +.BI /dev/i2c. n .data +.fi +.SH DESCRIPTION +.I I2c +serves a one-level directory with two files +that give access to the target device with address +.I n +(given in hexadecimal) +on the system's I2C bus. +.I N +is usually determined by the I2C device manufacturer. +I2C gives address 0 special meaning as the `general call' address. +See an I2C specification for details. +.PP +The control file +.BI i2c. n .ctl +accepts commands to set the valid address range and +subaddressing mode for the corresponding data file. +The following control messages can be written to it: +.TP +.B a10 +Force 10-bit addressing instead of 7-bit addressing. +Otherwise 10-bit addressing is used only if the device address +.I n +is bigger than 255. +.TP +.BI size " nbytes" +.br +Set the logical size of the target device to +.IR nbytes . +(By default when opened, it is 256 bytes, enough for most small I2C devices.) +IO requests will be kept within this limit. +This value is also returned by +.B Sys->stat +as the length of the data file. +.TP +.BI subaddress " \fR[\fP n \fR]\fP" +.br +Cause subsequent reads and writes +on the data file to use I2C subaddressing +with +.I n +byte subaddresses (default: 1 byte). +.I N +must be no larger than 4. +The target device must support subaddressing. +By default, the device is not subaddressed. +Setting +.I n +to zero switches off subaddressing. +.PP +When read, +the control file displays the current settings. +.PP +The data file +.BI i2c. n .data +can be read or written to +exchange data with the slave device with address +.I n +(where +.I n +is given in hexadecimal). +Each write request transmits the given data +to the device. +Each read request sends a receive +request to the device and returns the resulting data. +If the I2C target is subaddressed, the current file offset +is used as the subaddress; +otherwise the file offset is ignored, and the device typically starts at 0 for each transfer request. +Read and write requests are trimmed to the declared +size of the device. +.SH SOURCE +.B /sys/src/9/bcm/devi2c.c +.br +.B /sys/src/9/bcm/i2c.c diff --git a/sys/man/3/spi b/sys/man/3/spi new file mode 100644 index 0000000000..13ba21d867 --- /dev/null +++ b/sys/man/3/spi @@ -0,0 +1,66 @@ +.TH SPI 3 +.SH NAME +spi \- access to the main Raspberry Pi SPI interface +.SH SYNOPSIS +.B bind -a #π /dev +.PP +.B /dev/spictl +.br +.B /dev/spi0 +.br +.B /dev/spi1 +.SH DESCRIPTION +The Broadcom SoC on the Raspberry Pi has three SPI interfaces: +the main SPI interface, designated SPI0, and two auxiliary SPI +interfaces, designated SPI1 and SPI2. +On the first generation Pis, only SPI0 was brought out to the +header on the board. +For the B+ and Pi2 models, SPI0 and SPI1 are available. +The driver described in this man page only supports SPI0. +.PP +Reads and writes to the files +.B spi0 +and +.B spi1 +transfer data over the SPI bus. +Accesses to +.B spi0 +cause the transfers to take place with the CE0\_0 line asserted +low. +Similarly, transfers to +.B spi1 +are carried out with CE1\_0 asserted low. +.PP +The +.B spictl +file is used to set various control parameters. +It accepts the following commands: +.TP +.BI clock " freq" +Set the frequency of the SPI clock. +The clock from which the SPI clock is derived runs at 250MHz, +and the divisor must be a multiple of 2. +(The Broadcom documentation incorrectly says "power of 2".) +The driver sets the divisor to the highest multiple of 2 that results +in a clock rate that is less than or equal to the +.I freq +parameter in MHz. +.TP +.BI mode " n" +Treats +.I n +as a two-bit number specifying the settings for the clock phase +and clock polarity. +The default value of 0 matches the polarity and phase requirements +of most peripheral devices. +.TP +.B lossi +Enable a bidirectional mode where the MOSI line is used for both +reads and writes. +.SH SOURCE +.B /sys/src/9/bcm/devspi.c +.br +.B /sys/src/9/bcm/spi.c +.SH BUGS +The various SPI modes are untested and the LoSSI support is +unimplemented. From 4e34f4ee12e05fa575b0a15ac93c8e62fde4de17 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 19:09:40 +0000 Subject: [PATCH 061/402] sys/src/9/port: add TLS 1.2 support in devtls (thanks Cinap Lenrek) --- sys/man/3/tls | 17 ++++++--- sys/src/9/port/devtls.c | 84 ++++++++++++++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 23 deletions(-) diff --git a/sys/man/3/tls b/sys/man/3/tls index b266d3551a..eb130532e4 100644 --- a/sys/man/3/tls +++ b/sys/man/3/tls @@ -17,7 +17,8 @@ tls \- TLS1 and SSL3 record layer .fi .SH DESCRIPTION The TLS device implements the record layer protocols -of Transport Layer Security version 1.0 and Secure Sockets Layer version 3.0. +of Transport Layer Security versions 1.[0-2] and +Secure Sockets Layer version 3.0. It does not implement the handshake protocols, which are responsible for mutual authentication and key exchange. The @@ -54,9 +55,14 @@ Initially, outgoing messages use version format records, but incoming messages of either version are accepted. Valid versions are .B 0x300 -for SSLv3.0 and +for SSLv3.0, .B 0x301 -for TLSv1.0 (which could be known as SSLv3.01.) +for TLSv1.0, +.B 0x302 +for TLSv1.1, +and +.B 0x303 +for TLSv1.2. This command must be issued before any other command and before reading or writing any messages; it may only be executed once. @@ -265,9 +271,10 @@ Currently implemented encryption algorithms are and .BR 'aes_256_cbc' . Currently implemented hashing algorithms are -.B 'md5' +.BR "md5" , +.BR "sha1" , and -.BR 'sha1' . +.BR "sha2_256" . .SH "SEE ALSO" .IR listen (8), .IR dial (2), diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 67e2bad034..0e04531e1b 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -1,5 +1,5 @@ /* - * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0 + * devtls - record layer for transport layer security 1.0, 1.1, 1.2 and secure sockets layer 3.0 */ #include "u.h" #include "../port/lib.h" @@ -21,12 +21,13 @@ enum { MaxRecLen = 1<<14, /* max payload length of a record layer message */ MaxCipherRecLen = MaxRecLen + 2048, RecHdrLen = 5, - MaxMacLen = SHA1dlen, + MaxMacLen = SHA2_256dlen, /* protocol versions we can accept */ - TLSVersion = 0x0301, SSL3Version = 0x0300, - ProtocolVersion = 0x0301, /* maximum version we speak */ + TLS10Version = 0x0301, + TLS11Version = 0x0302, + TLS12Version = 0x0303, MinProtoVersion = 0x0300, /* limits on version we accept */ MaxProtoVersion = 0x03ff, @@ -73,6 +74,7 @@ enum { EInternalError = 80, EUserCanceled = 90, ENoRenegotiation = 100, + EUnrecognizedName = 112, EMAX = 256 }; @@ -800,6 +802,17 @@ if(tr->debug) pprint("consumed unprocessed %d\n", len); /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here should look alike, including timing of the response. */ unpad_len = (*in->sec->dec)(in->sec, p, len); + + /* excplicit iv */ + if(tr->version >= TLS11Version){ + len -= in->sec->block; + if(len < 0) + rcvError(tr, EDecodeError, "runt record message"); + + unpad_len -= in->sec->block; + p += in->sec->block; + } + if(unpad_len >= in->sec->maclen) len = unpad_len - in->sec->maclen; if(tr->debug) pprint("decrypted %d\n", unpad_len); @@ -814,7 +827,8 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:"); rcvError(tr, EBadRecordMac, "short record mac"); if(memcmp(hmac, p+len, in->sec->maclen) != 0) rcvError(tr, EBadRecordMac, "record mac mismatch"); - b->wp = b->rp + len; + b->rp = p; + b->wp = p+len; } qunlock(&in->seclock); poperror(); @@ -850,18 +864,25 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:"); /* * propate non-fatal alerts to handshaker */ - if(p[1] == ECloseNotify) { + switch(p[1]){ + case ECloseNotify: tlsclosed(tr, SRClose); if(tr->opened) error("tls hungup"); error("close notify"); - } - if(p[1] == ENoRenegotiation) + break; + case ENoRenegotiation: alertHand(tr, "no renegotiation"); - else if(p[1] == EUserCanceled) + break; + case EUserCanceled: alertHand(tr, "handshake canceled by user"); - else + break; + case EUnrecognizedName: + /* happens in response to SNI, can be ignored. */ + break; + default: rcvError(tr, EIllegalParameter, "invalid alert code"); + } break; case RHandshake: /* @@ -1202,6 +1223,13 @@ tlsread(Chan *c, void *a, long n, vlong off) return n; } +static void +randfill(uchar *buf, int len) +{ + while(len-- > 0) + *buf++ = nrand(256); +} + /* * write a block in tls records */ @@ -1212,7 +1240,7 @@ tlsrecwrite(TlsRec *tr, int type, Block *b) Block *nb; uchar *p, seq[8]; OneWay *volatile out; - int n, maclen, pad, ok; + int n, ivlen, maclen, pad, ok; out = &tr->out; bb = b; @@ -1245,21 +1273,24 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); qlock(&out->seclock); maclen = 0; pad = 0; + ivlen = 0; if(out->sec != nil){ maclen = out->sec->maclen; pad = maclen + out->sec->block; + if(tr->version >= TLS11Version) + ivlen = out->sec->block; } n = BLEN(bb); if(n > MaxRecLen){ n = MaxRecLen; - nb = allocb(n + pad + RecHdrLen); - memmove(nb->wp + RecHdrLen, bb->rp, n); + nb = allocb(RecHdrLen + ivlen + n + pad); + memmove(nb->wp + RecHdrLen + ivlen, bb->rp, n); bb->rp += n; }else{ /* * carefully reuse bb so it will get freed if we're out of memory */ - bb = padblock(bb, RecHdrLen); + bb = padblock(bb, RecHdrLen + ivlen); if(pad) nb = padblock(bb, -pad); else @@ -1275,9 +1306,15 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); if(out->sec != nil){ put64(seq, out->seq); out->seq++; - (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n); + (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n); n += maclen; + /* explicit iv */ + if(ivlen > 0){ + randfill(p + RecHdrLen, ivlen); + n += ivlen; + } + /* encrypt */ n = (*out->sec->enc)(out->sec, p + RecHdrLen, n); nb->wp = p + RecHdrLen + n; @@ -1380,11 +1417,22 @@ initsha1key(Hashalg *ha, int version, Secret *s, uchar *p) memmove(s->mackey, p, ha->maclen); } +static void +initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p) +{ + if(version == SSL3Version) + error("sha256 cannot be used with SSL"); + s->maclen = ha->maclen; + s->mac = hmac_sha2_256; + memmove(s->mackey, p, ha->maclen); +} + static Hashalg hashtab[] = { { "clear", 0, initclearmac, }, { "md5", MD5dlen, initmd5key, }, { "sha1", SHA1dlen, initsha1key, }, + { "sha256", SHA2_256dlen, initsha2_256key, }, { 0 } }; @@ -1555,12 +1603,12 @@ tlswrite(Chan *c, void *a, long n, vlong off) if(tr->verset) error("version already set"); m = strtol(cb->f[1], nil, 0); + if(m < MinProtoVersion || m > MaxProtoVersion) + error("unsupported version"); if(m == SSL3Version) tr->packMac = sslPackMac; - else if(m == TLSVersion) - tr->packMac = tlsPackMac; else - error("unsupported version"); + tr->packMac = tlsPackMac; tr->verset = 1; tr->version = m; }else if(strcmp(cb->f[0], "secret") == 0){ From 4e85e782dd5638886a739811a9c5f49bcf262814 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 21:50:38 +0000 Subject: [PATCH 062/402] sys/src/9/port: various bug fixes and improvements in devbridge (thanks Charles Forsyth) --- sys/src/9/port/devbridge.c | 119 +++++++++++++++---------------------- 1 file changed, 49 insertions(+), 70 deletions(-) diff --git a/sys/src/9/port/devbridge.c b/sys/src/9/port/devbridge.c index c94cd6c029..3b1f9f47d2 100644 --- a/sys/src/9/port/devbridge.c +++ b/sys/src/9/port/devbridge.c @@ -39,6 +39,7 @@ enum CacheLook= 5, // how many cache entries to examine CacheSize= (CacheHash+CacheLook-1), CacheTimeout= 5*60, // timeout for cache entry in seconds + MaxMTU= IP_MAX, // allow for jumbo frames and large UDP TcpMssMax = 1300, // max desirable Tcp MSS value TunnelMtu = 1400, @@ -109,9 +110,9 @@ struct Bridge struct Port { + Ref; int id; Bridge *bridge; - int ref; int closed; Chan *data[2]; // channel to data @@ -291,15 +292,21 @@ bridgeread(Chan *c, void *a, long n, vlong off) USED(off); switch(TYPE(c->qid)) { default: - error(Eperm); + error(Egreg); case Qtopdir: case Qbridgedir: case Qportdir: return devdirread(c, a, n, 0, 0, bridgegen); case Qlog: return logread(b, a, off, n); + case Qlocal: + return 0; /* TO DO */ case Qstatus: qlock(b); + if(waserror()){ + qunlock(b); + nexterror(); + } port = b->port[PORT(c->qid)]; if(port == 0) strcpy(buf, "unbound\n"); @@ -318,16 +325,15 @@ bridgeread(Chan *c, void *a, long n, vlong off) } ingood = port->in - port->inmulti - port->inunknown; outgood = port->out - port->outmulti - port->outunknown; - i += snprint(buf+i, sizeof(buf)-i, + snprint(buf+i, sizeof(buf)-i, "in=%d(%d:%d:%d) out=%d(%d:%d:%d:%d)\n", port->in, ingood, port->inmulti, port->inunknown, port->out, outgood, port->outmulti, port->outunknown, port->outfrag); - USED(i); } - n = readstr(off, a, n, buf); + poperror(); qunlock(b); - return n; + return readstr(off, a, n, buf); case Qbctl: snprint(buf, sizeof(buf), "%s tcpmss\ndelay %ld %ld\n", b->tcpmss ? "set" : "clear", b->delay0, b->delayn); @@ -513,7 +519,7 @@ portbind(Bridge *b, int argc, char *argv[]) Chan *ctl; int type = 0, i, n; ulong ownhash; - char *dev, *dev2 = nil, *p; + char *dev, *dev2 = nil; char buf[100], name[KNAMELEN], path[8*KNAMELEN]; static char usage[] = "usage: bind ether|tunnel name ownhash dev [dev2]"; @@ -574,11 +580,9 @@ portbind(Bridge *b, int argc, char *argv[]) // check addr? // get directory name - n = devtab[ctl->type]->read(ctl, buf, sizeof(buf), 0); + n = devtab[ctl->type]->read(ctl, buf, sizeof(buf)-1, 0); buf[n] = 0; - for(p = buf; *p == ' '; p++) - ; - snprint(path, sizeof(path), "%s/%lud/data", dev, strtoul(p, 0, 0)); + snprint(path, sizeof(path), "%s/%lud/data", dev, strtoul(buf, 0, 0)); // setup connection to be promiscuous snprint(buf, sizeof(buf), "connect -1"); @@ -613,8 +617,9 @@ portbind(Bridge *b, int argc, char *argv[]) b->nport = port->id+1; // assumes kproc always succeeds - kproc("etherread", etherread, port); // poperror must be next - port->ref++; + incref(port); + snprint(buf, sizeof(buf), "bridge:%s", dev); + kproc(buf, etherread, port); } // assumes b is locked @@ -816,21 +821,14 @@ cachedump(Bridge *b) -// assumes b is locked +// assumes b is locked, no error return static void ethermultiwrite(Bridge *b, Block *bp, Port *port) { Port *oport; - Block *bp2; Etherpkt *ep; int i, mcast; - if(waserror()) { - if(bp) - freeb(bp); - nexterror(); - } - ep = (Etherpkt*)bp->rp; mcast = ep->d[0] & 1; /* multicast bit of ethernet address */ @@ -850,26 +848,16 @@ ethermultiwrite(Bridge *b, Block *bp, Port *port) // delay one so that the last write does not copy if(oport != nil) { b->copy++; - bp2 = copyblock(bp, blocklen(bp)); - if(!waserror()) { - etherwrite(oport, bp2); - poperror(); - } + etherwrite(oport, copyblock(bp, blocklen(bp))); } oport = b->port[i]; } // last write free block - if(oport) { - bp2 = bp; bp = nil; USED(bp); - if(!waserror()) { - etherwrite(oport, bp2); - poperror(); - } - } else + if(oport) + etherwrite(oport, bp); + else freeb(bp); - - poperror(); } static void @@ -963,10 +951,10 @@ etherread(void *a) { Port *port = a; Bridge *b = port->bridge; - Block *bp, *bp2; + Block *bp; Etherpkt *ep; Centry *ce; - long md; + long md, n; qlock(b); port->readp = up; /* hide identity under a rock for unbind */ @@ -979,64 +967,56 @@ etherread(void *a) qlock(b); break; } - if(0) - print("devbridge: etherread: reading\n"); - bp = devtab[port->data[0]->type]->bread(port->data[0], - ETHERMAXTU, 0); - if(0) - print("devbridge: etherread: blocklen = %d\n", - blocklen(bp)); + bp = devtab[port->data[0]->type]->bread(port->data[0], MaxMTU, 0); poperror(); qlock(b); - if(bp == nil || port->closed) + if(bp == nil) break; + n = blocklen(bp); + if(port->closed || n < ETHERMINTU){ + freeb(bp); + continue; + } if(waserror()) { // print("etherread bridge error\n"); - if(bp) - freeb(bp); + freeb(bp); continue; } - if(blocklen(bp) < ETHERMINTU) - error("short packet"); port->in++; ep = (Etherpkt*)bp->rp; cacheupdate(b, ep->s, port->id); if(b->tcpmss) - tcpmsshack(ep, BLEN(bp)); + tcpmsshack(ep, n); /* * delay packets to simulate a slow link */ - if(b->delay0 || b->delayn){ - md = b->delay0 + b->delayn * BLEN(bp); + if(b->delay0 != 0 || b->delayn != 0){ + md = b->delay0 + b->delayn * n; if(md > 0) microdelay(md); } + poperror(); /* must now dispose of bp */ + if(ep->d[0] & 1) { log(b, Logmcast, "multicast: port=%d src=%E dst=%E type=%#.4ux\n", port->id, ep->s, ep->d, ep->type[0]<<8|ep->type[1]); port->inmulti++; - bp2 = bp; bp = nil; - ethermultiwrite(b, bp2, port); + ethermultiwrite(b, bp, port); } else { ce = cachelookup(b, ep->d); if(ce == nil) { b->miss++; port->inunknown++; - bp2 = bp; bp = nil; - ethermultiwrite(b, bp2, port); + ethermultiwrite(b, bp, port); }else if(ce->port != port->id){ b->hit++; - bp2 = bp; bp = nil; - etherwrite(b->port[ce->port], bp2); - } + etherwrite(b->port[ce->port], bp); + }else + freeb(bp); } - - poperror(); - if(bp) - freeb(bp); } // print("etherread: trying to exit\n"); port->readp = nil; @@ -1070,7 +1050,6 @@ fragment(Etherpkt *epkt, int n) return 1; } - static void etherwrite(Port *port, Block *bp) { @@ -1084,13 +1063,16 @@ etherwrite(Port *port, Block *bp) epkt = (Etherpkt*)bp->rp; n = blocklen(bp); if(port->type != Ttun || !fragment(epkt, n)) { - devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); + if(!waserror()){ + devtab[port->data[1]->type]->bwrite(port->data[1], bp, 0); + poperror(); + } return; } port->outfrag++; if(waserror()){ freeblist(bp); - nexterror(); + return; } seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7; @@ -1161,10 +1143,7 @@ etherwrite(Port *port, Block *bp) static void portfree(Port *port) { - port->ref--; - if(port->ref < 0) - panic("portfree: bad ref"); - if(port->ref > 0) + if(decref(port) != 0) return; if(port->data[0]) From a53998ea47b676f9c26ed99e2f9ad8001e1fbf24 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 21:53:59 +0000 Subject: [PATCH 063/402] sys/src/9/port: add mtu option to ethersink (thanks Charles Forsyth) --- sys/src/9/pc/ethersink.c | 47 +++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/sys/src/9/pc/ethersink.c b/sys/src/9/pc/ethersink.c index dd701804f2..fa51e71cab 100644 --- a/sys/src/9/pc/ethersink.c +++ b/sys/src/9/pc/ethersink.c @@ -12,24 +12,48 @@ #include "../port/netif.h" #include "etherif.h" +enum{ + CMea = 0, + CMmtu +}; + +static Cmdtab sinkcmds[] = { + {CMea, "ea", 2}, + {CMmtu, "mtu", 2}, +}; + static long ctl(Ether *ether, void *buf, long n) { uchar ea[Eaddrlen]; Cmdbuf *cb; + Cmdtab *ct; + long mtu; cb = parsecmd(buf, n); - if(cb->nf >= 2 - && strcmp(cb->f[0], "ea")==0 - && parseether(ea, cb->f[1]) == 0){ + if(waserror()){ free(cb); + nexterror(); + } + ct = lookupcmd(cb, sinkcmds, nelem(sinkcmds)); + switch(ct->index){ + case CMea: + if(parseether(ea, cb->f[1]) < 0) + cmderror(cb, "invalid ea"); memmove(ether->ea, ea, Eaddrlen); memmove(ether->addr, ether->ea, Eaddrlen); - return 0; + break; + case CMmtu: + mtu = strtol(cb->f[1], nil, 0); + if(mtu < ETHERMINTU || mtu > 9000) + cmderror(cb, "invalid mtu"); + ether->maxmtu = mtu; + ether->mtu = mtu; + break; } + poperror(); free(cb); - error(Ebadctl); - return -1; /* not reached */ + return n; } static void @@ -37,17 +61,20 @@ nop(Ether*) { } +static void +discard(Ether* ether) +{ + qflush(ether->oq); +} + static int reset(Ether* ether) { - uchar ea[Eaddrlen]; - if(ether->type==nil) return -1; - memset(ea, 0, sizeof ea); ether->mbps = 1000; ether->attach = nop; - ether->transmit = nop; + ether->transmit = discard; ether->irq = -1; ether->interrupt = nil; ether->ifstat = nil; From 5082d00619e45c2ca0d5669988411185d0a08ceb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 21:51:40 +0000 Subject: [PATCH 064/402] sys/src/9/port: handle stat and ifstat correctly in walk (thanks Charles Forsyth) --- sys/src/9/port/netif.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sys/src/9/port/netif.c b/sys/src/9/port/netif.c index 4399776df5..0fcb4645e4 100644 --- a/sys/src/9/port/netif.c +++ b/sys/src/9/port/netif.c @@ -66,7 +66,7 @@ netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp) /* second level contains clone plus all the conversations */ t = NETTYPE(c->qid.path); - if(t == N2ndqid || t == Ncloneqid || t == Naddrqid){ + if(t == N2ndqid || t == Ncloneqid || t == Naddrqid || t == Nstatqid || t == Nifstatqid){ switch(i) { case DEVDOTDOT: q.type = QTDIR; @@ -378,8 +378,10 @@ netifwstat(Netif *nif, Chan *c, uchar *db, int n) free(dir); error(Eshortstat); } - if(!emptystr(dir[0].uid)) - strncpy(f->owner, dir[0].uid, KNAMELEN); + if(!emptystr(dir[0].uid)){ + strncpy(f->owner, dir[0].uid, KNAMELEN-1); + f->owner[KNAMELEN-1] = 0; + } if(dir[0].mode != ~0UL) f->mode = dir[0].mode; free(dir); @@ -475,7 +477,8 @@ netown(Netfile *p, char *o, int omode) return -1; } } - strncpy(p->owner, o, KNAMELEN); + strncpy(p->owner, o, KNAMELEN-1); + p->owner[KNAMELEN-1] = 0; p->mode = 0660; unlock(&netlock); return 0; From 5a927a8a152f5843d16530f57f3d0713d615739e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 11:42:59 +0000 Subject: [PATCH 065/402] sys/src/9/ip: implement hangupxmit message on TCP connection control file (thanks Geoff Collyer) --- sys/src/9/ip/tcp.c | 54 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c index f472284c61..54f513d554 100644 --- a/sys/src/9/ip/tcp.c +++ b/sys/src/9/ip/tcp.c @@ -539,6 +539,44 @@ tcpannounce(Conv *c, char **argv, int argc) return nil; } +static void +tcpclosestate(Conv *c, Tcpctl *tcb, int state) +{ + tcb->flgcnt++; + tcb->snd.nxt++; + tcpsetstate(c, state); + tcpoutput(c); +} + +/* close the output half of a tcp connection */ +static char * +tcpxmitclose(Conv *c) +{ + Tcpctl *tcb; + + qhangup(c->wq, nil); + + tcb = (Tcpctl*)c->ptcl; + switch(tcb->state) { + case Listen: + /* + * reset any incoming calls to this listener + */ + Fsconnected(c, "Hangup"); + /* fall through */ + case Closed: + case Syn_sent: + localclose(c, nil); + break; + case Syn_received: + case Established: + case Close_wait: + tcpclosestate(c, tcb, tcb->state); + break; + } + return nil; +} + /* * tcpclose is always called with the q locked */ @@ -560,25 +598,17 @@ tcpclose(Conv *c) * reset any incoming calls to this listener */ Fsconnected(c, "Hangup"); - - localclose(c, nil); - break; + /* fall through */ case Closed: case Syn_sent: localclose(c, nil); break; case Syn_received: case Established: - tcb->flgcnt++; - tcb->snd.nxt++; - tcpsetstate(c, Finwait1); - tcpoutput(c); + tcpclosestate(c, tcb, Finwait1); break; case Close_wait: - tcb->flgcnt++; - tcb->snd.nxt++; - tcpsetstate(c, Last_ack); - tcpoutput(c); + tcpclosestate(c, tcb, Last_ack); break; } } @@ -3291,6 +3321,8 @@ tcpctl(Conv* c, char** f, int n) { if(n == 1 && strcmp(f[0], "hangup") == 0) return tcphangup(c); + if(n == 1 && strcmp(f[0], "hangupxmit") == 0) + return tcpxmitclose(c); if(n >= 1 && strcmp(f[0], "keepalive") == 0) return tcpstartka(c, f, n); if(n >= 1 && strcmp(f[0], "checksum") == 0) From 27ea451f0923b5c03f5ba8405f78ded794c71c82 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 11:42:59 +0000 Subject: [PATCH 066/402] sys/src/9/ip: implement close message on TCP connection control file --- sys/man/3/ip | 3 +++ sys/src/9/ip/tcp.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/sys/man/3/ip b/sys/man/3/ip index 27b69ad551..4471383675 100644 --- a/sys/man/3/ip +++ b/sys/man/3/ip @@ -720,6 +720,9 @@ files support the following additional messages: .TF "\fLkeepalive\fI n\fR" .PD .TP +.B close +gracefully close down this TCP connection +.TP .B hangup close down this TCP connection .TP diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c index 54f513d554..3dda5edac3 100644 --- a/sys/src/9/ip/tcp.c +++ b/sys/src/9/ip/tcp.c @@ -1439,6 +1439,16 @@ sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar ve } } +/* + * close the conversation + */ +static char* +tcpclose2(Conv *s) +{ + tcpclose(s); + return nil; +} + /* * send a reset to the remote side and close the conversation * called with s qlocked @@ -3319,6 +3329,8 @@ tcpporthogdefensectl(char *val) static char* tcpctl(Conv* c, char** f, int n) { + if(n == 1 && strcmp(f[0], "close") == 0) + return tcpclose2(c); if(n == 1 && strcmp(f[0], "hangup") == 0) return tcphangup(c); if(n == 1 && strcmp(f[0], "hangupxmit") == 0) From ef74a858fbfc01d6a0a265741a8e7b0029f3b42b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 3 Nov 2016 01:22:37 +0000 Subject: [PATCH 067/402] sys/src/9/port: fix buffer overflow in m5mouseputc (thanks Geoff Collyer) --- sys/src/9/port/devmouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c index fa95e6768b..4e5de193c2 100644 --- a/sys/src/9/port/devmouse.c +++ b/sys/src/9/port/devmouse.c @@ -680,7 +680,7 @@ m3mouseputc(Queue*, int c) int m5mouseputc(Queue*, int c) { - static uchar msg[3]; + static uchar msg[4]; static int nb; static ulong lasttick; ulong m; From 116620e985fdbffca0fb485456858e421a340975 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 23 Aug 2017 05:34:04 +0000 Subject: [PATCH 068/402] sys/src/9: handle more than 32 CPUs on 386 (thanks Geoff Collyer) --- sys/src/9/pc/dat.h | 6 +++++- sys/src/9/pc/main.c | 13 +++++++------ sys/src/9/pc/mem.h | 8 ++++---- sys/src/9/pc/mmu.c | 2 +- sys/src/9/pc/mp.c | 4 ++-- sys/src/9/pc/trap.c | 4 ++-- sys/src/9/port/devcons.c | 8 ++++---- sys/src/9/port/portclock.c | 2 +- sys/src/9/port/portfns.h | 3 +++ sys/src/9/port/proc.c | 39 +++++++++++++++++++++++++++++++++++++- 10 files changed, 67 insertions(+), 22 deletions(-) diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 068e5b9e02..b8f2251b53 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -282,7 +282,11 @@ void kunmap(KMap*); struct { Lock; - int machs; /* bitmap of active CPUs */ + union { + uvlong machs; /* bitmap of active CPUs */ + ulong machsmap[(MAXMACH+BI2WD-1)/BI2WD]; + }; + int nmachs; /* number of bits set in machs(map) */ int exiting; /* shutdown */ int ispanic; /* shutdown in response to a panic */ int thunderbirdsarego; /* lets the added processors continue to schedinit */ diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 34786f62b8..d476f853a7 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -180,7 +180,7 @@ mach0init(void) machinit(); - active.machs = 1; + cpuactive(0); active.exiting = 0; } @@ -762,9 +762,9 @@ shutdown(int ispanic) lock(&active); if(ispanic) active.ispanic = ispanic; - else if(m->machno == 0 && (active.machs & (1<machno)) == 0) + else if(m->machno == 0 && !iscpuactive(m->machno)) active.ispanic = 0; - once = active.machs & (1<machno); + once = iscpuactive(m->machno); /* * setting exiting will make hzclock() on each processor call exit(0), * which calls shutdown(0) and arch->reset(), which on mp systems is @@ -772,7 +772,7 @@ shutdown(int ispanic) * processors (to permit a reboot). clearing our bit in machs avoids * calling exit(0) from hzclock() on this processor. */ - active.machs &= ~(1<machno); + cpuinactive(m->machno); active.exiting = 1; unlock(&active); @@ -783,7 +783,7 @@ shutdown(int ispanic) spllo(); for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ delay(TK2MS(2)); - if(active.machs == 0 && consactive() == 0) + if(active.nmachs == 0 && consactive() == 0) break; } @@ -836,7 +836,8 @@ reboot(void *entry, void *code, ulong size) /* * should be the only processor running now */ - active.machs = 0; + memset(active.machsmap, 0, sizeof active.machsmap); + active.nmachs = 0; if (m->machno != 0) print("on cpu%d (not 0)!\n", m->machno); diff --git a/sys/src/9/pc/mem.h b/sys/src/9/pc/mem.h index 9412f2d92e..88a8176fec 100644 --- a/sys/src/9/pc/mem.h +++ b/sys/src/9/pc/mem.h @@ -18,11 +18,11 @@ #define FPalign 16 /* required for FXSAVE */ /* - * In 32-bit mode, the MAXMACH limit is 32 without - * changing the way active.machs is defined and used - * (unfortunately, it is also used in the port code). + * Must define MACHS_BITMAP in ports that support MAXMACH > 64; + * optional otherwise. */ -#define MAXMACH 32 /* max # cpus system can run */ +#define MAXMACH 64 /* max # cpus system can run */ +#define MACHS_BITMAP #define KSTACK 4096 /* Size of kernel stack */ /* diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index ee5a22076f..db6574f381 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -683,7 +683,7 @@ vunmap(void *v, int size) for(i=0; imachno) { nm = MACHP(i); - while((active.machs&(1<machno)) && nm->flushmmu) + while(iscpuactive(nm->machno) && nm->flushmmu) ; } } diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index 43d9bb307c..6a140ac04d 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -417,7 +417,7 @@ squidboy(Apic* apic) fpoff(); lock(&active); - active.machs |= 1<machno; + cpuactive(m->machno); unlock(&active); while(!active.thunderbirdsarego) @@ -920,7 +920,7 @@ mpshutdown(void) if(active.rebooting) return; - print("apshutdown: active = %#8.8ux\n", active.machs); + print("apshutdown: %d active cpus\n", active.nmachs); delay(1000); splhi(); arch->resetothers(); diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index 51ea084cef..b4a1680fef 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -397,8 +397,8 @@ trap(Ureg* ureg) if(0)print("cpu%d: spurious interrupt %d, last %d\n", m->machno, vno, m->lastintr); if(0)if(conf.nmach > 1){ - for(i = 0; i < 32; i++){ - if(!(active.machs & (1<machno == mach->machno) diff --git a/sys/src/9/port/devcons.c b/sys/src/9/port/devcons.c index a7b27423aa..51f208c8db 100644 --- a/sys/src/9/port/devcons.c +++ b/sys/src/9/port/devcons.c @@ -871,8 +871,8 @@ consread(Chan *c, void *buf, long n, vlong off) case Qsysstat: b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */ bp = b; - for(id = 0; id < 32; id++) { - if(active.machs & (1<cs = 0; mp->intr = 0; diff --git a/sys/src/9/port/portclock.c b/sys/src/9/port/portclock.c index ecff5e92ae..d313e6612a 100644 --- a/sys/src/9/port/portclock.c +++ b/sys/src/9/port/portclock.c @@ -151,7 +151,7 @@ hzclock(Ureg *ur) if(kproftimer != nil) kproftimer(ur->pc); - if((active.machs&(1<machno)) == 0) + if(!iscpuactive(m->machno)) return; if(active.exiting) { diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index af68b0889a..6856e7e7dc 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -48,6 +48,8 @@ Block* concatblock(Block*); Block* copyblock(Block*, int); void copypage(Page*, Page*); void countpagerefs(ulong*, int); +void cpuactive(uint); +void cpuinactive(uint); int cread(Chan*, uchar*, int, vlong); void cunmount(Chan*, Chan*); void cupdate(Chan*, uchar*, int, vlong); @@ -137,6 +139,7 @@ long incref(Ref*); void initmark(Watermark *, int, char *); void initseg(void); int iprint(char*, ...); +int iscpuactive(uint); void isdir(Chan*); int iseve(void); int islo(void); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 711fe167d1..6c84b50490 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -589,6 +589,43 @@ canpage(Proc *p) return ok; } +/* + * these assume that active.Lock is held when needed. + */ + +void +cpuactive(uint cpu) +{ +#ifdef MACHS_BITMAP + active.machsmap[cpu / BI2WD] |= 1ULL << (cpu % BI2WD); + active.nmachs++; +#else + active.machs |= 1ULL << cpu; +#endif +} + +void +cpuinactive(uint cpu) +{ +#ifdef MACHS_BITMAP + active.machsmap[cpu / BI2WD] &= ~(1ULL << (cpu % BI2WD)); + active.nmachs--; +#else + active.machs &= ~(1ULL << cpu); +#endif +} + +int +iscpuactive(uint cpu) +{ +#ifdef MACHS_BITMAP + return (active.machsmap[cpu / BI2WD] & (1ULL << (cpu % BI2WD))) != 0; +#else + return (active.machs & (1ULL << cpu)) != 0; +#endif +} + + void noprocpanic(char *msg) { @@ -598,7 +635,7 @@ noprocpanic(char *msg) * on this processor. */ lock(&active); - active.machs &= ~(1<machno); + cpuinactive(m->machno); active.exiting = 1; unlock(&active); From 06b376a36f31dfb214e07ff0ffa5cc86d2b09170 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 23 Aug 2017 06:14:53 +0000 Subject: [PATCH 069/402] sys/src/9: move ispow2, isulpow2 and log2 functions to port (thanks Geoff Collyer) --- sys/src/9/kw/archkw.c | 21 --------------------- sys/src/9/kw/fns.h | 3 --- sys/src/9/kw/mkfile | 1 + sys/src/9/omap/archomap.c | 21 --------------------- sys/src/9/omap/fns.h | 3 --- sys/src/9/omap/mkfile | 1 + sys/src/9/pc/devarch.c | 10 ++++++++++ sys/src/9/pc/l.s | 7 +++++++ sys/src/9/pc/mkfile | 1 + sys/src/9/pc/mtrr.c | 6 ------ sys/src/9/pcboot/bootmkfile | 1 + sys/src/9/pcboot/l32v.s | 7 +++++++ sys/src/9/{teg2/v7-arch.c => port/logpow.c} | 12 +----------- sys/src/9/port/portfns.h | 4 ++++ sys/src/9/teg2/fns.h | 3 --- sys/src/9/teg2/mkfile | 1 + sys/src/9/teg2/ts | 1 - 17 files changed, 34 insertions(+), 69 deletions(-) rename sys/src/9/{teg2/v7-arch.c => port/logpow.c} (60%) diff --git a/sys/src/9/kw/archkw.c b/sys/src/9/kw/archkw.c index f7b21c3f5c..7027706bd5 100644 --- a/sys/src/9/kw/archkw.c +++ b/sys/src/9/kw/archkw.c @@ -227,27 +227,6 @@ praddrmap(void) praddrwin(&map->win[i], i); } -int -ispow2(uvlong ul) -{ - /* see Hacker's Delight if this isn't obvious */ - return (ul & (ul - 1)) == 0; -} - -/* - * return exponent of smallest power of 2 ≥ n - */ -int -log2(ulong n) -{ - int i; - - i = 31 - clz(n); - if (!ispow2(n) || n == 0) - i++; - return i; -} - void cacheinfo(int level, int kind, Memcache *cp) /* l1 only */ { diff --git a/sys/src/9/kw/fns.h b/sys/src/9/kw/fns.h index 3766bcbf0f..59ec976b2e 100644 --- a/sys/src/9/kw/fns.h +++ b/sys/src/9/kw/fns.h @@ -28,7 +28,6 @@ extern void cacheiinv(void); extern void cacheuwbinv(void); extern uintptr cankaddr(uintptr pa); extern void clockshutdown(void); -extern int clz(ulong); int cmpswap(long*, long, long); #define coherence barriers @@ -47,7 +46,6 @@ extern u32int dacget(void); extern void dacput(u32int); extern u32int farget(void); extern u32int fsrget(void); -extern int ispow2(uvlong); extern void l1cachesoff(void); extern void l1cacheson(void); extern void l2cachecfgoff(void); @@ -60,7 +58,6 @@ extern void l2cacheuwbinv(void); extern void l2cacheuwbinvse(void*, int); extern void l2cacheuwbse(void*, int); extern void lastresortprint(char *buf, long bp); -extern int log2(ulong); extern void mmuidmap(uintptr phys, int mbs); extern void mmuinvalidate(void); /* 'mmu' or 'tlb'? */ extern void mmuinvalidateaddr(u32int); /* 'mmu' or 'tlb'? */ diff --git a/sys/src/9/kw/mkfile b/sys/src/9/kw/mkfile index 9aad171250..2c22b967d4 100644 --- a/sys/src/9/kw/mkfile +++ b/sys/src/9/kw/mkfile @@ -25,6 +25,7 @@ PORT=\ latin1.$O\ mul64fract.$O\ rebootcmd.$O\ + logpow.$O\ page.$O\ parse.$O\ pgrp.$O\ diff --git a/sys/src/9/omap/archomap.c b/sys/src/9/omap/archomap.c index fb4c78c606..86e63c9847 100644 --- a/sys/src/9/omap/archomap.c +++ b/sys/src/9/omap/archomap.c @@ -347,27 +347,6 @@ archomaplink(void) { } -int -ispow2(uvlong ul) -{ - /* see Hacker's Delight if this isn't obvious */ - return (ul & (ul - 1)) == 0; -} - -/* - * return exponent of smallest power of 2 ≥ n - */ -int -log2(ulong n) -{ - int i; - - i = 31 - clz(n); - if (n == 0 || !ispow2(n)) - i++; - return i; -} - void archconfinit(void) { diff --git a/sys/src/9/omap/fns.h b/sys/src/9/omap/fns.h index a46dff739f..7f9542c80b 100644 --- a/sys/src/9/omap/fns.h +++ b/sys/src/9/omap/fns.h @@ -25,7 +25,6 @@ extern void cacheuwbinv(void); extern uintptr cankaddr(uintptr pa); extern void chkmissing(void); extern void clockshutdown(void); -extern int clz(ulong); extern int cmpswap(long*, long, long); extern void coherence(void); extern void configscreengpio(void); @@ -54,13 +53,11 @@ extern u32int ifsrget(void); extern void intrsoff(void); extern int isaconfig(char*, int, ISAConf*); extern int isdmadone(int); -extern int ispow2(uvlong); extern void kbdenable(void); extern void l2cacheuinv(void); extern void l2cacheuwb(void); extern void l2cacheuwbinv(void); extern void lastresortprint(char *buf, long bp); -extern int log2(ulong); extern void machinit(void); extern void mmuidmap(uintptr phys, int mbs); extern void mmuinvalidate(void); /* 'mmu' or 'tlb'? */ diff --git a/sys/src/9/omap/mkfile b/sys/src/9/omap/mkfile index 03401f11a1..dc10009851 100644 --- a/sys/src/9/omap/mkfile +++ b/sys/src/9/omap/mkfile @@ -25,6 +25,7 @@ PORT=\ latin1.$O\ mul64fract.$O\ rebootcmd.$O\ + logpow.$O\ page.$O\ parse.$O\ pgrp.$O\ diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 5958d6e909..bea2cd0ef8 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -51,6 +51,8 @@ enum { /* cpuid standard function codes */ typedef long Rdwrfn(Chan*, void*, long, vlong); +int bsr(ulong n); /* l.s */ + static Rdwrfn *readfn[Qmax]; static Rdwrfn *writefn[Qmax]; @@ -1260,3 +1262,11 @@ timerset(Tval x) if(doi8253set) (*arch->timerset)(x); } + +int +clz(ulong n) /* count leading zeroes */ +{ + if (n == 0) + return BI2BY*BY2WD; + return BI2BY*BY2WD - 1 - bsr(n); +} diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index fe0678ebdf..c86b214eb0 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -877,6 +877,13 @@ TEXT islo(SB), $0 ANDL $0x200, AX /* interrupt enable flag */ RET +/* + * Miscellany + */ +TEXT bsr(SB), $0 + BSRL word+0(FP), AX /* return bit index of leftmost 1 bit */ + RET + /* * Test-And-Set */ diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index a6d06dc82f..a91d3f30ed 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -29,6 +29,7 @@ PORT=\ edf.$O\ fault.$O\ latin1.$O\ + logpow.$O\ page.$O\ parse.$O\ pgrp.$O\ diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index 2a9fc5ecf3..41037013ab 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -131,12 +131,6 @@ sanity(Mtrreg *mtrr) mtrr->mask &= Paerange - 1; } -static int -ispow2(uvlong ul) -{ - return (ul & (ul - 1)) == 0; -} - /* true if mtrr is valid */ static int mtrrdec(Mtrreg *mtrr, uvlong *ptr, uvlong *size, int *type) diff --git a/sys/src/9/pcboot/bootmkfile b/sys/src/9/pcboot/bootmkfile index 226803694e..085b8a0789 100644 --- a/sys/src/9/pcboot/bootmkfile +++ b/sys/src/9/pcboot/bootmkfile @@ -19,6 +19,7 @@ PORT=\ dev.$O\ edf.$O\ latin1.$O\ + logpow.$O\ page.$O\ parse.$O\ pgrp.$O\ diff --git a/sys/src/9/pcboot/l32v.s b/sys/src/9/pcboot/l32v.s index e208eaa1d3..6c7a4cddfe 100644 --- a/sys/src/9/pcboot/l32v.s +++ b/sys/src/9/pcboot/l32v.s @@ -539,6 +539,13 @@ TEXT islo(SB), $0 ANDL $0x200, AX /* interrupt enable flag */ RET +/* + * Miscellany + */ +TEXT bsr(SB), $0 + BSRL word+0(FP), AX /* count leading zeros */ + RET + /* * basic timing loop to determine CPU frequency */ diff --git a/sys/src/9/teg2/v7-arch.c b/sys/src/9/port/logpow.c similarity index 60% rename from sys/src/9/teg2/v7-arch.c rename to sys/src/9/port/logpow.c index 40b1e09faa..4f1aff8b19 100644 --- a/sys/src/9/teg2/v7-arch.c +++ b/sys/src/9/port/logpow.c @@ -1,17 +1,11 @@ /* - * arm arch v7 routines other than cache-related ones. - * - * calling this arch-v7.c would confuse the mk scripts, - * to which a filename arch*.c is magic. + * log2 and pow2 routines. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" -#include "../port/error.h" -#include "io.h" -#include "arm.h" /* * these routines should be cheap enough that there will @@ -20,13 +14,9 @@ * once 5c in-lines vlong ops, just use the vlong versions. */ -/* see Hacker's Delight if this isn't obvious */ -#define ISPOW2(i) (((i) & ((i) - 1)) == 0) - int ispow2(uvlong uvl) { - /* see Hacker's Delight if this isn't obvious */ return ISPOW2(uvl); } diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 6856e7e7dc..1cf1bf6058 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -38,6 +38,7 @@ void closefgrp(Fgrp*); void closepgrp(Pgrp*); void closergrp(Rgrp*); long clrfpintr(void); +int clz(ulong); void cmderror(Cmdbuf*, char*); int cmount(Chan**, Chan*, int, char*); void confinit(void); @@ -146,6 +147,8 @@ int islo(void); Segment* isoverlap(Proc*, ulong, int); int ispages(void*); int isphysseg(char*); +#define ISPOW2(i) (((i) & ((i) - 1)) == 0) /* see Hacker's Delight */ +int ispow2(uvlong); void ixsummary(void); int kbdcr2nl(Queue*, int); int kbdgetmap(uint, int*, int*, Rune*); @@ -163,6 +166,7 @@ ulong l2be(long); long latin1(Rune*, int); int lock(Lock*); void logopen(Log*); +int log2(ulong); void logclose(Log*); char* logctl(Log*, int, char**, Logflag*); void logn(Log*, int, void*, int); diff --git a/sys/src/9/teg2/fns.h b/sys/src/9/teg2/fns.h index ca0087a257..a7c30ea777 100644 --- a/sys/src/9/teg2/fns.h +++ b/sys/src/9/teg2/fns.h @@ -33,7 +33,6 @@ extern uintptr cankaddr(uintptr pa); extern void chkmissing(void); extern void clockprod(Ureg *); extern void clockshutdown(void); -extern int clz(ulong); extern int cmpswap(long*, long, long); extern void coherence(void); extern void configscreengpio(void); @@ -79,11 +78,9 @@ extern void intrshutdown(void); extern void intrsoff(void); extern int isaconfig(char*, int, ISAConf*); extern int isdmadone(int); -extern int ispow2(uvlong); extern void kbdenable(void); extern void l1diag(void); extern void l2pl310init(void); -extern int log2(ulong); extern void machoff(uint cpu); extern void machon(uint cpu); extern void memdiag(ulong *); diff --git a/sys/src/9/teg2/mkfile b/sys/src/9/teg2/mkfile index a2a77133fc..31d7e7acd6 100644 --- a/sys/src/9/teg2/mkfile +++ b/sys/src/9/teg2/mkfile @@ -26,6 +26,7 @@ PORT=\ latin1.$O\ mul64fract.$O\ rebootcmd.$O\ + logpow.$O\ page.$O\ parse.$O\ pgrp.$O\ diff --git a/sys/src/9/teg2/ts b/sys/src/9/teg2/ts index 5684c69ac6..5e6881a059 100644 --- a/sys/src/9/teg2/ts +++ b/sys/src/9/teg2/ts @@ -57,7 +57,6 @@ misc pci rdb coproc - v7-arch caches caches-v7 cache-l2-pl310 From 2cb644c98562bba74ba825efa56dce9f55efbb4b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 10:03:02 +0000 Subject: [PATCH 070/402] sys/src/9: replace _xinc and _xdec by ainc and adec (thanks Geoff Collyer) --- sys/src/9/ip/gre.c | 4 ++-- sys/src/9/kw/arch.c | 31 +++++-------------------------- sys/src/9/kw/ether1116.c | 2 +- sys/src/9/mtx/l.s | 4 ++-- sys/src/9/omap/arch.c | 31 +++++-------------------------- sys/src/9/pc/ether82543gc.c | 2 +- sys/src/9/pc/ether82563.c | 2 +- sys/src/9/pc/ether82598.c | 2 +- sys/src/9/pc/etherdp83820.c | 2 +- sys/src/9/pc/etherigbe.c | 2 +- sys/src/9/pc/etherm10g.c | 2 +- sys/src/9/pc/ethervt6105m.c | 2 +- sys/src/9/pc/l.s | 12 ++++++------ sys/src/9/pc/mtrr.c | 8 ++++---- sys/src/9/pcboot/l.s | 12 ++++++------ sys/src/9/port/allocb.c | 4 ++-- sys/src/9/port/portfns.h | 4 ++-- sys/src/9/port/taslock.c | 4 ++-- sys/src/9/port/ucallocb.c | 4 ++-- sys/src/9/ppc/l.s | 4 ++-- sys/src/9/rb/devether.c | 2 +- sys/src/9/rb/l.s | 4 ++-- sys/src/9/teg2/ether8169.c | 2 +- 23 files changed, 52 insertions(+), 94 deletions(-) diff --git a/sys/src/9/ip/gre.c b/sys/src/9/ip/gre.c index b7982dc33c..5be3ab1e56 100644 --- a/sys/src/9/ip/gre.c +++ b/sys/src/9/ip/gre.c @@ -440,7 +440,7 @@ gredownlink(Conv *c, Block *bp) /* * Make sure the packet does not go away. */ - _xinc(&bp->ref); + ainc(&bp->ref); assert(bp->ref == 2); ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil); @@ -803,7 +803,7 @@ grectldlresume(Conv *c, int, char **) /* * Make sure the packet does not go away. */ - _xinc(&bp->ref); + ainc(&bp->ref); assert(bp->ref == 2); ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil); diff --git a/sys/src/9/kw/arch.c b/sys/src/9/kw/arch.c index 3c7d6cf656..3a696c558c 100644 --- a/sys/src/9/kw/arch.c +++ b/sys/src/9/kw/arch.c @@ -182,30 +182,9 @@ userureg(Ureg* ureg) */ long -_xdec(long *p) +ainc(long *p) { - int s, v; - - s = splhi(); - v = --*p; - splx(s); - return v; -} - -void -_xinc(long *p) -{ - int s; - - s = splhi(); - ++*p; - splx(s); -} - -int -ainc(int *p) -{ - int s, v; + long s, v; s = splhi(); v = ++*p; @@ -213,10 +192,10 @@ ainc(int *p) return v; } -int -adec(int *p) +long +adec(long *p) { - int s, v; + long s, v; s = splhi(); v = --*p; diff --git a/sys/src/9/kw/ether1116.c b/sys/src/9/kw/ether1116.c index 3e2d01788f..b5c98bf104 100644 --- a/sys/src/9/kw/ether1116.c +++ b/sys/src/9/kw/ether1116.c @@ -485,7 +485,7 @@ static void rxfreeb(Block *b) { /* freeb(b) will have previously decremented b->ref to 0; raise to 1 */ - _xinc(&b->ref); + ainc(&b->ref); b->wp = b->rp = (uchar*)((uintptr)(b->lim - Rxblklen) & ~(Bufalign - 1)); assert(((uintptr)b->rp & (Bufalign - 1)) == 0); diff --git a/sys/src/9/mtx/l.s b/sys/src/9/mtx/l.s index c880c53909..204a84d6b7 100644 --- a/sys/src/9/mtx/l.s +++ b/sys/src/9/mtx/l.s @@ -281,7 +281,7 @@ tas0: ISYNC RETURN -TEXT _xinc(SB),$0 /* void _xinc(long *); */ +TEXT ainc(SB),$0 /* void ainc(long *); */ MOVW R3, R4 xincloop: DCBF (R4) /* fix for 603x bug */ @@ -291,7 +291,7 @@ xincloop: BNE xincloop RETURN -TEXT _xdec(SB),$0 /* long _xdec(long *); */ +TEXT adec(SB),$0 /* long adec(long *); */ MOVW R3, R4 xdecloop: DCBF (R4) /* fix for 603x bug */ diff --git a/sys/src/9/omap/arch.c b/sys/src/9/omap/arch.c index 2b2d11aee5..635066a499 100644 --- a/sys/src/9/omap/arch.c +++ b/sys/src/9/omap/arch.c @@ -183,30 +183,9 @@ userureg(Ureg* ureg) */ long -_xdec(long *p) +ainc(long *p) { - int s, v; - - s = splhi(); - v = --*p; - splx(s); - return v; -} - -void -_xinc(long *p) -{ - int s; - - s = splhi(); - ++*p; - splx(s); -} - -int -ainc(int *p) -{ - int s, v; + long s, v; s = splhi(); v = ++*p; @@ -214,10 +193,10 @@ ainc(int *p) return v; } -int -adec(int *p) +long +adec(long *p) { - int s, v; + long s, v; s = splhi(); v = --*p; diff --git a/sys/src/9/pc/ether82543gc.c b/sys/src/9/pc/ether82543gc.c index 0271fbd888..00b86723b9 100644 --- a/sys/src/9/pc/ether82543gc.c +++ b/sys/src/9/pc/ether82543gc.c @@ -761,7 +761,7 @@ gc82543allocb(Ctlr* ctlr) if((bp = *(ctlr->freehead)) != nil){ *(ctlr->freehead) = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&freelistlock); return bp; diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index d77bf6bd5b..05ce6034c0 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -861,7 +861,7 @@ i82563rballoc(void) if((bp = i82563rbpool) != nil){ i82563rbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&i82563rblock); diff --git a/sys/src/9/pc/ether82598.c b/sys/src/9/pc/ether82598.c index c6c133ae2e..637f8d8886 100644 --- a/sys/src/9/pc/ether82598.c +++ b/sys/src/9/pc/ether82598.c @@ -466,7 +466,7 @@ rballoc(void) if((bp = rbpool) != nil){ rbpool = bp->next; bp->next = 0; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&rblock); return bp; diff --git a/sys/src/9/pc/etherdp83820.c b/sys/src/9/pc/etherdp83820.c index c0cea6408c..1d0a4041a0 100644 --- a/sys/src/9/pc/etherdp83820.c +++ b/sys/src/9/pc/etherdp83820.c @@ -512,7 +512,7 @@ dp83820rballoc(Desc* desc) } dp83820rbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ iunlock(&dp83820rblock); desc->bufptr = PCIWADDR(bp->rp); diff --git a/sys/src/9/pc/etherigbe.c b/sys/src/9/pc/etherigbe.c index 070ec7a17e..a69d27ca16 100644 --- a/sys/src/9/pc/etherigbe.c +++ b/sys/src/9/pc/etherigbe.c @@ -789,7 +789,7 @@ igberballoc(void) if((bp = igberbpool) != nil){ igberbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&igberblock); diff --git a/sys/src/9/pc/etherm10g.c b/sys/src/9/pc/etherm10g.c index 5375882823..ab60e696ea 100644 --- a/sys/src/9/pc/etherm10g.c +++ b/sys/src/9/pc/etherm10g.c @@ -861,7 +861,7 @@ balloc(Rx* rx) if((bp = rx->pool->head) != nil){ rx->pool->head = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ rx->pool->n--; } iunlock(rx->pool); diff --git a/sys/src/9/pc/ethervt6105m.c b/sys/src/9/pc/ethervt6105m.c index 49ea7d0884..9af39c060f 100644 --- a/sys/src/9/pc/ethervt6105m.c +++ b/sys/src/9/pc/ethervt6105m.c @@ -594,7 +594,7 @@ vt6105Mrballoc(void) if((bp = vt6105Mrbpool) != nil){ vt6105Mrbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&vt6105Mrblock); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index c86b214eb0..a69ea262cc 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -893,22 +893,22 @@ TEXT tas(SB), $0 XCHGL AX, (BX) /* lock->key */ RET -TEXT _xinc(SB), $0 /* void _xinc(long*); */ +TEXT ainc(SB), $0 /* void ainc(long*); */ MOVL l+0(FP), AX LOCK; INCL 0(AX) RET -TEXT _xdec(SB), $0 /* long _xdec(long*); */ +TEXT adec(SB), $0 /* long adec(long*); */ MOVL l+0(FP), BX XORL AX, AX LOCK; DECL 0(BX) - JLT _xdeclt - JGT _xdecgt + JLT adeclt + JGT adecgt RET -_xdecgt: +adecgt: INCL AX RET -_xdeclt: +adeclt: DECL AX RET diff --git a/sys/src/9/pc/mtrr.c b/sys/src/9/pc/mtrr.c index 41037013ab..eeed042be0 100644 --- a/sys/src/9/pc/mtrr.c +++ b/sys/src/9/pc/mtrr.c @@ -188,7 +188,7 @@ mtrrop(Mtrrop **op) * wait for all CPUs to sync here, so that the MTRR setup gets * done at roughly the same time on all processors. */ - _xinc(&bar1); + ainc(&bar1); while(bar1 < conf.nmach) microdelay(10); @@ -212,14 +212,14 @@ mtrrop(Mtrrop **op) * wait for all CPUs to sync up again, so that we don't continue * executing while the MTRRs are still being set up. */ - _xinc(&bar2); + ainc(&bar2); while(bar2 < conf.nmach) microdelay(10); *op = nil; - _xdec(&bar1); + adec(&bar1); while(bar1 > 0) microdelay(10); - _xdec(&bar2); + adec(&bar2); wakeup(&oprend); splx(s); } diff --git a/sys/src/9/pcboot/l.s b/sys/src/9/pcboot/l.s index 92d7ce8357..1a7b15693f 100644 --- a/sys/src/9/pcboot/l.s +++ b/sys/src/9/pcboot/l.s @@ -259,22 +259,22 @@ TEXT tas(SB), $0 XCHGL AX, (BX) /* lock->key */ RET -TEXT _xinc(SB), $0 /* void _xinc(long*); */ +TEXT ainc(SB), $0 /* void ainc(long*); */ MOVL l+0(FP), AX LOCK; INCL 0(AX) RET -TEXT _xdec(SB), $0 /* long _xdec(long*); */ +TEXT adec(SB), $0 /* long adec(long*); */ MOVL l+0(FP), BX XORL AX, AX LOCK; DECL 0(BX) - JLT _xdeclt - JGT _xdecgt + JLT adeclt + JGT adecgt RET -_xdecgt: +adecgt: INCL AX RET -_xdeclt: +adeclt: DECL AX RET diff --git a/sys/src/9/port/allocb.c b/sys/src/9/port/allocb.c index 82e1de3975..6e0e8b251e 100644 --- a/sys/src/9/port/allocb.c +++ b/sys/src/9/port/allocb.c @@ -52,7 +52,7 @@ mem2block(void *buf, ulong usable, int malloced) b->flag = 0; b->ref = 0; b->magic = Bmagic; - _xinc(&b->ref); + ainc(&b->ref); /* align start of data portion by rounding up */ b->base = (uchar*)ALIGNUP((ulong)b + sizeof(Block)); @@ -151,7 +151,7 @@ freeb(Block *b) panic("freeb: bad magic %#lux in Block %#p; caller pc %#p", b->magic, b, getcallerpc(&b)); - if((ref = _xdec(&b->ref)) > 0) + if((ref = adec(&b->ref)) > 0) return; if(ref < 0){ dumpstack(); diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 1cf1bf6058..20c9a83f2d 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -401,8 +401,8 @@ uvlong nhgetv(void*); uint nhgetl(void*); ushort nhgets(void*); ulong µs(void); -void _xinc(long*); -long _xdec(long*); +long ainc(long*); +long adec(long*); long lcycles(void); #pragma varargck argpos iprint 1 diff --git a/sys/src/9/port/taslock.c b/sys/src/9/port/taslock.c index 6296b16802..421b249fdb 100644 --- a/sys/src/9/port/taslock.c +++ b/sys/src/9/port/taslock.c @@ -23,7 +23,7 @@ struct static void inccnt(Ref *r) { - _xinc(&r->ref); + ainc(&r->ref); } static int @@ -31,7 +31,7 @@ deccnt(Ref *r) { int x; - x = _xdec(&r->ref); + x = adec(&r->ref); if(x < 0) panic("deccnt pc=%#p", getcallerpc(&r)); return x; diff --git a/sys/src/9/port/ucallocb.c b/sys/src/9/port/ucallocb.c index 954c5d96aa..b7c5d29177 100644 --- a/sys/src/9/port/ucallocb.c +++ b/sys/src/9/port/ucallocb.c @@ -34,7 +34,7 @@ _ucallocb(int size) b->free = 0; b->flag = 0; b->ref = 0; - _xinc(&b->ref); + ainc(&b->ref); /* align start of data portion by rounding up */ addr = (ulong)b; @@ -119,7 +119,7 @@ ucfreeb(Block *b) void *dead = (void*)Bdead; long ref; - if(b == nil || (ref = _xdec(&b->ref)) > 0) + if(b == nil || (ref = adec(&b->ref)) > 0) return; if(ref < 0){ diff --git a/sys/src/9/ppc/l.s b/sys/src/9/ppc/l.s index ca0bbf0de7..0907078aec 100644 --- a/sys/src/9/ppc/l.s +++ b/sys/src/9/ppc/l.s @@ -361,7 +361,7 @@ tas0: SYNC RETURN -TEXT _xinc(SB), $0 /* void _xinc(long *); */ +TEXT ainc(SB), $0 /* long ainc(long *); */ MOVW R3, R4 xincloop: DCBF (R4) /* fix for 603x bug */ @@ -371,7 +371,7 @@ xincloop: BNE xincloop RETURN -TEXT _xdec(SB), $0 /* long _xdec(long *); */ +TEXT adec(SB), $0 /* long adec(long *); */ MOVW R3, R4 xdecloop: DCBF (R4) /* fix for 603x bug */ diff --git a/sys/src/9/rb/devether.c b/sys/src/9/rb/devether.c index 5d546b9e6d..84a9c308e2 100644 --- a/sys/src/9/rb/devether.c +++ b/sys/src/9/rb/devether.c @@ -711,7 +711,7 @@ athrballoc(void) if((bp = athrbpool) != nil){ athrbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&athrblock); return bp; diff --git a/sys/src/9/rb/l.s b/sys/src/9/rb/l.s index 70e1d922fd..3a40d9ba24 100644 --- a/sys/src/9/rb/l.s +++ b/sys/src/9/rb/l.s @@ -836,7 +836,7 @@ tas1: NOP RETURN -TEXT _xinc(SB), $0 +TEXT ainc(SB), $0 MOVW R1, R2 /* address of counter */ loop: MOVW $1, R3 @@ -850,7 +850,7 @@ loop: NOP RETURN -TEXT _xdec(SB), $0 +TEXT adec(SB), $0 SYNC MOVW R1, R2 /* address of counter */ loop1: diff --git a/sys/src/9/teg2/ether8169.c b/sys/src/9/teg2/ether8169.c index 0f3b1ec9df..a9bf950afb 100644 --- a/sys/src/9/teg2/ether8169.c +++ b/sys/src/9/teg2/ether8169.c @@ -462,7 +462,7 @@ rballoc(void) if((bp = rbpool) != nil){ rbpool = bp->next; bp->next = nil; - _xinc(&bp->ref); /* prevent bp from being freed */ + ainc(&bp->ref); /* prevent bp from being freed */ } iunlock(&rblock); return bp; From ee2afe68aaf465813dedd8e7356147f4a036787f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 23 Aug 2017 18:26:45 +0000 Subject: [PATCH 071/402] sys/src/9: fix typo in portusbehci (thanks Geoff Collyer) --- sys/src/9/port/portusbehci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/port/portusbehci.h b/sys/src/9/port/portusbehci.h index c15150ae7f..f928181a4d 100644 --- a/sys/src/9/port/portusbehci.h +++ b/sys/src/9/port/portusbehci.h @@ -1,5 +1,5 @@ /* - * ECHI portable hardware definitions + * EHCI portable hardware definitions */ typedef struct Ecapio Ecapio; @@ -61,7 +61,7 @@ enum Sherr = 0x00010, /* host system error */ Sfrroll = 0x00008, /* frame list roll over */ Sportchg = 0x00004, /* port change detect */ - Serrintr = 0x00002, /* error interrupt */ + Serrintr = 0x00002, /* error interrupt */ Sintr = 0x00001, /* interrupt */ Sintrs = 0x0003F, /* interrupts status */ From dbac6c1cee18ffab1943ec2905b7ddd1fb1fbf22 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 23 Aug 2017 19:13:11 +0000 Subject: [PATCH 072/402] sys/src/9: remove definitions of the cistrcmp and cistrncmp functions (thanks Geoff Collyer) --- sys/src/9/mtx/main.c | 47 ----------------------------------------- sys/src/9/pc/main.c | 47 ----------------------------------------- sys/src/9/pcboot/main.c | 47 ----------------------------------------- sys/src/9/ppc/main.c | 47 ----------------------------------------- 4 files changed, 188 deletions(-) diff --git a/sys/src/9/mtx/main.c b/sys/src/9/mtx/main.c index e7e37e2dc5..3f8278bd99 100644 --- a/sys/src/9/mtx/main.c +++ b/sys/src/9/mtx/main.c @@ -416,50 +416,3 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) } return 1; } - -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index d476f853a7..571a248753 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -913,53 +913,6 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) return 1; } -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} - /* * put the processor in the halt state if we've no processes to run. * an interrupt will get us going again. diff --git a/sys/src/9/pcboot/main.c b/sys/src/9/pcboot/main.c index 5f3cae9666..76b7f43b3f 100644 --- a/sys/src/9/pcboot/main.c +++ b/sys/src/9/pcboot/main.c @@ -613,53 +613,6 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) return 1; } -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} - int less_power_slower; /* diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c index dc350bb904..a9028e29a9 100644 --- a/sys/src/9/ppc/main.c +++ b/sys/src/9/ppc/main.c @@ -462,50 +462,3 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) } return 1; } - -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} From fec07159b59fd75770c5300586f572088b5e5f67 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 15 Feb 2019 20:25:19 +0000 Subject: [PATCH 073/402] sys/src/9/port: increase MaxTlsDevs in devtls --- sys/src/9/port/devtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 0e04531e1b..7721c41858 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -180,7 +180,7 @@ static TlsErrs tlserrs[] = { enum { /* max. open tls connections */ - MaxTlsDevs = 1024 + MaxTlsDevs = 16*1024 }; static Lock tdlock; From 2e235f39d7b308bde882cfc41a4f4ff30dbc5d62 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 27 Sep 2021 06:42:21 +0000 Subject: [PATCH 074/402] sys/src/9/port: fix leak in devtls (thanks Cinap Lenrek) --- sys/src/9/port/devtls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 7721c41858..6b50cf0833 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -1254,6 +1254,8 @@ tlsrecwrite(TlsRec *tr, int type, Block *b) if(tr->debug)pprint("send %ld\n", BLEN(b)); if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); + if(type == RApplication) + checkstate(tr, 0, SOpen); ok = SHandshake|SOpen|SRClose; if(type == RAlert) @@ -1371,7 +1373,6 @@ tlsbwrite(Chan *c, Block *b, ulong offset) tr->handout += n; break; case Qdata: - checkstate(tr, 0, SOpen); tlsrecwrite(tr, RApplication, b); tr->dataout += n; break; From be518a9fb157c9a87325a75a076eefa8b09a3e4e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 7 Dec 2021 07:57:11 +0000 Subject: [PATCH 075/402] sys/src/9/port: reject zero length records (thanks Cinap Lenrek) --- sys/src/9/port/devtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 6b50cf0833..05cecb29a0 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -769,8 +769,8 @@ if(tr->debug)pprint("consumed %d header\n", RecHdrLen); if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'", tr->version, tr->verset?"/set":"", len, type, ver, (char*)header); - if(len > MaxCipherRecLen || len < 0) - rcvError(tr, ERecordOverflow, "record message too long %d", len); + if(len > MaxCipherRecLen || len <= 0) + rcvError(tr, ERecordOverflow, "bad record message length %d", len); ensure(tr, &tr->unprocessed, len); nconsumed = 0; poperror(); From 98f042b5f303ae7cedb175c1412dc51059f6d8d8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 31 Oct 2021 07:04:18 +0000 Subject: [PATCH 076/402] sys/src/9/bcm: import bcm changes (2021-04-11) (thanks Richard Miller) --- sys/src/9/bcm/arch.c | 192 ++- sys/src/9/bcm/archbcm.c | 109 +- sys/src/9/bcm/archbcm2.c | 280 +++++ sys/src/9/bcm/archbcm4.c | 280 +++++ sys/src/9/bcm/arm.h | 55 +- sys/src/9/bcm/arm.s | 31 +- sys/src/9/bcm/armv6.s | 324 +++++ sys/src/9/bcm/armv7.s | 492 ++++++++ sys/src/9/bcm/bootwifi.rc | 70 ++ sys/src/9/bcm/cache.v7.s | 221 ++++ sys/src/9/bcm/clock.c | 90 +- sys/src/9/bcm/dat.h | 46 +- sys/src/9/bcm/devarch.c | 27 +- sys/src/9/bcm/devgpio.c | 161 +++ sys/src/9/bcm/devi2c.c | 227 ++++ sys/src/9/bcm/devrtc3231.c | 371 ++++++ sys/src/9/bcm/devspi.c | 234 ++++ sys/src/9/bcm/devusb.c | 167 ++- sys/src/9/bcm/dma.c | 34 +- sys/src/9/bcm/emmc.c | 192 ++- sys/src/9/bcm/ether4330.c | 2392 ++++++++++++++++++++++++++++++++++++ sys/src/9/bcm/ethergenet.c | 971 +++++++++++++++ sys/src/9/bcm/ethermii.c | 262 ++++ sys/src/9/bcm/ethermii.h | 122 ++ sys/src/9/bcm/etherusb.c | 92 +- sys/src/9/bcm/fns.h | 73 +- sys/src/9/bcm/fpiarm.c | 2 + sys/src/9/bcm/gisb.c | 90 ++ sys/src/9/bcm/gpio.c | 111 ++ sys/src/9/bcm/i2c.c | 236 ++++ sys/src/9/bcm/io.h | 22 + sys/src/9/bcm/l.s | 361 ++---- sys/src/9/bcm/lexception.s | 54 +- sys/src/9/bcm/main.c | 252 +++- sys/src/9/bcm/mem.h | 34 +- sys/src/9/bcm/mkfile | 35 +- sys/src/9/bcm/mmu.c | 334 +++-- sys/src/9/bcm/pci.c | 1136 +++++++++++++++++ sys/src/9/bcm/pci.h | 241 ++++ sys/src/9/bcm/pi | 17 +- sys/src/9/bcm/pi2 | 72 ++ sys/src/9/bcm/pi2cpu | 72 ++ sys/src/9/bcm/pi2wifi | 79 ++ sys/src/9/bcm/pi4 | 76 ++ sys/src/9/bcm/pi4cpu | 76 ++ sys/src/9/bcm/pi4wifi | 86 ++ sys/src/9/bcm/picpu | 17 +- sys/src/9/bcm/pifat | 6 +- sys/src/9/bcm/pitft.c | 277 +++++ sys/src/9/bcm/piwifi | 79 ++ sys/src/9/bcm/rebootcode.s | 189 ++- sys/src/9/bcm/screen.c | 32 +- sys/src/9/bcm/screen.h | 7 + sys/src/9/bcm/sdhc.c | 579 +++++++++ sys/src/9/bcm/sdhost.c | 389 ++++++ sys/src/9/bcm/sdmmc.c | 355 ++++++ sys/src/9/bcm/spi.c | 149 +++ sys/src/9/bcm/trap.c | 148 ++- sys/src/9/bcm/trap4.c | 993 +++++++++++++++ sys/src/9/bcm/uartmini.c | 103 +- sys/src/9/bcm/usb.h | 205 +++ sys/src/9/bcm/usbdwc.c | 154 ++- sys/src/9/bcm/usbxhci.c | 1837 +++++++++++++++++++++++++++ sys/src/9/bcm/vcore.c | 146 ++- sys/src/9/bcm/vfp3.c | 513 +++++++- sys/src/9/bcm/words.pi2 | 11 + sys/src/9/bcm/words.pi4 | 14 + 67 files changed, 16293 insertions(+), 811 deletions(-) create mode 100644 sys/src/9/bcm/archbcm2.c create mode 100644 sys/src/9/bcm/archbcm4.c create mode 100644 sys/src/9/bcm/armv6.s create mode 100644 sys/src/9/bcm/armv7.s create mode 100644 sys/src/9/bcm/bootwifi.rc create mode 100644 sys/src/9/bcm/cache.v7.s create mode 100644 sys/src/9/bcm/devgpio.c create mode 100644 sys/src/9/bcm/devi2c.c create mode 100644 sys/src/9/bcm/devrtc3231.c create mode 100644 sys/src/9/bcm/devspi.c create mode 100644 sys/src/9/bcm/ether4330.c create mode 100644 sys/src/9/bcm/ethergenet.c create mode 100644 sys/src/9/bcm/ethermii.c create mode 100644 sys/src/9/bcm/ethermii.h create mode 100644 sys/src/9/bcm/gisb.c create mode 100644 sys/src/9/bcm/gpio.c create mode 100644 sys/src/9/bcm/i2c.c create mode 100644 sys/src/9/bcm/pci.c create mode 100644 sys/src/9/bcm/pci.h create mode 100644 sys/src/9/bcm/pi2 create mode 100644 sys/src/9/bcm/pi2cpu create mode 100644 sys/src/9/bcm/pi2wifi create mode 100644 sys/src/9/bcm/pi4 create mode 100644 sys/src/9/bcm/pi4cpu create mode 100644 sys/src/9/bcm/pi4wifi create mode 100644 sys/src/9/bcm/pitft.c create mode 100644 sys/src/9/bcm/piwifi create mode 100644 sys/src/9/bcm/sdhc.c create mode 100644 sys/src/9/bcm/sdhost.c create mode 100644 sys/src/9/bcm/sdmmc.c create mode 100644 sys/src/9/bcm/spi.c create mode 100644 sys/src/9/bcm/trap4.c create mode 100644 sys/src/9/bcm/usb.h create mode 100644 sys/src/9/bcm/usbxhci.c create mode 100644 sys/src/9/bcm/words.pi2 create mode 100644 sys/src/9/bcm/words.pi4 diff --git a/sys/src/9/bcm/arch.c b/sys/src/9/bcm/arch.c index 22d63fb43c..40240b14de 100644 --- a/sys/src/9/bcm/arch.c +++ b/sys/src/9/bcm/arch.c @@ -1 +1,191 @@ -#include "../omap/arch.c" +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include +#include "ureg.h" + +#include "arm.h" + +/* + * A lot of this stuff doesn't belong here + * but this is a convenient dumping ground for + * later sorting into the appropriate buckets. + */ + +/* Give enough context in the ureg to produce a kernel stack for + * a sleeping process + */ +void +setkernur(Ureg* ureg, Proc* p) +{ + ureg->pc = p->sched.pc; + ureg->sp = p->sched.sp+4; + ureg->r14 = PTR2UINT(sched); +} + +/* + * called in syscallfmt.c, sysfile.c, sysproc.c + */ +void +validalign(uintptr addr, unsigned align) +{ + /* + * Plan 9 is a 32-bit O/S, and the hardware it runs on + * does not usually have instructions which move 64-bit + * quantities directly, synthesizing the operations + * with 32-bit move instructions. Therefore, the compiler + * (and hardware) usually only enforce 32-bit alignment, + * if at all. + * + * Take this out if the architecture warrants it. + */ + if(align == sizeof(vlong)) + align = sizeof(long); + + /* + * Check align is a power of 2, then addr alignment. + */ + if((align != 0 && !(align & (align-1))) && !(addr & (align-1))) + return; + postnote(up, 1, "sys: odd address", NDebug); + error(Ebadarg); + /*NOTREACHED*/ +} + +/* go to user space */ +void +kexit(Ureg*) +{ + uvlong t; + Tos *tos; + + /* precise time accounting, kernel exit */ + tos = (Tos*)(USTKTOP-sizeof(Tos)); + cycles(&t); + tos->kcycles += t - up->kentry; + tos->pcycles = up->pcycles; + tos->cyclefreq = m->cpuhz; + tos->pid = up->pid; + + /* make visible immediately to user proc */ + cachedwbinvse(tos, sizeof *tos); +} + +/* + * return the userpc the last exception happened at + */ +uintptr +userpc(void) +{ + Ureg *ureg = up->dbgreg; + return ureg->pc; +} + +/* This routine must save the values of registers the user is not permitted + * to write from devproc and then restore the saved values before returning. + */ +void +setregisters(Ureg* ureg, char* pureg, char* uva, int n) +{ + USED(ureg, pureg, uva, n); +} + +/* + * this is the body for all kproc's + */ +static void +linkproc(void) +{ + spllo(); + up->kpfun(up->kparg); + pexit("kproc exiting", 0); +} + +/* + * setup stack and initial PC for a new kernel proc. This is architecture + * dependent because of the starting stack location + */ +void +kprocchild(Proc *p, void (*func)(void*), void *arg) +{ + p->sched.pc = PTR2UINT(linkproc); + p->sched.sp = PTR2UINT(p->kstack+KSTACK); + + p->kpfun = func; + p->kparg = arg; +} + +/* + * pc output by dumpaproc + */ +uintptr +dbgpc(Proc* p) +{ + Ureg *ureg; + + ureg = p->dbgreg; + if(ureg == 0) + return 0; + + return ureg->pc; +} + +/* + * set mach dependent process state for a new process + */ +void +procsetup(Proc* p) +{ + fpusysprocsetup(p); +} + +/* + * Save the mach dependent part of the process state. + */ +void +procsave(Proc* p) +{ + uvlong t; + + cycles(&t); + p->pcycles += t; + +// TODO: save and restore VFPv3 FP state once 5[cal] know the new registers. + fpuprocsave(p); + /* + * Prevent the following scenario: + * pX sleeps on cpuA, leaving its page tables in mmul1 + * pX wakes up on cpuB, and exits, freeing its page tables + * pY on cpuB allocates a freed page table page and overwrites with data + * cpuA takes an interrupt, and is now running with bad page tables + * In theory this shouldn't hurt because only user address space tables + * are affected, and mmuswitch will clear mmul1 before a user process is + * dispatched. But empirically it correlates with weird problems, eg + * resetting of the core clock at 0x4000001C which confuses local timers. + */ + if(conf.nmach > 1) + mmuswitch(nil); +} + +void +procrestore(Proc* p) +{ + uvlong t; + + if(p->kp) + return; + cycles(&t); + p->pcycles -= t; + + fpuprocrestore(p); +} + +int +userureg(Ureg* ureg) +{ + return (ureg->psr & PsrMask) == PsrMusr; +} diff --git a/sys/src/9/bcm/archbcm.c b/sys/src/9/bcm/archbcm.c index 568f4919f5..6427539fc1 100644 --- a/sys/src/9/bcm/archbcm.c +++ b/sys/src/9/bcm/archbcm.c @@ -1,5 +1,5 @@ /* - * bcm2835 (e.g. raspberry pi) architecture-specific stuff + * bcm2835 (e.g. original raspberry pi) architecture-specific stuff */ #include "u.h" @@ -16,9 +16,19 @@ #define POWERREGS (VIRTIO+0x100000) +Soc soc = { + .dramsize = 512*MiB, + .physio = 0x20000000, + .busdram = 0x40000000, + .busio = 0x7E000000, + .armlocal = 0, + .l1ptedramattrs = Cached | Buffered, + .l2ptedramattrs = Cached | Buffered, +}; + enum { Wdogfreq = 65536, - Wdogtime = 5, /* seconds, ≤ 15 */ + Wdogtime = 10, /* seconds, ≤ 15 */ }; /* @@ -52,7 +62,7 @@ archreboot(void) ; } -static void +void wdogfeed(void) { u32int *r; @@ -71,10 +81,33 @@ wdogoff(void) r[Rstc] = Password | (r[Rstc] & ~CfgMask); } +char * +cputype2name(char *buf, int size) +{ + seprint(buf, buf + size, "1176JZF-S"); + return buf; +} + void cpuidprint(void) { - print("cpu%d: %dMHz ARM1176JZF-S\n", m->machno, m->cpumhz); + char name[64]; + + cputype2name(name, sizeof name); + delay(50); /* let uart catch up */ + print("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name); +} + +int +getncpus(void) +{ + return 1; +} + +int +startcpus(uint) +{ + return 1; } void @@ -86,15 +119,63 @@ archbcmlink(void) int archether(unsigned ctlrno, Ether *ether) { - switch(ctlrno) { - case 0: - ether->type = "usb"; - ether->ctlrno = ctlrno; - ether->irq = -1; - ether->nopt = 0; - ether->mbps = 100; - return 1; - } - return -1; + ether->type = "usb"; + ether->ctlrno = ctlrno; + ether->irq = -1; + ether->nopt = 0; + return 1; +} + +int +l2ap(int ap) +{ + return (AP(3, (ap))|AP(2, (ap))|AP(1, (ap))|AP(0, (ap))); +} + +/* + * atomic ops + * make sure that we don't drag in the C library versions + */ + +long +ainc(long *p) +{ + int s, v; + + s = splhi(); + v = ++*p; + splx(s); + return v; +} + +long +adec(long *p) +{ + int s, v; + + s = splhi(); + v = --*p; + splx(s); + return v; +} + +int +cas32(void* addr, u32int old, u32int new) +{ + int r, s; + + s = splhi(); + if(r = (*(u32int*)addr == old)) + *(u32int*)addr = new; + splx(s); + if (r) + coherence(); + return r; +} + +int +cmpswap(long *addr, long old, long new) +{ + return cas32(addr, old, new); } diff --git a/sys/src/9/bcm/archbcm2.c b/sys/src/9/bcm/archbcm2.c new file mode 100644 index 0000000000..a5e07224de --- /dev/null +++ b/sys/src/9/bcm/archbcm2.c @@ -0,0 +1,280 @@ +/* + * bcm2836 (e.g.raspberry pi 2) architecture-specific stuff + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "io.h" +#include "arm.h" + +#include "../port/netif.h" +#include "etherif.h" + +typedef struct Mbox Mbox; +typedef struct Mboxes Mboxes; + +#define POWERREGS (VIRTIO+0x100000) + +Soc soc = { + .dramsize = 0x3F000000, /* was 1024*MiB, but overlaps with physio */ + .physio = 0x3F000000, + .busdram = 0xC0000000, + .busio = 0x7E000000, + .armlocal = 0x40000000, + .oscfreq = 19200000, + .l1ptedramattrs = Cached | Buffered | L1wralloc | L1sharable, + .l2ptedramattrs = Cached | Buffered | L2wralloc | L2sharable, +}; + +enum { + Wdogfreq = 65536, + Wdogtime = 10, /* seconds, ≤ 15 */ +}; + +/* + * Power management / watchdog registers + */ +enum { + Rstc = 0x1c>>2, + Password = 0x5A<<24, + CfgMask = 0x03<<4, + CfgReset = 0x02<<4, + Rsts = 0x20>>2, + Wdog = 0x24>>2, +}; + +/* + * Arm local regs for smp + */ +struct Mbox { + u32int doorbell; + u32int mbox1; + u32int mbox2; + u32int startcpu; +}; +struct Mboxes { + Mbox set[4]; + Mbox clr[4]; +}; + +enum { + Mboxregs = 0x80 +}; + +static Lock startlock[MAXMACH + 1]; + +void +archreset(void) +{ + fpon(); +} + +void +archreboot(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Wdog] = Password | 1; + r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset; + coherence(); + for(;;) + ; +} + +void +wdogfeed(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Wdog] = Password | (Wdogtime * Wdogfreq); + r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset; +} + +void +wdogoff(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Rstc] = Password | (r[Rstc] & ~CfgMask); +} + + +char * +cputype2name(char *buf, int size) +{ + u32int r; + uint part; + char *p; + + r = cpidget(); /* main id register */ + assert((r >> 24) == 'A'); + part = (r >> 4) & MASK(12); + switch(part){ + case 0xc07: + p = seprint(buf, buf + size, "Cortex-A7"); + break; + case 0xd03: + p = seprint(buf, buf + size, "Cortex-A53"); + break; + case 0xd08: + p = seprint(buf, buf + size, "Cortex-A72"); + break; + default: + p = seprint(buf, buf + size, "Unknown-%#x", part); + break; + } + seprint(p, buf + size, " r%ldp%ld", + (r >> 20) & MASK(4), r & MASK(4)); + return buf; +} + +void +cpuidprint(void) +{ + char name[64]; + + cputype2name(name, sizeof name); + delay(50); /* let uart catch up */ + print("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name); +} + +int +getncpus(void) +{ + int n, max; + char *p; + + n = 4; + if(n > MAXMACH) + n = MAXMACH; + p = getconf("*ncpu"); + if(p && (max = atoi(p)) > 0 && n > max) + n = max; + return n; +} + +static int +startcpu(uint cpu) +{ + Mboxes *mb; + int i; + void cpureset(); + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + if(mb->clr[cpu].startcpu) + return -1; + mb->set[cpu].startcpu = PADDR(cpureset); + coherence(); + sev(); + for(i = 0; i < 1000; i++) + if(mb->clr[cpu].startcpu == 0) + return 0; + mb->clr[cpu].startcpu = PADDR(cpureset); + mb->set[cpu].doorbell = 1; + return 0; +} + +void +mboxclear(uint cpu) +{ + Mboxes *mb; + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->clr[cpu].mbox1 = 1; +} + +void +wakecpu(uint cpu) +{ + Mboxes *mb; + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->set[cpu].mbox1 = 1; +} + +int +startcpus(uint ncpu) +{ + int i, timeout; + + for(i = 0; i < ncpu; i++) + lock(&startlock[i]); + cachedwbse(startlock, sizeof startlock); + for(i = 1; i < ncpu; i++){ + if(startcpu(i) < 0) + return i; + timeout = 10000000; + while(!canlock(&startlock[i])) + if(--timeout == 0) + return i; + unlock(&startlock[i]); + } + return ncpu; +} + +void +archbcm2link(void) +{ + addclock0link(wdogfeed, HZ); +} + +int +archether(unsigned ctlrno, Ether *ether) +{ + switch(ctlrno){ + case 0: + ether->type = "usb"; + break; + case 1: + ether->type = "4330"; + break; + default: + return 0; + } + ether->ctlrno = ctlrno; + ether->irq = -1; + ether->nopt = 0; + ether->maxmtu = 9014; + return 1; +} + +int +l2ap(int ap) +{ + return (AP(0, (ap))); +} + +int +cmpswap(long *addr, long old, long new) +{ + return cas((ulong*)addr, old, new); +} + +void +cpustart(int cpu) +{ + Mboxes *mb; + void machon(int); + + up = nil; + machinit(); + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->clr[cpu].doorbell = 1; + trapinit(); + clockinit(); + mmuinit1(); + timersinit(); + cpuidprint(); + archreset(); + machon(m->machno); + unlock(&startlock[cpu]); + schedinit(); + panic("schedinit returned"); +} diff --git a/sys/src/9/bcm/archbcm4.c b/sys/src/9/bcm/archbcm4.c new file mode 100644 index 0000000000..78133a6b57 --- /dev/null +++ b/sys/src/9/bcm/archbcm4.c @@ -0,0 +1,280 @@ +/* + * bcm2711 (raspberry pi 4) architecture-specific stuff + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "io.h" +#include "arm.h" + +#include "../port/netif.h" +#include "etherif.h" + +typedef struct Mbox Mbox; +typedef struct Mboxes Mboxes; + +#define POWERREGS (VIRTIO+0x100000) + +Soc soc = { + .dramsize = 0xFC000000, + .physio = 0xFE000000, + .busdram = 0xC0000000, + .busio = 0x7E000000, + .armlocal = 0xFF800000, + .oscfreq = 54000000, + .l1ptedramattrs = Cached | Buffered | L1wralloc | L1sharable, + .l2ptedramattrs = Cached | Buffered | L2wralloc | L2sharable, +}; + +enum { + Wdogfreq = 65536, + Wdogtime = 10, /* seconds, ≤ 15 */ +}; + +/* + * Power management / watchdog registers + */ +enum { + Rstc = 0x1c>>2, + Password = 0x5A<<24, + CfgMask = 0x03<<4, + CfgReset = 0x02<<4, + Rsts = 0x20>>2, + Wdog = 0x24>>2, +}; + +/* + * Arm local regs for smp + */ +struct Mbox { + u32int doorbell; + u32int mbox1; + u32int mbox2; + u32int startcpu; +}; +struct Mboxes { + Mbox set[4]; + Mbox clr[4]; +}; + +enum { + Mboxregs = 0x80 +}; + +static Lock startlock[MAXMACH + 1]; + +void +archreset(void) +{ + fpon(); +} + +void +archreboot(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Wdog] = Password | 1; + r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset; + coherence(); + for(;;) + ; +} + +void +wdogfeed(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Wdog] = Password | (Wdogtime * Wdogfreq); + r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset; +} + +void +wdogoff(void) +{ + u32int *r; + + r = (u32int*)POWERREGS; + r[Rstc] = Password | (r[Rstc] & ~CfgMask); +} + + +char * +cputype2name(char *buf, int size) +{ + u32int r; + uint part; + char *p; + + r = cpidget(); /* main id register */ + assert((r >> 24) == 'A'); + part = (r >> 4) & MASK(12); + switch(part){ + case 0xc07: + p = seprint(buf, buf + size, "Cortex-A7"); + break; + case 0xd03: + p = seprint(buf, buf + size, "Cortex-A53"); + break; + case 0xd08: + p = seprint(buf, buf + size, "Cortex-A72"); + break; + default: + p = seprint(buf, buf + size, "Unknown-%#x", part); + break; + } + seprint(p, buf + size, " r%ldp%ld", + (r >> 20) & MASK(4), r & MASK(4)); + return buf; +} + +void +cpuidprint(void) +{ + char name[64]; + + cputype2name(name, sizeof name); + delay(50); /* let uart catch up */ + print("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name); +} + +int +getncpus(void) +{ + int n, max; + char *p; + + n = 4; + if(n > MAXMACH) + n = MAXMACH; + p = getconf("*ncpu"); + if(p && (max = atoi(p)) > 0 && n > max) + n = max; + return n; +} + +static int +startcpu(uint cpu) +{ + Mboxes *mb; + int i; + void cpureset(); + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + if(mb->clr[cpu].startcpu) + return -1; + mb->set[cpu].startcpu = PADDR(cpureset); + coherence(); + sev(); + for(i = 0; i < 1000; i++) + if(mb->clr[cpu].startcpu == 0) + return 0; + mb->clr[cpu].startcpu = PADDR(cpureset); + mb->set[cpu].doorbell = 1; + return 0; +} + +void +mboxclear(uint cpu) +{ + Mboxes *mb; + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->clr[cpu].mbox1 = 1; +} + +void +wakecpu(uint cpu) +{ + Mboxes *mb; + + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->set[cpu].mbox1 = 1; +} + +int +startcpus(uint ncpu) +{ + int i, timeout; + + for(i = 0; i < ncpu; i++) + lock(&startlock[i]); + cachedwbse(startlock, sizeof startlock); + for(i = 1; i < ncpu; i++){ + if(startcpu(i) < 0) + return i; + timeout = 10000000; + while(!canlock(&startlock[i])) + if(--timeout == 0) + return i; + unlock(&startlock[i]); + } + return ncpu; +} + +void +archbcm4link(void) +{ + addclock0link(wdogfeed, HZ); +} + +int +archether(unsigned ctlrno, Ether *ether) +{ + switch(ctlrno){ + case 0: + ether->type = "genet"; + break; + case 1: + ether->type = "4330"; + break; + default: + return 0; + } + ether->ctlrno = ctlrno; + ether->irq = -1; + ether->nopt = 0; + ether->maxmtu = 9014; + return 1; +} + +int +l2ap(int ap) +{ + return (AP(0, (ap))); +} + +int +cmpswap(long *addr, long old, long new) +{ + return cas((ulong*)addr, old, new); +} + +void +cpustart(int cpu) +{ + Mboxes *mb; + void machon(int); + + up = nil; + machinit(); + mb = (Mboxes*)(ARMLOCAL + Mboxregs); + mb->clr[cpu].doorbell = 1; + trapinit(); + clockinit(); + mmuinit1(); + timersinit(); + cpuidprint(); + archreset(); + machon(m->machno); + unlock(&startlock[cpu]); + schedinit(); + panic("schedinit returned"); +} diff --git a/sys/src/9/bcm/arm.h b/sys/src/9/bcm/arm.h index 534f42d291..662c2d911a 100644 --- a/sys/src/9/bcm/arm.h +++ b/sys/src/9/bcm/arm.h @@ -1,5 +1,5 @@ /* - * arm-specific definitions for armv6 + * arm-specific definitions for armv6 (arm11), armv7 (cortex-a8 and -a7) * these are used in C and assembler */ @@ -12,6 +12,7 @@ #define PsrMsvc 0x00000013 /* `protected mode for OS' */ #define PsrMmon 0x00000016 /* `secure monitor' (trustzone hyper) */ #define PsrMabt 0x00000017 +#define PsrMhyp 0x0000001A #define PsrMund 0x0000001B #define PsrMsys 0x0000001F /* `privileged user mode for OS' (trustzone) */ #define PsrMask 0x0000001F @@ -52,8 +53,18 @@ #define CpTLD 10 /* TLB Lockdown, with op2 */ #define CpVECS 12 /* vector bases, op1==0, Crm==0, op2s (cortex) */ #define CpPID 13 /* Process ID */ +#define CpTIMER 14 /* Generic timer (cortex-a7) */ #define CpSPM 15 /* system performance monitor (arm1176) */ +/* + * CpTIMER op1==0 Crm and opcode2 registers (cortex-a7) + */ +#define CpTIMERcntfrq 0 +#define CpTIMERphys 2 + +#define CpTIMERphysval 0 +#define CpTIMERphysctl 1 + /* * CpTTB op1==0, Crm==0 opcode2 values. */ @@ -71,6 +82,7 @@ * CpID Secondary (CRm) registers. */ #define CpIDidct 0 +#define CpIDfeat 1 /* * CpID op1==0 opcode2 fields. @@ -80,6 +92,7 @@ #define CpIDct 1 /* cache type */ #define CpIDtlb 3 /* tlb type (cortex) */ #define CpIDmpid 5 /* multiprocessor id (cortex) */ +#define CpIDrevid 6 /* extra revision ID */ /* CpIDid op1 values */ #define CpIDcsize 1 /* cache size (cortex) */ @@ -133,6 +146,10 @@ #define CpACasa (1<<4) /* enable speculative accesses */ #define CpACl1pe (1<<3) /* l1 cache parity enable */ #define CpACl2en (1<<1) /* l2 cache enable; default 1 */ + +/* cortex-a7 and cortex-a9 */ +#define CpACsmp (1<<6) /* SMP l1 caches coherence; needed for ldrex/strex */ +#define CpACl1pctl (3<<13) /* l1 prefetch control */ /* * CpCONTROL Secondary (CRm) registers and opcode2 fields. */ @@ -151,9 +168,9 @@ #define CpCACHEinvd 6 /* data or unified */ #define CpCACHEinvu 7 /* unified (not on cortex) */ #define CpCACHEva2pa 8 /* va -> pa translation (cortex) */ -#define CpCACHEwb 10 /* writeback */ -#define CpCACHEinvdse 11 /* data or unified by mva */ -#define CpCACHEwbi 14 /* writeback+invalidate */ +#define CpCACHEwb 10 /* writeback to PoC */ +#define CpCACHEwbu 11 /* writeback to PoU */ +#define CpCACHEwbi 14 /* writeback+invalidate (to PoC) */ #define CpCACHEall 0 /* entire (not for invd nor wb(i) on cortex) */ #define CpCACHEse 1 /* single entry */ @@ -223,7 +240,7 @@ #define CpVECSmon 1 /* secure monitor base addr */ /* - * CpSPM Secondary (CRm) registers and opcode2 fields. + * CpSPM Secondary (CRm) registers and opcode2 fields (armv6) */ #define CpSPMperf 12 /* various counters */ @@ -238,6 +255,21 @@ #define CpCACHERANGEdwb 12 /* writeback */ #define CpCACHERANGEdwbi 14 /* writeback+invalidate */ +/* + * CpTTB cache control bits + */ +#define CpTTBnos (1<<5) /* only Inner cache shareable */ +#define CpTTBinc (0<<0|0<<6) /* inner non-cacheable */ +#define CpTTBiwba (0<<0|1<<6) /* inner write-back write-allocate */ +#define CpTTBiwt (1<<0|0<<6) /* inner write-through */ +#define CpTTBiwb (1<<0|1<<6) /* inner write-back no write-allocate */ +#define CpTTBonc (0<<3) /* outer non-cacheable */ +#define CpTTBowba (1<<3) /* outer write-back write-allocate */ +#define CpTTBowt (2<<3) /* outer write-through */ +#define CpTTBowb (3<<3) /* outer write-back no write-allocate */ +#define CpTTBs (1<<1) /* page table in shareable memory */ +#define CpTTBbase ~0x7F /* mask off control bits */ + /* * MMU page table entries. * Mbz (0x10) bit is implementation-defined and must be 0 on the cortex. @@ -248,6 +280,7 @@ #define Coarse (Mbz|1) /* L1 */ #define Section (Mbz|2) /* L1 1MB */ #define Fine (Mbz|3) /* L1 */ +#define Super (1<<18) /* L1 16MB */ #define Large 0x00000001 /* L2 64KB */ #define Small 0x00000002 /* L2 4KB */ @@ -256,6 +289,16 @@ #define Cached 0x00000008 /* L[12] */ #define Dom0 0 +#define L1wralloc (1<<12) /* L1 TEX */ +#define L1sharable (1<<16) +#define L1noexec (1<<4) +#define L2wralloc (1<<6) /* L2 TEX (small pages) */ +#define L2sharable (1<<10) + +/* attributes for memory containing locks -- differs between armv6 and armv7 */ +//#define L1ptedramattrs (Cached | Buffered | L1wralloc | L1sharable) +//#define L2ptedramattrs (Cached | Buffered | L2wralloc | L2sharable) + #define Noaccess 0 /* AP, DAC */ #define Krw 1 /* AP */ /* armv7 deprecates AP[2] == 1 & AP[1:0] == 2 (Uro), prefers 3 (new in v7) */ @@ -267,7 +310,7 @@ #define F(v, o, w) (((v) & ((1<<(w))-1))<<(o)) #define AP(n, v) F((v), ((n)*2)+4, 2) #define L1AP(ap) (AP(3, (ap))) -#define L2AP(ap) (AP(3, (ap))|AP(2, (ap))|AP(1, (ap))|AP(0, (ap))) /* pre-armv7 */ +/* L2AP differs between armv6 and armv7 -- see l2ap in arch*.c */ #define DAC(n, v) F((v), (n)*2, 2) #define HVECTORS 0xffff0000 diff --git a/sys/src/9/bcm/arm.s b/sys/src/9/bcm/arm.s index 2dbb8778aa..cb69db455a 100644 --- a/sys/src/9/bcm/arm.s +++ b/sys/src/9/bcm/arm.s @@ -1,5 +1,5 @@ /* - * armv6 machine assist, definitions + * armv6/v7 machine assist, definitions * * loader uses R11 as scratch. */ @@ -11,8 +11,6 @@ #define L1X(va) (((((va))>>20) & 0x0fff)<<2) -#define PTEDRAM (Dom0|L1AP(Krw)|Section|Cached|Buffered) - /* * new instructions */ @@ -25,12 +23,37 @@ MOVW $0, R0; \ MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait -#define BARRIERS ISB; DSB +#define BARRIERS DSB; ISB #define MCRR(coproc, op, rd, rn, crm) \ WORD $(0xec400000|(rn)<<16|(rd)<<12|(coproc)<<8|(op)<<4|(crm)) +#define MRRC(coproc, op, rd, rn, crm) \ + WORD $(0xec500000|(rn)<<16|(rd)<<12|(coproc)<<8|(op)<<4|(crm)) +#define MSR(R, rn, m, m1) \ + WORD $(0xe120f200|(R)<<22|(m1)<<16|(m)<<8|(rn)) + +#define LDREX(fp,t) WORD $(0xe<<28|0x01900f9f | (fp)<<16 | (t)<<12) +/* `The order of operands is from left to right in dataflow order' - asm man */ +#define STREX(f,tp,r) WORD $(0xe<<28|0x01800f90 | (tp)<<16 | (r)<<12 | (f)<<0) +#define CLREX WORD $0xf57ff01f + +#define CPSIE WORD $0xf1080080 /* intr enable: zeroes I bit */ +#define CPSID WORD $0xf10c0080 /* intr disable: sets I bit */ #define OKAY \ MOVW $0x7E200028,R2; \ MOVW $0x10000,R3; \ MOVW R3,(R2) + +#define PUTC(s) + +/* + * get cpu id, or zero if armv6 + */ +#define CPUID(r) \ + MRC CpSC, 0, r, C(CpID), C(CpIDfeat), 7; \ + CMP $0, r; \ + B.EQ 2(PC); \ + MRC CpSC, 0, r, C(CpID), C(CpIDidct), CpIDmpid; \ + AND.S $(MAXMACH-1), r + diff --git a/sys/src/9/bcm/armv6.s b/sys/src/9/bcm/armv6.s new file mode 100644 index 0000000000..68714f924d --- /dev/null +++ b/sys/src/9/bcm/armv6.s @@ -0,0 +1,324 @@ +/* + * Broadcom bcm2835 SoC, as used in Raspberry Pi + * arm1176jzf-s processor (armv6) + */ + +#include "arm.s" + +#define CACHELINESZ 32 + +TEXT armstart(SB), 1, $-4 + + /* + * SVC mode, interrupts disabled + */ + MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 + MOVW R1, CPSR + + /* + * disable the mmu and L1 caches + * invalidate caches and tlb + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache|CpCpredict|CpCmmu), R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvu), CpCACHEall + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + ISB + + /* + * clear mach and page tables + */ + MOVW $PADDR(MACHADDR), R1 + MOVW $PADDR(KTZERO), R2 +_ramZ: + MOVW R0, (R1) + ADD $4, R1 + CMP R1, R2 + BNE _ramZ + + /* + * start stack at top of mach (physical addr) + * set up page tables for kernel + */ + MOVW $PADDR(MACHADDR+MACHSIZE-4), R13 + MOVW $PADDR(L1), R0 + BL ,mmuinit(SB) + + /* + * set up domain access control and page table base + */ + MOVW $Client, R1 + MCR CpSC, 0, R1, C(CpDAC), C(0) + MOVW $PADDR(L1), R1 + MCR CpSC, 0, R1, C(CpTTB), C(0) + + /* + * enable caches, mmu, and high vectors + */ + MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + ORR $(CpChv|CpCdcache|CpCicache|CpCpredict|CpCmmu), R0 + MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + ISB + + /* + * switch SB, SP, and PC into KZERO space + */ + MOVW $setR12(SB), R12 + MOVW $(MACHADDR+MACHSIZE-4), R13 + MOVW $_startpg(SB), R15 + +TEXT _startpg(SB), 1, $-4 + + /* + * enable cycle counter + */ + MOVW $1, R1 + MCR CpSC, 0, R1, C(CpSPM), C(CpSPMperf), CpSPMctl + + /* + * call main and loop forever if it returns + */ + BL ,main(SB) + B ,0(PC) + + BL _div(SB) /* hack to load _div, etc. */ + +TEXT cpidget(SB), 1, $-4 /* main ID */ + MRC CpSC, 0, R0, C(CpID), C(0), CpIDid + RET + +TEXT fsrget(SB), 1, $-4 /* data fault status */ + MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata + RET + +TEXT ifsrget(SB), 1, $-4 /* instruction fault status */ + MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst + RET + +TEXT farget(SB), 1, $-4 /* fault address */ + MRC CpSC, 0, R0, C(CpFAR), C(0x0) + RET + +TEXT lcycles(SB), 1, $-4 + MRC CpSC, 0, R0, C(CpSPM), C(CpSPMperf), CpSPMcyc + RET + +TEXT splhi(SB), 1, $-4 + MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */ + MOVW R14, 0(R2) + + MOVW CPSR, R0 /* turn off irqs (but not fiqs) */ + ORR $(PsrDirq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splfhi(SB), 1, $-4 + MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */ + MOVW R14, 0(R2) + + MOVW CPSR, R0 /* turn off irqs and fiqs */ + ORR $(PsrDirq|PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splflo(SB), 1, $-4 + MOVW CPSR, R0 /* turn on fiqs */ + BIC $(PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT spllo(SB), 1, $-4 + MOVW CPSR, R0 /* turn on irqs and fiqs */ + BIC $(PsrDirq|PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splx(SB), 1, $-4 + MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */ + MOVW R14, 0(R2) + + MOVW R0, R1 /* reset interrupt level */ + MOVW CPSR, R0 + MOVW R1, CPSR + RET + +TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */ + RET + +TEXT islo(SB), 1, $-4 + MOVW CPSR, R0 + AND $(PsrDirq), R0 + EOR $(PsrDirq), R0 + RET + +TEXT tas(SB), $-4 +TEXT _tas(SB), $-4 + MOVW R0,R1 + MOVW $1,R0 + SWPW R0,(R1) /* fix: deprecated in armv6 */ + RET + +TEXT setlabel(SB), 1, $-4 + MOVW R13, 0(R0) /* sp */ + MOVW R14, 4(R0) /* pc */ + MOVW $0, R0 + RET + +TEXT gotolabel(SB), 1, $-4 + MOVW 0(R0), R13 /* sp */ + MOVW 4(R0), R14 /* pc */ + MOVW $1, R0 + RET + +TEXT getcallerpc(SB), 1, $-4 + MOVW 0(R13), R0 + RET + +TEXT idlehands(SB), $-4 + MOVW CPSR, R3 + ORR $(PsrDirq|PsrDfiq), R3, R1 /* splfhi */ + MOVW R1, CPSR + + DSB + MOVW nrdy(SB), R0 + CMP $0, R0 + MCR.EQ CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait + DSB + + MOVW R3, CPSR /* splx */ + RET + + +TEXT coherence(SB), $-4 + BARRIERS + RET + +/* + * invalidate tlb + */ +TEXT mmuinvalidate(SB), 1, $-4 + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc + RET + +/* + * mmuinvalidateaddr(va) + * invalidate tlb entry for virtual page address va, ASID 0 + */ +TEXT mmuinvalidateaddr(SB), 1, $-4 + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse + BARRIERS + RET + +/* + * drain write buffer + * writeback data cache + */ +TEXT cachedwb(SB), 1, $-4 + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEall + RET + +/* + * drain write buffer + * writeback and invalidate data cache + */ +TEXT cachedwbinv(SB), 1, $-4 + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall + RET + +/* + * cachedwbinvse(va, n) + * drain write buffer + * writeback and invalidate data cache range [va, va+n) + */ +TEXT cachedwbinvse(SB), 1, $-4 + MOVW R0, R1 /* DSB clears R0 */ + DSB + MOVW n+4(FP), R2 + ADD R1, R2 + SUB $1, R2 + BIC $(CACHELINESZ-1), R1 + BIC $(CACHELINESZ-1), R2 + MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwbi) + RET + +/* + * cachedwbse(va, n) + * drain write buffer + * writeback data cache range [va, va+n) + */ +TEXT cachedwbtlb(SB), 1, $-4 +TEXT cachedwbse(SB), 1, $-4 + + MOVW R0, R1 /* DSB clears R0 */ + DSB + MOVW n+4(FP), R2 + ADD R1, R2 + BIC $(CACHELINESZ-1), R1 + BIC $(CACHELINESZ-1), R2 + MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwb) + RET + +/* + * cachedinvse(va, n) + * drain write buffer + * invalidate data cache range [va, va+n) + */ +TEXT cachedinvse(SB), 1, $-4 + MOVW R0, R1 /* DSB clears R0 */ + DSB + MOVW n+4(FP), R2 + ADD R1, R2 + SUB $1, R2 + BIC $(CACHELINESZ-1), R1 + BIC $(CACHELINESZ-1), R2 + MCRR(CpSC, 0, 2, 1, CpCACHERANGEinvd) + RET + +/* + * drain write buffer and prefetch buffer + * writeback and invalidate data cache + * invalidate instruction cache + */ +TEXT cacheuwbinv(SB), 1, $-4 + BARRIERS + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall + RET + +/* + * L2 cache is not enabled + */ +TEXT l2cacheuwbinv(SB), 1, $-4 + RET + +/* + * invalidate instruction cache + */ +TEXT cacheiinv(SB), 1, $-4 + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall + RET + +/* + * invalidate range of instruction cache + */ +TEXT cacheiinvse(SB), 1, $-4 + MOVW R0, R1 /* DSB clears R0 */ + DSB + MOVW n+4(FP), R2 + ADD R1, R2 + SUB $1, R2 + MCRR(CpSC, 0, 2, 1, CpCACHERANGEinvi) + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc + DSB + ISB + RET diff --git a/sys/src/9/bcm/armv7.s b/sys/src/9/bcm/armv7.s new file mode 100644 index 0000000000..d149183b4c --- /dev/null +++ b/sys/src/9/bcm/armv7.s @@ -0,0 +1,492 @@ +/* + * Broadcom bcm2836 SoC, as used in Raspberry Pi 2 + * 4 x Cortex-A7 processor (armv7) + */ + +#include "arm.s" + +#define CACHELINESZ 64 +#define ICACHELINESZ 32 + +#undef DSB +#undef DMB +#undef ISB +#define DSB WORD $0xf57ff04f /* data synch. barrier; last f = SY */ +#define DMB WORD $0xf57ff05f /* data mem. barrier; last f = SY */ +#define ISB WORD $0xf57ff06f /* instr. sync. barrier; last f = SY */ +#define WFI WORD $0xe320f003 /* wait for interrupt */ +#define WFI_EQ WORD $0x0320f003 /* wait for interrupt if eq */ +#define ERET WORD $0xe160006e /* exception return from HYP */ +#define SEV WORD $0xe320f004 /* send event */ + +/* tas/cas strex debugging limits; started at 10000 */ +#define MAXSC 1000000 + +TEXT armstart(SB), 1, $-4 + + /* + * if not cpu0, go to secondary startup + */ + CPUID(R1) + BNE reset + + /* + * go to SVC mode, interrupts disabled + */ + BL svcmode(SB) + + /* + * disable the mmu and caches + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache|CpCmmu), R1 + ORR $(CpCsbo|CpCsw), R1 + BIC $CpCsbz, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BARRIERS + + /* + * clear mach and page tables + */ + MOVW $PADDR(MACHADDR), R1 + MOVW $PADDR(KTZERO), R2 +_ramZ: + MOVW R0, (R1) + ADD $4, R1 + CMP R1, R2 + BNE _ramZ + + /* + * turn SMP on + * invalidate tlb + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + ORR $CpACsmp, R1 /* turn SMP on */ + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + BARRIERS + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS + + /* + * start stack at top of mach (physical addr) + * set up page tables for kernel + */ + MOVW $PADDR(MACHADDR+MACHSIZE-4), R13 + MOVW $PADDR(L1), R0 + BL mmuinit(SB) + + /* + * set up domain access control and page table base + */ + MOVW $Client, R1 + MCR CpSC, 0, R1, C(CpDAC), C(0) + MOVW $PADDR(L1), R1 + ORR $(CpTTBs|CpTTBowba|CpTTBiwba), R1 + MCR CpSC, 0, R1, C(CpTTB), C(0) + MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + + /* + * invalidate my caches before enabling + */ + BL cachedinv(SB) + BL cacheiinv(SB) + BL l2cacheuinv(SB) + BARRIERS + + /* + * enable caches, mmu, and high vectors + */ + + MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + ORR $(CpChv|CpCdcache|CpCicache|CpCmmu), R0 + MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + BARRIERS + + /* + * switch SB, SP, and PC into KZERO space + */ + MOVW $setR12(SB), R12 + MOVW $(MACHADDR+MACHSIZE-4), R13 + MOVW $_startpg(SB), R15 + +TEXT _startpg(SB), 1, $-4 + + /* + * enable cycle counter + */ + MOVW $(1<<31), R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc + MOVW $1, R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc + + /* + * call main and loop forever if it returns + */ + BL ,main(SB) + B ,0(PC) + + BL _div(SB) /* hack to load _div, etc. */ + +/* + * startup entry for cpu(s) other than 0 + */ +TEXT cpureset(SB), 1, $-4 +reset: + /* + * load physical base for SB addressing while mmu is off + * keep a handy zero in R0 until first function call + */ + MOVW $setR12(SB), R12 + SUB $KZERO, R12 + ADD $PHYSDRAM, R12 + MOVW $0, R0 + + /* + * SVC mode, interrupts disabled + */ + BL svcmode(SB) + + /* + * disable the mmu and caches + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache|CpCmmu), R1 + ORR $(CpCsbo|CpCsw), R1 + BIC $CpCsbz, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BARRIERS + + /* + * turn SMP on + * invalidate tlb + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + ORR $CpACsmp, R1 /* turn SMP on */ + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + BARRIERS + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS + + /* + * find Mach for this cpu + */ + MRC CpSC, 0, R2, C(CpID), C(CpIDidct), CpIDmpid + AND $(MAXMACH-1), R2 /* mask out non-cpu-id bits */ + SLL $2, R2 /* convert to word index */ + MOVW $machaddr(SB), R0 + BIC $KSEGM, R0 + ADD R2, R0 /* R0 = &machaddr[cpuid] */ + MOVW (R0), R0 /* R0 = machaddr[cpuid] */ + CMP $0, R0 + BEQ 0(PC) /* must not be zero */ + SUB $KZERO, R0, R(MACH) /* m = PADDR(machaddr[cpuid]) */ + + /* + * start stack at top of local Mach + */ + ADD $(MACHSIZE-4), R(MACH), R13 + + /* + * set up domain access control and page table base + */ + MOVW $Client, R1 + MCR CpSC, 0, R1, C(CpDAC), C(0) + MOVW 12(R(MACH)), R1 /* m->mmul1 */ + SUB $KZERO, R1 /* phys addr */ + ORR $(CpTTBs|CpTTBowba|CpTTBiwba), R1 + MCR CpSC, 0, R1, C(CpTTB), C(0) + MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + + /* + * invalidate my caches before enabling + */ + BL cachedinv(SB) + BL cacheiinv(SB) + BARRIERS + + /* + * enable caches, mmu, and high vectors + */ + MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + ORR $(CpChv|CpCdcache|CpCicache|CpCmmu), R0 + MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + BARRIERS + + /* + * switch MACH, SB, SP, and PC into KZERO space + */ + ADD $KZERO, R(MACH) + MOVW $setR12(SB), R12 + ADD $KZERO, R13 + MOVW $_startpg2(SB), R15 + +TEXT _startpg2(SB), 1, $-4 + + /* + * enable cycle counter + */ + MOVW $(1<<31), R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc + MOVW $1, R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc + + /* + * call cpustart and loop forever if it returns + */ + MRC CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDmpid + AND $(MAXMACH-1), R0 /* mask out non-cpu-id bits */ + BL ,cpustart(SB) + B ,0(PC) + +/* + * get into SVC mode with interrupts disabled + * raspberry pi firmware since 29 Sept 2015 starts in HYP mode + */ +TEXT svcmode(SB), 1, $-4 + MOVW CPSR, R1 + AND $PsrMask, R1 + MOVW $PsrMhyp, R2 + CMP R2, R1 + MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 + BNE nothyp + MSR(1, 1, 1, 0xe) /* MOVW R1, SPSR_HYP */ + MSR(0, 14, 1, 0xe) /* MOVW R14, ELR_HYP */ + ERET +nothyp: + MOVW R1, CPSR + RET + +TEXT cpidget(SB), 1, $-4 /* main ID */ + MRC CpSC, 0, R0, C(CpID), C(0), CpIDid + RET + +TEXT fsrget(SB), 1, $-4 /* data fault status */ + MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata + RET + +TEXT ifsrget(SB), 1, $-4 /* instruction fault status */ + MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst + RET + +TEXT farget(SB), 1, $-4 /* fault address */ + MRC CpSC, 0, R0, C(CpFAR), C(0x0) + RET + +TEXT cpctget(SB), 1, $-4 /* cache type */ + MRC CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct + RET + +TEXT lcycles(SB), 1, $-4 + MRC CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0 + RET + +TEXT splhi(SB), 1, $-4 + MOVW R14, 4(R(MACH)) /* save caller pc in m->splpc */ + + MOVW CPSR, R0 /* turn off irqs (but not fiqs) */ + ORR $(PsrDirq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splfhi(SB), 1, $-4 + MOVW R14, 4(R(MACH)) /* save caller pc in m->splpc */ + + MOVW CPSR, R0 /* turn off irqs and fiqs */ + ORR $(PsrDirq|PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splflo(SB), 1, $-4 + MOVW CPSR, R0 /* turn on fiqs */ + BIC $(PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT spllo(SB), 1, $-4 + MOVW CPSR, R0 /* turn on irqs and fiqs */ + MOVW $0, R1 + CMP.S R1, R(MACH) + MOVW.NE R1, 4(R(MACH)) /* clear m->splpc */ + BIC $(PsrDirq|PsrDfiq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splx(SB), 1, $-4 + MOVW R14, 4(R(MACH)) /* save caller pc in m->splpc */ + + MOVW R0, R1 /* reset interrupt level */ + MOVW CPSR, R0 + MOVW R1, CPSR + RET + +TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */ + RET + +TEXT islo(SB), 1, $-4 + MOVW CPSR, R0 + AND $(PsrDirq), R0 + EOR $(PsrDirq), R0 + RET + +TEXT tas(SB), $-4 +TEXT _tas(SB), $-4 /* _tas(ulong *) */ + /* returns old (R0) after modifying (R0) */ + MOVW R0,R5 + DMB + + MOVW $1,R2 /* new value of (R0) */ + MOVW $MAXSC, R8 +tas1: + LDREX(5,7) /* LDREX 0(R5),R7 */ + CMP.S $0, R7 /* old value non-zero (lock taken)? */ + BNE lockbusy /* we lose */ + SUB.S $1, R8 + BEQ lockloop2 + STREX(2,5,4) /* STREX R2,(R5),R4 */ + CMP.S $0, R4 + BNE tas1 /* strex failed? try again */ + DMB + B tas0 +lockloop2: + BL abort(SB) +lockbusy: + CLREX +tas0: + MOVW R7, R0 /* return old value */ + RET + +TEXT setlabel(SB), 1, $-4 + MOVW R13, 0(R0) /* sp */ + MOVW R14, 4(R0) /* pc */ + MOVW $0, R0 + RET + +TEXT gotolabel(SB), 1, $-4 + MOVW 0(R0), R13 /* sp */ + MOVW 4(R0), R14 /* pc */ + MOVW $1, R0 + RET + +TEXT getcallerpc(SB), 1, $-4 + MOVW 0(R13), R0 + RET + +TEXT idlehands(SB), $-4 + MOVW CPSR, R3 + ORR $(PsrDirq|PsrDfiq), R3, R1 /* splfhi */ + MOVW R1, CPSR + + DSB + MOVW nrdy(SB), R0 + CMP $0, R0 + WFI_EQ + DSB + + MOVW R3, CPSR /* splx */ + RET + + +TEXT coherence(SB), $-4 + BARRIERS + RET + +TEXT sev(SB), $-4 + SEV + RET + +/* + * invalidate tlb + */ +TEXT mmuinvalidate(SB), 1, $-4 + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS + RET + +/* + * mmuinvalidateaddr(va) + * invalidate tlb entry for virtual page address va, ASID 0 + */ +TEXT mmuinvalidateaddr(SB), 1, $-4 + DSB + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse + BARRIERS + RET + +/* + * `single-element' cache operations. + * in arm arch v7, if effective to PoC, they operate on all cache levels, so separate + * l2 functions are unnecessary. + */ + +TEXT cachedwbse(SB), $-4 /* D writeback SE */ + MOVW R0, R2 + + MOVW CPSR, R3 + CPSID /* splhi */ + + BARRIERS /* force outstanding stores to cache */ + MOVW R2, R0 + MOVW 4(FP), R1 + ADD R0, R1 /* R1 is end address */ + BIC $(CACHELINESZ-1), R0 /* cache line start */ +_dwbse: + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse + /* can't have a BARRIER here since it zeroes R0 */ + ADD $CACHELINESZ, R0 + CMP.S R0, R1 + BGT _dwbse + B _wait + +/* + * TLB on armv7 loads from cache, so no need for writeback + */ +TEXT cachedwbtlb(SB), $-4 + DSB + ISB + RET + +TEXT cachedwbinvse(SB), $-4 /* D writeback+invalidate SE */ + MOVW R0, R2 + + MOVW CPSR, R3 + CPSID /* splhi */ + + BARRIERS /* force outstanding stores to cache */ + MOVW R2, R0 + MOVW 4(FP), R1 + ADD R0, R1 /* R1 is end address */ + BIC $(CACHELINESZ-1), R0 /* cache line start */ +_dwbinvse: + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse + /* can't have a BARRIER here since it zeroes R0 */ + ADD $CACHELINESZ, R0 + CMP.S R0, R1 + BGT _dwbinvse +_wait: /* drain write buffer */ + BARRIERS + + MOVW R3, CPSR /* splx */ + RET + +TEXT cachedinvse(SB), $-4 /* D invalidate SE */ + MOVW R0, R2 + + MOVW CPSR, R3 + CPSID /* splhi */ + + BARRIERS /* force outstanding stores to cache */ + MOVW R2, R0 + MOVW 4(FP), R1 + ADD R0, R1 /* R1 is end address */ + BIC $(CACHELINESZ-1), R0 /* cache line start */ +_dinvse: + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse + /* can't have a BARRIER here since it zeroes R0 */ + ADD $CACHELINESZ, R0 + CMP.S R0, R1 + BGT _dinvse + B _wait + +#include "cache.v7.s" diff --git a/sys/src/9/bcm/bootwifi.rc b/sys/src/9/bcm/bootwifi.rc new file mode 100644 index 0000000000..f88f4e6d38 --- /dev/null +++ b/sys/src/9/bcm/bootwifi.rc @@ -0,0 +1,70 @@ +#!/boot/rc -m /boot/rcmain + +wifi=/net/ether1 + +fn need { + while (~ $#$1 0) { + echo -n $1': ' + $1=`{read} + } +} + +fn joinwifi { + need essid + echo essid $essid >$wifi/clone + need wificrypt + wifip=p + if (! ~ $#wifipass 0) { + factotum -g 'proto=wpapsk essid='$essid' !password='$wifipass + wifip='' + } + switch ($wificrypt) { + case wep + echo crypt wep >$wifi/clone + need wep_password + echo key0 $wep_password >$wifi/clone + rm /env/wep_password + case wpa wpa1 + wpa -1p $wifi + case wpa2 + wpa -2$wifip $wifi + } +} + +path=(/bin /boot) +bind '#p' /proc +bind '#d' /fd +bind -a '#P' /dev +bind -a '#t' /dev +bind -a '#S' /dev +bind -a '#I' /net +bind -a '#l0' /net +bind -a '#l1' /net || wifi=/net/ether0 + +usbd + +need fs +need auth + +factotum -u -s factotum -a $auth +joinwifi +ipconfig ether $wifi +srv tcp!$fs!564 boot + +rootdir=/root +rootspec='' +mount -c /srv/boot /root +bind -ac $rootdir / +bind -ac $rootdir/mnt /mnt + +bind /$cputype/bin /bin +bind -a /rc/bin /bin +path=(. /bin) + +if (! ~ $#init 0) + exec `{echo $init} +if (~ $service cpu) + exec /$cputype/init -c +if not + exec /$cputype/init -t +exec /boot/rc -m/boot/rcmain -i diff --git a/sys/src/9/bcm/cache.v7.s b/sys/src/9/bcm/cache.v7.s new file mode 100644 index 0000000000..8c9b26ebaf --- /dev/null +++ b/sys/src/9/bcm/cache.v7.s @@ -0,0 +1,221 @@ +/* + * cortex arm arch v7 cache flushing and invalidation + * shared by l.s and rebootcode.s + */ + +#define BPIALL MCR CpSC, 0, R0, C(CpCACHE), C(5), 6 /* branch predictor invalidate all */ + +TEXT cacheiinv(SB), $-4 /* I invalidate */ + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall /* ok on cortex */ + BPIALL /* redundant? */ + DSB + ISB + RET + +TEXT cacheiinvse(SB), $0 /* I invalidate SE */ + MOVW 4(FP), R1 + ADD R0, R1 + BIC $(ICACHELINESZ - 1), R0 + DSB +_iinvse: + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEse + ADD $ICACHELINESZ, R0 + CMP.S R0, R1 + BGT _iinvse + BPIALL + DSB + ISB + RET + +/* + * set/way operators, passed a suitable set/way value in R0. + */ +TEXT cachedwb_sw(SB), $-4 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEsi + RET + +TEXT cachedwbinv_sw(SB), $-4 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEsi + RET + +TEXT cachedinv_sw(SB), $-4 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEsi + RET + + /* set cache size select */ +TEXT setcachelvl(SB), $-4 + MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 + DSB + ISB + RET + + /* return cache sizes */ +TEXT getwayssets(SB), $-4 + MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 + RET + +/* + * l1 cache operations. + * l1 and l2 ops are intended to be called from C, thus need save no + * caller's regs, only those we need to preserve across calls. + */ + +TEXT cachedwb(SB), $-4 + MOVW.W R14, -8(R13) + MOVW $cachedwb_sw(SB), R0 + MOVW $1, R8 + BL wholecache(SB) + MOVW.P 8(R13), R15 + +TEXT cachedwbinv(SB), $-4 + MOVW.W R14, -8(R13) + MOVW $cachedwbinv_sw(SB), R0 + MOVW $1, R8 + BL wholecache(SB) + MOVW.P 8(R13), R15 + +TEXT cachedinv(SB), $-4 + MOVW.W R14, -8(R13) + MOVW $cachedinv_sw(SB), R0 + MOVW $1, R8 + BL wholecache(SB) + MOVW.P 8(R13), R15 + +TEXT cacheuwbinv(SB), $-4 + MOVM.DB.W [R14], (R13) /* save lr on stack */ + MOVW CPSR, R1 + CPSID /* splhi */ + + MOVM.DB.W [R1], (R13) /* save R1 on stack */ + + BL cachedwbinv(SB) + BL cacheiinv(SB) + + MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */ + MOVW R1, CPSR + MOVM.IA.W (R13), [R14] /* restore lr */ + RET + +/* + * l2 cache operations + */ + +TEXT l2cacheuwb(SB), $-4 + MOVW.W R14, -8(R13) + MOVW $cachedwb_sw(SB), R0 + MOVW $2, R8 + BL wholecache(SB) + MOVW.P 8(R13), R15 + +TEXT l2cacheuwbinv(SB), $-4 + MOVW.W R14, -8(R13) + MOVW CPSR, R1 + CPSID /* splhi */ + + MOVM.DB.W [R1], (R13) /* save R1 on stack */ + + MOVW $cachedwbinv_sw(SB), R0 + MOVW $2, R8 + BL wholecache(SB) + BL l2cacheuinv(SB) + + MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */ + MOVW R1, CPSR + MOVW.P 8(R13), R15 + +TEXT l2cacheuinv(SB), $-4 + MOVW.W R14, -8(R13) + MOVW $cachedinv_sw(SB), R0 + MOVW $2, R8 + BL wholecache(SB) + MOVW.P 8(R13), R15 + +/* + * these shift values are for the Cortex-A8 L1 cache (A=2, L=6) and + * the Cortex-A8 L2 cache (A=3, L=6). + * A = log2(# of ways), L = log2(bytes per cache line). + * see armv7 arch ref p. 1403. + */ +#define L1WAYSH 30 +#define L1SETSH 6 +#define L2WAYSH 29 +#define L2SETSH 6 + +/* + * callers are assumed to be the above l1 and l2 ops. + * R0 is the function to call in the innermost loop. + * R8 is the cache level (one-origin: 1 or 2). + * + * initial translation by 5c, then massaged by hand. + */ +TEXT wholecache+0(SB), $-4 + MOVW R0, R1 /* save argument for inner loop in R1 */ + SUB $1, R8 /* convert cache level to zero origin */ + + /* we may not have the MMU on yet, so map R1 to PC's space */ + BIC $KSEGM, R1 /* strip segment from address */ + MOVW PC, R2 /* get PC's segment ... */ + AND $KSEGM, R2 + ORR R2, R1 /* combine them */ + + /* drain write buffers */ + BARRIERS + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait + ISB + + MOVW CPSR, R2 + MOVM.DB.W [R2,R14], (SP) /* save regs on stack */ + CPSID /* splhi to make entire op atomic */ + + /* get cache sizes */ + SLL $1, R8, R0 /* R0 = (cache - 1) << 1 */ + MCR CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 /* set cache size select */ + ISB + MRC CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 /* get cache sizes */ + + /* compute # of ways and sets for this cache level */ + SRA $3, R0, R5 /* R5 (ways) = R0 >> 3 */ + AND $1023, R5 /* R5 = (R0 >> 3) & MASK(10) */ + ADD $1, R5 /* R5 (ways) = ((R0 >> 3) & MASK(10)) + 1 */ + + SRA $13, R0, R2 /* R2 = R0 >> 13 */ + AND $32767, R2 /* R2 = (R0 >> 13) & MASK(15) */ + ADD $1, R2 /* R2 (sets) = ((R0 >> 13) & MASK(15)) + 1 */ + + /* precompute set/way shifts for inner loop */ + CMP $0, R8 /* cache == 1? */ + MOVW.EQ $L1WAYSH, R3 /* yes */ + MOVW.EQ $L1SETSH, R4 + MOVW.NE $L2WAYSH, R3 /* no */ + MOVW.NE $L2SETSH, R4 + + /* iterate over ways */ + MOVW $0, R7 /* R7: way */ +outer: + /* iterate over sets */ + MOVW $0, R6 /* R6: set */ +inner: + /* compute set/way register contents */ + SLL R3, R7, R0 /* R0 = way << R3 (L?WAYSH) */ + ORR R8<<1, R0 /* R0 = way << L?WAYSH | (cache - 1) << 1 */ + ORR R6<= sets? */ + BLT inner /* no, do next set */ + + ADD $1, R7 /* way++ */ + CMP R5, R7 /* way >= ways? */ + BLT outer /* no, do next way */ + + MOVM.IA.W (SP), [R2,R14] /* restore regs */ + MOVW R2, CPSR /* splx */ + + /* drain write buffers */ + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait + ISB + RET diff --git a/sys/src/9/bcm/clock.c b/sys/src/9/bcm/clock.c index e1693864bd..441e0a2c84 100644 --- a/sys/src/9/bcm/clock.c +++ b/sys/src/9/bcm/clock.c @@ -1,11 +1,13 @@ /* - * bcm2835 timers + * bcm283[56] timers * System timers run at 1MHz (timers 1 and 2 are used by GPU) * ARM timer usually runs at 250MHz (may be slower in low power modes) * Cycle counter runs at 700MHz (unless overclocked) * All are free-running up-counters + * Cortex-a7 has local generic timers per cpu (which we run at 1MHz) * * Use system timer 3 (64 bits) for hzclock interrupts and fastticks + * For smp on bcm2836, use local generic timer for interrupts on cpu1-3 * Use ARM timer (32 bits) for perfticks * Use ARM timer to force immediate interrupt * Use cycle counter for cycles() @@ -17,14 +19,21 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "ureg.h" +#include "arm.h" enum { SYSTIMERS = VIRTIO+0x3000, ARMTIMER = VIRTIO+0xB400, + Localctl = 0x00, + Prescaler = 0x08, + Localintpending = 0x60, + SystimerFreq = 1*Mhz, MaxPeriod = SystimerFreq / HZ, - MinPeriod = SystimerFreq / (100*HZ), + MinPeriod = 10, + }; typedef struct Systimers Systimers; @@ -64,6 +73,11 @@ enum { TmrPrescale256 = 0x02<<2, CntWidth16 = 0<<1, CntWidth32 = 1<<1, + + /* generic timer (cortex-a7) */ + Enable = 1<<0, + Imask = 1<<1, + Istatus = 1<<2, }; static void @@ -71,12 +85,24 @@ clockintr(Ureg *ureg, void *) { Systimers *tn; + if(m->machno != 0) + panic("cpu%d: unexpected system timer interrupt", m->machno); tn = (Systimers*)SYSTIMERS; /* dismiss interrupt */ + tn->c3 = tn->clo - 1; tn->cs = 1<<3; timerintr(ureg, 0); } +static void +localclockintr(Ureg *ureg, void *) +{ + if(m->machno == 0) + panic("cpu0: Unexpected local generic timer interrupt"); + cpwrtimerphysctl(Imask|Enable); + timerintr(ureg, 0); +} + void clockshutdown(void) { @@ -84,7 +110,10 @@ clockshutdown(void) tm = (Armtimer*)ARMTIMER; tm->ctl = 0; - wdogoff(); + if(cpuserver) + wdogfeed(); + else + wdogoff(); } void @@ -94,11 +123,18 @@ clockinit(void) Armtimer *tm; u32int t0, t1, tstart, tend; - tn = (Systimers*)SYSTIMERS; - tm = (Armtimer*)ARMTIMER; - tm->load = 0; - tm->ctl = TmrPrescale1|CntEnable|CntWidth32; + if(((cprdfeat1() >> 16) & 0xF) != 0) { + /* generic timer supported */ + if(m->machno == 0){ + /* input clock is 19.2MHz or 54MHz crystal */ + *(ulong*)(ARMLOCAL + Localctl) = 0; + /* divide by (2^31/Prescaler) for 1Mhz */ + *(ulong*)(ARMLOCAL + Prescaler) = (((uvlong)SystimerFreq<<31)/soc.oscfreq)&~1UL; + } + cpwrtimerphysctl(Imask); + } + tn = (Systimers*)SYSTIMERS; tstart = tn->clo; do{ t0 = lcycles(); @@ -111,25 +147,36 @@ clockinit(void) m->cpuhz = 100 * t1; m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz; m->cyclefreq = m->cpuhz; - - tn->c3 = tn->clo - 1; - intrenable(IRQtimer3, clockintr, nil, 0, "clock"); + if(m->machno == 0){ + tn->c3 = tn->clo - 1; + tm = (Armtimer*)ARMTIMER; + tm->load = 0; + tm->ctl = TmrPrescale1|CntEnable|CntWidth32; + intrenable(IRQtimer3, clockintr, nil, 0, "clock"); + }else + intrenable(IRQcntpns, localclockintr, nil, 0, "clock"); } void timerset(uvlong next) { Systimers *tn; - vlong now, period; + uvlong now; + long period; - tn = (Systimers*)SYSTIMERS; now = fastticks(nil); - period = next - fastticks(nil); + period = next - now; if(period < MinPeriod) - next = now + MinPeriod; + period = MinPeriod; else if(period > MaxPeriod) - next = now + MaxPeriod; - tn->c3 = (ulong)next; + period = MaxPeriod; + if(m->machno > 0){ + cpwrtimerphysval(period); + cpwrtimerphysctl(Enable); + }else{ + tn = (Systimers*)SYSTIMERS; + tn->c3 = tn->clo + period; + } } uvlong @@ -137,16 +184,17 @@ fastticks(uvlong *hz) { Systimers *tn; ulong lo, hi; + uvlong now; - tn = (Systimers*)SYSTIMERS; if(hz) *hz = SystimerFreq; + tn = (Systimers*)SYSTIMERS; do{ hi = tn->chi; lo = tn->clo; }while(tn->chi != hi); - m->fastclock = (uvlong)hi<<32 | lo; - return m->fastclock; + now = (uvlong)hi<<32 | lo; + return now; } ulong @@ -179,7 +227,7 @@ ulong { if(SystimerFreq != 1*Mhz) return fastticks2us(fastticks(nil)); - return fastticks(nil); + return ((Systimers*)SYSTIMERS)->clo; } void @@ -188,8 +236,8 @@ microdelay(int n) Systimers *tn; u32int now, diff; - tn = (Systimers*)SYSTIMERS; diff = n + 1; + tn = (Systimers*)SYSTIMERS; now = tn->clo; while(tn->clo - now < diff) ; diff --git a/sys/src/9/bcm/dat.h b/sys/src/9/bcm/dat.h index a4355057eb..39fc81ce10 100644 --- a/sys/src/9/bcm/dat.h +++ b/sys/src/9/bcm/dat.h @@ -15,6 +15,7 @@ enum { typedef struct Conf Conf; typedef struct Confmem Confmem; typedef struct FPsave FPsave; +typedef struct I2Cdev I2Cdev; typedef struct ISAConf ISAConf; typedef struct Label Label; typedef struct Lock Lock; @@ -27,6 +28,7 @@ typedef struct PhysUart PhysUart; typedef struct PMMU PMMU; typedef struct Proc Proc; typedef u32int PTE; +typedef struct Soc Soc; typedef struct Uart Uart; typedef struct Ureg Ureg; typedef uvlong Tval; @@ -105,7 +107,7 @@ struct Conf { ulong nmach; /* processors */ ulong nproc; /* processes */ - Confmem mem[1]; /* physical memory */ + Confmem mem[2]; /* physical memory */ ulong npage; /* total physical pages of memory */ usize upages; /* user page pool */ ulong copymode; /* 0 is copy on write, 1 is copy on reference */ @@ -119,6 +121,28 @@ struct Conf int monitor; /* flag */ }; +struct I2Cdev { + int salen; + int addr; + int tenbit; +}; + +/* + * GPIO + */ +enum { + Input = 0x0, + Output = 0x1, + Alt0 = 0x4, + Alt1 = 0x5, + Alt2 = 0x6, + Alt3 = 0x7, + Alt4 = 0x3, + Alt5 = 0x2, +}; + + + /* * things saved in the Proc structure during a notify */ @@ -135,16 +159,20 @@ struct MMMU int mmul1lo; int mmul1hi; int mmupid; + PTE* kmapl2; /* l2 for section containing kmap area and vectors */ }; /* * MMU stuff in proc */ #define NCOLOR 1 /* 1 level cache, don't worry about VCE's */ +#define NKMAPS 4 struct PMMU { Page* mmul2; Page* mmul2cache; /* free mmu pages */ + int nkmap; + PTE kmaptab[NKMAPS]; }; #include "../port/portdat.h" @@ -216,8 +244,9 @@ struct Mach */ typedef void KMap; #define VA(k) ((uintptr)(k)) -#define kmap(p) (KMap*)((p)->pa|kseg0) -#define kunmap(k) +//#define kmap(p) (KMap*)((p)->pa|kseg0) +extern KMap* kmap(Page*); +extern void kunmap(KMap*); struct { @@ -284,3 +313,14 @@ struct DevConf Devport *ports; /* The ports themselves */ }; +struct Soc { /* SoC dependent configuration */ + ulong dramsize; + uintptr physio; + uintptr busdram; + uintptr busio; + uintptr armlocal; + uint oscfreq; + u32int l1ptedramattrs; + u32int l2ptedramattrs; +}; +extern Soc soc; diff --git a/sys/src/9/bcm/devarch.c b/sys/src/9/bcm/devarch.c index 3ef0cdc089..da4dc66060 100644 --- a/sys/src/9/bcm/devarch.c +++ b/sys/src/9/bcm/devarch.c @@ -150,9 +150,30 @@ Dev archdevtab = { static long cputyperead(Chan*, void *a, long n, vlong offset) { - char str[128]; + char name[64], str[128]; - snprint(str, sizeof str, "ARM11 %d\n", m->cpumhz); + cputype2name(name, sizeof name); + snprint(str, sizeof str, "ARM %s %d\n", name, m->cpumhz); + return readstr(offset, a, n, str); +} + +static long +cputempread(Chan*, void *a, long n, vlong offset) +{ + char str[16]; + + snprint(str, sizeof str, "%ud\n", (getcputemp()+500)/1000); + return readstr(offset, a, n, str); +} + +extern uvlong getserial(void); + +static long +cpuserread(Chan*, void *a, long n, vlong offset) +{ + char str[16]; + + snprint(str, sizeof str, "%16.16llux", getserial()); return readstr(offset, a, n, str); } @@ -160,4 +181,6 @@ void archinit(void) { addarchfile("cputype", 0444, cputyperead, nil); + addarchfile("cputemp", 0444, cputempread, nil); + addarchfile("serial", 0444, cpuserread, nil)->length = 16; } diff --git a/sys/src/9/bcm/devgpio.c b/sys/src/9/bcm/devgpio.c new file mode 100644 index 0000000000..6b019c0b23 --- /dev/null +++ b/sys/src/9/bcm/devgpio.c @@ -0,0 +1,161 @@ +/* + * Raspberry Pi (BCM2835) GPIO + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +enum { + // GPIO registers + GPLEV = VIRTIO + 0x200034, +}; + +enum{ + Qdir = 0, + Qgpio, +}; + +Dirtab gpiodir[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, + "gpio", {Qgpio, 0}, 0, 0664, +}; + +enum { + // commands + CMfunc, + CMset, + CMpullup, + CMpulldown, + CMfloat, +}; + +static Cmdtab gpiocmd[] = { + {CMfunc, "function", 3}, + {CMset, "set", 3}, + {CMpullup, "pullup", 2}, + {CMpulldown, "pulldown", 2}, + {CMfloat, "float", 2}, +}; + +static char *funcs[] = { "in", "out", "alt5", "alt4", "alt0", + "alt1", "alt2", "alt3", "pulse"}; +static int ifuncs[] = { Input, Output, Alt5, Alt4, Alt0, + Alt1, Alt2, Alt3, -1}; + +static Chan* +gpioattach(char* spec) +{ + return devattach('G', spec); +} + +static Walkqid* +gpiowalk(Chan* c, Chan *nc, char** name, int nname) +{ + return devwalk(c, nc, name, nname, gpiodir, nelem(gpiodir), devgen); +} + +static int +gpiostat(Chan* c, uchar* dp, int n) +{ + return devstat(c, dp, n, gpiodir, nelem(gpiodir), devgen); +} + +static Chan* +gpioopen(Chan* c, int omode) +{ + return devopen(c, omode, gpiodir, nelem(gpiodir), devgen); +} + +static void +gpioclose(Chan*) +{ +} + +static long +gpioread(Chan* c, void *buf, long n, vlong) +{ + char lbuf[20]; + char *e; + + USED(c); + if(c->qid.path == Qdir) + return devdirread(c, buf, n, gpiodir, nelem(gpiodir), devgen); + e = lbuf + sizeof(lbuf); + seprint(lbuf, e, "%08ulx%08ulx", ((ulong *)GPLEV)[1], ((ulong *)GPLEV)[0]); + return readstr(0, buf, n, lbuf); +} + +static long +gpiowrite(Chan* c, void *buf, long n, vlong) +{ + Cmdbuf *cb; + Cmdtab *ct; + int pin, i; + + if(c->qid.type & QTDIR) + error(Eperm); + cb = parsecmd(buf, n); + if(waserror()) { + free(cb); + nexterror(); + } + ct = lookupcmd(cb, gpiocmd, nelem(gpiocmd)); + pin = atoi(cb->f[1]); + switch(ct->index) { + case CMfunc: + for(i = 0; i < nelem(funcs); i++) + if(strcmp(funcs[i], cb->f[2]) == 0) + break; + if(i >= nelem(funcs)) + error(Ebadctl); + if(ifuncs[i] == -1) { + gpiosel(pin, Output); + microdelay(2); + gpiosel(pin, Input); + } + else { + gpiosel(pin, ifuncs[i]); + } + break; + case CMset: + gpioout(pin, atoi(cb->f[2])); + break; + case CMpullup: + gpiopullup(pin); + break; + case CMpulldown: + gpiopulldown(pin); + break; + case CMfloat: + gpiopulloff(pin); + break; + } + free(cb); + poperror(); + return n; +} + +Dev gpiodevtab = { + 'G', + "gpio", + + devreset, + devinit, + devshutdown, + gpioattach, + gpiowalk, + gpiostat, + gpioopen, + devcreate, + gpioclose, + gpioread, + devbread, + gpiowrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/sys/src/9/bcm/devi2c.c b/sys/src/9/bcm/devi2c.c new file mode 100644 index 0000000000..5051224858 --- /dev/null +++ b/sys/src/9/bcm/devi2c.c @@ -0,0 +1,227 @@ +/* + * i2c + * + * Copyright © 1998, 2003 Vita Nuova Limited. + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +typedef struct I2Cdir I2Cdir; + +enum{ + Qdir, + Qdata, + Qctl, +}; + +static +Dirtab i2ctab[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, + "i2cdata", {Qdata, 0}, 256, 0660, + "i2cctl", {Qctl, 0}, 0, 0660, +}; + +struct I2Cdir { + Ref; + I2Cdev; + Dirtab tab[nelem(i2ctab)]; +}; + +static void +i2creset(void) +{ + i2csetup(0); +} + +static Chan* +i2cattach(char* spec) +{ + char *s; + ulong addr; + I2Cdir *d; + Chan *c; + + addr = strtoul(spec, &s, 16); + if(*spec == 0 || *s || addr >= (1<<10)) + error("invalid i2c address"); + d = malloc(sizeof(I2Cdir)); + if(d == nil) + error(Enomem); + d->ref = 1; + d->addr = addr; + d->salen = 0; + d->tenbit = addr >= 128; + memmove(d->tab, i2ctab, sizeof(d->tab)); + sprint(d->tab[1].name, "i2c.%lux.data", addr); + sprint(d->tab[2].name, "i2c.%lux.ctl", addr); + + c = devattach('J', spec); + c->aux = d; + return c; +} + +static Walkqid* +i2cwalk(Chan* c, Chan *nc, char **name, int nname) +{ + Walkqid *wq; + I2Cdir *d; + + d = c->aux; + wq = devwalk(c, nc, name, nname, d->tab, nelem(d->tab), devgen); + if(wq != nil && wq->clone != nil && wq->clone != c) + incref(d); + return wq; +} + +static int +i2cstat(Chan* c, uchar *dp, int n) +{ + I2Cdir *d; + + d = c->aux; + return devstat(c, dp, n, d->tab, nelem(d->tab), devgen); +} + +static Chan* +i2copen(Chan* c, int omode) +{ + I2Cdir *d; + + d = c->aux; + return devopen(c, omode, d->tab, nelem(d->tab), devgen); +} + +static void +i2cclose(Chan *c) +{ + I2Cdir *d; + + d = c->aux; + if(decref(d) == 0) + free(d); +} + +static long +i2cread(Chan *c, void *a, long n, vlong offset) +{ + I2Cdir *d; + char *s, *e; + ulong len; + + d = c->aux; + switch((ulong)c->qid.path){ + case Qdir: + return devdirread(c, a, n, d->tab, nelem(d->tab), devgen); + case Qdata: + len = d->tab[1].length; + if(offset+n >= len){ + n = len - offset; + if(n <= 0) + return 0; + } + n = i2crecv(d, a, n, offset); + break; + case Qctl: + s = smalloc(READSTR); + if(waserror()){ + free(s); + nexterror(); + } + e = seprint(s, s+READSTR, "size %lud\n", (ulong)d->tab[1].length); + if(d->salen) + e = seprint(e, s+READSTR, "subaddress %d\n", d->salen); + if(d->tenbit) + seprint(e, s+READSTR, "a10\n"); + n = readstr(offset, a, n, s); + poperror(); + free(s); + return n; + default: + n=0; + break; + } + return n; +} + +static long +i2cwrite(Chan *c, void *a, long n, vlong offset) +{ + I2Cdir *d; + long len; + Cmdbuf *cb; + + USED(offset); + switch((ulong)c->qid.path){ + case Qdata: + d = c->aux; + len = d->tab[1].length; + if(offset+n >= len){ + n = len - offset; + if(n <= 0) + return 0; + } + n = i2csend(d, a, n, offset); + break; + case Qctl: + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } + if(cb->nf < 1) + error(Ebadctl); + d = c->aux; + if(strcmp(cb->f[0], "subaddress") == 0){ + if(cb->nf > 1){ + len = strtol(cb->f[1], nil, 0); + if(len <= 0) + len = 0; + if(len > 4) + cmderror(cb, "subaddress too long"); + }else + len = 1; + d->salen = len; + }else if(cb->nf > 1 && strcmp(cb->f[0], "size") == 0){ + len = strtol(cb->f[1], nil, 0); + if(len < 0) + cmderror(cb, "size is negative"); + d->tab[1].length = len; + }else if(strcmp(cb->f[0], "a10") == 0) + d->tenbit = 1; + else + cmderror(cb, "unknown control request"); + poperror(); + free(cb); + break; + default: + error(Ebadusefd); + } + return n; +} + +Dev i2cdevtab = { + 'J', + "i2c", + + i2creset, + devinit, + devshutdown, + i2cattach, + i2cwalk, + i2cstat, + i2copen, + devcreate, + i2cclose, + i2cread, + devbread, + i2cwrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/sys/src/9/bcm/devrtc3231.c b/sys/src/9/bcm/devrtc3231.c new file mode 100644 index 0000000000..0a7454ace6 --- /dev/null +++ b/sys/src/9/bcm/devrtc3231.c @@ -0,0 +1,371 @@ +/* + * Maxim DS3231 realtime clock (accessed via rtc) + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +enum { + /* DS3231 registers */ + Seconds= 0, + Minutes= 1, + Hours= 2, + Weekday= 3, + Mday= 4, + Month= 5, + Year= 6, + Nbcd= 7, + + /* Hours register may be in 12-hour or 24-hour mode */ + Twelvehr= 1<<6, + Pm= 1<<5, + + I2Caddr= 0x68, + +}; + +typedef struct Rtc Rtc; + +struct Rtc +{ + int sec; + int min; + int hour; + int mday; + int mon; + int year; +}; + +enum{ + Qdir = 0, + Qrtc, +}; + +Dirtab rtcdir[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, + "rtc", {Qrtc, 0}, 0, 0664, +}; + +static ulong rtc2sec(Rtc*); +static void sec2rtc(ulong, Rtc*); + +static void +i2cread(uint addr, void *buf, int len) +{ + I2Cdev d; + + d.addr = addr; + d.tenbit = 0; + d.salen = 0; + i2crecv(&d, buf, len, 0); +} + +static void +i2cwrite(uint addr, void *buf, int len) +{ + I2Cdev d; + + d.addr = addr; + d.tenbit = 0; + d.salen = 0; + i2csend(&d, buf, len, 0); +} + +static void +rtcinit() +{ + i2csetup(0); +} + +static Chan* +rtcattach(char* spec) +{ + return devattach('r', spec); +} + +static Walkqid* +rtcwalk(Chan* c, Chan *nc, char** name, int nname) +{ + return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen); +} + +static int +rtcstat(Chan* c, uchar* dp, int n) +{ + return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen); +} + +static Chan* +rtcopen(Chan* c, int omode) +{ + char dummy; + + omode = openmode(omode); + switch((ulong)c->qid.path){ + case Qrtc: + if(strcmp(up->user, eve)!=0 && omode!=OREAD) + error(Eperm); + /* if it's not there, this will throw an error */ + i2cread(I2Caddr, &dummy, 1); + break; + } + return devopen(c, omode, rtcdir, nelem(rtcdir), devgen); +} + +static void +rtcclose(Chan*) +{ +} + +static int +bcd(int n) +{ + return (n & 0xF) + (10 * (n >> 4)); +} + +long +rtctime(void) +{ + uchar clk[Nbcd]; + Rtc rtc; + + clk[0] = 0; + i2cwrite(I2Caddr, clk, 1); + i2cread(I2Caddr, clk, Nbcd); + + /* + * convert from BCD + */ + rtc.sec = bcd(clk[Seconds]); + rtc.min = bcd(clk[Minutes]); + rtc.hour = bcd(clk[Hours]); + if(clk[Hours] & Twelvehr){ + rtc.hour = bcd(clk[Hours] & 0x1F); + if(clk[Hours] & Pm) + rtc.hour += 12; + } + rtc.mday = bcd(clk[Mday]); + rtc.mon = bcd(clk[Month] & 0x1F); + rtc.year = bcd(clk[Year]); + + /* + * the world starts jan 1 1970 + */ + if(rtc.year < 70) + rtc.year += 2000; + else + rtc.year += 1900; + return rtc2sec(&rtc); +} + + +static long +rtcread(Chan* c, void* buf, long n, vlong off) +{ + ulong t; + ulong offset = off; + + if(c->qid.type & QTDIR) + return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen); + + switch((ulong)c->qid.path){ + case Qrtc: + t = rtctime(); + n = readnum(offset, buf, n, t, 12); + return n; + } + error(Ebadarg); + return 0; +} + +#define PUTBCD(n,o) bcdclock[1+o] = (n % 10) | (((n / 10) % 10)<<4) + +static long +rtcwrite(Chan* c, void* buf, long n, vlong off) +{ + Rtc rtc; + ulong secs; + uchar bcdclock[1+Nbcd]; + char *cp, *ep; + ulong offset = off; + + if(offset!=0) + error(Ebadarg); + + + switch((ulong)c->qid.path){ + case Qrtc: + /* + * read the time + */ + cp = ep = buf; + ep += n; + while(cp < ep){ + if(*cp>='0' && *cp<='9') + break; + cp++; + } + secs = strtoul(cp, 0, 0); + + /* + * convert to bcd + */ + sec2rtc(secs, &rtc); + PUTBCD(rtc.sec, Seconds); + PUTBCD(rtc.min, Minutes); /* forces 24 hour mode */ + PUTBCD(rtc.hour, Hours); + PUTBCD(0, Weekday); /* hope no other OS uses this */ + PUTBCD(rtc.mday, Mday); + PUTBCD(rtc.mon, Month); + PUTBCD(rtc.year, Year); + + /* + * write the clock + */ + bcdclock[0] = 0; + i2cwrite(I2Caddr, bcdclock, 1+Nbcd); + return n; + } + error(Ebadarg); + return 0; +} + +Dev rtc3231devtab = { + 'r', + "rtc", + + devreset, + rtcinit, + devshutdown, + rtcattach, + rtcwalk, + rtcstat, + rtcopen, + devcreate, + rtcclose, + rtcread, + devbread, + rtcwrite, + devbwrite, + devremove, + devwstat, +}; + +#define SEC2MIN 60L +#define SEC2HOUR (60L*SEC2MIN) +#define SEC2DAY (24L*SEC2HOUR) + +/* + * days per month plus days/year + */ +static int dmsize[] = +{ + 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; +static int ldmsize[] = +{ + 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +/* + * return the days/month for the given year + */ +static int* +yrsize(int y) +{ + if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0)) + return ldmsize; + else + return dmsize; +} + +/* + * compute seconds since Jan 1 1970 + */ +static ulong +rtc2sec(Rtc *rtc) +{ + ulong secs; + int i; + int *d2m; + + secs = 0; + + /* + * seconds per year + */ + for(i = 1970; i < rtc->year; i++){ + d2m = yrsize(i); + secs += d2m[0] * SEC2DAY; + } + + /* + * seconds per month + */ + d2m = yrsize(rtc->year); + for(i = 1; i < rtc->mon; i++) + secs += d2m[i] * SEC2DAY; + + secs += (rtc->mday-1) * SEC2DAY; + secs += rtc->hour * SEC2HOUR; + secs += rtc->min * SEC2MIN; + secs += rtc->sec; + + return secs; +} + +/* + * compute rtc from seconds since Jan 1 1970 + */ +static void +sec2rtc(ulong secs, Rtc *rtc) +{ + int d; + long hms, day; + int *d2m; + + /* + * break initial number into days + */ + hms = secs % SEC2DAY; + day = secs / SEC2DAY; + if(hms < 0) { + hms += SEC2DAY; + day -= 1; + } + + /* + * generate hours:minutes:seconds + */ + rtc->sec = hms % 60; + d = hms / 60; + rtc->min = d % 60; + d /= 60; + rtc->hour = d; + + /* + * year number + */ + if(day >= 0) + for(d = 1970; day >= *yrsize(d); d++) + day -= *yrsize(d); + else + for (d = 1970; day < 0; d--) + day += *yrsize(d-1); + rtc->year = d; + + /* + * generate month + */ + d2m = yrsize(rtc->year); + for(d = 1; day >= d2m[d]; d++) + day -= d2m[d]; + rtc->mday = day + 1; + rtc->mon = d; + + return; +} diff --git a/sys/src/9/bcm/devspi.c b/sys/src/9/bcm/devspi.c new file mode 100644 index 0000000000..8c39712224 --- /dev/null +++ b/sys/src/9/bcm/devspi.c @@ -0,0 +1,234 @@ +/* + * minimal spi interface for testing + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#define SPIREGS (VIRTIO+0x204000) + +extern int qstate(Queue*); + +enum { + QMAX = 64*1024, + Nspislave = 2, +}; + +typedef struct Spi Spi; + +struct Spi { + int csel; + int opens; + QLock; + Queue *iq; + Queue *oq; +}; + +Spi spidev[Nspislave]; + +enum{ + Qdir = 0, + Qctl, + Qspi, +}; + +Dirtab spidir[]={ + ".", {Qdir, 0, QTDIR}, 0, 0555, + "spictl", {Qctl, 0}, 0, 0664, + "spi0", {Qspi+0, 0}, 0, 0664, + "spi1", {Qspi+1, 0}, 0, 0664, +}; + +#define DEVID(path) ((ulong)path - Qspi) + +enum { + CMclock, + CMmode, + CMlossi, +}; + +Cmdtab spitab[] = { + {CMclock, "clock", 2}, + {CMmode, "mode", 2}, + {CMlossi, "lossi", 1}, +}; + +static void +spikick(void *a) +{ + Block *b; + Spi *spi; + + spi = a; + b = qget(spi->oq); + if(b == nil) + return; + if(waserror()){ + freeb(b); + nexterror(); + } + spirw(spi->csel, b->rp, BLEN(b)); + qpass(spi->iq, b); + poperror(); +} + +static void +spiinit(void) +{ +} + +static long +spiread(Chan *c, void *a, long n, vlong off) +{ + Spi *spi; + u32int *sp; + char *p, *e; + char buf[256]; + + if(c->qid.type & QTDIR) + return devdirread(c, a, n, spidir, nelem(spidir), devgen); + + if(c->qid.path == Qctl) { + sp = (u32int *)SPIREGS; + p = buf; + e = p + sizeof(buf); + p = seprint(p, e, "CS: %08x\n", sp[0]); + p = seprint(p, e, "CLK: %08x\n", sp[2]); + p = seprint(p, e, "DLEN: %08x\n", sp[3]); + p = seprint(p, e, "LTOH: %08x\n", sp[4]); + seprint(p, e, "DC: %08x\n", sp[5]); + return readstr(off, a, n, buf); + } + + spi = &spidev[DEVID(c->qid.path)]; + n = qread(spi->iq, a, n); + + return n; +} + +static long +spiwrite(Chan*c, void *a, long n, vlong) +{ + Spi *spi; + Cmdbuf *cb; + Cmdtab *ct; + + if(c->qid.type & QTDIR) + error(Eperm); + + if(c->qid.path == Qctl) { + cb = parsecmd(a, n); + if(waserror()) { + free(cb); + nexterror(); + } + ct = lookupcmd(cb, spitab, nelem(spitab)); + switch(ct->index) { + case CMclock: + spiclock(atoi(cb->f[1])); + break; + case CMmode: + spimode(atoi(cb->f[1])); + break; + case CMlossi: + break; + } + poperror(); + return n; + } + + spi = &spidev[DEVID(c->qid.path)]; + n = qwrite(spi->oq, a, n); + + return n; +} + +static Chan* +spiattach(char* spec) +{ + return devattach(L'π', spec); +} + +static Walkqid* +spiwalk(Chan* c, Chan *nc, char** name, int nname) +{ + return devwalk(c, nc, name, nname, spidir, nelem(spidir), devgen); +} + +static int +spistat(Chan* c, uchar* dp, int n) +{ + return devstat(c, dp, n, spidir, nelem(spidir), devgen); +} + +static Chan* +spiopen(Chan* c, int omode) +{ + Spi *spi; + + c = devopen(c, omode, spidir, nelem(spidir), devgen); + if(c->qid.type & QTDIR) + return c; + + spi = &spidev[DEVID(c->qid.path)]; + qlock(spi); + if(spi->opens++ == 0){ + spi->csel = DEVID(c->qid.path); + if(spi->iq == nil) + spi->iq = qopen(QMAX, 0, nil, nil); + else + qreopen(spi->iq); + if(spi->oq == nil) + spi->oq = qopen(QMAX, Qkick, spikick, spi); + else + qreopen(spi->oq); + } + qunlock(spi); + c->iounit = qiomaxatomic; + return c; +} + +static void +spiclose(Chan *c) +{ + Spi *spi; + + if(c->qid.type & QTDIR) + return; + if((c->flag & COPEN) == 0) + return; + spi = &spidev[DEVID(c->qid.path)]; + qlock(spi); + if(--spi->opens == 0){ + qclose(spi->iq); + qhangup(spi->oq, nil); + qclose(spi->oq); + } + qunlock(spi); +} + +Dev spidevtab = { + L'π', + "spi", + + devreset, + spiinit, + devshutdown, + spiattach, + spiwalk, + spistat, + spiopen, + devcreate, + spiclose, + spiread, + devbread, + spiwrite, + devbwrite, + devremove, + devwstat, +}; + diff --git a/sys/src/9/bcm/devusb.c b/sys/src/9/bcm/devusb.c index ce98511807..38420db597 100644 --- a/sys/src/9/bcm/devusb.c +++ b/sys/src/9/bcm/devusb.c @@ -45,7 +45,7 @@ #include "fns.h" #include "io.h" #include "../port/error.h" -#include "../port/usb.h" +#include "usb.h" typedef struct Hcitype Hcitype; @@ -73,7 +73,7 @@ enum /* Ep. ctls */ CMnew = 0, /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */ - CMnewdev, /* newdev full|low|high portnb (allocate new devices) */ + CMnewdev, /* newdev full|low|high|super portnb (allocate new devices) */ CMhub, /* hub (set the device as a hub) */ CMspeed, /* speed full|low|high|no */ CMmaxpkt, /* maxpkt size */ @@ -154,6 +154,7 @@ static char *ttname[] = static char *spname[] = { + [Superspeed] "super", [Fullspeed] "full", [Lowspeed] "low", [Highspeed] "high", @@ -289,6 +290,8 @@ seprintep(char *s, char *se, Ep *ep, int all) s = seprint(s, se, " hz %ld", ep->hz); s = seprint(s, se, " hub %d", ep->dev->hub); s = seprint(s, se, " port %d", ep->dev->port); + s = seprint(s, se, " rootport %d", ep->dev->rootport); + s = seprint(s, se, " addr %d", ep->dev->addr); if(ep->inuse) s = seprint(s, se, " busy"); else @@ -452,15 +455,16 @@ newdev(Hci *hp, int ishub, int isroot) ep = epalloc(hp); d = ep->dev = smalloc(sizeof(Udev)); d->nb = newusbid(hp); + d->addr = 0; d->eps[0] = ep; ep->nb = 0; ep->toggle[0] = ep->toggle[1] = 0; d->ishub = ishub; d->isroot = isroot; - if(hp->highspeed != 0) - d->speed = Highspeed; - else - d->speed = Fullspeed; + d->rootport = 0; + d->routestr = 0; + d->depth = -1; + d->speed = Fullspeed; d->state = Dconfig; /* address not yet set */ ep->dev = d; ep->ep0 = ep; /* no ref counted here */ @@ -721,6 +725,17 @@ usbreset(void) print("usbreset: bug: Nhcis too small\n"); } +static int +numbits(uint n) +{ + int c = 0; + while(n != 0){ + c++; + n = (n-1) & n; + } + return c; +} + static void usbinit(void) { @@ -733,13 +748,37 @@ usbinit(void) for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){ hp = hcis[ctlrno]; if(hp != nil){ - if(hp->init != nil) + int n; + + if(hp->init != nil){ + if(waserror()){ + print("usbinit: %s: %s\n", hp->type, up->errstr); + continue; + } hp->init(hp); - d = newdev(hp, 1, 1); /* new root hub */ - d->dev->state = Denabled; /* although addr == 0 */ - d->maxpkt = 64; - snprint(info, sizeof(info), "ports %d", hp->nports); - kstrdup(&d->info, info); + poperror(); + } + + hp->superspeed &= (1<nports)-1; + n = hp->nports - numbits(hp->superspeed); + if(n > 0){ + d = newdev(hp, 1, 1); /* new LS/FS/HS root hub */ + d->maxpkt = 64; + if(hp->highspeed != 0) + d->dev->speed = Highspeed; + d->dev->state = Denabled; /* although addr == 0 */ + snprint(info, sizeof(info), "roothub ports %d", n); + kstrdup(&d->info, info); + } + n = numbits(hp->superspeed); + if(n > 0){ + d = newdev(hp, 1, 1); /* new SS root hub */ + d->maxpkt = 512; + d->dev->speed = Superspeed; + d->dev->state = Denabled; /* although addr == 0 */ + snprint(info, sizeof(info), "roothub ports %d", n); + kstrdup(&d->info, info); + } } } } @@ -838,7 +877,7 @@ usbopen(Chan *c, int omode) error(Enotconf); ep->clrhalt = 0; ep->rhrepl = -1; - if(ep->load == 0) + if(ep->load == 0 && ep->dev->speed != Superspeed) ep->load = usbload(ep->dev->speed, ep->maxpkt); ep->hp->epopen(ep); @@ -960,20 +999,57 @@ ctlread(Chan *c, void *a, long n, vlong offset) static long rhubread(Ep *ep, void *a, long n) { - char *b; + uchar b[8]; - if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2) - return -1; - if(ep->rhrepl < 0) + if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2 || ep->rhrepl == -1) return -1; - b = a; - memset(b, 0, n); - PUT2(b, ep->rhrepl); + b[0] = ep->rhrepl; + b[1] = ep->rhrepl>>8; + b[2] = ep->rhrepl>>16; + b[3] = ep->rhrepl>>24; + b[4] = ep->rhrepl>>32; + b[5] = ep->rhrepl>>40; + b[6] = ep->rhrepl>>48; + b[7] = ep->rhrepl>>56; + ep->rhrepl = -1; + + if(n > sizeof(b)) + n = sizeof(b); + memmove(a, b, n); + return n; } +static int +rootport(Ep *ep, int port) +{ + Hci *hp; + Udev *hub; + uint mask; + int rootport; + + hp = ep->hp; + hub = ep->dev; + if(!hub->isroot) + return hub->rootport; + + mask = hp->superspeed; + if(hub->speed != Superspeed) + mask = (1<nports)-1 & ~mask; + + for(rootport = 1; mask != 0; rootport++){ + if(mask & 1){ + if(--port == 0) + return rootport; + } + mask >>= 1; + } + + return 0; +} + static long rhubwrite(Ep *ep, void *a, long n) { @@ -994,8 +1070,8 @@ rhubwrite(Ep *ep, void *a, long n) hp = ep->hp; cmd = s[Rreq]; feature = GET2(s+Rvalue); - port = GET2(s+Rindex); - if(port < 1 || port > hp->nports) + port = rootport(ep, GET2(s+Rindex)); + if(port == 0) error("bad hub port number"); switch(feature){ case Rportenable: @@ -1068,20 +1144,34 @@ pow2(int n) static void setmaxpkt(Ep *ep, char* s) { - long spp; /* samples per packet */ + long spp, max; /* samples per packet */ - if(ep->dev->speed == Highspeed) - spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000; - else + if(ep->dev->speed == Fullspeed) spp = (ep->hz * ep->pollival + 999) / 1000; + else + spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000; ep->maxpkt = spp * ep->samplesz; deprint("usb: %s: setmaxpkt: hz %ld poll %ld" " ntds %d %s speed -> spp %ld maxpkt %ld\n", s, ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed], spp, ep->maxpkt); - if(ep->maxpkt > 1024){ - print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt); - ep->maxpkt = 1024; + switch(ep->dev->speed){ + case Fullspeed: + max = 1024; + break; + case Highspeed: + max = 3*1024; + break; + case Superspeed: + max = 48*1024; + break; + default: + return; + } + if(ep->maxpkt*ep->ntds > max){ + print("usb: %s: maxpkt %ld > %ld for %s, truncating\n", + s, ep->maxpkt*ep->ntds, max, spname[ep->dev->speed]); + ep->maxpkt = max/ep->ntds; } } @@ -1138,13 +1228,20 @@ epctl(Ep *ep, Chan *c, void *a, long n) error("not a hub setup endpoint"); l = name2speed(cb->f[1]); if(l == Nospeed) - error("speed must be full|low|high"); + error("speed must be full|low|high|super"); + if(l != d->speed && (l == Superspeed || d->speed == Superspeed)) + error("wrong speed for superspeed hub/device"); nep = newdev(ep->hp, 0, 0); nep->dev->speed = l; - if(nep->dev->speed != Lowspeed) + if(l == Superspeed) + nep->maxpkt = 512; + else if(l != Lowspeed) nep->maxpkt = 64; /* assume full speed */ - nep->dev->hub = d->nb; + nep->dev->hub = d->addr; nep->dev->port = atoi(cb->f[2]); + nep->dev->depth = d->depth+1; + nep->dev->rootport = rootport(ep, nep->dev->port); + nep->dev->routestr = d->routestr | (((nep->dev->port&15) << 4*nep->dev->depth) >> 4); /* next read request will read * the name for the new endpoint */ @@ -1160,7 +1257,9 @@ epctl(Ep *ep, Chan *c, void *a, long n) l = name2speed(cb->f[1]); deprint("usb epctl %s %d\n", cb->f[0], l); if(l == Nospeed) - error("speed must be full|low|high"); + error("speed must be full|low|high|super"); + if(l != d->speed && (l == Superspeed || d->speed == Superspeed)) + error("cannot change speed on superspeed device"); qlock(ep->ep0); d->speed = l; qunlock(ep->ep0); @@ -1252,6 +1351,8 @@ epctl(Ep *ep, Chan *c, void *a, long n) break; case CMaddress: deprint("usb epctl %s\n", cb->f[0]); + if(ep->dev->addr == 0) + ep->dev->addr = ep->dev->nb; ep->dev->state = Denabled; break; case CMdetach: diff --git a/sys/src/9/bcm/dma.c b/sys/src/9/bcm/dma.c index e07c2145cd..f0f3672351 100644 --- a/sys/src/9/bcm/dma.c +++ b/sys/src/9/bcm/dma.c @@ -25,7 +25,7 @@ enum { Nchan = 7, /* number of dma channels */ Regsize = 0x100, /* size of regs for each chan */ - Cbalign = 32, /* control block byte alignment */ + Cbalign = 64, /* control block byte alignment (allow for 64-byte cache on bcm2836) */ Dbg = 0, /* registers for each dma controller */ @@ -97,6 +97,20 @@ struct Cb { static Ctlr dma[Nchan]; static u32int *dmaregs = (u32int*)DMAREGS; +uintptr +dmaaddr(void *va) +{ + if(PTR2UINT(va)&0x40000000) + panic("dma address %#p (from%#p)\n", va, getcallerpc(&va)); + return soc.busdram | (PTR2UINT(va) & ~KSEGM); +} + +static uintptr +dmaioaddr(void *va) +{ + return soc.busio | (PTR2UINT(va) & ~VIRTIO); +} + static void dump(char *msg, uchar *p, int n) { @@ -158,21 +172,21 @@ dmastart(int chan, int dev, int dir, void *src, void *dst, int len) case DmaD2M: cachedwbinvse(dst, len); ti = Srcdreq | Destinc; - cb->sourcead = DMAIO(src); - cb->destad = DMAADDR(dst); + cb->sourcead = dmaioaddr(src); + cb->destad = dmaaddr(dst); break; case DmaM2D: cachedwbse(src, len); ti = Destdreq | Srcinc; - cb->sourcead = DMAADDR(src); - cb->destad = DMAIO(dst); + cb->sourcead = dmaaddr(src); + cb->destad = dmaioaddr(dst); break; case DmaM2M: cachedwbse(src, len); - cachedwbinvse(dst, len); + cachedinvse(dst, len); ti = Srcinc | Destinc; - cb->sourcead = DMAADDR(src); - cb->destad = DMAADDR(dst); + cb->sourcead = dmaaddr(src); + cb->destad = dmaaddr(dst); break; } cb->ti = ti | dev<regs[Cs] = 0; microdelay(1); - ctlr->regs[Conblkad] = DMAADDR(cb); + ctlr->regs[Conblkad] = dmaaddr(cb); DBG print("dma start: %ux %ux %ux %ux %ux %ux\n", cb->ti, cb->sourcead, cb->destad, cb->txfrlen, cb->stride, cb->nextconbk); DBG print("intstatus %ux\n", dmaregs[Intstatus]); dmaregs[Intstatus] = 0; ctlr->regs[Cs] = Int; - microdelay(1); coherence(); + microdelay(1); DBG dumpdregs("before Active", ctlr->regs); ctlr->regs[Cs] = Active; DBG dumpdregs("after Active", ctlr->regs); diff --git a/sys/src/9/bcm/emmc.c b/sys/src/9/bcm/emmc.c index 1fddb7cdce..1326e83fc5 100644 --- a/sys/src/9/bcm/emmc.c +++ b/sys/src/9/bcm/emmc.c @@ -4,6 +4,14 @@ * Copyright © 2012 Richard Miller */ +/* + Not officially documented: emmc can be connected to different gpio pins + 48-53 (SD card) + 22-27 (P1 header) + 34-39 (wifi - pi3 only) + using ALT3 function to activate the required routing + */ + #include "u.h" #include "../port/lib.h" #include "../port/error.h" @@ -20,10 +28,17 @@ enum { /* not available from vcore */ Initfreq = 400000, /* initialisation frequency for MMC */ SDfreq = 25*Mhz, /* standard SD frequency */ + SDfreqhs = 50*Mhz, /* high speed frequency */ DTO = 14, /* data timeout exponent (guesswork) */ + GoIdle = 0, /* mmc/sdio go idle state */ MMCSelect = 7, /* mmc/sd card select command */ Setbuswidth = 6, /* mmc/sd set bus width command */ + Switchfunc = 6, /* mmc/sd switch function command */ + Voltageswitch = 11, /* md/sdio switch to 1.8V */ + IORWdirect = 52, /* sdio read/write direct command */ + IORWextended = 53, /* sdio read/write extended command */ + Appcmd = 55, /* mmc/sd application command prefix */ }; enum { @@ -56,6 +71,7 @@ enum { Slotisrver = 0xfc>>2, /* Control0 */ + Hispeed = 1<<2, Dwidth4 = 1<<1, Dwidth1 = 0<<1, @@ -105,7 +121,7 @@ enum { Ccrcerr = 1<<17, Ctoerr = 1<<16, Err = 1<<15, - Cardintr = 1<<8, /* not in Broadcom datasheet */ + Cardintr = 1<<8, Cardinsert = 1<<6, /* not in Broadcom datasheet */ Readrdy = 1<<5, Writerdy = 1<<4, @@ -122,14 +138,16 @@ enum { Cmdinhibit = 1<<0, }; -int cmdinfo[64] = { +static int cmdinfo[64] = { [0] Ixchken, [2] Resp136, [3] Resp48 | Ixchken | Crcchken, +[5] Resp48, [6] Resp48 | Ixchken | Crcchken, [7] Resp48busy | Ixchken | Crcchken, [8] Resp48 | Ixchken | Crcchken, [9] Resp136, +[11] Resp48 | Ixchken | Crcchken, [12] Resp48busy | Ixchken | Crcchken, [13] Resp48 | Ixchken | Crcchken, [16] Resp48, @@ -138,6 +156,8 @@ int cmdinfo[64] = { [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken, [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken, [41] Resp48, +[52] Resp48 | Ixchken | Crcchken, +[53] Resp48 | Ixchken | Crcchken | Isdata, [55] Resp48 | Ixchken | Crcchken, }; @@ -145,9 +165,10 @@ typedef struct Ctlr Ctlr; struct Ctlr { Rendez r; - int datadone; + Rendez cardr; int fastclock; ulong extclk; + int appcmd; }; static Ctlr emmc; @@ -161,6 +182,7 @@ WR(int reg, u32int val) if(0)print("WR %2.2ux %ux\n", reg<<2, val); microdelay(emmc.fastclock? 2 : 20); + coherence(); r[reg] = val; } @@ -175,10 +197,46 @@ clkdiv(uint d) return v; } +static void +emmcclk(uint freq) +{ + u32int *r; + uint div; + int i; + + r = (u32int*)EMMCREGS; + div = emmc.extclk / (freq<<1); + if(emmc.extclk / (div<<1) > freq) + div++; + WR(Control1, clkdiv(div) | + DTO<ticks-now > HZ) break; if((i&(Cmddone|Err)) != Cmddone){ - if((i&~Err) != Ctoerr) - print("emmc: cmd %ux error intr %ux stat %ux\n", c, i, r[Status]); + if((i&~(Err|Cardintr)) != Ctoerr) + print("emmc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); WR(Interrupt, i); if(r[Status]&Cmdinhibit){ WR(Control1, r[Control1]|Srstcmd); @@ -308,11 +394,9 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) break; } if((c & Respmask) == Resp48busy){ - WR(Irpten, Datadone|Err); + WR(Irpten, r[Irpten]|Datadone|Err); tsleep(&emmc.r, datadone, 0, 3000); - i = emmc.datadone; - emmc.datadone = 0; - WR(Irpten, 0); + i = r[Interrupt]; if((i & Datadone) == 0) print("emmcio: no Datadone after CMD%d\n", cmd); if(i & Err) @@ -324,30 +408,46 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) * Once card is selected, use faster clock */ if(cmd == MMCSelect){ - delay(10); - WR(Control1, clkdiv(emmc.extclk/SDfreq - 1) | - DTO<> 8; + return p + 2; +} + +static uchar* +put4(uchar *p, long v) +{ + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; + return p + 4; +} + +static ushort +get2(uchar *p) +{ + return p[0] | p[1]<<8; +} + +static ulong +get4(uchar *p) +{ + return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24; +} + +static void +dump(char *s, void *a, int n) +{ + int i; + uchar *p; + + p = a; + print("%s:", s); + for(i = 0; i < n; i++) + print("%c%2.2x", i&15? ' ' : '\n', *p++); + print("\n"); +} + +/* + * SDIO communication with dongle + */ +static ulong +sdiocmd_locked(int cmd, ulong arg) +{ + u32int resp[4]; + + sdio.cmd(cmd, arg, resp); + return resp[0]; +} + +static ulong +sdiocmd(int cmd, ulong arg) +{ + ulong r; + + qlock(&sdiolock); + if(waserror()){ + if(SDIODEBUG) print("sdiocmd error: cmd %d arg %lux\n", cmd, arg); + qunlock(&sdiolock); + nexterror(); + } + r = sdiocmd_locked(cmd, arg); + qunlock(&sdiolock); + poperror(); + return r; + +} + +static ulong +trysdiocmd(int cmd, ulong arg) +{ + ulong r; + + if(waserror()) + return 0; + r = sdiocmd(cmd, arg); + poperror(); + return r; +} + +static int +sdiord(int fn, int addr) +{ + int r; + + r = sdiocmd(IO_RW_DIRECT, (0<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9)); + if(r & 0xCF00){ + print("ether4330: sdiord(%x, %x) fail: %2.2ux %2.2ux\n", fn, addr, (r>>8)&0xFF, r&0xFF); + error(Eio); + } + return r & 0xFF; +} + +static void +sdiowr(int fn, int addr, int data) +{ + int r; + int retry; + + r = 0; + for(retry = 0; retry < 10; retry++){ + r = sdiocmd(IO_RW_DIRECT, (1<<31)|((fn&7)<<28)|((addr&0x1FFFF)<<9)|(data&0xFF)); + if((r & 0xCF00) == 0) + return; + } + print("ether4330: sdiowr(%x, %x, %x) fail: %2.2ux %2.2ux\n", fn, addr, data, (r>>8)&0xFF, r&0xFF); + error(Eio); +} + +static void +sdiorwext(int fn, int write, void *a, int len, int addr, int incr) +{ + int bsize, blk, bcount, m; + + bsize = fn == Fn2? 512 : 64; + while(len > 0){ + if(len >= 511*bsize){ + blk = 1; + bcount = 511; + m = bcount*bsize; + }else if(len > bsize){ + blk = 1; + bcount = len/bsize; + m = bcount*bsize; + }else{ + blk = 0; + bcount = len; + m = bcount; + } + qlock(&sdiolock); + if(waserror()){ + print("ether4330: sdiorwext fail: %s\n", up->errstr); + qunlock(&sdiolock); + nexterror(); + } + if(blk) + sdio.iosetup(write, a, bsize, bcount); + else + sdio.iosetup(write, a, bcount, 1); + sdiocmd_locked(IO_RW_EXTENDED, + write<<31 | (fn&7)<<28 | blk<<27 | incr<<26 | (addr&0x1FFFF)<<9 | (bcount&0x1FF)); + sdio.io(write, a, m); + qunlock(&sdiolock); + poperror(); + len -= m; + a = (char*)a + m; + if(incr) + addr += m; + } +} + +static void +sdioset(int fn, int addr, int bits) +{ + sdiowr(fn, addr, sdiord(fn, addr) | bits); +} + +static void +sdioinit(void) +{ + ulong ocr, rca; + int i; + + /* disconnect emmc from SD card (connect sdhost instead) */ + for(i = 48; i <= 53; i++) + gpiosel(i, Alt0); + /* connect emmc to wifi */ + for(i = 34; i <= 39; i++){ + gpiosel(i, Alt3); + if(i == 34) + gpiopulloff(i); + else + gpiopullup(i); + } + sdio.init(); + sdio.enable(); + sdiocmd(GO_IDLE_STATE, 0); + ocr = trysdiocmd(IO_SEND_OP_COND, 0); + i = 0; + while((ocr & (1<<31)) == 0){ + if(++i > 5){ + print("ether4330: no response to sdio access: ocr = %lux\n", ocr); + error(Eio); + } + ocr = trysdiocmd(IO_SEND_OP_COND, V3_3); + tsleep(&up->sleep, return0, nil, 100); + } + rca = sdiocmd(SEND_RELATIVE_ADDR, 0) >> Rcashift; + sdiocmd(SELECT_CARD, rca << Rcashift); + sdioset(Fn0, Highspeed, 2); + sdioset(Fn0, Busifc, 2); /* bus width 4 */ + sdiowr(Fn0, Fbr1+Blksize, 64); + sdiowr(Fn0, Fbr1+Blksize+1, 64>>8); + sdiowr(Fn0, Fbr2+Blksize, 512); + sdiowr(Fn0, Fbr2+Blksize+1, 512>>8); + sdioset(Fn0, Ioenable, 1<sleep, return0, nil, 100); + } +} + +static void +sdioreset(void) +{ + sdiowr(Fn0, Ioabort, 1<<3); /* reset */ +} + +static void +sdioabort(int fn) +{ + sdiowr(Fn0, Ioabort, fn); +} + +/* + * Chip register and memory access via SDIO + */ + +static void +cfgw(ulong off, int val) +{ + sdiowr(Fn1, off, val); +} + +static int +cfgr(ulong off) +{ + return sdiord(Fn1, off); +} + +static ulong +cfgreadl(int fn, ulong off) +{ + uchar cbuf[2*CACHELINESZ]; + uchar *p; + + p = (uchar*)ROUND((uintptr)cbuf, CACHELINESZ); + memset(p, 0, 4); + sdiorwext(fn, 0, p, 4, off|Sb32bit, 1); + if(SDIODEBUG) print("cfgreadl %lux: %2.2x %2.2x %2.2x %2.2x\n", off, p[0], p[1], p[2], p[3]); + return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24; +} + +static void +cfgwritel(int fn, ulong off, u32int data) +{ + uchar cbuf[2*CACHELINESZ]; + uchar *p; + int retry; + + p = (uchar*)ROUND((uintptr)cbuf, CACHELINESZ); + put4(p, data); + if(SDIODEBUG) print("cfgwritel %lux: %2.2x %2.2x %2.2x %2.2x\n", off, p[0], p[1], p[2], p[3]); + retry = 0; + while(waserror()){ + print("ether4330: cfgwritel retry %lux %ux\n", off, data); + sdioabort(fn); + if(++retry == 3) + nexterror(); + } + sdiorwext(fn, 1, p, 4, off|Sb32bit, 1); + poperror(); +} + +static void +sbwindow(ulong addr) +{ + addr &= ~(Sbwsize-1); + cfgw(Sbaddr, addr>>8); + cfgw(Sbaddr+1, addr>>16); + cfgw(Sbaddr+2, addr>>24); +} + +static void +sbrw(int fn, int write, uchar *buf, int len, ulong off) +{ + int n; + USED(fn); + + if(waserror()){ + print("ether4330: sbrw err off %lux len %ud\n", off, len); + nexterror(); + } + if(write){ + if(len >= 4){ + n = len; + n &= ~3; + sdiorwext(Fn1, write, buf, n, off|Sb32bit, 1); + off += n; + buf += n; + len -= n; + } + while(len > 0){ + sdiowr(Fn1, off|Sb32bit, *buf); + off++; + buf++; + len--; + } + }else{ + if(len >= 4){ + n = len; + n &= ~3; + sdiorwext(Fn1, write, buf, n, off|Sb32bit, 1); + off += n; + buf += n; + len -= n; + } + while(len > 0){ + *buf = sdiord(Fn1, off|Sb32bit); + off++; + buf++; + len--; + } + } + poperror(); +} + +static void +sbmem(int write, uchar *buf, int len, ulong off) +{ + ulong n; + + n = ROUNDUP(off, Sbwsize) - off; + if(n == 0) + n = Sbwsize; + while(len > 0){ + if(n > len) + n = len; + sbwindow(off); + sbrw(Fn1, write, buf, n, off & (Sbwsize-1)); + off += n; + buf += n; + len -= n; + n = Sbwsize; + } +} + +static void +packetrw(int write, uchar *buf, int len) +{ + int n; + int retry; + + n = 2048; + while(len > 0){ + if(n > len) + n = ROUND(len, 4); + retry = 0; + while(waserror()){ + sdioabort(Fn2); + if(++retry == 3) + nexterror(); + } + sdiorwext(Fn2, write, buf, n, Enumbase, 0); + poperror(); + buf += n; + len -= n; + } +} + +/* + * Configuration and control of chip cores via Silicon Backplane + */ + +static void +sbdisable(ulong regs, int pre, int ioctl) +{ + sbwindow(regs); + if((cfgreadl(Fn1, regs + Resetctrl) & 1) != 0){ + cfgwritel(Fn1, regs + Ioctrl, 3|ioctl); + cfgreadl(Fn1, regs + Ioctrl); + return; + } + cfgwritel(Fn1, regs + Ioctrl, 3|pre); + cfgreadl(Fn1, regs + Ioctrl); + cfgwritel(Fn1, regs + Resetctrl, 1); + microdelay(10); + while((cfgreadl(Fn1, regs + Resetctrl) & 1) == 0) + ; + cfgwritel(Fn1, regs + Ioctrl, 3|ioctl); + cfgreadl(Fn1, regs + Ioctrl); +} + +static void +sbreset(ulong regs, int pre, int ioctl) +{ + sbdisable(regs, pre, ioctl); + sbwindow(regs); + if(SBDEBUG) print("sbreset %#p %#lux %#lux ->", regs, + cfgreadl(Fn1, regs+Ioctrl), cfgreadl(Fn1, regs+Resetctrl)); + while((cfgreadl(Fn1, regs + Resetctrl) & 1) != 0){ + cfgwritel(Fn1, regs + Resetctrl, 0); + microdelay(40); + } + cfgwritel(Fn1, regs + Ioctrl, 1|ioctl); + cfgreadl(Fn1, regs + Ioctrl); + if(SBDEBUG) print("%#lux %#lux\n", + cfgreadl(Fn1, regs+Ioctrl), cfgreadl(Fn1, regs+Resetctrl)); +} + +static void +corescan(Ctlr *ctl, ulong r) +{ + uchar *buf; + int i, coreid, corerev; + ulong addr; + + buf = sdmalloc(Corescansz); + if(buf == nil) + error(Enomem); + sbmem(0, buf, Corescansz, r); + coreid = 0; + corerev = 0; + for(i = 0; i < Corescansz; i += 4){ + switch(buf[i]&0xF){ + case 0xF: /* end */ + sdfree(buf); + return; + case 0x1: /* core info */ + if((buf[i+4]&0xF) != 0x1) + break; + coreid = (buf[i+1] | buf[i+2]<<8) & 0xFFF; + i += 4; + corerev = buf[i+3]; + break; + case 0x05: /* address */ + addr = buf[i+1]<<8 | buf[i+2]<<16 | buf[i+3]<<24; + addr &= ~0xFFF; + if(SBDEBUG) print("core %x %s %#p\n", coreid, buf[i]&0xC0? "ctl" : "mem", addr); + switch(coreid){ + case 0x800: + if((buf[i] & 0xC0) == 0) + ctl->chipcommon = addr; + break; + case ARMcm3: + case ARM7tdmi: + case ARMcr4: + ctl->armcore = coreid; + if(buf[i] & 0xC0){ + if(ctl->armctl == 0) + ctl->armctl = addr; + }else{ + if(ctl->armregs == 0) + ctl->armregs = addr; + } + break; + case 0x80E: + if(buf[i] & 0xC0) + ctl->socramctl = addr; + else if(ctl->socramregs == 0) + ctl->socramregs = addr; + ctl->socramrev = corerev; + break; + case 0x829: + if((buf[i] & 0xC0) == 0) + ctl->sdregs = addr; + ctl->sdiorev = corerev; + break; + case 0x812: + if(buf[i] & 0xC0) + ctl->d11ctl = addr; + break; + } + } + } + sdfree(buf); +} + +static void +ramscan(Ctlr *ctl) +{ + ulong r, n, size; + int banks, i; + + if(ctl->armcore == ARMcr4){ + r = ctl->armregs; + sbwindow(r); + n = cfgreadl(Fn1, r + Cr4Cap); + if(SBDEBUG) print("cr4 banks %lux\n", n); + banks = ((n>>4) & 0xF) + (n & 0xF); + size = 0; + for(i = 0; i < banks; i++){ + cfgwritel(Fn1, r + Cr4Bankidx, i); + n = cfgreadl(Fn1, r + Cr4Bankinfo); + if(SBDEBUG) print("bank %d reg %lux size %lud\n", i, n, 8192 * ((n & 0x3F) + 1)); + size += 8192 * ((n & 0x3F) + 1); + } + ctl->socramsize = size; + ctl->rambase = 0x198000; + return; + } + if(ctl->socramrev <= 7 || ctl->socramrev == 12){ + print("ether4330: SOCRAM rev %d not supported\n", ctl->socramrev); + error(Eio); + } + sbreset(ctl->socramctl, 0, 0); + r = ctl->socramregs; + sbwindow(r); + n = cfgreadl(Fn1, r + Coreinfo); + if(SBDEBUG) print("socramrev %d coreinfo %lux\n", ctl->socramrev, n); + banks = (n>>4) & 0xF; + size = 0; + for(i = 0; i < banks; i++){ + cfgwritel(Fn1, r + Bankidx, i); + n = cfgreadl(Fn1, r + Bankinfo); + if(SBDEBUG) print("bank %d reg %lux size %lud\n", i, n, 8192 * ((n & 0x3F) + 1)); + size += 8192 * ((n & 0x3F) + 1); + } + ctl->socramsize = size; + ctl->rambase = 0; + if(ctl->chipid == 43430){ + cfgwritel(Fn1, r + Bankidx, 3); + cfgwritel(Fn1, r + Bankpda, 0); + } +} + +static void +sbinit(Ctlr *ctl) +{ + ulong r; + int chipid; + char buf[16]; + + sbwindow(Enumbase); + r = cfgreadl(Fn1, Enumbase); + chipid = r & 0xFFFF; + sprint(buf, chipid > 43000 ? "%d" : "%#x", chipid); + print("ether4330: chip %s rev %ld type %ld\n", buf, (r>>16)&0xF, (r>>28)&0xF); + switch(chipid){ + case 0x4330: + case 43362: + case 43430: + case 0x4345: + ctl->chipid = chipid; + ctl->chiprev = (r>>16)&0xF; + break; + default: + print("ether4330: chipid %#x (%d) not supported\n", chipid, chipid); + error(Eio); + } + r = cfgreadl(Fn1, Enumbase + 63*4); + corescan(ctl, r); + if(ctl->armctl == 0 || ctl->d11ctl == 0 || + (ctl->armcore == ARMcm3 && (ctl->socramctl == 0 || ctl->socramregs == 0))) + error("corescan didn't find essential cores\n"); + if(ctl->armcore == ARMcr4) + sbreset(ctl->armctl, Cr4Cpuhalt, Cr4Cpuhalt); + else + sbdisable(ctl->armctl, 0, 0); + sbreset(ctl->d11ctl, 8|4, 4); + ramscan(ctl); + if(SBDEBUG) print("ARM %#p D11 %#p SOCRAM %#p,%#p %lud bytes @ %#p\n", + ctl->armctl, ctl->d11ctl, ctl->socramctl, ctl->socramregs, ctl->socramsize, ctl->rambase); + cfgw(Clkcsr, 0); + microdelay(10); + if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr)); + cfgw(Clkcsr, Nohwreq | ReqALP); + while((cfgr(Clkcsr) & (HTavail|ALPavail)) == 0) + microdelay(10); + cfgw(Clkcsr, Nohwreq | ForceALP); + microdelay(65); + if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr)); + cfgw(Pullups, 0); + sbwindow(ctl->chipcommon); + cfgwritel(Fn1, ctl->chipcommon + Gpiopullup, 0); + cfgwritel(Fn1, ctl->chipcommon + Gpiopulldown, 0); + if(ctl->chipid != 0x4330 && ctl->chipid != 43362) + return; + cfgwritel(Fn1, ctl->chipcommon + Chipctladdr, 1); + if(cfgreadl(Fn1, ctl->chipcommon + Chipctladdr) != 1) + print("ether4330: can't set Chipctladdr\n"); + else{ + r = cfgreadl(Fn1, ctl->chipcommon + Chipctldata); + if(SBDEBUG) print("chipcommon PMU (%lux) %lux", cfgreadl(Fn1, ctl->chipcommon + Chipctladdr), r); + /* set SDIO drive strength >= 6mA */ + r &= ~0x3800; + if(ctl->chipid == 0x4330) + r |= 3<<11; + else + r |= 7<<11; + cfgwritel(Fn1, ctl->chipcommon + Chipctldata, r); + if(SBDEBUG) print("-> %lux (= %lux)\n", r, cfgreadl(Fn1, ctl->chipcommon + Chipctldata)); + } +} + +static void +sbenable(Ctlr *ctl) +{ + int i; + + if(SBDEBUG) print("enabling HT clock..."); + cfgw(Clkcsr, 0); + delay(1); + cfgw(Clkcsr, ReqHT); + for(i = 0; (cfgr(Clkcsr) & HTavail) == 0; i++){ + if(i == 50){ + print("ether4330: can't enable HT clock: csr %x\n", cfgr(Clkcsr)); + error(Eio); + } + tsleep(&up->sleep, return0, nil, 100); + } + cfgw(Clkcsr, cfgr(Clkcsr) | ForceHT); + delay(10); + if(SBDEBUG) print("chipclk: %x\n", cfgr(Clkcsr)); + sbwindow(ctl->sdregs); + cfgwritel(Fn1, ctl->sdregs + Sbmboxdata, 4 << 16); /* protocol version */ + cfgwritel(Fn1, ctl->sdregs + Intmask, FrameInt | MailboxInt | Fcchange); + sdioset(Fn0, Ioenable, 1<sleep, return0, nil, 100); + } + sdiowr(Fn0, Intenable, (1<genbuf, sizeof up->genbuf, "can't find %s in /boot or /sys/lib/firmware", file); + error(up->genbuf); + } + return c; +} + +static int +upload(Ctlr *ctl, char *file, int isconfig) +{ + Chan *c; + uchar *buf; + uchar *cbuf; + int off, n; + + buf = cbuf = nil; + c = findfirmware(file); + if(waserror()){ + cclose(c); + sdfree(buf); + sdfree(cbuf); + nexterror(); + } + buf = sdmalloc(Uploadsz); + if(buf == nil) + error(Enomem); + if(Firmwarecmp){ + cbuf = sdmalloc(Uploadsz); + if(cbuf == nil) + error(Enomem); + } + off = 0; + for(;;){ + n = devtab[c->type]->read(c, buf, Uploadsz, off); + if(n <= 0) + break; + if(isconfig){ + n = condense(buf, n); + off = ctl->socramsize - n - 4; + }else if(off == 0) + memmove(ctl->resetvec.c, buf, sizeof(ctl->resetvec.c)); + while(n&3) + buf[n++] = 0; + sbmem(1, buf, n, ctl->rambase + off); + if(isconfig) + break; + off += n; + } + if(Firmwarecmp){ + if(FWDEBUG) print("compare..."); + if(!isconfig) + off = 0; + for(;;){ + if(!isconfig){ + n = devtab[c->type]->read(c, buf, Uploadsz, off); + if(n <= 0) + break; + while(n&3) + buf[n++] = 0; + } + sbmem(0, cbuf, n, ctl->rambase + off); + if(memcmp(buf, cbuf, n) != 0){ + print("ether4330: firmware load failed offset %d\n", off); + error(Eio); + } + if(isconfig) + break; + off += n; + } + } + if(FWDEBUG) print("\n"); + poperror(); + cclose(c); + sdfree(buf); + sdfree(cbuf); + return n; +} + +/* + * Upload regulatory file (.clm) to firmware. + * Packet format is + * [2]flag [2]type [4]len [4]crc [len]data + */ +static void +reguload(Ctlr *ctl, char *file) +{ + Chan *c; + uchar *buf; + int off, n, flag; + enum { + Reguhdr = 2+2+4+4, + Regusz = 1400, + Regutyp = 2, + Flagclm = 1<<12, + Firstpkt= 1<<1, + Lastpkt = 1<<2, + }; + + buf = nil; + c = findfirmware(file); + if(waserror()){ + cclose(c); + free(buf); + nexterror(); + } + buf = malloc(Reguhdr+Regusz+1); + if(buf == nil) + error(Enomem); + put2(buf+2, Regutyp); + put2(buf+8, 0); + off = 0; + flag = Flagclm | Firstpkt; + while((flag&Lastpkt) == 0){ + n = devtab[c->type]->read(c, buf+Reguhdr, Regusz+1, off); + if(n <= 0) + break; + if(n == Regusz+1) + --n; + else{ + while(n&7) + buf[Reguhdr+n++] = 0; + flag |= Lastpkt; + } + put2(buf+0, flag); + put4(buf+4, n); + wlsetvar(ctl, "clmload", buf, Reguhdr + n); + off += n; + flag &= ~Firstpkt; + } + poperror(); + cclose(c); + free(buf); +} + +static void +fwload(Ctlr *ctl) +{ + uchar buf[4]; + uint i, n; + + i = 0; + while(firmware[i].chipid != ctl->chipid || + firmware[i].chiprev != ctl->chiprev){ + if(++i == nelem(firmware)){ + print("ether4330: no firmware for chipid %x (%d) chiprev %d\n", + ctl->chipid, ctl->chipid, ctl->chiprev); + error("no firmware"); + } + } + ctl->regufile = firmware[i].regufile; + cfgw(Clkcsr, ReqALP); + while((cfgr(Clkcsr) & ALPavail) == 0) + microdelay(10); + memset(buf, 0, 4); + sbmem(1, buf, 4, ctl->rambase + ctl->socramsize - 4); + if(FWDEBUG) print("firmware load..."); + upload(ctl, firmware[i].fwfile, 0); + if(FWDEBUG) print("config load..."); + n = upload(ctl, firmware[i].cfgfile, 1); + n /= 4; + n = (n & 0xFFFF) | (~n << 16); + put4(buf, n); + sbmem(1, buf, 4, ctl->rambase + ctl->socramsize - 4); + if(ctl->armcore == ARMcr4){ + sbwindow(ctl->sdregs); + cfgwritel(Fn1, ctl->sdregs + Intstatus, ~0); + if(ctl->resetvec.i != 0){ + if(SBDEBUG) print("%ux\n", ctl->resetvec.i); + sbmem(1, ctl->resetvec.c, sizeof(ctl->resetvec.c), 0); + } + sbreset(ctl->armctl, Cr4Cpuhalt, 0); + }else + sbreset(ctl->armctl, 0, 0); +} + +/* + * Communication of data and control packets + */ + +void +intwait(Ctlr *ctlr, int wait) +{ + ulong ints, mbox; + int i; + + if(waserror()) + return; + for(;;){ + sdiocardintr(wait); + sbwindow(ctlr->sdregs); + i = sdiord(Fn0, Intpend); + if(i == 0){ + tsleep(&up->sleep, return0, 0, 10); + continue; + } + ints = cfgreadl(Fn1, ctlr->sdregs + Intstatus); + cfgwritel(Fn1, ctlr->sdregs + Intstatus, ints); + if(0) print("INTS: (%x) %lux -> %lux\n", i, ints, cfgreadl(Fn1, ctlr->sdregs + Intstatus)); + if(ints & MailboxInt){ + mbox = cfgreadl(Fn1, ctlr->sdregs + Hostmboxdata); + cfgwritel(Fn1, ctlr->sdregs + Sbmbox, 2); /* ack */ + if(mbox & 0x8) + print("ether4330: firmware ready\n"); + } + if(ints & FrameInt) + break; + } + poperror(); +} + +static Block* +wlreadpkt(Ctlr *ctl) +{ + Block *b; + Sdpcm *p; + int len, lenck; + + b = allocb(2048); + p = (Sdpcm*)b->wp; + qlock(&ctl->pktlock); + for(;;){ + packetrw(0, b->wp, sizeof(*p)); + len = p->len[0] | p->len[1]<<8; + if(len == 0){ + freeb(b); + b = nil; + break; + } + lenck = p->lenck[0] | p->lenck[1]<<8; + if(lenck != (len ^ 0xFFFF) || + len < sizeof(*p) || len > 2048){ + print("ether4330: wlreadpkt error len %.4x lenck %.4x\n", len, lenck); + cfgw(Framectl, Rfhalt); + while(cfgr(Rfrmcnt+1)) + ; + while(cfgr(Rfrmcnt)) + ; + continue; + } + if(len > sizeof(*p)) + packetrw(0, b->wp + sizeof(*p), len - sizeof(*p)); + b->wp += len; + break; + } + qunlock(&ctl->pktlock); + return b; +} + +static void +txstart(Ether *edev) +{ + Ctlr *ctl; + Sdpcm *p; + Block *b; + int len, off; + + ctl = edev->ctlr; + if(!canqlock(&ctl->tlock)) + return; + if(waserror()){ + qunlock(&ctl->tlock); + return; + } + for(;;){ + lock(&ctl->txwinlock); + if(ctl->txseq == ctl->txwindow){ + //print("f"); + unlock(&ctl->txwinlock); + break; + } + if(ctl->fcmask & 1<<2){ + //print("x"); + unlock(&ctl->txwinlock); + break; + } + unlock(&ctl->txwinlock); + b = qget(edev->oq); + if(b == nil) + break; + off = ((uintptr)b->rp & 3) + sizeof(Sdpcm); + b = padblock(b, off + 4); + len = BLEN(b); + p = (Sdpcm*)b->rp; + memset(p, 0, off); /* TODO: refactor dup code */ + put2(p->len, len); + put2(p->lenck, ~len); + p->chanflg = 2; + p->seq = ctl->txseq; + p->doffset = off; + put4(b->rp + off, 0x20); /* BDC header */ + if(iodebug) dump("send", b->rp, len); + qlock(&ctl->pktlock); + if(waserror()){ + if(iodebug) print("halt frame %x %x\n", cfgr(Wfrmcnt+1), cfgr(Wfrmcnt+1)); + cfgw(Framectl, Wfhalt); + while(cfgr(Wfrmcnt+1)) + ; + while(cfgr(Wfrmcnt)) + ; + qunlock(&ctl->pktlock); + nexterror(); + } + packetrw(1, b->rp, len); + ctl->txseq++; + poperror(); + qunlock(&ctl->pktlock); + freeb(b); + } + poperror(); + qunlock(&ctl->tlock); +} + +static void +rproc(void *a) +{ + Ether *edev; + Ctlr *ctl; + Block *b; + Sdpcm *p; + Cmd *q; + int flowstart; + int bdc; + + edev = a; + ctl = edev->ctlr; + flowstart = 0; + for(;;){ + if(flowstart){ + //print("F"); + flowstart = 0; + txstart(edev); + } + b = wlreadpkt(ctl); + if(b == nil){ + intwait(ctl, 1); + continue; + } + p = (Sdpcm*)b->rp; + if(p->window != ctl->txwindow || p->fcmask != ctl->fcmask){ + lock(&ctl->txwinlock); + if(p->window != ctl->txwindow){ + if(ctl->txseq == ctl->txwindow) + flowstart = 1; + ctl->txwindow = p->window; + } + if(p->fcmask != ctl->fcmask){ + if((p->fcmask & 1<<2) == 0) + flowstart = 1; + ctl->fcmask = p->fcmask; + } + unlock(&ctl->txwinlock); + } + switch(p->chanflg & 0xF){ + case 0: + if(iodebug) dump("rsp", b->rp, BLEN(b)); + if(BLEN(b) < sizeof(Sdpcm) + sizeof(Cmd)) + break; + q = (Cmd*)(b->rp + sizeof(*p)); + if((q->id[0] | q->id[1]<<8) != ctl->reqid) + break; + ctl->rsp = b; + wakeup(&ctl->cmdr); + continue; + case 1: + if(iodebug) dump("event", b->rp, BLEN(b)); + if(BLEN(b) > p->doffset + 4){ + bdc = 4 + (b->rp[p->doffset + 3] << 2); + if(BLEN(b) > p->doffset + bdc){ + b->rp += p->doffset + bdc; /* skip BDC header */ + bcmevent(ctl, b->rp, BLEN(b)); + break; + } + } + if(iodebug && BLEN(b) != p->doffset) + print("short event %ld %d\n", BLEN(b), p->doffset); + break; + case 2: + if(iodebug) dump("packet", b->rp, BLEN(b)); + if(BLEN(b) > p->doffset + 4){ + bdc = 4 + (b->rp[p->doffset + 3] << 2); + if(BLEN(b) >= p->doffset + bdc + ETHERHDRSIZE){ + b->rp += p->doffset + bdc; /* skip BDC header */ + etheriq(edev, b, 1); + continue; + } + } + break; + default: + dump("ether4330: bad packet", b->rp, BLEN(b)); + break; + } + freeb(b); + } +} + +static void +linkdown(Ctlr *ctl) +{ + Ether *edev; + Netfile *f; + int i; + + edev = ctl->edev; + if(edev == nil || ctl->status != Connected) + return; + ctl->status = Disconnected; + /* send eof to aux/wpa */ + for(i = 0; i < edev->nfile; i++){ + f = edev->f[i]; + if(f == nil || f->in == nil || f->inuse == 0 || f->type != 0x888e) + continue; + qwrite(f->in, 0, 0); + } +} + +/* + * Command interface between host and firmware + */ + +static char *eventnames[] = { + [0] = "set ssid", + [1] = "join", + [2] = "start", + [3] = "auth", + [4] = "auth ind", + [5] = "deauth", + [6] = "deauth ind", + [7] = "assoc", + [8] = "assoc ind", + [9] = "reassoc", + [10] = "reassoc ind", + [11] = "disassoc", + [12] = "disassoc ind", + [13] = "quiet start", + [14] = "quiet end", + [15] = "beacon rx", + [16] = "link", + [17] = "mic error", + [18] = "ndis link", + [19] = "roam", + [20] = "txfail", + [21] = "pmkid cache", + [22] = "retrograde tsf", + [23] = "prune", + [24] = "autoauth", + [25] = "eapol msg", + [26] = "scan complete", + [27] = "addts ind", + [28] = "delts ind", + [29] = "bcnsent ind", + [30] = "bcnrx msg", + [31] = "bcnlost msg", + [32] = "roam prep", + [33] = "pfn net found", + [34] = "pfn net lost", + [35] = "reset complete", + [36] = "join start", + [37] = "roam start", + [38] = "assoc start", + [39] = "ibss assoc", + [40] = "radio", + [41] = "psm watchdog", + [44] = "probreq msg", + [45] = "scan confirm ind", + [46] = "psk sup", + [47] = "country code changed", + [48] = "exceeded medium time", + [49] = "icv error", + [50] = "unicast decode error", + [51] = "multicast decode error", + [52] = "trace", + [53] = "bta hci event", + [54] = "if", + [55] = "p2p disc listen complete", + [56] = "rssi", + [57] = "pfn scan complete", + [58] = "extlog msg", + [59] = "action frame", + [60] = "action frame complete", + [61] = "pre assoc ind", + [62] = "pre reassoc ind", + [63] = "channel adopted", + [64] = "ap started", + [65] = "dfs ap stop", + [66] = "dfs ap resume", + [67] = "wai sta event", + [68] = "wai msg", + [69] = "escan result", + [70] = "action frame off chan complete", + [71] = "probresp msg", + [72] = "p2p probreq msg", + [73] = "dcs request", + [74] = "fifo credit map", + [75] = "action frame rx", + [76] = "wake event", + [77] = "rm complete", + [78] = "htsfsync", + [79] = "overlay req", + [80] = "csa complete ind", + [81] = "excess pm wake event", + [82] = "pfn scan none", + [83] = "pfn scan allgone", + [84] = "gtk plumbed", + [85] = "assoc ind ndis", + [86] = "reassoc ind ndis", + [87] = "assoc req ie", + [88] = "assoc resp ie", + [89] = "assoc recreated", + [90] = "action frame rx ndis", + [91] = "auth req", + [92] = "tdls peer event", + [127] = "bcmc credit support" +}; + +static char* +evstring(uint event) +{ + static char buf[12]; + + if(event >= nelem(eventnames) || eventnames[event] == 0){ + /* not reentrant but only called from one kproc */ + snprint(buf, sizeof buf, "%d", event); + return buf; + } + return eventnames[event]; +} + +static void +bcmevent(Ctlr *ctl, uchar *p, int len) +{ + int flags; + long event, status, reason; + + if(len < ETHERHDRSIZE + 10 + 46) + return; + p += ETHERHDRSIZE + 10; /* skip bcm_ether header */ + len -= ETHERHDRSIZE + 10; + flags = nhgets(p + 2); + event = nhgets(p + 6); + status = nhgetl(p + 8); + reason = nhgetl(p + 12); + if(EVENTDEBUG) + print("ether4330: [%s] status %ld flags %#x reason %ld\n", + evstring(event), status, flags, reason); + switch(event){ + case 19: /* E_ROAM */ + if(status == 0) + break; + /* fall through */ + case 0: /* E_SET_SSID */ + ctl->joinstatus = 1 + status; + wakeup(&ctl->joinr); + break; + case 16: /* E_LINK */ + if(flags&1) /* link up */ + break; + /* fall through */ + case 5: /* E_DEAUTH */ + case 6: /* E_DEAUTH_IND */ + case 12: /* E_DISASSOC_IND */ + linkdown(ctl); + break; + case 26: /* E_SCAN_COMPLETE */ + break; + case 69: /* E_ESCAN_RESULT */ + wlscanresult(ctl->edev, p + 48, len - 48); + break; + default: + if(status){ + if(!EVENTDEBUG) + print("ether4330: [%s] error status %ld flags %#x reason %ld\n", + evstring(event), status, flags, reason); + dump("event", p, len); + } + } +} + +static int +joindone(void *a) +{ + return ((Ctlr*)a)->joinstatus; +} + +static int +waitjoin(Ctlr *ctl) +{ + int n; + + sleep(&ctl->joinr, joindone, ctl); + n = ctl->joinstatus; + ctl->joinstatus = 0; + return n - 1; +} + +static int +cmddone(void *a) +{ + return ((Ctlr*)a)->rsp != nil; +} + +static void +wlcmd(Ctlr *ctl, int write, int op, void *data, int dlen, void *res, int rlen) +{ + Block *b; + Sdpcm *p; + Cmd *q; + int len, tlen; + + if(write) + tlen = dlen + rlen; + else + tlen = MAX(dlen, rlen); + len = sizeof(Sdpcm) + sizeof(Cmd) + tlen; + b = allocb(len); + qlock(&ctl->cmdlock); + if(waserror()){ + freeb(b); + qunlock(&ctl->cmdlock); + nexterror(); + } + memset(b->wp, 0, len); + qlock(&ctl->pktlock); + p = (Sdpcm*)b->wp; + put2(p->len, len); + put2(p->lenck, ~len); + p->seq = ctl->txseq; + p->doffset = sizeof(Sdpcm); + b->wp += sizeof(*p); + + q = (Cmd*)b->wp; + put4(q->cmd, op); + put4(q->len, tlen); + put2(q->flags, write? 2 : 0); + put2(q->id, ++ctl->reqid); + put4(q->status, 0); + b->wp += sizeof(*q); + + if(dlen > 0) + memmove(b->wp, data, dlen); + if(write) + memmove(b->wp + dlen, res, rlen); + b->wp += tlen; + + if(iodebug) dump("cmd", b->rp, len); + packetrw(1, b->rp, len); + ctl->txseq++; + qunlock(&ctl->pktlock); + freeb(b); + b = nil; + USED(b); + sleep(&ctl->cmdr, cmddone, ctl); + b = ctl->rsp; + ctl->rsp = nil; + assert(b != nil); + p = (Sdpcm*)b->rp; + q = (Cmd*)(b->rp + p->doffset); + if(q->status[0] | q->status[1] | q->status[2] | q->status[3]){ + print("ether4330: cmd %d error status %ld\n", op, get4(q->status)); + dump("ether4330: cmd error", b->rp, BLEN(b)); + error("wlcmd error"); + } + if(!write) + memmove(res, q + 1, rlen); + freeb(b); + qunlock(&ctl->cmdlock); + poperror(); +} + +static void +wlcmdint(Ctlr *ctl, int op, int val) +{ + uchar buf[4]; + + put4(buf, val); + wlcmd(ctl, 1, op, buf, 4, nil, 0); +} + +static void +wlgetvar(Ctlr *ctl, char *name, void *val, int len) +{ + wlcmd(ctl, 0, GetVar, name, strlen(name) + 1, val, len); +} + +static void +wlsetvar(Ctlr *ctl, char *name, void *val, int len) +{ + if(VARDEBUG){ + char buf[32]; + snprint(buf, sizeof buf, "wlsetvar %s:", name); + dump(buf, val, len); + } + wlcmd(ctl, 1, SetVar, name, strlen(name) + 1, val, len); +} + +static void +wlsetint(Ctlr *ctl, char *name, int val) +{ + uchar buf[4]; + + put4(buf, val); + wlsetvar(ctl, name, buf, 4); +} + +static void +wlwepkey(Ctlr *ctl, int i) +{ + uchar params[164]; + uchar *p; + + memset(params, 0, sizeof params); + p = params; + p = put4(p, i); /* index */ + p = put4(p, ctl->keys[i].len); + memmove(p, ctl->keys[i].dat, ctl->keys[i].len); + p += 32 + 18*4; /* keydata, pad */ + if(ctl->keys[i].len == WMinKeyLen) + p = put4(p, 1); /* algo = WEP1 */ + else + p = put4(p, 3); /* algo = WEP128 */ + put4(p, 2); /* flags = Primarykey */ + + wlsetvar(ctl, "wsec_key", params, sizeof params); +} + +static void +memreverse(char *dst, char *src, int len) +{ + src += len; + while(len-- > 0) + *dst++ = *--src; +} + +static void +wlwpakey(Ctlr *ctl, int id, uvlong iv, uchar *ea) +{ + uchar params[164]; + uchar *p; + int pairwise; + + if(id == CMrxkey) + return; + pairwise = (id == CMrxkey || id == CMtxkey); + memset(params, 0, sizeof params); + p = params; + if(pairwise) + p = put4(p, 0); + else + p = put4(p, id - CMrxkey0); /* group key id */ + p = put4(p, ctl->keys[0].len); + memmove((char*)p, ctl->keys[0].dat, ctl->keys[0].len); + p += 32 + 18*4; /* keydata, pad */ + if(ctl->cryptotype == Wpa) + p = put4(p, 2); /* algo = TKIP */ + else + p = put4(p, 4); /* algo = AES_CCM */ + if(pairwise) + p = put4(p, 0); + else + p = put4(p, 2); /* flags = Primarykey */ + p += 3*4; + p = put4(p, 0); //pairwise); /* iv initialised */ + p += 4; + p = put4(p, iv>>16); /* iv high */ + p = put2(p, iv&0xFFFF); /* iv low */ + p += 2 + 2*4; /* align, pad */ + if(pairwise) + memmove(p, ea, Eaddrlen); + + wlsetvar(ctl, "wsec_key", params, sizeof params); +} + +static void +wljoin(Ctlr *ctl, char *ssid, int chan) +{ + uchar params[72]; + uchar *p; + int n; + + if(chan != 0) + chan |= 0x2b00; /* 20Mhz channel width */ + p = params; + n = strlen(ssid); + n = MIN(n, 32); + p = put4(p, n); + memmove(p, ssid, n); + memset(p + n, 0, 32 - n); + p += 32; + p = put4(p, 0xff); /* scan type */ + if(chan != 0){ + p = put4(p, 2); /* num probes */ + p = put4(p, 120); /* active time */ + p = put4(p, 390); /* passive time */ + }else{ + p = put4(p, -1); /* num probes */ + p = put4(p, -1); /* active time */ + p = put4(p, -1); /* passive time */ + } + p = put4(p, -1); /* home time */ + memset(p, 0xFF, Eaddrlen); /* bssid */ + p += Eaddrlen; + p = put2(p, 0); /* pad */ + if(chan != 0){ + p = put4(p, 1); /* num chans */ + p = put2(p, chan); /* chan spec */ + p = put2(p, 0); /* pad */ + assert(p == params + sizeof(params)); + }else{ + p = put4(p, 0); /* num chans */ + assert(p == params + sizeof(params) - 4); + } + + wlsetvar(ctl, "join", params, chan? sizeof params : sizeof params - 4); + ctl->status = Connecting; + switch(waitjoin(ctl)){ + case 0: + ctl->status = Connected; + break; + case 3: + ctl->status = Disconnected; + error("wifi join: network not found"); + case 1: + ctl->status = Disconnected; + error("wifi join: failed"); + default: + ctl->status = Disconnected; + error("wifi join: error"); + } +} + +static void +wlscanstart(Ctlr *ctl) +{ + /* version[4] action[2] sync_id[2] ssidlen[4] ssid[32] bssid[6] bss_type[1] + scan_type[1] nprobes[4] active_time[4] passive_time[4] home_time[4] + nchans[2] nssids[2] chans[nchans][2] ssids[nssids][32] */ + /* hack - this is only correct on a little-endian cpu */ + static uchar params[4+2+2+4+32+6+1+1+4*4+2+2+14*2+32+4] = { + 1,0,0,0, + 1,0, + 0x34,0x12, + 0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0xff,0xff,0xff,0xff,0xff,0xff, + 2, + 0, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 14,0, + 1,0, + 0x01,0x2b,0x02,0x2b,0x03,0x2b,0x04,0x2b,0x05,0x2e,0x06,0x2e,0x07,0x2e, + 0x08,0x2b,0x09,0x2b,0x0a,0x2b,0x0b,0x2b,0x0c,0x2b,0x0d,0x2b,0x0e,0x2b, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + }; + + wlcmdint(ctl, 49, 0); /* PASSIVE_SCAN */ + wlsetvar(ctl, "escan", params, sizeof params); +} + +static uchar* +gettlv(uchar *p, uchar *ep, int tag) +{ + int len; + + while(p + 1 < ep){ + len = p[1]; + if(p + 2 + len > ep) + return nil; + if(p[0] == tag) + return p; + p += 2 + len; + } + return nil; +} + +static void +addscan(Block *bp, uchar *p, int len) +{ + char bssid[24]; + char *auth, *auth2; + uchar *t, *et; + int ielen; + static uchar wpaie1[4] = { 0x00, 0x50, 0xf2, 0x01 }; + + snprint(bssid, sizeof bssid, ";bssid=%E", p + 8); + if(strstr((char*)bp->rp, bssid) != nil) + return; + bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim, + "ssid=%.*s%s;signal=%d;noise=%d;chan=%d", + p[18], (char*)p+19, bssid, + (short)get2(p+78), (signed char)p[80], + get2(p+72) & 0xF); + auth = auth2 = ""; + if(get2(p + 16) & 0x10) + auth = ";wep"; + ielen = get4(p + 0x78); + if(ielen > 0){ + t = p + get4(p + 0x74); + et = t + ielen; + if(et > p + len) + return; + if(gettlv(t, et, 0x30) != nil){ + auth = ""; + auth2 = ";wpa2"; + } + while((t = gettlv(t, et, 0xdd)) != nil){ + if(t[1] > 4 && memcmp(t+2, wpaie1, 4) == 0){ + auth = ";wpa"; + break; + } + t += 2 + t[1]; + } + } + bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim, + "%s%s\n", auth, auth2); +} + + +static void +wlscanresult(Ether *edev, uchar *p, int len) +{ + Ctlr *ctlr; + Netfile **ep, *f, **fp; + Block *bp; + int nbss, i; + + ctlr = edev->ctlr; + if(get4(p) > len) + return; + /* TODO: more syntax checking */ + bp = ctlr->scanb; + if(bp == nil) + ctlr->scanb = bp = allocb(8192); + nbss = get2(p+10); + p += 12; + len -= 12; + if(0) dump("SCAN", p, len); + if(nbss){ + addscan(bp, p, len); + return; + } + i = edev->scan; + ep = &edev->f[Ntypes]; + for(fp = edev->f; fp < ep && i > 0; fp++){ + f = *fp; + if(f == nil || f->scan == 0) + continue; + if(i == 1) + qpass(f->in, bp); + else + qpass(f->in, copyblock(bp, BLEN(bp))); + i--; + } + if(i) + freeb(bp); + ctlr->scanb = nil; +} + +static void +lproc(void *a) +{ + Ether *edev; + Ctlr *ctlr; + int secs; + + edev = a; + ctlr = edev->ctlr; + secs = 0; + for(;;){ + tsleep(&up->sleep, return0, 0, 1000); + if(ctlr->scansecs){ + if(secs == 0){ + if(waserror()) + ctlr->scansecs = 0; + else{ + wlscanstart(ctlr); + poperror(); + } + secs = ctlr->scansecs; + } + --secs; + }else + secs = 0; + } +} + +static void +wlinit(Ether *edev, Ctlr *ctlr) +{ + uchar ea[Eaddrlen]; + uchar eventmask[16]; + char version[128]; + char *p; + static uchar keepalive[12] = {1, 0, 11, 0, 0xd8, 0xd6, 0, 0, 0, 0, 0, 0}; + + wlgetvar(ctlr, "cur_etheraddr", ea, Eaddrlen); + memmove(edev->ea, ea, Eaddrlen); + memmove(edev->addr, ea, Eaddrlen); + print("ether4330: addr %E\n", edev->ea); + wlsetint(ctlr, "assoc_listen", 10); + if(ctlr->chipid == 43430 || ctlr->chipid == 0x4345) + wlcmdint(ctlr, 0x56, 0); /* powersave off */ + else + wlcmdint(ctlr, 0x56, 2); /* powersave FAST */ + wlsetint(ctlr, "bus:txglom", 0); + wlsetint(ctlr, "bcn_timeout", 10); + wlsetint(ctlr, "assoc_retry_max", 3); + if(ctlr->chipid == 0x4330){ + wlsetint(ctlr, "btc_wire", 4); + wlsetint(ctlr, "btc_mode", 1); + wlsetvar(ctlr, "mkeep_alive", keepalive, 11); + } + memset(eventmask, 0xFF, sizeof eventmask); +#define ENABLE(n) eventmask[n/8] |= 1<<(n%8) +#define DISABLE(n) eventmask[n/8] &= ~(1<<(n%8)) + DISABLE(40); /* E_RADIO */ + DISABLE(44); /* E_PROBREQ_MSG */ + DISABLE(54); /* E_IF */ + DISABLE(71); /* E_PROBRESP_MSG */ + DISABLE(20); /* E_TXFAIL */ + DISABLE(124); /* ? */ + wlsetvar(ctlr, "event_msgs", eventmask, sizeof eventmask); + wlcmdint(ctlr, 0xb9, 0x28); /* SET_SCAN_CHANNEL_TIME */ + wlcmdint(ctlr, 0xbb, 0x28); /* SET_SCAN_UNASSOC_TIME */ + wlcmdint(ctlr, 0x102, 0x82); /* SET_SCAN_PASSIVE_TIME */ + wlcmdint(ctlr, 2, 0); /* UP */ + memset(version, 0, sizeof version); + wlgetvar(ctlr, "ver", version, sizeof version - 1); + if((p = strchr(version, '\n')) != nil) + *p = '\0'; + if(0) print("ether4330: %s\n", version); + wlsetint(ctlr, "roam_off", 1); + wlcmdint(ctlr, 0x14, 1); /* SET_INFRA 1 */ + wlcmdint(ctlr, 10, 0); /* SET_PROMISC */ + //wlcmdint(ctlr, 0x8e, 0); /* SET_BAND 0 */ + //wlsetint(ctlr, "wsec", 1); + wlcmdint(ctlr, 2, 1); /* UP */ + ctlr->keys[0].len = WMinKeyLen; + //wlwepkey(ctlr, 0); +} + +/* + * Plan 9 driver interface + */ + +static long +etherbcmifstat(Ether* edev, void* a, long n, ulong offset) +{ + Ctlr *ctlr; + char *p; + int l; + static char *cryptoname[4] = { + [0] "off", + [Wep] "wep", + [Wpa] "wpa", + [Wpa2] "wpa2", + }; + /* these strings are known by aux/wpa */ + static char* connectstate[] = { + [Disconnected] = "unassociated", + [Connecting] = "connecting", + [Connected] = "associated", + }; + + ctlr = edev->ctlr; + if(ctlr == nil) + return 0; + p = malloc(READSTR); + l = 0; + + l += snprint(p+l, READSTR-l, "channel: %d\n", ctlr->chanid); + l += snprint(p+l, READSTR-l, "essid: %s\n", ctlr->essid); + l += snprint(p+l, READSTR-l, "crypt: %s\n", cryptoname[ctlr->cryptotype]); + l += snprint(p+l, READSTR-l, "oq: %d\n", qlen(edev->oq)); + l += snprint(p+l, READSTR-l, "txwin: %d\n", ctlr->txwindow); + l += snprint(p+l, READSTR-l, "txseq: %d\n", ctlr->txseq); + l += snprint(p+l, READSTR-l, "status: %s\n", connectstate[ctlr->status]); + USED(l); + n = readstr(offset, a, n, p); + free(p); + return n; +} + +static void +etherbcmtransmit(Ether *edev) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr == nil) + return; + txstart(edev); +} + +static int +parsehex(char *buf, int buflen, char *a) +{ + int i, k, n; + + k = 0; + for(i = 0;k < buflen && *a; i++){ + if(*a >= '0' && *a <= '9') + n = *a++ - '0'; + else if(*a >= 'a' && *a <= 'f') + n = *a++ - 'a' + 10; + else if(*a >= 'A' && *a <= 'F') + n = *a++ - 'A' + 10; + else + break; + + if(i & 1){ + buf[k] |= n; + k++; + } + else + buf[k] = n<<4; + } + if(i & 1) + return -1; + return k; +} + +static int +wepparsekey(WKey* key, char* a) +{ + int i, k, len, n; + char buf[WMaxKeyLen]; + + len = strlen(a); + if(len == WMinKeyLen || len == WMaxKeyLen){ + memset(key->dat, 0, sizeof(key->dat)); + memmove(key->dat, a, len); + key->len = len; + + return 0; + } + else if(len == WMinKeyLen*2 || len == WMaxKeyLen*2){ + k = 0; + for(i = 0; i < len; i++){ + if(*a >= '0' && *a <= '9') + n = *a++ - '0'; + else if(*a >= 'a' && *a <= 'f') + n = *a++ - 'a' + 10; + else if(*a >= 'A' && *a <= 'F') + n = *a++ - 'A' + 10; + else + return -1; + + if(i & 1){ + buf[k] |= n; + k++; + } + else + buf[k] = n<<4; + } + + memset(key->dat, 0, sizeof(key->dat)); + memmove(key->dat, buf, k); + key->len = k; + + return 0; + } + + return -1; +} + +static int +wpaparsekey(WKey *key, uvlong *ivp, char *a) +{ + int len; + char *e; + + if(cistrncmp(a, "tkip:", 5) == 0 || cistrncmp(a, "ccmp:", 5) == 0) + a += 5; + else + return 1; + len = parsehex(key->dat, sizeof(key->dat), a); + if(len <= 0) + return 1; + key->len = len; + a += 2*len; + if(*a++ != '@') + return 1; + *ivp = strtoull(a, &e, 16); + if(e == a) + return -1; + return 0; +} + +static void +setauth(Ctlr *ctlr, Cmdbuf *cb, char *a) +{ + uchar wpaie[32]; + int i; + + i = parsehex((char*)wpaie, sizeof wpaie, a); + if(i < 2 || i != wpaie[1] + 2) + cmderror(cb, "bad wpa ie syntax"); + if(wpaie[0] == 0xdd) + ctlr->cryptotype = Wpa; + else if(wpaie[0] == 0x30) + ctlr->cryptotype = Wpa2; + else + cmderror(cb, "bad wpa ie"); + wlsetvar(ctlr, "wpaie", wpaie, i); + if(ctlr->cryptotype == Wpa){ + wlsetint(ctlr, "wpa_auth", 4|2); /* auth_psk | auth_unspecified */ + wlsetint(ctlr, "auth", 0); + wlsetint(ctlr, "wsec", 2); /* tkip */ + wlsetint(ctlr, "wpa_auth", 4); /* auth_psk */ + }else{ + wlsetint(ctlr, "wpa_auth", 0x80|0x40); /* auth_psk | auth_unspecified */ + wlsetint(ctlr, "auth", 0); + wlsetint(ctlr, "wsec", 4); /* aes */ + wlsetint(ctlr, "wpa_auth", 0x80); /* auth_psk */ + } +} + +static int +setcrypt(Ctlr *ctlr, Cmdbuf*, char *a) +{ + if(cistrcmp(a, "wep") == 0 || cistrcmp(a, "on") == 0) + ctlr->cryptotype = Wep; + else if(cistrcmp(a, "off") == 0 || cistrcmp(a, "none") == 0) + ctlr->cryptotype = 0; + else + return 0; + wlsetint(ctlr, "auth", ctlr->cryptotype); + return 1; +} + +static long +etherbcmctl(Ether* edev, void* buf, long n) +{ + Ctlr *ctlr; + Cmdbuf *cb; + Cmdtab *ct; + uchar ea[Eaddrlen]; + uvlong iv; + int i; + + if((ctlr = edev->ctlr) == nil) + error(Enonexist); + USED(ctlr); + + cb = parsecmd(buf, n); + if(waserror()){ + free(cb); + nexterror(); + } + ct = lookupcmd(cb, cmds, nelem(cmds)); + switch(ct->index){ + case CMauth: + setauth(ctlr, cb, cb->f[1]); + if(ctlr->essid[0]) + wljoin(ctlr, ctlr->essid, ctlr->chanid); + break; + case CMchannel: + if((i = atoi(cb->f[1])) < 0 || i > 16) + cmderror(cb, "bad channel number"); + //wlcmdint(ctlr, 30, i); /* SET_CHANNEL */ + ctlr->chanid = i; + break; + case CMcrypt: + if(setcrypt(ctlr, cb, cb->f[1])){ + if(ctlr->essid[0]) + wljoin(ctlr, ctlr->essid, ctlr->chanid); + }else + cmderror(cb, "bad crypt type"); + break; + case CMessid: + if(cistrcmp(cb->f[1], "default") == 0) + memset(ctlr->essid, 0, sizeof(ctlr->essid)); + else{ + strncpy(ctlr->essid, cb->f[1], sizeof(ctlr->essid) - 1); + ctlr->essid[sizeof(ctlr->essid) - 1] = '\0'; + } + if(!waserror()){ + wljoin(ctlr, ctlr->essid, ctlr->chanid); + poperror(); + } + break; + case CMjoin: /* join essid channel wep|on|off|wpakey */ + if(strcmp(cb->f[1], "") != 0){ /* empty string for no change */ + if(cistrcmp(cb->f[1], "default") != 0){ + strncpy(ctlr->essid, cb->f[1], sizeof(ctlr->essid)-1); + ctlr->essid[sizeof(ctlr->essid)-1] = 0; + }else + memset(ctlr->essid, 0, sizeof(ctlr->essid)); + }else if(ctlr->essid[0] == 0) + cmderror(cb, "essid not set"); + if((i = atoi(cb->f[2])) >= 0 && i <= 16) + ctlr->chanid = i; + else + cmderror(cb, "bad channel number"); + if(!setcrypt(ctlr, cb, cb->f[3])) + setauth(ctlr, cb, cb->f[3]); + if(ctlr->essid[0]) + wljoin(ctlr, ctlr->essid, ctlr->chanid); + break; + case CMkey1: + case CMkey2: + case CMkey3: + case CMkey4: + i = ct->index - CMkey1; + if(wepparsekey(&ctlr->keys[i], cb->f[1])) + cmderror(cb, "bad WEP key syntax"); + wlsetint(ctlr, "wsec", 1); /* wep enabled */ + wlwepkey(ctlr, i); + break; + case CMrxkey: + case CMrxkey0: + case CMrxkey1: + case CMrxkey2: + case CMrxkey3: + case CMtxkey: + if(parseether(ea, cb->f[1]) < 0) + cmderror(cb, "bad ether addr"); + if(wpaparsekey(&ctlr->keys[0], &iv, cb->f[2])) + cmderror(cb, "bad wpa key"); + wlwpakey(ctlr, ct->index, iv, ea); + break; + case CMdebug: + iodebug = atoi(cb->f[1]); + break; + } + poperror(); + free(cb); + return n; +} + +static void +etherbcmscan(void *a, uint secs) +{ + Ether* edev; + Ctlr* ctlr; + + edev = a; + ctlr = edev->ctlr; + ctlr->scansecs = secs; +} + +static void +etherbcmattach(Ether* edev) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + qlock(&ctlr->alock); + if(waserror()){ + //print("ether4330: attach failed: %s\n", up->errstr); + qunlock(&ctlr->alock); + nexterror(); + } + if(ctlr->edev == nil){ + if(ctlr->chipid == 0){ + sdioinit(); + sbinit(ctlr); + } + fwload(ctlr); + sbenable(ctlr); + kproc("wifireader", rproc, edev); + kproc("wifitimer", lproc, edev); + if(ctlr->regufile) + reguload(ctlr, ctlr->regufile); + wlinit(edev, ctlr); + ctlr->edev = edev; + } + qunlock(&ctlr->alock); + poperror(); +} + +static void +etherbcmshutdown(Ether*) +{ + sdioreset(); +} + + +static int +etherbcmpnp(Ether* edev) +{ + Ctlr *ctlr; + + ctlr = malloc(sizeof(Ctlr)); + ctlr->chanid = Wifichan; + edev->ctlr = ctlr; + edev->attach = etherbcmattach; + edev->transmit = etherbcmtransmit; + edev->ifstat = etherbcmifstat; + edev->ctl = etherbcmctl; + edev->scanbs = etherbcmscan; + edev->shutdown = etherbcmshutdown; + edev->arg = edev; + + return 0; +} + +void +ether4330link(void) +{ + addethercard("4330", etherbcmpnp); +} diff --git a/sys/src/9/bcm/ethergenet.c b/sys/src/9/bcm/ethergenet.c new file mode 100644 index 0000000000..27461e7dae --- /dev/null +++ b/sys/src/9/bcm/ethergenet.c @@ -0,0 +1,971 @@ +/* + * Broadcom 2711 native gigabit ethernet + * + * from 9front + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/netif.h" +#include "etherif.h" +#include "ethermii.h" + +#define MIIDBG if(0)print + +enum +{ + Rbsz = 10240, + Maxtu = 9014, + + DmaOWN = 0x8000, + DmaSOP = 0x2000, + DmaEOP = 0x4000, + DmaRxLg = 0x10, + DmaRxNo = 0x08, + DmaRxErr = 0x04, + DmaRxCrc = 0x02, + DmaRxOv = 0x01, + DmaRxErrors = DmaRxLg|DmaRxNo|DmaRxErr|DmaRxCrc|DmaRxOv, + + DmaTxQtag = 0x1F80, + DmaTxUnderrun = 0x0200, + DmaTxAppendCrc = 0x0040, + DmaTxOwCrc = 0x0020, + DmaTxDoCsum = 0x0010, + + /* Ctlr->regs */ + SysRevision = 0x00/4, + SysPortCtrl = 0x04/4, + PortModeIntEphy = 0, + PortModeIntGphy = 1, + PortModeExtEphy = 2, + PortModeExtGphy = 3, + PortModeExtRvmii50 = 4, + PortModeExtRvmii25 = 16 | 4, + LedActSourceMac = 1 << 9, + + SysRbufFlushCtrl = 0x08/4, + SysTbufFlushCtrl = 0x0C/4, + + ExtRgmiiOobCtrl = 0x8C/4, + RgmiiLink = 1 << 4, + OobDisable = 1 << 5, + RgmiiModeEn = 1 << 6, + IdModeDis = 1 << 16, + + Intrl0 = 0x200/4, + IrqScb = 1 << 0, + IrqEphy = 1 << 1, + IrqPhyDetR = 1 << 2, + IrqPhyDetF = 1 << 3, + IrqLinkUp = 1 << 4, + IrqLinkDown = 1 << 5, + IrqUmac = 1 << 6, + IrqUmacTsv = 1 << 7, + IrqTbufUnderrun = 1 << 8, + IrqRbufOverflow = 1 << 9, + IrqHfbSm = 1 << 10, + IrqHfbMm = 1 << 11, + IrqMpdR = 1 << 12, + IrqRxDmaDone = 1 << 13, + IrqRxDmaPDone = 1 << 14, + IrqRxDmaBDone = 1 << 15, + IrqTxDmaDone = 1 << 16, + IrqTxDmaPDone = 1 << 17, + IrqTxDmaBDone = 1 << 18, + IrqMdioDone = 1 << 23, + IrqMdioError = 1 << 24, + Intrl1 = 0x240/4, + /* Intrl0/1 + ... */ + IntrSts = 0x00/4, + IntrSet = 0x04/4, + IntrClr = 0x08/4, + IntrMaskSts = 0x0C/4, + IntrMaskSet = 0x10/4, + IntrMaskClr = 0x14/4, + + RbufCtrl = 0x300/4, + Rbuf64En = 1 << 0, + RbufAlign2B = 1 << 1, + RbufBadDis = 1 << 2, + + RbufChkCtrl = 0x314/4, + RbufChkRxChkEn = 1 << 0, + RbufChkSkipFcs = 1 << 4, + + RbufOvflCnt = 0x394/4, + RbufErrCnt = 0x398/4, + + RbufEnergyCtrl = 0x39c/4, + RbufEeeEn = 1 << 0, + RbufPmEn = 1 << 1, + + RbufTbufSizeCtrl= 0x3b4/4, + + TbufCtrl = 0x600/4, + TbufBpMc = 0x60C/4, + TbufEnergyCtrl = 0x614/4, + + UmacCmd = 0x808/4, + CmdTxEn = 1 << 0, + CmdRxEn = 1 << 1, + CmdSpeed10 = 0 << 2, + CmdSpeed100 = 1 << 2, + CmdSpeed1000 = 2 << 2, + CmdSpeedMask = 3 << 2, + CmdProm = 1 << 4, + CmdPadEn = 1 << 5, + CmdCrcFwd = 1 << 6, + CmdPauseFwd = 1 << 7, + CmdRxPauseIgn = 1 << 8, + CmdTxAddrIn = 1 << 9, + CmdHdEn = 1 << 10, + CmdSwReset = 1 << 13, + CmdLclLoopEn = 1 << 15, + CmdAutoConfig = 1 << 22, + CmdCntlFrmEn = 1 << 23, + CmdNoLenChk = 1 << 24, + CmdRmtLoopEn = 1 << 25, + CmdPrblEn = 1 << 27, + CmdTxPauseIgn = 1 << 28, + CmdTxRxEn = 1 << 29, + CmdRuntFilterDis= 1 << 30, + + UmacMac0 = 0x80C/4, + UmacMac1 = 0x810/4, + UmacMaxFrameLen = 0x814/4, + + UmacEeeCtrl = 0x864/4, + UmacEeeEn = 1<<3, + + UmacEeeLpiTimer = 0x868/4, + UmacEeeWakeTimer= 0x86C/4, + UmacEeeRefCount = 0x870/4, + EeeRefCountMask = 0xFFFF, + + UmacTxFlush = 0xb34/4, + + UmacMibCtrl = 0xd80/4, + MibResetRx = 1 << 0, + MibResetRunt = 1 << 1, + MibResetTx = 1 << 2, + + MdioCmd = 0xe14/4, + MdioStartBusy = 1 << 29, + MdioReadFail = 1 << 28, + MdioRead = 2 << 26, + MdioWrite = 1 << 26, + MdioPhyShift = 21, + MdioPhyMask = 0x1F, + MdioAddrShift = 16, + MdioAddrMask = 0x1F, + + UmacMpdCtrl = 0xe20/4, + MpdEn = 1 << 0, + MpdPwEn = 1 << 27, + + UmacMdfCtrl = 0xe50/4, + UmacMdfAddr0 = 0xe54/4, + + RdmaOffset = 0x2000/4, + TdmaOffset = 0x4000/4, + HfbOffset = 0x8000/4, + + HfbCtlr = 0xFC00/4, + HfbFltEnable = 0xFC04/4, + HfbFltLen = 0xFC1C/4, + + /* common Ring->regs */ + RdmaWP = 0x00/4, + TdmaRP = 0x00/4, + RxWP = 0x08/4, + TxRP = 0x08/4, + TxWP = 0x0C/4, + RxRP = 0x0C/4, + DmaRingBufSize = 0x10/4, + DmaStart = 0x14/4, + DmaEnd = 0x1C/4, + DmaDoneThresh = 0x24/4, + TdmaFlowPeriod = 0x28/4, + RdmaXonXoffThresh=0x28/4, + TdmaWP = 0x2C/4, + RdmaRP = 0x2C/4, + + /* + * reg offsets only for RING16 + * ctlr->rx->regs / ctlr->tx->regs + */ + RingCfg = 0x40/4, + RxRingCfgMask = 0x10000, + TxRingCfgMask = 0x1000F, + + DmaCtrl = 0x44/4, + DmaCtrlEn = 1 << 0, + DmaStatus = 0x48/4, + DmaStatusDis = 1 << 0, + DmaScbBurstSize = 0x4C/4, + + TdmaArbCtrl = 0x6C/4, + TdmaPriority0 = 0x70/4, + TdmaPriority1 = 0x74/4, + TdmaPriority2 = 0x78/4, + + RdmaTimeout0 = 0x6C/4, + RdmaIndex2Ring0 = 0xB0/4, +}; + +typedef struct Desc Desc; +typedef struct Ring Ring; +typedef struct Ctlr Ctlr; + +struct Desc +{ + u32int *d; /* hw descriptor */ + Block *b; +}; + +struct Ring +{ + Rendez; + u32int *regs; + u32int *intregs; + u32int intmask; + + Desc *d; + + u32int m; + u32int cp; + u32int rp; + u32int wp; + + int num; +}; + +struct Ctlr +{ + Lock; + u32int *regs; + + Desc rd[256]; + Desc td[256]; + + Ring rx[1+0]; + Ring tx[1+0]; + + Rendez avail[1]; + Rendez link[1]; + struct { + Mii; + Rendez; + } mii[1]; + + QLock; + char attached; +}; + +static Block *scratch; + +#define REG(x) (x) + +static void +interrupt0(Ureg*, void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + u32int sts; + + sts = REG(ctlr->regs[Intrl0 + IntrSts]) & ~REG(ctlr->regs[Intrl0 + IntrMaskSts]); + REG(ctlr->regs[Intrl0 + IntrClr]) = sts; + REG(ctlr->regs[Intrl0 + IntrMaskSet]) = sts; + + if(sts & ctlr->rx->intmask) + wakeup(ctlr->rx); + if(sts & ctlr->tx->intmask) + wakeup(ctlr->tx); + + if(sts & (IrqMdioDone|IrqMdioError)) + wakeup(ctlr->mii); + if(sts & (IrqLinkUp|IrqLinkDown)) + wakeup(ctlr->link); +} + +static void +interrupt1(Ureg*, void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + u32int sts; + int i; + + sts = REG(ctlr->regs[Intrl1 + IntrSts]) & ~REG(ctlr->regs[Intrl1 + IntrMaskSts]); + REG(ctlr->regs[Intrl1 + IntrClr]) = sts; + REG(ctlr->regs[Intrl1 + IntrMaskSet]) = sts; + + for(i = 1; i < nelem(ctlr->rx); i++) + if(sts & ctlr->rx[i].intmask) + wakeup(&ctlr->rx[i]); + + for(i = 1; i < nelem(ctlr->tx); i++) + if(sts & ctlr->tx[i].intmask) + wakeup(&ctlr->tx[i]); +} + +static void +setdma(Desc *d, void *v) +{ + u64int pa = PADDR(v); + REG(d->d[1]) = pa; + REG(d->d[2]) = pa >> 32; +} + +static void +replenish(Desc *d) +{ + d->b = allocb(Rbsz); + cachedwbse(d->b->rp, Rbsz); + setdma(d, d->b->rp); +} + +static int +rxdone(void *arg) +{ + Ring *r = arg; + + r->wp = REG(r->regs[RxWP]) & 0xFFFF; + if(r->rp != r->wp) + return 1; + REG(r->intregs[IntrMaskClr]) = r->intmask; + return 0; +} + +static void +recvproc(void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + Desc *d; + Block *b; + u32int s; + + while(waserror()) + ; + + for(;;){ + if(ctlr->rx->rp == ctlr->rx->wp){ + sleep(ctlr->rx, rxdone, ctlr->rx); + continue; + } + d = &ctlr->rx->d[ctlr->rx->rp & ctlr->rx->m]; + b = d->b; + cachedinvse(b->rp, Rbsz); + s = REG(d->d[0]); + replenish(d); + coherence(); + ctlr->rx->rp = (ctlr->rx->rp + 1) & 0xFFFF; + REG(ctlr->rx->regs[RxRP]) = ctlr->rx->rp; + if((s & (DmaSOP|DmaEOP|DmaRxErrors)) != (DmaSOP|DmaEOP)){ + freeb(b); + continue; + } + b->wp += (s & 0x7FFF0000) >> 16; + etheriq(edev, b, 1); + } +} + +static int +txavail(void *arg) +{ + Ring *r = arg; + + return ((r->wp+1) & r->m) != (r->cp & r->m); +} + +static void +sendproc(void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + Desc *d; + Block *b; + + while(waserror()) + ; + + for(;;){ + if(!txavail(ctlr->tx)){ + sleep(ctlr->avail, txavail, ctlr->tx); + continue; + } + if((b = qbread(edev->oq, 100000)) == nil) + break; + d = &ctlr->tx->d[ctlr->tx->wp & ctlr->tx->m]; + assert(d->b == nil); + d->b = b; + cachedwbse(b->rp, BLEN(b)); + setdma(d, b->rp); + REG(d->d[0]) = BLEN(b)<<16 | DmaTxQtag | DmaSOP | DmaEOP | DmaTxAppendCrc; + coherence(); + ctlr->tx->wp = (ctlr->tx->wp+1) & 0xFFFF; + REG(ctlr->tx->regs[TxWP]) = ctlr->tx->wp; + } +} + +static int +txdone(void *arg) +{ + Ring *r = arg; + + if(r->cp != r->wp){ + r->rp = REG(r->regs[TxRP]) & 0xFFFF; + if(r->cp != r->rp) + return 1; + } + REG(r->intregs[IntrMaskClr]) = r->intmask; + return 0; +} + +static void +freeproc(void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + Desc *d; + + while(waserror()) + ; + + for(;;){ + if(ctlr->tx->cp == ctlr->tx->rp){ + wakeup(ctlr->avail); + sleep(ctlr->tx, txdone, ctlr->tx); + continue; + } + d = &ctlr->tx->d[ctlr->tx->cp & ctlr->tx->m]; + assert(d->b != nil); + freeb(d->b); + d->b = nil; + coherence(); + ctlr->tx->cp = (ctlr->tx->cp+1) & 0xFFFF; + } +} + +static void +initring(Ring *ring, Desc *desc, int start, int size) +{ + ring->d = &desc[start]; + ring->m = size - 1; + ring->cp = ring->rp = ring->wp = 0; + REG(ring->regs[RxWP]) = 0; + REG(ring->regs[RxRP]) = 0; + REG(ring->regs[DmaStart]) = start*3; + REG(ring->regs[DmaEnd]) = (start+size)*3 - 1; + REG(ring->regs[RdmaWP]) = start*3; + REG(ring->regs[RdmaRP]) = start*3; + REG(ring->regs[DmaRingBufSize]) = (size << 16) | Rbsz; + REG(ring->regs[DmaDoneThresh]) = 1; +} + +static void +introff(Ctlr *ctlr) +{ + REG(ctlr->regs[Intrl0 + IntrMaskSet]) = -1; + REG(ctlr->regs[Intrl0 + IntrClr]) = -1; + REG(ctlr->regs[Intrl1 + IntrMaskSet]) = -1; + REG(ctlr->regs[Intrl1 + IntrClr]) = -1; +} + +static void +dmaoff(Ctlr *ctlr) +{ + REG(ctlr->rx->regs[DmaCtrl]) &= ~(RxRingCfgMask<<1 | DmaCtrlEn); + REG(ctlr->tx->regs[DmaCtrl]) &= ~(TxRingCfgMask<<1 | DmaCtrlEn); + + REG(ctlr->regs[UmacTxFlush]) = 1; + microdelay(10); + REG(ctlr->regs[UmacTxFlush]) = 0; + + while((REG(ctlr->rx->regs[DmaStatus]) & DmaStatusDis) == 0) + microdelay(10); + while((REG(ctlr->tx->regs[DmaStatus]) & DmaStatusDis) == 0) + microdelay(10); +} + +static void +dmaon(Ctlr *ctlr) +{ + REG(ctlr->rx->regs[DmaCtrl]) |= DmaCtrlEn; + REG(ctlr->tx->regs[DmaCtrl]) |= DmaCtrlEn; + + while(REG(ctlr->rx->regs[DmaStatus]) & DmaStatusDis) + microdelay(10); + while(REG(ctlr->tx->regs[DmaStatus]) & DmaStatusDis) + microdelay(10); +} + +static void +allocbufs(Ctlr *ctlr) +{ + int i; + + if(scratch == nil){ + scratch = allocb(Rbsz); + memset(scratch->rp, 0xFF, Rbsz); + cachedwbse(scratch->rp, Rbsz); + } + + for(i = 0; i < nelem(ctlr->rd); i++){ + ctlr->rd[i].d = &ctlr->regs[RdmaOffset + i*3]; + replenish(&ctlr->rd[i]); + } + + for(i = 0; i < nelem(ctlr->td); i++){ + ctlr->td[i].d = &ctlr->regs[TdmaOffset + i*3]; + setdma(&ctlr->td[i], scratch->rp); + REG(ctlr->td[i].d[0]) = DmaTxUnderrun; + } +} + +static void +freebufs(Ctlr *ctlr) +{ + int i; + + for(i = 0; i < nelem(ctlr->rd); i++){ + if(ctlr->rd[i].b != nil){ + freeb(ctlr->rd[i].b); + ctlr->rd[i].b = nil; + } + } + for(i = 0; i < nelem(ctlr->td); i++){ + if(ctlr->td[i].b != nil){ + freeb(ctlr->td[i].b); + ctlr->td[i].b = nil; + } + } +} + +static void +initrings(Ctlr *ctlr) +{ + u32int rcfg, tcfg, dmapri[3]; + int i; + + ctlr->rx->intregs = &ctlr->regs[Intrl0]; + ctlr->rx->intmask = IrqRxDmaDone; + ctlr->rx->num = 16; + rcfg = 1<<16; + for(i = 1; i < nelem(ctlr->rx); i++){ + ctlr->rx[i].regs = &ctlr->regs[RdmaOffset + nelem(ctlr->rd)*3 + (i-1)*RingCfg]; + ctlr->rx[i].intregs = &ctlr->regs[Intrl1]; + ctlr->rx[i].intmask = 0x10000 << (i - 1); + ctlr->rx[i].num = i - 1; + rcfg |= 1<<(i-1); + } + assert(rcfg && (rcfg & ~RxRingCfgMask) == 0); + + ctlr->tx->intregs = &ctlr->regs[Intrl0]; + ctlr->tx->intmask = IrqTxDmaDone; + ctlr->tx->num = 16; + tcfg = 1<<16; + for(i = 1; i < nelem(ctlr->tx); i++){ + ctlr->tx[i].regs = &ctlr->regs[TdmaOffset + nelem(ctlr->td)*3 + (i-1)*RingCfg]; + ctlr->tx[i].intregs = &ctlr->regs[Intrl1]; + ctlr->tx[i].intmask = 1 << (i - 1); + ctlr->tx[i].num = i - 1; + tcfg |= 1<<(i-1); + } + assert(tcfg && (tcfg & ~TxRingCfgMask) == 0); + + REG(ctlr->rx->regs[DmaScbBurstSize]) = 0x08; + for(i = 1; i < nelem(ctlr->rx); i++) + initring(&ctlr->rx[i], ctlr->rd, (i-1)*32, 32); + initring(ctlr->rx, ctlr->rd, (i-1)*32, nelem(ctlr->rd) - (i-1)*32); + + for(i = 0; i < nelem(ctlr->rx); i++){ + REG(ctlr->rx[i].regs[DmaDoneThresh]) = 1; + REG(ctlr->rx[i].regs[RdmaXonXoffThresh]) = (5 << 16) | ((ctlr->rx[i].m+1) >> 4); + + // set dma timeout to 50µs + REG(ctlr->rx->regs[RdmaTimeout0 + ctlr->rx[i].num]) = ((50*1000 + 8191)/8192); + } + + REG(ctlr->tx->regs[DmaScbBurstSize]) = 0x08; + for(i = 1; i < nelem(ctlr->tx); i++) + initring(&ctlr->tx[i], ctlr->td, (i-1)*32, 32); + initring(ctlr->tx, ctlr->td, (i-1)*32, nelem(ctlr->td) - (i-1)*32); + + dmapri[0] = dmapri[1] = dmapri[2] = 0; + for(i = 0; i < nelem(ctlr->tx); i++){ + REG(ctlr->tx[i].regs[DmaDoneThresh]) = 10; + REG(ctlr->tx[i].regs[TdmaFlowPeriod]) = i ? 0 : Maxtu << 16; + dmapri[ctlr->tx[i].num/6] |= i << ((ctlr->tx[i].num%6)*5); + } + + REG(ctlr->tx->regs[TdmaArbCtrl]) = 2; + REG(ctlr->tx->regs[TdmaPriority0]) = dmapri[0]; + REG(ctlr->tx->regs[TdmaPriority1]) = dmapri[1]; + REG(ctlr->tx->regs[TdmaPriority2]) = dmapri[2]; + + REG(ctlr->rx->regs[RingCfg]) = rcfg; + REG(ctlr->tx->regs[RingCfg]) = tcfg; + + REG(ctlr->rx->regs[DmaCtrl]) |= rcfg<<1; + REG(ctlr->tx->regs[DmaCtrl]) |= tcfg<<1; +} + +static void +umaccmd(Ctlr *ctlr, u32int set, u32int clr) +{ + ilock(ctlr); + REG(ctlr->regs[UmacCmd]) = (REG(ctlr->regs[UmacCmd]) & ~clr) | set; + iunlock(ctlr); +} + +static void +reset(Ctlr *ctlr) +{ + u32int r; + + // reset umac + r = REG(ctlr->regs[SysRbufFlushCtrl]); + REG(ctlr->regs[SysRbufFlushCtrl]) = r | 2; + microdelay(10); + REG(ctlr->regs[SysRbufFlushCtrl]) = r & ~2; + microdelay(10); + + // umac reset + REG(ctlr->regs[SysRbufFlushCtrl]) = 0; + microdelay(10); + + REG(ctlr->regs[UmacCmd]) = 0; + REG(ctlr->regs[UmacCmd]) = CmdSwReset | CmdLclLoopEn; + microdelay(2); + REG(ctlr->regs[UmacCmd]) = 0; +} + +static void +setmac(Ctlr *ctlr, uchar *ea) +{ + REG(ctlr->regs[UmacMac0]) = ea[0]<<24 | ea[1]<<16 | ea[2]<<8 | ea[3]; + REG(ctlr->regs[UmacMac1]) = ea[4]<<8 | ea[5]; +} + +static void +sethfb(Ctlr *ctlr) +{ + int i; + + REG(ctlr->regs[HfbCtlr]) = 0; + REG(ctlr->regs[HfbFltEnable]) = 0; + REG(ctlr->regs[HfbFltEnable+1]) = 0; + + for(i = 0; i < 8; i++) + REG(ctlr->rx->regs[RdmaIndex2Ring0+i]) = 0; + + for(i = 0; i < 48/4; i++) + REG(ctlr->regs[HfbFltLen + i]) = 0; + + for(i = 0; i < 48*128; i++) + REG(ctlr->regs[HfbOffset + i]) = 0; +} + +static int +mdiodone(void *arg) +{ + Ctlr *ctlr = arg; + REG(ctlr->regs[Intrl0 + IntrMaskClr]) = (IrqMdioDone|IrqMdioError); + return (REG(ctlr->regs[MdioCmd]) & MdioStartBusy) == 0; +} + +static int +mdiowait(Ctlr *ctlr) +{ + REG(ctlr->regs[MdioCmd]) |= MdioStartBusy; + while(REG(ctlr->regs[MdioCmd]) & MdioStartBusy) + tsleep(ctlr->mii, mdiodone, ctlr, 10); + return 0; +} + +static int +mdiow(Mii* mii, int phy, int addr, int data) +{ + Ctlr *ctlr = mii->ctlr; + + if(phy > MdioPhyMask) + return -1; + addr &= MdioAddrMask; + REG(ctlr->regs[MdioCmd]) = MdioWrite + | (phy << MdioPhyShift) | (addr << MdioAddrShift) | (data & 0xFFFF); + return mdiowait(ctlr); +} + +static int +mdior(Mii* mii, int phy, int addr) +{ + Ctlr *ctlr = mii->ctlr; + + if(phy > MdioPhyMask) + return -1; + addr &= MdioAddrMask; + REG(ctlr->regs[MdioCmd]) = MdioRead + | (phy << MdioPhyShift) | (addr << MdioAddrShift); + if(mdiowait(ctlr) < 0) + return -1; + if(REG(ctlr->regs[MdioCmd]) & MdioReadFail) + return -1; + return REG(ctlr->regs[MdioCmd]) & 0xFFFF; +} + +static int +bcmshdr(Mii *mii, int reg) +{ + miimiw(mii, 0x1C, (reg & 0x1F) << 10); + return miimir(mii, 0x1C) & 0x3FF; +} + +static int +bcmshdw(Mii *mii, int reg, int dat) +{ + return miimiw(mii, 0x1C, 0x8000 | (reg & 0x1F) << 10 | (dat & 0x3FF)); +} + +static int +linkevent(void *arg) +{ + Ctlr *ctlr = arg; + REG(ctlr->regs[Intrl0 + IntrMaskClr]) = IrqLinkUp|IrqLinkDown; + return 0; +} + +static void +linkproc(void *arg) +{ + Ether *edev = arg; + Ctlr *ctlr = edev->ctlr; + MiiPhy *phy; + int link = -1; + + while(waserror()) + ; + + for(;;){ + tsleep(ctlr->link, linkevent, ctlr, 1000); + miistatus(ctlr->mii); + phy = ctlr->mii->curphy; + if(phy == nil || phy->link == link) + continue; + link = phy->link; + if(link){ + u32int cmd = CmdRxEn|CmdTxEn; + switch(phy->speed){ + case 1000: cmd |= CmdSpeed1000; break; + case 100: cmd |= CmdSpeed100; break; + case 10: cmd |= CmdSpeed10; break; + } + if(!phy->fd) + cmd |= CmdHdEn; + if(!phy->rfc) + cmd |= CmdRxPauseIgn; + if(!phy->tfc) + cmd |= CmdTxPauseIgn; + + REG(ctlr->regs[ExtRgmiiOobCtrl]) = (REG(ctlr->regs[ExtRgmiiOobCtrl]) & ~OobDisable) | RgmiiLink; + umaccmd(ctlr, cmd, CmdSpeedMask|CmdHdEn|CmdRxPauseIgn|CmdTxPauseIgn); + + edev->mbps = phy->speed; + } + edev->link = link; + // print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps); + } +} + +static void +setmdfaddr(Ctlr *ctlr, int i, uchar *ea) +{ + REG(ctlr->regs[UmacMdfAddr0 + i*2 + 0]) = ea[0] << 8 | ea[1]; + REG(ctlr->regs[UmacMdfAddr0 + i*2 + 1]) = ea[2] << 24 | ea[3] << 16 | ea[4] << 8 | ea[5]; +} + +static void +rxmode(Ether *edev, int prom) +{ + Ctlr *ctlr = edev->ctlr; + Netaddr *na; + int i; + + if(prom || edev->nmaddr > 16-2){ + REG(ctlr->regs[UmacMdfCtrl]) = 0; + umaccmd(ctlr, CmdProm, 0); + return; + } + setmdfaddr(ctlr, 0, edev->bcast); + setmdfaddr(ctlr, 1, edev->ea); + for(i = 2, na = edev->maddr; na != nil; na = na->next, i++) + setmdfaddr(ctlr, i, na->addr); + REG(ctlr->regs[UmacMdfCtrl]) = (-0x10000 >> i) & 0x1FFFF; + umaccmd(ctlr, 0, CmdProm); +} + +static void +shutdown(Ether *edev) +{ + Ctlr *ctlr = edev->ctlr; + + dmaoff(ctlr); + introff(ctlr); +} + +static void +attach(Ether *edev) +{ + Ctlr *ctlr = edev->ctlr; + + qlock(ctlr); + if(ctlr->attached){ + qunlock(ctlr); + return; + } + if(waserror()){ + print("#l%d: %s\n", edev->ctlrno, up->errstr); + shutdown(edev); + freebufs(ctlr); + qunlock(ctlr); + nexterror(); + } + + // statistics + REG(ctlr->regs[UmacMibCtrl]) = MibResetRx | MibResetTx | MibResetRunt; + REG(ctlr->regs[UmacMibCtrl]) = 0; + + // wol + REG(ctlr->regs[UmacMpdCtrl]) &= ~(MpdPwEn|MpdEn); + + // power + REG(ctlr->regs[UmacEeeCtrl]) &= ~UmacEeeEn; + REG(ctlr->regs[RbufEnergyCtrl]) &= ~(RbufEeeEn|RbufPmEn); + REG(ctlr->regs[TbufEnergyCtrl]) &= ~(RbufEeeEn|RbufPmEn); + REG(ctlr->regs[TbufBpMc]) = 0; + + REG(ctlr->regs[UmacMaxFrameLen]) = Maxtu; + + REG(ctlr->regs[RbufTbufSizeCtrl]) = 1; + + REG(ctlr->regs[TbufCtrl]) &= ~(Rbuf64En); + REG(ctlr->regs[RbufCtrl]) &= ~(Rbuf64En|RbufAlign2B); + REG(ctlr->regs[RbufChkCtrl]) &= ~(RbufChkRxChkEn|RbufChkSkipFcs); + + allocbufs(ctlr); + initrings(ctlr); + dmaon(ctlr); + + setmac(ctlr, edev->ea); + sethfb(ctlr); + rxmode(edev, 0); + + REG(ctlr->regs[SysPortCtrl]) = PortModeExtGphy; + REG(ctlr->regs[ExtRgmiiOobCtrl]) |= RgmiiModeEn | IdModeDis; + + ctlr->mii->ctlr = ctlr; + ctlr->mii->mir = mdior; + ctlr->mii->miw = mdiow; + mii(ctlr->mii, ~0); + + if(ctlr->mii->curphy == nil) + error("no phy"); + + MIIDBG("#l%d: phy%d id %.8ux oui %x\n", + edev->ctlrno, ctlr->mii->curphy->phyno, + ctlr->mii->curphy->id, ctlr->mii->curphy->oui); + + miireset(ctlr->mii); + + switch(ctlr->mii->curphy->id){ + case 0x600d84a2: /* BCM54312PE */ + /* mask interrupts */ + miimiw(ctlr->mii, 0x10, miimir(ctlr->mii, 0x10) | 0x1000); + + /* SCR3: clear DLLAPD_DIS */ + bcmshdw(ctlr->mii, 0x05, bcmshdr(ctlr->mii, 0x05) &~0x0002); + /* APD: set APD_EN */ + bcmshdw(ctlr->mii, 0x0a, bcmshdr(ctlr->mii, 0x0a) | 0x0020); + + /* blinkenlights */ + bcmshdw(ctlr->mii, 0x09, bcmshdr(ctlr->mii, 0x09) | 0x0010); + bcmshdw(ctlr->mii, 0x0d, 3<<0 | 0<<4); + break; + } + + /* don't advertise EEE */ + miimmdw(ctlr->mii, 7, 60, 0); + + miiane(ctlr->mii, ~0, AnaAP|AnaP, ~0); + + ctlr->attached = 1; + + kproc("genet-recv", recvproc, edev); + kproc("genet-send", sendproc, edev); + kproc("genet-free", freeproc, edev); + kproc("genet-link", linkproc, edev); + + qunlock(ctlr); + poperror(); +} + +static void +prom(void *arg, int on) +{ + Ether *edev = arg; + rxmode(edev, on); +} + +static void +multi(void *arg, uchar*, int) +{ + Ether *edev = arg; + rxmode(edev, edev->prom > 0); +} + +static int +pnp(Ether *edev) +{ + static Ctlr ctlr[1]; + + if(ctlr->regs != nil) + return -1; + + ctlr->regs = (u32int*)(VIRTIO + 0x580000); + ctlr->rx->regs = &ctlr->regs[RdmaOffset + nelem(ctlr->rd)*3 + 16*RingCfg]; + ctlr->tx->regs = &ctlr->regs[TdmaOffset + nelem(ctlr->td)*3 + 16*RingCfg]; + + edev->port = (uintptr)ctlr->regs; + edev->irq = IRQether; + edev->ctlr = ctlr; + edev->attach = attach; + edev->shutdown = shutdown; + edev->promiscuous = prom; + edev->multicast = multi; + edev->arg = edev; + edev->mbps = 1000; + edev->maxmtu = Maxtu; + + parseether(edev->ea, getethermac()); + + reset(ctlr); + dmaoff(ctlr); + introff(ctlr); + + intrenable(edev->irq+0, interrupt0, edev, BUSUNKNOWN, edev->name); + intrenable(edev->irq+1, interrupt1, edev, BUSUNKNOWN, edev->name); + + return 0; +} + +void +ethergenetlink(void) +{ + addethercard("genet", pnp); +} diff --git a/sys/src/9/bcm/ethermii.c b/sys/src/9/bcm/ethermii.c new file mode 100644 index 0000000000..352654db39 --- /dev/null +++ b/sys/src/9/bcm/ethermii.c @@ -0,0 +1,262 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" +#include "etherif.h" + +#include "ethermii.h" + +int +mii(Mii* mii, int mask) +{ + MiiPhy *miiphy; + int bit, oui, phyno, rmask; + u32int id; + + /* + * Probe through mii for PHYs in mask; + * return the mask of those found in the current probe. + * If the PHY has not already been probed, update + * the Mii information. + */ + rmask = 0; + for(phyno = 0; phyno < NMiiPhy; phyno++){ + bit = 1<mask & bit){ + rmask |= bit; + continue; + } + if(mii->mir(mii, phyno, Bmsr) == -1) + continue; + id = mii->mir(mii, phyno, Phyidr1) << 16; + id |= mii->mir(mii, phyno, Phyidr2); + oui = (id & 0x3FFFFC00)>>10; + if(oui == 0xFFFFF || oui == 0) + continue; + + if((miiphy = malloc(sizeof(MiiPhy))) == nil) + continue; + + miiphy->mii = mii; + miiphy->id = id; + miiphy->oui = oui; + miiphy->phyno = phyno; + + miiphy->anar = ~0; + miiphy->fc = ~0; + miiphy->mscr = ~0; + + mii->phy[phyno] = miiphy; + if(mii->curphy == nil) + mii->curphy = miiphy; + mii->mask |= bit; + mii->nphy++; + + rmask |= bit; + } + return rmask; +} + +int +miimir(Mii* mii, int r) +{ + if(mii == nil || mii->ctlr == nil || mii->curphy == nil) + return -1; + return mii->mir(mii, mii->curphy->phyno, r); +} + +int +miimiw(Mii* mii, int r, int data) +{ + if(mii == nil || mii->ctlr == nil || mii->curphy == nil) + return -1; + return mii->miw(mii, mii->curphy->phyno, r, data); +} + +int +miireset(Mii* mii) +{ + int bmcr; + + if(mii == nil || mii->ctlr == nil || mii->curphy == nil) + return -1; + bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr); + bmcr |= BmcrR; + mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr); + microdelay(1); + + return 0; +} + +int +miiane(Mii* mii, int a, int p, int e) +{ + int anar, bmsr, mscr, r, phyno; + + if(mii == nil || mii->ctlr == nil || mii->curphy == nil) + return -1; + phyno = mii->curphy->phyno; + + bmsr = mii->mir(mii, phyno, Bmsr); + if(!(bmsr & BmsrAna)) + return -1; + + if(a != ~0) + anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a; + else if(mii->curphy->anar != ~0) + anar = mii->curphy->anar; + else{ + anar = mii->mir(mii, phyno, Anar); + anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD); + if(bmsr & Bmsr10THD) + anar |= Ana10HD; + if(bmsr & Bmsr10TFD) + anar |= Ana10FD; + if(bmsr & Bmsr100TXHD) + anar |= AnaTXHD; + if(bmsr & Bmsr100TXFD) + anar |= AnaTXFD; + } + mii->curphy->anar = anar; + + if(p != ~0) + anar |= (AnaAP|AnaP) & p; + else if(mii->curphy->fc != ~0) + anar |= mii->curphy->fc; + mii->curphy->fc = (AnaAP|AnaP) & anar; + + if(bmsr & BmsrEs){ + mscr = mii->mir(mii, phyno, Mscr); + mscr &= ~(Mscr1000TFD|Mscr1000THD); + if(e != ~0) + mscr |= (Mscr1000TFD|Mscr1000THD) & e; + else if(mii->curphy->mscr != ~0) + mscr = mii->curphy->mscr; + else{ + r = mii->mir(mii, phyno, Esr); + if(r & Esr1000THD) + mscr |= Mscr1000THD; + if(r & Esr1000TFD) + mscr |= Mscr1000TFD; + } + mii->curphy->mscr = mscr; + mii->miw(mii, phyno, Mscr, mscr); + } + mii->miw(mii, phyno, Anar, anar); + + r = mii->mir(mii, phyno, Bmcr); + if(!(r & BmcrR)){ + r |= BmcrAne|BmcrRan; + mii->miw(mii, phyno, Bmcr, r); + } + + return 0; +} + +int +miistatus(Mii* mii) +{ + MiiPhy *phy; + int anlpar, bmsr, p, r, phyno; + + if(mii == nil || mii->ctlr == nil || mii->curphy == nil) + return -1; + phy = mii->curphy; + phyno = phy->phyno; + + /* + * Check Auto-Negotiation is complete and link is up. + * (Read status twice as the Ls bit is sticky). + */ + bmsr = mii->mir(mii, phyno, Bmsr); + if(!(bmsr & (BmsrAnc|BmsrAna))) { + // print("miistatus: auto-neg incomplete\n"); + return -1; + } + + bmsr = mii->mir(mii, phyno, Bmsr); + if(!(bmsr & BmsrLs)){ + // print("miistatus: link down\n"); + phy->link = 0; + return -1; + } + + phy->speed = phy->fd = phy->rfc = phy->tfc = 0; + if(phy->mscr){ + r = mii->mir(mii, phyno, Mssr); + if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){ + phy->speed = 1000; + phy->fd = 1; + } + else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD)) + phy->speed = 1000; + } + + anlpar = mii->mir(mii, phyno, Anlpar); + if(phy->speed == 0){ + r = phy->anar & anlpar; + if(r & AnaTXFD){ + phy->speed = 100; + phy->fd = 1; + } + else if(r & AnaTXHD) + phy->speed = 100; + else if(r & Ana10FD){ + phy->speed = 10; + phy->fd = 1; + } + else if(r & Ana10HD) + phy->speed = 10; + } + if(phy->speed == 0) { + // print("miistatus: phy speed 0\n"); + return -1; + } + + if(phy->fd){ + p = phy->fc; + r = anlpar & (AnaAP|AnaP); + if(p == AnaAP && r == (AnaAP|AnaP)) + phy->tfc = 1; + else if(p == (AnaAP|AnaP) && r == AnaAP) + phy->rfc = 1; + else if((p & AnaP) && (r & AnaP)) + phy->rfc = phy->tfc = 1; + } + + phy->link = 1; + + return 0; +} + +int +miimmdr(Mii* mii, int a, int r) +{ + a &= 0x1F; + if(miimiw(mii, Mmdctrl, a) == -1) + return -1; + if(miimiw(mii, Mmddata, r) == -1) + return -1; + if(miimiw(mii, Mmdctrl, a | 0x4000) == -1) + return -1; + return miimir(mii, Mmddata); +} + +int +miimmdw(Mii* mii, int a, int r, int data) +{ + a &= 0x1F; + if(miimiw(mii, Mmdctrl, a) == -1) + return -1; + if(miimiw(mii, Mmddata, r) == -1) + return -1; + if(miimiw(mii, Mmdctrl, a | 0x4000) == -1) + return -1; + return miimiw(mii, Mmddata, data); +} diff --git a/sys/src/9/bcm/ethermii.h b/sys/src/9/bcm/ethermii.h new file mode 100644 index 0000000000..4fea978b86 --- /dev/null +++ b/sys/src/9/bcm/ethermii.h @@ -0,0 +1,122 @@ +typedef struct Mii Mii; +typedef struct MiiPhy MiiPhy; + +enum { /* registers */ + Bmcr = 0x00, /* Basic Mode Control */ + Bmsr = 0x01, /* Basic Mode Status */ + Phyidr1 = 0x02, /* PHY Identifier #1 */ + Phyidr2 = 0x03, /* PHY Identifier #2 */ + Anar = 0x04, /* Auto-Negotiation Advertisement */ + Anlpar = 0x05, /* AN Link Partner Ability */ + Aner = 0x06, /* AN Expansion */ + Annptr = 0x07, /* AN Next Page TX */ + Annprr = 0x08, /* AN Next Page RX */ + Mscr = 0x09, /* MASTER-SLAVE Control */ + Mssr = 0x0A, /* MASTER-SLAVE Status */ + Mmdctrl = 0x0D, /* MMD Access Control */ + Mmddata = 0x0E, /* MMD Access Data Register */ + Esr = 0x0F, /* Extended Status */ + + NMiiPhyr = 32, + NMiiPhy = 32, +}; + +enum { /* Bmcr */ + BmcrSs1 = 0x0040, /* Speed Select[1] */ + BmcrCte = 0x0080, /* Collision Test Enable */ + BmcrDm = 0x0100, /* Duplex Mode */ + BmcrRan = 0x0200, /* Restart Auto-Negotiation */ + BmcrI = 0x0400, /* Isolate */ + BmcrPd = 0x0800, /* Power Down */ + BmcrAne = 0x1000, /* Auto-Negotiation Enable */ + BmcrSs0 = 0x2000, /* Speed Select[0] */ + BmcrLe = 0x4000, /* Loopback Enable */ + BmcrR = 0x8000, /* Reset */ +}; + +enum { /* Bmsr */ + BmsrEc = 0x0001, /* Extended Capability */ + BmsrJd = 0x0002, /* Jabber Detect */ + BmsrLs = 0x0004, /* Link Status */ + BmsrAna = 0x0008, /* Auto-Negotiation Ability */ + BmsrRf = 0x0010, /* Remote Fault */ + BmsrAnc = 0x0020, /* Auto-Negotiation Complete */ + BmsrPs = 0x0040, /* Preamble Suppression Capable */ + BmsrEs = 0x0100, /* Extended Status */ + Bmsr100T2HD = 0x0200, /* 100BASE-T2 HD Capable */ + Bmsr100T2FD = 0x0400, /* 100BASE-T2 FD Capable */ + Bmsr10THD = 0x0800, /* 10BASE-T HD Capable */ + Bmsr10TFD = 0x1000, /* 10BASE-T FD Capable */ + Bmsr100TXHD = 0x2000, /* 100BASE-TX HD Capable */ + Bmsr100TXFD = 0x4000, /* 100BASE-TX FD Capable */ + Bmsr100T4 = 0x8000, /* 100BASE-T4 Capable */ +}; + +enum { /* Anar/Anlpar */ + Ana10HD = 0x0020, /* Advertise 10BASE-T */ + Ana10FD = 0x0040, /* Advertise 10BASE-T FD */ + AnaTXHD = 0x0080, /* Advertise 100BASE-TX */ + AnaTXFD = 0x0100, /* Advertise 100BASE-TX FD */ + AnaT4 = 0x0200, /* Advertise 100BASE-T4 */ + AnaP = 0x0400, /* Pause */ + AnaAP = 0x0800, /* Asymmetrical Pause */ + AnaRf = 0x2000, /* Remote Fault */ + AnaAck = 0x4000, /* Acknowledge */ + AnaNp = 0x8000, /* Next Page Indication */ +}; + +enum { /* Mscr */ + Mscr1000THD = 0x0100, /* Advertise 1000BASE-T HD */ + Mscr1000TFD = 0x0200, /* Advertise 1000BASE-T FD */ +}; + +enum { /* Mssr */ + Mssr1000THD = 0x0400, /* Link Partner 1000BASE-T HD able */ + Mssr1000TFD = 0x0800, /* Link Partner 1000BASE-T FD able */ +}; + +enum { /* Esr */ + Esr1000THD = 0x1000, /* 1000BASE-T HD Capable */ + Esr1000TFD = 0x2000, /* 1000BASE-T FD Capable */ + Esr1000XHD = 0x4000, /* 1000BASE-X HD Capable */ + Esr1000XFD = 0x8000, /* 1000BASE-X FD Capable */ +}; + +typedef struct Mii { + Lock; + int nphy; + int mask; + MiiPhy* phy[NMiiPhy]; + MiiPhy* curphy; + + void* ctlr; + int (*mir)(Mii*, int, int); + int (*miw)(Mii*, int, int, int); +} Mii; + +typedef struct MiiPhy { + Mii* mii; + u32int id; + int oui; + int phyno; + + int anar; + int fc; + int mscr; + + int link; + int speed; + int fd; + int rfc; + int tfc; +}; + +extern int mii(Mii*, int); +extern int miiane(Mii*, int, int, int); +extern int miimir(Mii*, int); +extern int miimiw(Mii*, int, int); +extern int miireset(Mii*); +extern int miistatus(Mii*); + +extern int miimmdr(Mii*, int, int); +extern int miimmdw(Mii*, int, int, int); diff --git a/sys/src/9/bcm/etherusb.c b/sys/src/9/bcm/etherusb.c index b0aad0dedc..88d9816650 100644 --- a/sys/src/9/bcm/etherusb.c +++ b/sys/src/9/bcm/etherusb.c @@ -8,6 +8,7 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "ureg.h" #include "../port/error.h" #include "../port/netif.h" @@ -29,6 +30,8 @@ enum { SmscRxerror = 0x8000, SmscTxfirst = 0x2000, SmscTxlast = 0x1000, + Lan78Rxerror = 0x00400000, + Lan78Txfcs = 1<<22, }; typedef struct Ctlr Ctlr; @@ -63,16 +66,19 @@ static Cmdtab cmds[] = { { Unbind, "unbind", 0, }, }; -static Unpackfn unpackcdc, unpackasix, unpacksmsc; -static Transmitfn transmitcdc, transmitasix, transmitsmsc; +static Unpackfn unpackcdc, unpackasix, unpacksmsc, unpacklan78; +static Transmitfn transmitcdc, transmitasix, transmitsmsc, transmitlan78; static Udev udevtab[] = { { "cdc", unpackcdc, transmitcdc, }, { "asix", unpackasix, transmitasix, }, { "smsc", unpacksmsc, transmitsmsc, }, + { "lan78xx", unpacklan78, transmitlan78, }, { nil }, }; +static char nullea[Eaddrlen]; + static void dump(int c, Block *b) { @@ -175,6 +181,33 @@ unpacksmsc(Ether *edev, Block *b) return 0; } +static int +unpacklan78(Ether *edev, Block *b) +{ + ulong hd; + int m; + + if(BLEN(b) < 10) + return -1; + hd = GET4(b->rp); + b->rp += 10; + m = hd & 0x3FFF; + if(m < 6 || m > BLEN(b)) + return -1; + if(hd & Lan78Rxerror){ + edev->frames++; + b->rp += m; + if(BLEN(b) == 0){ + freeb(b); + return 1; + } + }else if(unpack(edev, b, m) == 1) + return 1; + if(BLEN(b) > 0) + b->rp = (uchar*)((((uintptr)b->rp)+3)&~3); + return 0; +} + static void transmit(Ctlr *ctlr, Block *b) { @@ -198,10 +231,10 @@ transmitasix(Ctlr *ctlr, Block *b) n = BLEN(b) & 0xFFFF; n |= ~n << 16; - padblock(b, 4); + b = padblock(b, 4); PUT4(b->rp, n); if(BLEN(b) % ctlr->maxpkt == 0){ - padblock(b, -4); + b = padblock(b, -4); PUT4(b->wp, 0xFFFF0000); b->wp += 4; } @@ -214,12 +247,24 @@ transmitsmsc(Ctlr *ctlr, Block *b) int n; n = BLEN(b) & 0x7FF; - padblock(b, 8); + b = padblock(b, 8); PUT4(b->rp, n | SmscTxfirst | SmscTxlast); PUT4(b->rp+4, n); transmit(ctlr, b); } +static void +transmitlan78(Ctlr *ctlr, Block *b) +{ + int n; + + n = BLEN(b) & 0xFFFFF; + b = padblock(b, 8); + PUT4(b->rp, n | Lan78Txfcs); + PUT4(b->rp+4, n); + transmit(ctlr, b); +} + static void etherusbproc(void *a) { @@ -263,6 +308,7 @@ bind(Ctlr *ctlr, Udev *udev, Cmdbuf *cb) Chan *inchan, *outchan; char *buf; uint bufsize, maxpkt; + uchar ea[Eaddrlen]; qlock(ctlr); inchan = outchan = nil; @@ -288,10 +334,12 @@ bind(Ctlr *ctlr, Udev *udev, Cmdbuf *cb) inchan = namec(cb->f[2], Aopen, OREAD, 0); outchan = namec(cb->f[3], Aopen, OWRITE, 0); assert(inchan != nil && outchan != nil); - if(parsemac(ctlr->edev->ea, cb->f[4], Eaddrlen) != Eaddrlen) + if(parsemac(ea, cb->f[4], Eaddrlen) != Eaddrlen) cmderror(cb, "bad etheraddr"); - memmove(ctlr->edev->addr, ctlr->edev->ea, Eaddrlen); - print("\netherusb %s: %E\n", udev->name, ctlr->edev->addr); + if(memcmp(ctlr->edev->ea, nullea, Eaddrlen) == 0) + memmove(ctlr->edev->ea, ea, Eaddrlen); + else if(memcmp(ctlr->edev->ea, ea, Eaddrlen) != 0) + cmderror(cb, "wrong ether address"); ctlr->buf = buf; ctlr->inchan = inchan; ctlr->outchan = outchan; @@ -299,6 +347,8 @@ bind(Ctlr *ctlr, Udev *udev, Cmdbuf *cb) ctlr->maxpkt = maxpkt; ctlr->udev = udev; kproc("etherusb", etherusbproc, ctlr->edev); + memmove(ctlr->edev->addr, ea, Eaddrlen); + print("\netherusb %s: %E\n", udev->name, ctlr->edev->addr); poperror(); qunlock(ctlr); } @@ -396,13 +446,33 @@ etherusbctl(Ether* edev, void* buf, long n) return n; } +static void +etherusbmulticast(void*, uchar*, int) +{ + /* nothing to do, we allow all multicast packets in */ +} + +static void +etherusbshutdown(Ether*) +{ +} + static void etherusbattach(Ether* edev) { Ctlr *ctlr; ctlr = edev->ctlr; - ctlr->edev = edev; + if(ctlr->edev == 0){ + /* + * Don't let boot process access etherusb until + * usbether driver has assigned an address. + */ + if(up->pid == 1 && strcmp(up->text, "boot") == 0) + while(memcmp(edev->ea, nullea, Eaddrlen) == 0) + tsleep(&up->sleep, return0, 0, 100); + ctlr->edev = edev; + } } static int @@ -427,8 +497,8 @@ etherusbpnp(Ether* edev) edev->arg = edev; /* TODO: promiscuous, multicast (for ipv6), shutdown (for reboot) */ // edev->promiscuous = etherusbpromiscuous; -// edev->shutdown = etherusbshutdown; -// edev->multicast = etherusbmulticast; + edev->shutdown = etherusbshutdown; + edev->multicast = etherusbmulticast; return 0; } diff --git a/sys/src/9/bcm/fns.h b/sys/src/9/bcm/fns.h index a20427f5bf..1117dfec8f 100644 --- a/sys/src/9/bcm/fns.h +++ b/sys/src/9/bcm/fns.h @@ -5,75 +5,115 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*, void*, long, vlong), extern void archreboot(void); extern void archreset(void); extern void armtimerset(int); +extern void cachedwb(void); extern void cachedwbinv(void); +extern void cachedinvse(void*, int); extern void cachedwbse(void*, int); extern void cachedwbinvse(void*, int); +extern void cachedwbtlb(void*, int); extern void cacheiinv(void); +extern void cacheiinvse(void*, int); extern void cacheuwbinv(void); extern uintptr cankaddr(uintptr pa); extern int cas32(void*, u32int, u32int); +extern int cas(ulong*, ulong, ulong); extern void checkmmu(uintptr, uintptr); extern void clockinit(void); extern void clockshutdown(void); extern int cmpswap(long*, long, long); extern void coherence(void); -extern ulong cprd(int cp, int op1, int crn, int crm, int op2); -extern ulong cprdsc(int op1, int crn, int crm, int op2); +extern u32int cpidget(void); +extern u32int cprdcpaccess(void); +extern u32int cprdfeat1(void); extern void cpuidprint(void); -extern void cpwr(int cp, int op1, int crn, int crm, int op2, ulong val); -extern void cpwrsc(int op1, int crn, int crm, int op2, ulong val); +extern char *cputype2name(char *buf, int size); +extern void cpwrcpaccess(u32int); +extern void cpwrtimerphysctl(u32int); +extern void cpwrtimerphysval(u32int); #define cycles(ip) *(ip) = lcycles() +extern uintptr dmaaddr(void *va); extern void dmastart(int, int, int, void*, void*, int); extern int dmawait(int); extern int fbblank(int); extern void* fbinit(int, int*, int*, int*); extern u32int farget(void); extern void fpon(void); -extern ulong fprd(int fpreg); +extern ulong fprdexc(void); +extern ulong fprdscr(void); +extern ulong fprdsid(void); +extern void fpwrexc(ulong); +extern void fpwrscr(ulong); extern void fprestreg(int fpreg, uvlong val); +extern void fprestregs(uvlong*, int); extern void fpsave(FPsave *); extern ulong fpsavereg(int fpreg, uvlong *fpp); -extern void fpwr(int fpreg, ulong val); +extern void fpsaveregs(uvlong*, int); extern u32int fsrget(void); +extern uint getboardrev(void); extern ulong getclkrate(int); extern char* getconf(char*); +extern uint getcputemp(void); extern char *getethermac(void); extern uint getfirmware(void); +extern int getncpus(void); extern int getpower(int); extern void getramsize(Confmem*); +extern void gpiosel(uint, int); +extern void gpiopullup(uint); +extern void gpiopulloff(uint); +extern void gpiopulldown(uint); +extern void gpioout(uint, int); +extern int gpioin(uint); +extern void i2csetup(int); +extern long i2crecv(I2Cdev*, void*, long, ulong); +extern long i2csend(I2Cdev*, void*, long, ulong); extern u32int ifsrget(void); extern void irqenable(int, void (*)(Ureg*, void*), void*); #define intrenable(i, f, a, b, n) irqenable((i), (f), (a)) +extern void intrcpushutdown(void); +extern void intrshutdown(void); extern void intrsoff(void); extern int isaconfig(char*, int, ISAConf*); +extern int l2ap(int); +extern void l2cacheuwbinv(void); extern void links(void); -extern void mmuinit(void); +extern void mmuinit(void*); extern void mmuinit1(void); extern void mmuinvalidate(void); extern void mmuinvalidateaddr(u32int); -extern uintptr mmukmap(uintptr, uintptr, usize); extern void okay(int); extern void procrestore(Proc *); extern void procsave(Proc*); extern void procsetup(Proc*); extern void screeninit(void); #define sdfree(p) free(p) -#define sdmalloc(n) mallocalign(n, CACHELINESZ, 0, 0) +#define sdmalloc(n) mallocalign(n, BLOCKALIGN, 0, 0) +extern void setclkrate(int, ulong); extern void setpower(int, int); extern void setr13(int, u32int*); +extern void sev(void); +extern void spiclock(uint); +extern void spimode(int); +extern void spirw(uint, void*, int); extern int splfhi(void); extern int splflo(void); extern void swcursorinit(void); extern void syscallfmt(int syscallno, ulong pc, va_list list); extern void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop); +extern int startcpus(uint); +extern void stopcpu(uint); extern int tas(void *); extern void touser(uintptr); extern void trapinit(void); extern void uartconsinit(void); extern int userureg(Ureg*); extern void vectors(void); +extern void vgpinit(void); +extern void vgpset(uint, int); extern void vtable(void); extern void wdogoff(void); +extern void wdogfeed(void); +extern int xhcireset(int devaddr); /* * floating point emulation @@ -89,6 +129,19 @@ extern void fpusysprocsetup(Proc*); extern void fpusysrfork(Ureg*); extern void fpusysrforkchild(Proc*, Ureg*, Proc*); extern int fpuemu(Ureg*); +/* + * Miscellaneous machine dependent stuff. + */ +extern char* getenv(char*, char*, int); +uintptr mmukmap(uintptr, uintptr, usize); +uintptr mmukmapx(uintptr, uvlong, usize); +uintptr mmukunmap(uintptr, uintptr, usize); +extern void* mmuuncache(void*, usize); +extern void* ucalloc(usize); +extern Block* ucallocb(int); +extern void* ucallocalign(usize size, int align, int span); +extern void ucfree(void*); +extern void ucfreeb(Block*); /* * Things called from port. */ @@ -114,7 +167,5 @@ extern void kexit(Ureg*); #define KADDR(pa) UINT2PTR(KZERO | ((uintptr)(pa) & ~KSEGM)) #define PADDR(va) PTR2UINT(PHYSDRAM | ((uintptr)(va) & ~KSEGM)) -#define DMAADDR(va) PTR2UINT(BUSDRAM | ((uintptr)(va) & ~KSEGM)) -#define DMAIO(va) PTR2UINT(BUSIO | ((uintptr)(va) & ~VIRTIO)) #define MASK(v) ((1UL << (v)) - 1) /* mask `v' bits wide */ diff --git a/sys/src/9/bcm/fpiarm.c b/sys/src/9/bcm/fpiarm.c index 716ec19f7f..9501ec4770 100644 --- a/sys/src/9/bcm/fpiarm.c +++ b/sys/src/9/bcm/fpiarm.c @@ -220,6 +220,7 @@ fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp) { void *mem; + validaddr(ea, n, 0); mem = (void*)ea; (*f)(&FR(ufp, d), mem); if(fpemudebug) @@ -232,6 +233,7 @@ fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp) Internal tmp; void *mem; + validaddr(ea, n, 1); mem = (void*)ea; tmp = FR(ufp, s); if(fpemudebug) diff --git a/sys/src/9/bcm/gisb.c b/sys/src/9/bcm/gisb.c new file mode 100644 index 0000000000..55c1375c2a --- /dev/null +++ b/sys/src/9/bcm/gisb.c @@ -0,0 +1,90 @@ +/* + * from 9front + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "ureg.h" + +/* + * GISB arbiter registers + */ +static u32int *regs = (u32int*)(VIRTIO + 0x400000); + +enum { + ArbMasterMask = 0x004/4, + ArbTimer = 0x008/4, + TimerFreq = 216000000, // 216MHz + + ArbErrCapClear = 0x7e4/4, + ArbErrCapAddrHi = 0x7e8/4, + ArbErrCapAddr = 0x7ec/4, + ArbErrCapData = 0x7f0/4, + ArbErrCapStatus = 0x7f4/4, + CapStatusTimeout = 1<<12, + CapStatusAbort = 1<<11, + CapStatusStrobe = 15<<2, + CapStatusWrite = 1<<1, + CapStatusValid = 1<<0, + ArbErrCapMaster = 0x7f8/4, + + ArbIntrSts = 0x3000/4, + ArbIntrSet = 0x3004/4, + ArbIntrClr = 0x3008/4, + + ArbCpuMaskSet = 0x3010/4, +}; + +static int +arberror(Ureg*) +{ + u32int status, intr; + u32int master, data; + uvlong addr; + + status = regs[ArbErrCapStatus]; + if((status & CapStatusValid) == 0) + return 0; + intr = regs[ArbIntrSts]; + master = regs[ArbErrCapMaster]; + addr = regs[ArbErrCapAddr]; + addr |= (uvlong)regs[ArbErrCapAddrHi]<<32; + data = regs[ArbErrCapData]; + if(intr) + regs[ArbIntrClr] = intr; + regs[ArbErrCapClear] = CapStatusValid; + + iprint("cpu%d: GISB arbiter error: %s%s %s bus addr %llux data %.8ux, " + "master %.8ux, status %.8ux, intr %.8ux\n", + m->machno, + (status & CapStatusTimeout) ? "timeout" : "", + (status & CapStatusAbort) ? "abort" : "", + (status & CapStatusWrite) ? "writing" : "reading", + addr, data, + master, status, intr); + + return 1; +} + +static void +arbclock(void) +{ + arberror(nil); +} + +void +gisblink(void) +{ + extern int (*buserror)(Ureg*); // trap.c + + regs[ArbErrCapClear] = CapStatusValid; + regs[ArbIntrClr] = -1; + + addclock0link(arbclock, 100); + + //buserror = arberror; +} diff --git a/sys/src/9/bcm/gpio.c b/sys/src/9/bcm/gpio.c new file mode 100644 index 0000000000..ee3756ac00 --- /dev/null +++ b/sys/src/9/bcm/gpio.c @@ -0,0 +1,111 @@ +/* + * Raspberry Pi GPIO support + */ + +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#define GPIOREGS (VIRTIO+0x200000) + +/* GPIO regs */ +enum { + Fsel0 = 0x00>>2, + FuncMask= 0x7, + Set0 = 0x1c>>2, + Clr0 = 0x28>>2, + Lev0 = 0x34>>2, + PUD = 0x94>>2, + Off = 0x0, + Pulldown= 0x1, + Pullup = 0x2, + PUDclk0 = 0x98>>2, + PUDclk1 = 0x9c>>2, + /* BCM2711 only */ + PUPPDN0 = 0xe4>>2, + PUPPDN1 = 0xe8>>2, + PUPPDN2 = 0xec>>2, + PUPPDN3 = 0xf0>>2, +}; + +void +gpiosel(uint pin, int func) +{ + u32int *gp, *fsel; + int off; + + gp = (u32int*)GPIOREGS; + fsel = &gp[Fsel0 + pin/10]; + off = (pin % 10) * 3; + *fsel = (*fsel & ~(FuncMask< 100 KHz assuming 150Mhz input clock */ + u32int delay; /* default (48<<16)|48 falling:rising edge */ + u32int clktimeout; /* default 64 */ +}; + +/* + * Per-controller info + */ +struct I2c { + QLock lock; + Lock reglock; + Rendez r; + Bsc *regs; +}; + +static I2c i2c; + +enum { + /* ctrl */ + I2cen = 1<<15, /* I2c enable */ + Intr = 1<<10, /* interrupt on reception */ + Intt = 1<<9, /* interrupt on transmission */ + Intd = 1<<8, /* interrupt on done */ + Start = 1<<7, /* aka ST, start a transfer */ + Clear = 1<<4, /* clear fifo */ + Read = 1<<0, /* read transfer */ + Write = 0<<0, /* write transfer */ + + /* stat */ + Clkt = 1<<9, /* clock stretch timeout */ + Err = 1<<8, /* NAK */ + Rxf = 1<<7, /* RX fifo full */ + Txe = 1<<6, /* TX fifo full */ + Rxd = 1<<5, /* RX fifo has data */ + Txd = 1<<4, /* TX fifo has space */ + Rxr = 1<<3, /* RX fiio needs reading */ + Txw = 1<<2, /* TX fifo needs writing */ + Done = 1<<1, /* transfer done */ + Ta = 1<<0, /* Transfer active */ + + /* maximum I2C I/O (can change) */ + MaxIO = 128, + MaxSA = 2, /* longest subaddress */ + Bufsize = (MaxIO+MaxSA+1+4)&~3, /* extra space for subaddress/clock bytes and alignment */ + + Chatty = 0, +}; + +static void +i2cinterrupt(Ureg*, void*) +{ + Bsc *r; + int st; + + r = i2c.regs; + st = 0; + if((r->ctrl & Intr) && (r->stat & Rxd)) + st |= Intr; + if((r->ctrl & Intt) && (r->stat & Txd)) + st |= Intt; + if(r->stat & Done) + st |= Intd; + if(st){ + r->ctrl &= ~st; + wakeup(&i2c.r); + } +} + +static int +i2cready(void *st) +{ + return (i2c.regs->stat & (uintptr)st); +} + +static void +i2cinit(void) +{ + i2c.regs = (Bsc*)I2CREGS; + i2c.regs->clkdiv = 2500; + + gpiosel(SDA0Pin, Alt0); + gpiosel(SCL0Pin, Alt0); + gpiopullup(SDA0Pin); + gpiopullup(SCL0Pin); + + intrenable(IRQi2c, i2cinterrupt, 0, 0, "i2c"); +} + +/* + * To do subaddressing avoiding a STOP condition between the address and payload. + * - write the subaddress, + * - poll until the transfer starts, + * - overwrite the registers for the payload transfer, before the subaddress + * transaction has completed. + * + * FIXME: neither 10bit adressing nor 100Khz transfers implemented yet. + */ +static void +i2cio(int rw, int tenbit, uint addr, void *buf, int len, int salen, uint subaddr) +{ + Bsc *r; + uchar *p; + int st; + + if(tenbit) + error("10bit addressing not supported"); + if(salen == 0 && subaddr) /* default subaddress len == 1byte */ + salen = 1; + + qlock(&i2c.lock); + r = i2c.regs; + r->ctrl = I2cen | Clear; + r->addr = addr; + r->stat = Clkt|Err|Done; + + if(salen){ + r->dlen = salen; + r->ctrl = I2cen | Start | Write; + while((r->stat & Ta) == 0) { + if(r->stat & (Err|Clkt)) { + qunlock(&i2c.lock); + error(Eio); + } + } + r->dlen = len; + r->ctrl = I2cen | Start | Intd | rw; + for(; salen > 0; salen--) + r->fifo = subaddr >> ((salen-1)*8); + /* + * Adapted from Linux code...uses undocumented + * status information. + */ + if(rw == Read) { + do { + if(r->stat & (Err|Clkt)) { + qunlock(&i2c.lock); + error(Eio); + } + st = r->stat >> 28; + } while(st != 0 && st != 4 && st != 5); + } + } + else { + r->dlen = len; + r->ctrl = I2cen | Start | Intd | rw; + } + + p = buf; + st = rw == Read? Rxd : Txd; + while(len > 0){ + while((r->stat & (st|Done)) == 0){ + r->ctrl |= rw == Read? Intr : Intt; + sleep(&i2c.r, i2cready, (void*)(st|Done)); + } + if(r->stat & (Err|Clkt)){ + qunlock(&i2c.lock); + error(Eio); + } + if(rw == Read){ + do{ + *p++ = r->fifo; + len--; + }while ((r->stat & Rxd) && len > 0); + }else{ + do{ + r->fifo = *p++; + len--; + }while((r->stat & Txd) && len > 0); + } + } + while((r->stat & Done) == 0) + sleep(&i2c.r, i2cready, (void*)Done); + if(r->stat & (Err|Clkt)){ + qunlock(&i2c.lock); + error(Eio); + } + r->ctrl = 0; + qunlock(&i2c.lock); +} + + +void +i2csetup(int) +{ + //print("i2csetup\n"); + i2cinit(); +} + +long +i2csend(I2Cdev *d, void *buf, long len, ulong offset) +{ + i2cio(Write, d->tenbit, d->addr, buf, len, d->salen, offset); + return len; +} + +long +i2crecv(I2Cdev *d, void *buf, long len, ulong offset) +{ + i2cio(Read, d->tenbit, d->addr, buf, len, d->salen, offset); + return len; +} diff --git a/sys/src/9/bcm/io.h b/sys/src/9/bcm/io.h index 55fb7b8858..3287f98046 100644 --- a/sys/src/9/bcm/io.h +++ b/sys/src/9/bcm/io.h @@ -8,11 +8,26 @@ enum { IRQdma0 = 16, #define IRQDMA(chan) (IRQdma0+(chan)) IRQaux = 29, + IRQi2c = 53, + IRQspi = 54, + IRQsdhost = 56, IRQmmc = 62, IRQbasic = 64, IRQtimerArm = IRQbasic + 0, + IRQpci = 84, + IRQether = 93, + + IRQlocal = 96, + IRQcntps = IRQlocal + 0, + IRQcntpns = IRQlocal + 1, + IRQmbox0 = IRQlocal + 4, + IRQmbox1 = IRQlocal + 5, + IRQmbox2 = IRQlocal + 6, + IRQmbox3 = IRQlocal + 7, + IRQlocaltmr = IRQlocal + 11, + IRQfiq = IRQusb, /* only one source can be FIQ */ DmaD2M = 0, /* device to memory */ @@ -20,7 +35,14 @@ enum { DmaM2M = 2, /* memory to memory */ DmaChanEmmc = 4, /* can only use 2-5, maybe 0 */ + DmaChanSdhost = 5, + DmaChanSpiTx= 2, + DmaChanSpiRx= 0, + + DmaDevSpiTx = 6, + DmaDevSpiRx = 7, DmaDevEmmc = 11, + DmaDevSdhost = 13, PowerSd = 0, PowerUart0, diff --git a/sys/src/9/bcm/l.s b/sys/src/9/bcm/l.s index 6c716350f4..763286371d 100644 --- a/sys/src/9/bcm/l.s +++ b/sys/src/9/bcm/l.s @@ -1,10 +1,14 @@ /* - * Broadcom bcm2835 SoC, as used in Raspberry Pi - * arm1176jzf-s processor (armv6) + * Common startup and coprocessor instructions for armv6 and armv7 + * The rest of l.s has been moved to armv[67].s */ #include "arm.s" +/* + * on bcm2836, only cpu0 starts here + * other cpus enter at cpureset in armv7.s + */ TEXT _start(SB), 1, $-4 /* * load physical base for SB addressing while mmu is off @@ -15,260 +19,145 @@ TEXT _start(SB), 1, $-4 ADD $PHYSDRAM, R12 MOVW $0, R0 - /* - * SVC mode, interrupts disabled - */ - MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 - MOVW R1, CPSR - - /* - * disable the mmu and L1 caches - * invalidate caches and tlb - */ - MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl - BIC $(CpCdcache|CpCicache|CpCpredict|CpCmmu), R1 - MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvu), CpCACHEall - MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv - ISB - - /* - * clear mach and page tables - */ - MOVW $PADDR(MACHADDR), R1 - MOVW $PADDR(KTZERO), R2 -_ramZ: - MOVW R0, (R1) - ADD $4, R1 - CMP R1, R2 - BNE _ramZ - /* * start stack at top of mach (physical addr) - * set up page tables for kernel */ MOVW $PADDR(MACHADDR+MACHSIZE-4), R13 - BL ,mmuinit(SB) /* - * set up domain access control and page table base + * do arch-dependent startup (no return) */ - MOVW $Client, R1 - MCR CpSC, 0, R1, C(CpDAC), C(0) - MOVW $PADDR(L1), R1 - MCR CpSC, 0, R1, C(CpTTB), C(0) - - /* - * enable caches, mmu, and high vectors - */ - MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl - ORR $(CpChv|CpCdcache|CpCicache|CpCmmu), R0 - MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl - ISB - - /* - * switch SB, SP, and PC into KZERO space - */ - MOVW $setR12(SB), R12 - MOVW $(MACHADDR+MACHSIZE-4), R13 - MOVW $_startpg(SB), R15 - -TEXT _startpg(SB), 1, $-4 - - /* - * enable cycle counter - */ - MOVW $1, R1 - MCR CpSC, 0, R1, C(CpSPM), C(CpSPMperf), CpSPMctl - - /* - * call main and loop forever if it returns - */ - BL ,main(SB) + BL ,armstart(SB) B ,0(PC) - BL _div(SB) /* hack to load _div, etc. */ - -TEXT fsrget(SB), 1, $-4 /* data fault status */ - MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata - RET - -TEXT ifsrget(SB), 1, $-4 /* instruction fault status */ - MRC CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst - RET - -TEXT farget(SB), 1, $-4 /* fault address */ - MRC CpSC, 0, R0, C(CpFAR), C(0x0) - RET - -TEXT lcycles(SB), 1, $-4 - MRC CpSC, 0, R0, C(CpSPM), C(CpSPMperf), CpSPMcyc - RET - -TEXT splhi(SB), 1, $-4 - MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */ - MOVW R14, 0(R2) - - MOVW CPSR, R0 /* turn off irqs (but not fiqs) */ - ORR $(PsrDirq), R0, R1 - MOVW R1, CPSR - RET - -TEXT splfhi(SB), 1, $-4 - MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */ - MOVW R14, 0(R2) - - MOVW CPSR, R0 /* turn off irqs and fiqs */ - ORR $(PsrDirq|PsrDfiq), R0, R1 - MOVW R1, CPSR - RET - -TEXT splflo(SB), 1, $-4 - MOVW CPSR, R0 /* turn on fiqs */ - BIC $(PsrDfiq), R0, R1 - MOVW R1, CPSR - RET - -TEXT spllo(SB), 1, $-4 - MOVW CPSR, R0 /* turn on irqs and fiqs */ - BIC $(PsrDirq|PsrDfiq), R0, R1 - MOVW R1, CPSR - RET - -TEXT splx(SB), 1, $-4 - MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */ - MOVW R14, 0(R2) - - MOVW R0, R1 /* reset interrupt level */ - MOVW CPSR, R0 - MOVW R1, CPSR - RET - -TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */ - RET - -TEXT islo(SB), 1, $-4 - MOVW CPSR, R0 - AND $(PsrDirq), R0 - EOR $(PsrDirq), R0 - RET - -TEXT tas(SB), $-4 -TEXT _tas(SB), $-4 - MOVW R0,R1 - MOVW $1,R0 - SWPW R0,(R1) /* fix: deprecated in armv6 */ - RET - -TEXT setlabel(SB), 1, $-4 - MOVW R13, 0(R0) /* sp */ - MOVW R14, 4(R0) /* pc */ - MOVW $0, R0 - RET - -TEXT gotolabel(SB), 1, $-4 - MOVW 0(R0), R13 /* sp */ - MOVW 4(R0), R14 /* pc */ - MOVW $1, R0 - RET - -TEXT getcallerpc(SB), 1, $-4 - MOVW 0(R13), R0 - RET - -TEXT idlehands(SB), $-4 - BARRIERS - MOVW CPSR, R3 - BIC $(PsrDirq|PsrDfiq), R3, R1 /* spllo */ - MOVW R1, CPSR - - MOVW $0, R0 /* wait for interrupt */ - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait - ISB - - MOVW R3, CPSR /* splx */ - RET - - -TEXT coherence(SB), $-4 - BARRIERS RET /* - * invalidate tlb + * coprocessor instructions for local timer (armv7) */ -TEXT mmuinvalidate(SB), 1, $-4 - MOVW $0, R0 - MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv - BARRIERS +TEXT cprdfeat1(SB), 1, $-4 + MRC CpSC, 0, R0, C(CpID), C(CpIDfeat), 1 RET - -/* - * mmuinvalidateaddr(va) - * invalidate tlb entry for virtual page address va, ASID 0 - */ -TEXT mmuinvalidateaddr(SB), 1, $-4 - MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse - BARRIERS - RET - -/* - * drain write buffer - * writeback and invalidate data cache - */ -TEXT cachedwbinv(SB), 1, $-4 - DSB - MOVW $0, R0 - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall +TEXT cpwrtimerphysctl(SB), 1, $-4 + MCR CpSC, 0, R0, C(CpTIMER), C(CpTIMERphys), CpTIMERphysctl RET - -/* - * cachedwbinvse(va, n) - * drain write buffer - * writeback and invalidate data cache range [va, va+n) - */ -TEXT cachedwbinvse(SB), 1, $-4 - MOVW R0, R1 /* DSB clears R0 */ - DSB - MOVW n+4(FP), R2 - ADD R1, R2 - SUB $1, R2 - BIC $(CACHELINESZ-1), R1 - BIC $(CACHELINESZ-1), R2 - MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwbi) +TEXT cpwrtimerphysval(SB), 1, $-4 + MCR CpSC, 0, R0, C(CpTIMER), C(CpTIMERphys), CpTIMERphysval RET /* - * cachedwbse(va, n) - * drain write buffer - * writeback data cache range [va, va+n) + * coprocessor instructions for vfp3 */ -TEXT cachedwbse(SB), 1, $-4 - MOVW R0, R1 /* DSB clears R0 */ - DSB - MOVW n+4(FP), R2 - ADD R1, R2 - BIC $(CACHELINESZ-1), R1 - BIC $(CACHELINESZ-1), R2 - MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwb) - RET -/* - * drain write buffer and prefetch buffer - * writeback and invalidate data cache - * invalidate instruction cache - */ -TEXT cacheuwbinv(SB), 1, $-4 +#define VSTR(fpreg,Rn,off) \ + WORD $(0xed800000 | (fpreg&15)<<12 | ((fpreg&16)<<(22-4)) | Rn<<16 | CpDFP<<8 | (off)) +#define VLDR(fpreg,Rn,off) \ + WORD $(0xed900000 | (fpreg&15)<<12 | ((fpreg&16)<<(22-4)) | Rn<<16 | CpDFP<<8 | (off)) +#define VMSR(fpctlreg,Rt) WORD $(0xeee00010 | fpctlreg<<16 | Rt<<12 | CpFP<<8) +#define VMRS(Rt,fpctlreg) WORD $(0xeef00010 | fpctlreg<<16 | Rt<<12 | CpFP<<8) +#define Fpsid 0 +#define Fpscr 1 +#define Fpexc 8 + +TEXT cprdcpaccess(SB), 1, $-4 + MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpCPaccess + RET +TEXT cpwrcpaccess(SB), 1, $-4 + MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpCPaccess BARRIERS - MOVW $0, R0 - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall RET - -/* - * invalidate instruction cache - */ -TEXT cacheiinv(SB), 1, $-4 - MOVW $0, R0 - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall +TEXT fprdsid(SB), 1, $-4 + VMRS(0,Fpsid) + RET +TEXT fprdscr(SB), 1, $-4 + VMRS(0,Fpscr) + RET +TEXT fprdexc(SB), 1, $-4 + VMRS(0,Fpexc) + RET +TEXT fpwrscr(SB), 1, $-4 + VMSR(Fpscr,0) + RET +TEXT fpwrexc(SB), 1, $-4 + VMSR(Fpexc,0) + RET + +TEXT fpsaveregs(SB), 1, $-4 + MOVW R0, R1 /* dest */ + MOVW 4(FP), R2 /* reg count */ + VSTR(0, 1, 0*2) + VSTR(1, 1, 1*2) + VSTR(2, 1, 2*2) + VSTR(3, 1, 3*2) + VSTR(4, 1, 4*2) + VSTR(5, 1, 5*2) + VSTR(6, 1, 6*2) + VSTR(7, 1, 7*2) + VSTR(8, 1, 8*2) + VSTR(9, 1, 9*2) + VSTR(10, 1, 10*2) + VSTR(11, 1, 11*2) + VSTR(12, 1, 12*2) + VSTR(13, 1, 13*2) + VSTR(14, 1, 14*2) + VSTR(15, 1, 15*2) + CMP $16, R2 + BEQ fpsavex + VSTR(16, 1, 16*2) + VSTR(17, 1, 17*2) + VSTR(18, 1, 18*2) + VSTR(19, 1, 19*2) + VSTR(20, 1, 20*2) + VSTR(21, 1, 21*2) + VSTR(22, 1, 22*2) + VSTR(23, 1, 23*2) + VSTR(24, 1, 24*2) + VSTR(25, 1, 25*2) + VSTR(26, 1, 26*2) + VSTR(27, 1, 27*2) + VSTR(28, 1, 28*2) + VSTR(29, 1, 29*2) + VSTR(30, 1, 30*2) + VSTR(31, 1, 31*2) +fpsavex: + RET + +TEXT fprestregs(SB), 1, $-4 + MOVW R0, R1 /* src */ + MOVW 4(FP), R2 /* reg count */ + VLDR(0, 1, 0*2) + VLDR(1, 1, 1*2) + VLDR(2, 1, 2*2) + VLDR(3, 1, 3*2) + VLDR(4, 1, 4*2) + VLDR(5, 1, 5*2) + VLDR(6, 1, 6*2) + VLDR(7, 1, 7*2) + VLDR(8, 1, 8*2) + VLDR(9, 1, 9*2) + VLDR(10, 1, 10*2) + VLDR(11, 1, 11*2) + VLDR(12, 1, 12*2) + VLDR(13, 1, 13*2) + VLDR(14, 1, 14*2) + VLDR(15, 1, 15*2) + CMP $16, R2 + BEQ fprestx + VLDR(16, 1, 16*2) + VLDR(17, 1, 17*2) + VLDR(18, 1, 18*2) + VLDR(19, 1, 19*2) + VLDR(20, 1, 20*2) + VLDR(21, 1, 21*2) + VLDR(22, 1, 22*2) + VLDR(23, 1, 23*2) + VLDR(24, 1, 24*2) + VLDR(25, 1, 25*2) + VLDR(26, 1, 26*2) + VLDR(27, 1, 27*2) + VLDR(28, 1, 28*2) + VLDR(29, 1, 29*2) + VLDR(30, 1, 30*2) + VLDR(31, 1, 31*2) +fprestx: RET diff --git a/sys/src/9/bcm/lexception.s b/sys/src/9/bcm/lexception.s index d9653ecd73..bb1693d7be 100644 --- a/sys/src/9/bcm/lexception.s +++ b/sys/src/9/bcm/lexception.s @@ -27,6 +27,7 @@ TEXT vtable(SB), 1, $-4 WORD $_vfiq(SB) /* FIQ, switch to svc mode */ TEXT _vsvc(SB), 1, $-4 /* SWI */ + CLREX MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */ MOVW SPSR, R14 /* ureg->psr = SPSR */ MOVW.W R14, -4(R13) /* ... */ @@ -39,9 +40,16 @@ TEXT _vsvc(SB), 1, $-4 /* SWI */ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ -// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ - MOVW $(MACHADDR), R10 /* m */ - MOVW 8(R10), R9 /* up */ + /* get R(MACH) for this cpu */ + CPUID(R1) + SLL $2, R1 /* convert to word index */ + MOVW $machaddr(SB), R2 + ADD R1, R2 + MOVW (R2), R(MACH) /* m = machaddr[cpuid] */ + CMP $0, R(MACH) + MOVW.EQ $MACHADDR, R0 /* paranoia: use MACHADDR if 0 */ + + MOVW 8(R(MACH)), R(USER) /* up */ MOVW R13, R0 /* first arg is pointer to ureg */ SUB $8, R13 /* space for argument+link */ @@ -81,6 +89,7 @@ TEXT _virq(SB), 1, $-4 /* IRQ */ * we'll switch to SVC mode and then call trap. */ _vswitch: + CLREX MOVW SPSR, R1 /* save SPSR for ureg */ MOVW R14, R2 /* save interrupted pc for ureg */ MOVW R13, R3 /* save pointer to where the original [R0-R4] are */ @@ -119,7 +128,16 @@ _vswitch: BL trap(SB) + MOVW $setR12(SB), R12 /* reload kernel's SB (ORLY?) */ ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */ + /* + * if we interrupted a previous trap's handler and are now + * returning to it, we need to propagate the current R(MACH) (R10) + * by overriding the saved one on the stack, since we may have + * been rescheduled and be on a different processor now than + * at entry. + */ + MOVW R(MACH), (-(15-MACH)*4)(R13) /* restore current cpu's MACH */ MOVW 8(R13), R14 /* restore link */ MOVW 4(R13), R0 /* restore SPSR */ MOVW R0, SPSR /* ... */ @@ -140,9 +158,16 @@ _userexcep: MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ -// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ - MOVW $(MACHADDR), R10 /* m */ - MOVW 8(R10), R9 /* up */ + /* get R(MACH) for this cpu */ + CPUID(R1) + SLL $2, R1 /* convert to word index */ + MOVW $machaddr(SB), R2 + ADD R1, R2 + MOVW (R2), R(MACH) /* m = machaddr[cpuid] */ + CMP $0, R(MACH) + MOVW.EQ $MACHADDR, R(MACH) /* paranoia: use MACHADDR if 0 */ + + MOVW 8(R(MACH)), R(USER) /* up */ MOVW R13, R0 /* first arg is pointer to ureg */ SUB $(4*2), R13 /* space for argument+link (for debugger) */ @@ -158,14 +183,24 @@ _userexcep: RFE /* MOVM.IA.S.W (R13), [R15] */ TEXT _vfiq(SB), 1, $-4 /* FIQ */ + CLREX MOVW $PsrMfiq, R8 /* trap type */ MOVW SPSR, R9 /* interrupted psr */ MOVW R14, R10 /* interrupted pc */ MOVM.DB.W [R8-R10], (R13) /* save in ureg */ - MOVM.DB.W.S [R0-R14], (R13) /* save interrupted regs */ + MOVM.DB.S [R0-R14], (R13) /* save interrupted regs */ + SUB $(15*4), R13 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ - MOVW $(MACHADDR), R10 /* m */ - MOVW 8(R10), R9 /* up */ + /* get R(MACH) for this cpu */ + CPUID(R1) + SLL $2, R1 /* convert to word index */ + MOVW $machaddr(SB), R2 + ADD R1, R2 + MOVW (R2), R(MACH) /* m = machaddr[cpuid] */ + CMP $0, R(MACH) + MOVW.EQ $MACHADDR, R(MACH) /* paranoia: use MACHADDR if 0 */ + + MOVW 8(R(MACH)), R(USER) /* up */ MOVW R13, R0 /* first arg is pointer to ureg */ SUB $(4*2), R13 /* space for argument+link (for debugger) */ @@ -187,6 +222,7 @@ TEXT setr13(SB), 1, $-4 MOVW CPSR, R2 BIC $PsrMask, R2, R3 + ORR $(PsrDirq|PsrDfiq), R3 ORR R0, R3 MOVW R3, CPSR /* switch to new mode */ diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c index 69e9a37a28..28e4d74ed5 100644 --- a/sys/src/9/bcm/main.c +++ b/sys/src/9/bcm/main.c @@ -3,6 +3,7 @@ #include "../port/lib.h" #include "mem.h" #include "dat.h" +#include "io.h" #include "fns.h" #include "init.h" @@ -193,23 +194,92 @@ ataginit(Atag *a) } } +/* enable scheduling of this cpu */ +void +machon(uint cpu) +{ + ulong cpubit; + + cpubit = 1 << cpu; + lock(&active); + if ((active.machs & cpubit) == 0) { /* currently off? */ + conf.nmach++; + active.machs |= cpubit; + } + unlock(&active); +} + +/* disable scheduling of this cpu */ +void +machoff(uint cpu) +{ + ulong cpubit; + + cpubit = 1 << cpu; + lock(&active); + if (active.machs & cpubit) { /* currently on? */ + conf.nmach--; + active.machs &= ~cpubit; + } + unlock(&active); +} + void machinit(void) { - m->machno = 0; - machaddr[m->machno] = m; + Mach *m0; m->ticks = 1; m->perf.period = 1; + m0 = MACHP(0); + if (m->machno != 0) { + /* synchronise with cpu 0 */ + m->ticks = m0->ticks; + } +} - conf.nmach = 1; +void +mach0init(void) +{ + conf.nmach = 0; - active.machs = 1; + m->machno = 0; + machaddr[m->machno] = m; + + machinit(); active.exiting = 0; up = nil; } +void +launchinit(int ncpus) +{ + int mach; + Mach *mm; + PTE *l1; + + if(ncpus > MAXMACH) + ncpus = MAXMACH; + for(mach = 1; mach < ncpus; mach++){ + machaddr[mach] = mm = mallocalign(MACHSIZE, MACHSIZE, 0, 0); + l1 = mallocalign(L1SIZE, L1SIZE, 0, 0); + if(mm == nil || l1 == nil) + panic("launchinit"); + memset(mm, 0, MACHSIZE); + mm->machno = mach; + + memmove(l1, m->mmul1, L1SIZE); /* clone cpu0's l1 table */ + cachedwbse(l1, L1SIZE); + mm->mmul1 = l1; + cachedwbse(mm, MACHSIZE); + + } + cachedwbse(machaddr, sizeof machaddr); + if((mach = startcpus(ncpus)) < ncpus) + print("only %d cpu%s started\n", mach, mach == 1? "" : "s"); +} + static void optionsinit(char* s) { @@ -224,13 +294,13 @@ void main(void) { extern char edata[], end[]; - uint rev; + uint fw, board; - okay(1); m = (Mach*)MACHADDR; memset(edata, 0, end - edata); /* clear bss */ - machinit(); - mmuinit1(); + mach0init(); + m->mmul1 = (PTE*)L1; + machon(0); optionsinit("/boot/boot boot"); quotefmtinstall(); @@ -242,14 +312,17 @@ main(void) screeninit(); print("\nPlan 9 from Bell Labs\n"); - rev = getfirmware(); - print("firmware: rev %d\n", rev); - if(rev < Minfirmrev){ + board = getboardrev(); + fw = getfirmware(); + print("board rev: %#ux firmware rev: %d\n", board, fw); + if(fw < Minfirmrev){ print("Sorry, firmware (start*.elf) must be at least rev %d" " or newer than %s\n", Minfirmrev, Minfirmdate); for(;;) ; } + /* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */ + setclkrate(ClkArm, 0); trapinit(); clockinit(); printinit(); @@ -257,7 +330,10 @@ main(void) if(conf.monitor) swcursorinit(); cpuidprint(); + print("clocks: CPU %lud core %lud UART %lud EMMC %lud\n", + getclkrate(ClkArm), getclkrate(ClkCore), getclkrate(ClkUart), getclkrate(ClkEmmc)); archreset(); + vgpinit(); procinit0(); initseg(); @@ -266,6 +342,9 @@ main(void) pageinit(); swapinit(); userinit(); + launchinit(getncpus()); + mmuinit1(); + schedinit(); assert(0); /* shouldn't have returned */ } @@ -277,6 +356,7 @@ void init0(void) { int i; + Chan *c; char buf[2*KNAMELEN]; up->nerrlab = 0; @@ -310,6 +390,14 @@ init0(void) ksetenv(confname[i], confval[i], 0); ksetenv(confname[i], confval[i], 1); } + if(getconf("pitft")){ + c = namec("#P/pitft", Aopen, OWRITE, 0); + if(!waserror()){ + devtab[c->type]->write(c, "init", 4, 0); + poperror(); + } + cclose(c); + } poperror(); } kproc("alarm", alarmkproc, 0); @@ -418,7 +506,7 @@ userinit(void) void confinit(void) { - int i; + int i, userpcnt; ulong kpages; uintptr pa; char *p; @@ -439,8 +527,40 @@ confinit(void) if(conf.mem[0].limit == 0){ conf.mem[0].base = PHYSDRAM; conf.mem[0].limit = PHYSDRAM + memsize; - }else if(p != nil) - conf.mem[0].limit = conf.mem[0].base + memsize; + } + /* + * pi4 extra memory (beyond video ram) indicated by board id + */ + switch(getboardrev()&0xF00000){ + case 0xA00000: + break; + case 0xB00000: + conf.mem[1].base = 1*GiB; + conf.mem[1].limit = 2*GiB; + break; + case 0xC00000: + conf.mem[1].base = 1*GiB; + conf.mem[1].limit = 0xFFF00000; + break; + case 0xD00000: + conf.mem[1].base = 1*GiB; + conf.mem[1].limit = 0xFFF00000; + break; + } + if(conf.mem[1].limit > soc.dramsize) + conf.mem[1].limit = soc.dramsize; + if(p != nil){ + if(memsize < conf.mem[0].limit){ + conf.mem[0].limit = memsize; + conf.mem[1].limit = 0; + }else if(memsize >= conf.mem[1].base && memsize < conf.mem[1].limit) + conf.mem[1].limit = memsize; + } + + if(p = getconf("*kernelpercent")) + userpcnt = 100 - strtol(p, 0, 0); + else + userpcnt = 0; conf.npage = 0; pa = PADDR(PGROUND(PTR2UINT(end))); @@ -458,12 +578,13 @@ confinit(void) conf.npage += conf.mem[i].npage; } - conf.upages = (conf.npage*80)/100; + if(userpcnt < 10 || userpcnt > 99) + userpcnt = 90; + conf.upages = (conf.npage*userpcnt)/100; + if(conf.npage - conf.upages > 256*MiB/BY2PG) + conf.upages = conf.npage - 256*MiB/BY2PG; conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; - /* only one processor */ - conf.nmach = 1; - /* set up other configuration parameters */ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; if(cpuserver) @@ -474,7 +595,7 @@ confinit(void) conf.nswppo = 4096; conf.nimage = 200; - conf.copymode = 0; /* copy on write */ + conf.copymode = 1; /* copy on reference, not copy on write */ /* * Guess how much is taken by the large permanent @@ -514,15 +635,29 @@ shutdown(int ispanic) active.exiting = 1; unlock(&active); - if(once) + if(once) { + delay(m->machno*100); /* stagger them */ iprint("cpu%d: exiting\n", m->machno); + } spllo(); - for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){ + if (m->machno == 0) + ms = 5*1000; + else + ms = 2*1000; + for(; ms > 0; ms -= TK2MS(2)){ delay(TK2MS(2)); if(active.machs == 0 && consactive() == 0) break; } - delay(1000); + if(active.ispanic){ + if(!cpuserver) + for(;;) + ; + if(getconf("*debug")) + delay(5*60*1000); + else + delay(10000); + } } /* @@ -531,9 +666,21 @@ shutdown(int ispanic) void exit(int code) { + void (*f)(ulong, ulong, ulong); + shutdown(code); splfhi(); - archreboot(); + if(m->machno == 0) + archreboot(); + else{ + f = (void*)REBOOTADDR; + intrcpushutdown(); + memmove(f, rebootcode, sizeof(rebootcode)); + cachedwbse(f, sizeof(rebootcode)); + cacheiinvse(f, sizeof(rebootcode)); + (*f)(0, soc.armlocal, 0); + for(;;){} + } } /* @@ -542,9 +689,23 @@ exit(int code) int isaconfig(char *class, int ctlrno, ISAConf *isa) { - USED(ctlrno); - USED(isa); - return strcmp(class, "ether") == 0; + char cc[32], *p; + int i; + + if(strcmp(class, "ether") != 0) + return 0; + snprint(cc, sizeof cc, "%s%d", class, ctlrno); + p = getconf(cc); + if(p == nil) + return (ctlrno == 0); + isa->type = ""; + isa->nopt = tokenize(p, isa->opt, NISAOPT); + for(i = 0; i < isa->nopt; i++){ + p = isa->opt[i]; + if(cistrncmp(p, "type=", 5) == 0) + isa->type = p + 5; + } + return 1; } /* @@ -556,14 +717,31 @@ reboot(void *entry, void *code, ulong size) { void (*f)(ulong, ulong, ulong); - print("starting reboot..."); writeconf(); + + /* + * the boot processor is cpu0. execute this function on it + * so that the new kernel has the same cpu0. + */ + if (m->machno != 0) { + procwired(up, 0); + sched(); + } + if (m->machno != 0) + print("on cpu%d (not 0)!\n", m->machno); + + /* setup reboot trampoline function */ + f = (void*)REBOOTADDR; + memmove(f, rebootcode, sizeof(rebootcode)); + cachedwbse(f, sizeof(rebootcode)); + shutdown(0); /* * should be the only processor running now */ + delay(500); print("reboot entry %#lux code %#lux size %ld\n", PADDR(entry), PADDR(code), size); delay(100); @@ -574,29 +752,23 @@ reboot(void *entry, void *code, ulong size) screenputs = nil; /* shutdown devices */ - chandevshutdown(); + if(!waserror()){ + chandevshutdown(); + poperror(); + } /* stop the clock (and watchdog if any) */ clockshutdown(); splfhi(); - intrsoff(); - - /* setup reboot trampoline function */ - f = (void*)REBOOTADDR; - memmove(f, rebootcode, sizeof(rebootcode)); - cacheuwbinv(); + intrshutdown(); /* off we go - never to return */ + cacheuwbinv(); + l2cacheuwbinv(); (*f)(PADDR(entry), PADDR(code), size); iprint("loaded kernel returned!\n"); delay(1000); archreboot(); } - -int -cmpswap(long *addr, long old, long new) -{ - return cas32(addr, old, new); -} diff --git a/sys/src/9/bcm/mem.h b/sys/src/9/bcm/mem.h index eb83641595..96391c071d 100644 --- a/sys/src/9/bcm/mem.h +++ b/sys/src/9/bcm/mem.h @@ -11,12 +11,20 @@ #define BY2PG (4*KiB) /* bytes per page */ #define PGSHIFT 12 /* log(BY2PG) */ -#define MAXMACH 1 /* max # cpus system can run */ +#define MAXMACH 4 /* max # cpus system can run */ #define MACHSIZE BY2PG +#define L1SIZE (4 * BY2PG) #define KSTKSIZE (8*KiB) #define STACKALIGN(sp) ((sp) & ~3) /* bug: assure with alloc */ +/* + * Magic registers + */ + +#define USER 9 /* R9 is up-> */ +#define MACH 10 /* R10 is m-> */ + /* * Address spaces. * KTZERO is used by kprof and dumpstack (if any). @@ -28,8 +36,8 @@ */ #define KSEG0 0x80000000 /* kernel segment */ -/* mask to check segment; good for 512MB dram */ -#define KSEGM 0xE0000000 +/* mask to check segment; good for 2GB dram */ +#define KSEGM 0x80000000 #define KZERO KSEG0 /* kernel address space */ #define CONFADDR (KZERO+0x100) /* unparsed plan9.ini */ #define MACHADDR (KZERO+0x2000) /* Mach structure */ @@ -38,24 +46,28 @@ #define FIQSTKTOP (KZERO+0x4000) /* FIQ stack */ #define L1 (KZERO+0x4000) /* tt ptes: 16KiB aligned */ #define KTZERO (KZERO+0x8000) /* kernel text start */ -#define VIRTIO 0x7E000000 /* i/o registers */ -#define FRAMEBUFFER 0xA0000000 /* video framebuffer */ +#define VIRTPCI 0xFD000000 /* pcie address space (pi4 only) */ +#define VIRTIO 0xFE000000 /* i/o registers */ +#define IOSIZE (10*MiB) +#define ARMLOCAL (VIRTIO+IOSIZE) /* armv7 only */ +#define VGPIO (ARMLOCAL+MiB) /* virtual gpio for pi3 ACT LED */ +#define FRAMEBUFFER (VGPIO+MiB) /* video framebuffer */ #define UZERO 0 /* user segment */ #define UTZERO (UZERO+BY2PG) /* user text start */ #define UTROUND(t) ROUNDUP((t), BY2PG) -#define USTKTOP 0x20000000 /* user segment end +1 */ +#define USTKTOP 0x40000000 /* user segment end +1 */ #define USTKSIZE (8*1024*1024) /* user stack size */ #define TSTKTOP (USTKTOP-USTKSIZE) /* sysexec temporary stack */ #define TSTKSIZ 256 /* address at which to copy and execute rebootcode */ -#define REBOOTADDR (KZERO+0x3400) +#define REBOOTADDR (KZERO+0x1800) /* * Legacy... */ -#define BLOCKALIGN 32 /* only used in allocb.c */ +#define BLOCKALIGN 64 /* only used in allocb.c */ #define KSTACK KSTKSIZE /* @@ -66,7 +78,6 @@ #define BY2WD 4 #define BY2V 8 /* only used in xalloc.c */ -#define CACHELINESZ 32 #define PTEMAPMEM (1024*1024) #define PTEPERTAB (PTEMAPMEM/BY2PG) #define SEGMAPSIZE 1984 @@ -88,8 +99,3 @@ * BUS addresses as seen from the videocore gpu. */ #define PHYSDRAM 0 -#define BUSDRAM 0x40000000 -#define DRAMSIZE (512*MiB) -#define PHYSIO 0x20000000 -#define BUSIO 0x7E000000 -#define IOSIZE (16*MiB) diff --git a/sys/src/9/bcm/mkfile b/sys/src/9/bcm/mkfile index a49c26c983..f155a051fc 100644 --- a/sys/src/9/bcm/mkfile +++ b/sys/src/9/bcm/mkfile @@ -1,5 +1,5 @@ -CONF=pi -CONFLIST=pi picpu pifat +CONF=pi2 +CONFLIST=pi picpu pifat pi2 pi2cpu pi4 pi4cpu piwifi pi2wifi pi4wifi EXTRACOPIES= loadaddr=0x80008000 @@ -8,7 +8,7 @@ objtype=arm soc.dramsize) + pe = soc.dramsize; + for(pa = PHYSDRAM; pa < PHYSDRAM+pe; pa += MiB){ + l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1ptedramattrs; va += MiB; } /* * identity map first MB of ram so mmu can be enabled */ - l1[L1X(PHYSDRAM)] = PHYSDRAM|Dom0|L1AP(Krw)|Section|Cached|Buffered; + l1[L1X(PHYSDRAM)] = PHYSDRAM|Dom0|L1AP(Krw)|Section|L1ptedramattrs; /* * map i/o registers */ va = VIRTIO; - for(pa = PHYSIO; pa < PHYSIO+IOSIZE; pa += MiB){ - l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section; + for(pa = soc.physio; pa < soc.physio+IOSIZE; pa += MiB){ + l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; va += MiB; } - + pa = soc.armlocal; + if(pa) + l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; /* - * double map exception vectors at top of virtual memory + * pi4 hack: ether and pcie are in segment 0xFD5xxxxx not 0xFE5xxxxx + * gisb is in segment 0xFC4xxxxx not FE4xxxxx + */ + va = VIRTIO + 0x500000; + pa = soc.physio - 0x1000000 + 0x500000; + l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; + va = VIRTIO + 0x400000; + pa = soc.physio - 0x2000000 + 0x400000; + l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; + + /* + * double map exception vectors near top of virtual memory */ va = HVECTORS; l1[L1X(va)] = (uintptr)l2|Dom0|Coarse; - l2[L2X(va)] = PHYSDRAM|L2AP(Krw)|Small; + l2[L2X(va)] = PHYSDRAM|L2AP(Krw)|Small|L2ptedramattrs; } void -mmuinit1(void) +mmuinit1() { - PTE *l1; + PTE *l1, *l2; + uintptr va; - l1 = (PTE*)L1; - m->mmul1 = l1; + l1 = m->mmul1; /* * undo identity map of first MB of ram */ l1[L1X(PHYSDRAM)] = 0; - cachedwbse(&l1[L1X(PHYSDRAM)], sizeof(PTE)); - mmuinvalidate(); + cachedwbtlb(&l1[L1X(PHYSDRAM)], sizeof(PTE)); + mmuinvalidateaddr(PHYSDRAM); + + /* + * make a local mapping for highest MB of virtual space + * containing kmap area and exception vectors + */ + if(m->machno == 0) + m->kmapl2 = (PTE*)L2; + else{ + va = HVECTORS; + m->kmapl2 = l2 = mallocalign(L2size, L2size, 0, 0); + l1[L1X(va)] = PADDR(l2)|Dom0|Coarse; + l2[L2X(va)] = PHYSDRAM|L2AP(Krw)|Small|L2ptedramattrs; + cachedwbtlb(&l1[L1X(va)], sizeof(PTE)); + mmuinvalidateaddr(va); + } } static void @@ -75,15 +116,20 @@ mmul2empty(Proc* proc, int clear) { PTE *l1; Page **l2, *page; + KMap *k; l1 = m->mmul1; l2 = &proc->mmul2; for(page = *l2; page != nil; page = page->next){ - if(clear) - memset(UINT2PTR(page->va), 0, BY2PG); + if(clear){ + k = kmap(page); + memset((void*)VA(k), 0, L2size); + kunmap(k); + } l1[page->daddr] = Fault; l2 = &page->next; } + coherence(); *l2 = proc->mmul2cache; proc->mmul2cache = proc->mmul2; proc->mmul2 = nil; @@ -92,29 +138,26 @@ mmul2empty(Proc* proc, int clear) static void mmul1empty(void) { -#ifdef notdef -/* there's a bug in here */ PTE *l1; /* clean out any user mappings still in l1 */ - if(m->mmul1lo > L1lo){ + if(m->mmul1lo > 0){ if(m->mmul1lo == 1) m->mmul1[L1lo] = Fault; else memset(&m->mmul1[L1lo], 0, m->mmul1lo*sizeof(PTE)); - m->mmul1lo = L1lo; + m->mmul1lo = 0; } - if(m->mmul1hi < L1hi){ - l1 = &m->mmul1[m->mmul1hi]; - if((L1hi - m->mmul1hi) == 1) + if(m->mmul1hi > 0){ + l1 = &m->mmul1[L1hi - m->mmul1hi]; + if(m->mmul1hi == 1) *l1 = Fault; else - memset(l1, 0, (L1hi - m->mmul1hi)*sizeof(PTE)); - m->mmul1hi = L1hi; + memset(l1, 0, m->mmul1hi*sizeof(PTE)); + m->mmul1hi = 0; } -#else - memset(&m->mmul1[L1lo], 0, (L1hi - L1lo)*sizeof(PTE)); -#endif /* notdef */ + if(m->kmapl2 != nil) + memset(m->kmapl2, 0, NKMAPS*sizeof(PTE)); } void @@ -124,15 +167,7 @@ mmuswitch(Proc* proc) PTE *l1; Page *page; - /* do kprocs get here and if so, do they need to? */ - if(m->mmupid == proc->pid && !proc->newtlb) - return; - m->mmupid = proc->pid; - - /* write back dirty and invalidate l1 caches */ - cacheuwbinv(); - - if(proc->newtlb){ + if(proc != nil && proc->newtlb){ mmul2empty(proc, 1); proc->newtlb = 0; } @@ -141,19 +176,26 @@ mmuswitch(Proc* proc) /* move in new map */ l1 = m->mmul1; - for(page = proc->mmul2; page != nil; page = page->next){ + if(proc != nil){ + for(page = proc->mmul2; page != nil; page = page->next){ x = page->daddr; l1[x] = PPN(page->pa)|Dom0|Coarse; - /* know here that L1lo < x < L1hi */ - if(x+1 - m->mmul1lo < m->mmul1hi - x) - m->mmul1lo = x+1; - else - m->mmul1hi = x; + if(x >= L1lo + m->mmul1lo && x < L1hi - m->mmul1hi){ + if(x+1 - L1lo < L1hi - x) + m->mmul1lo = x+1 - L1lo; + else + m->mmul1hi = L1hi - x; + } + } + if(proc->nkmap) + memmove(m->kmapl2, proc->kmaptab, sizeof(proc->kmaptab)); } /* make sure map is in memory */ /* could be smarter about how much? */ - cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); + cachedwbtlb(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); + if(proc != nil && proc->nkmap) + cachedwbtlb(m->kmapl2, sizeof(proc->kmaptab)); /* lose any possible stale tlb entries */ mmuinvalidate(); @@ -175,9 +217,6 @@ mmurelease(Proc* proc) { Page *page, *next; - /* write back dirty and invalidate l1 caches */ - cacheuwbinv(); - mmul2empty(proc, 0); for(page = proc->mmul2cache; page != nil; page = next){ next = page->next; @@ -193,7 +232,7 @@ mmurelease(Proc* proc) /* make sure map is in memory */ /* could be smarter about how much? */ - cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); + cachedwbtlb(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); /* lose any possible stale tlb entries */ mmuinvalidate(); @@ -202,42 +241,52 @@ mmurelease(Proc* proc) void putmmu(uintptr va, uintptr pa, Page* page) { - int x; + int x, s; Page *pg; PTE *l1, *pte; + KMap *k; + /* + * disable interrupts to prevent flushmmu (called from hzclock) + * from clearing page tables while we are setting them + */ + s = splhi(); x = L1X(va); l1 = &m->mmul1[x]; if(*l1 == Fault){ - /* wasteful - l2 pages only have 256 entries - fix */ + /* l2 pages only have 256 entries - wastes 3K per 1M of address space */ if(up->mmul2cache == nil){ - /* auxpg since we don't need much? memset if so */ - pg = newpage(1, 0, 0); - pg->va = VA(kmap(pg)); - } - else{ + spllo(); + pg = newpage(0, 0, 0); + splhi(); + /* if newpage slept, we might be on a different cpu */ + l1 = &m->mmul1[x]; + }else{ pg = up->mmul2cache; up->mmul2cache = pg->next; - memset(UINT2PTR(pg->va), 0, BY2PG); } pg->daddr = x; pg->next = up->mmul2; up->mmul2 = pg; /* force l2 page to memory */ - cachedwbse((void *)pg->va, BY2PG); + k = kmap(pg); + memset((void*)VA(k), 0, L2size); + cachedwbtlb((void*)VA(k), L2size); + kunmap(k); *l1 = PPN(pg->pa)|Dom0|Coarse; - cachedwbse(l1, sizeof *l1); + cachedwbtlb(l1, sizeof *l1); - if(x >= m->mmul1lo && x < m->mmul1hi){ - if(x+1 - m->mmul1lo < m->mmul1hi - x) - m->mmul1lo = x+1; + if(x >= L1lo + m->mmul1lo && x < L1hi - m->mmul1hi){ + if(x+1 - L1lo < L1hi - x) + m->mmul1lo = x+1 - L1lo; else - m->mmul1hi = x; + m->mmul1hi = L1hi - x; } } - pte = UINT2PTR(KADDR(PPN(*l1))); + k = kmapp(PPN(*l1)); + pte = (PTE*)VA(k); /* protection bits are * PTERONLY|PTEVALID; @@ -246,30 +295,53 @@ putmmu(uintptr va, uintptr pa, Page* page) */ x = Small; if(!(pa & PTEUNCACHED)) - x |= Cached|Buffered; + x |= L2ptedramattrs; if(pa & PTEWRITE) x |= L2AP(Urw); else x |= L2AP(Uro); pte[L2X(va)] = PPN(pa)|x; - cachedwbse(&pte[L2X(va)], sizeof pte[0]); + cachedwbtlb(&pte[L2X(va)], sizeof(PTE)); + kunmap(k); /* clear out the current entry */ mmuinvalidateaddr(PPN(va)); - /* write back dirty entries - we need this because the pio() in - * fault.c is writing via a different virt addr and won't clean - * its changes out of the dcache. Page coloring doesn't work - * on this mmu because the virtual cache is set associative - * rather than direct mapped. - */ - cachedwbinv(); - if(page->cachectl[0] == PG_TXTFLUSH){ + if(page->cachectl[m->machno] == PG_TXTFLUSH){ /* pio() sets PG_TXTFLUSH whenever a text pg has been written */ - cacheiinv(); - page->cachectl[0] = PG_NOFLUSH; + if(cankaddr(page->pa)) + cachedwbse((void*)(page->pa|KZERO), BY2PG); + cacheiinvse((void*)page->va, BY2PG); + page->cachectl[m->machno] = PG_NOFLUSH; } - checkmmu(va, PPN(pa)); + //checkmmu(va, PPN(pa)); + splx(s); +} + +void* +mmuuncache(void* v, usize size) +{ + int x; + PTE *pte; + uintptr va; + + /* + * Simple helper for ucalloc(). + * Uncache a Section, must already be + * valid in the MMU. + */ + va = PTR2UINT(v); + assert(!(va & (1*MiB-1)) && size == 1*MiB); + + x = L1X(va); + pte = &m->mmul1[x]; + if((*pte & (Fine|Section|Coarse)) != Section) + return nil; + *pte &= ~L1ptedramattrs; + mmuinvalidateaddr(va); + cachedwbinvse(pte, 4); + + return v; } /* @@ -279,8 +351,8 @@ putmmu(uintptr va, uintptr pa, Page* page) uintptr cankaddr(uintptr pa) { - if(pa < PHYSDRAM + memsize) /* assumes PHYSDRAM is 0 */ - return PHYSDRAM + memsize - pa; + if((pa - PHYSDRAM) < VIRTPCI-KZERO) + return PHYSDRAM + VIRTPCI-KZERO - pa; return 0; } @@ -301,18 +373,108 @@ mmukmap(uintptr va, uintptr pa, usize size) return 0; pte = pte0; for(n = 0; n < size; n += MiB){ - *pte++ = (pa+n)|Dom0|L1AP(Krw)|Section; + *pte++ = (pa+n)|Dom0|L1AP(Krw)|Section|L1noexec; mmuinvalidateaddr(va+n); } - cachedwbse(pte0, pte - pte0); + cachedwbtlb(pte0, (uintptr)pte - (uintptr)pte0); return va + o; } +uintptr +mmukmapx(uintptr va, uvlong pa, usize size) +{ + int o; + usize n; + PTE ptex, *pte, *pte0; + + assert((va & (16*MiB-1)) == 0); + assert(size <= 16*MiB); + o = (int)pa & (16*MiB-1); + pa -= o; + ptex = FEXT(pa,24,8)<<24 | FEXT(pa,32,4)<<20 | FEXT(pa,36,4)<<5; + pte = pte0 = &m->mmul1[L1X(va)]; + for(n = 0; n < 16*MiB; n += MiB) + if(*pte++ != Fault) + return 0; + pte = pte0; + for(n = 0; n < 16*MiB; n += MiB) + *pte++ = ptex|L1AP(Krw)|Super|Section|L1noexec; + mmuinvalidateaddr(va); + cachedwbtlb(pte0, (uintptr)pte - (uintptr)pte0); + return va + o; +} void checkmmu(uintptr va, uintptr pa) { - USED(va); - USED(pa); + int x; + PTE *l1, *pte; + KMap *k; + + x = L1X(va); + l1 = &m->mmul1[x]; + if(*l1 == Fault){ + iprint("checkmmu cpu%d va=%lux l1 %p=%ux\n", m->machno, va, l1, *l1); + return; + } + k = kmapp(PPN(*l1)); + pte = (PTE*)VA(k); + pte += L2X(va); + if(pa == ~0 || (pa != 0 && PPN(*pte) != pa)) + iprint("checkmmu va=%lux pa=%lux l1 %p=%ux pte %p=%ux\n", va, pa, l1, *l1, pte, *pte); + kunmap(k); +} + +static KMap* +kmapp(ulong pa) +{ + int s, i; + uintptr va; + + if(cankaddr(pa)) + return KADDR(pa); + if(up == nil) + panic("kmap without up %#p", getcallerpc(&pa)); + s = splhi(); + if(up->nkmap == NKMAPS) + panic("kmap overflow %#p", getcallerpc(&pa)); + for(i = 0; i < NKMAPS; i++) + if(up->kmaptab[i] == 0) + break; + if(i == NKMAPS) + panic("can't happen"); + up->nkmap++; + va = KMAPADDR + i*BY2PG; + up->kmaptab[i] = pa | L2AP(Krw)|Small|L2ptedramattrs; + m->kmapl2[i] = up->kmaptab[i]; + cachedwbtlb(&m->kmapl2[i], sizeof(PTE)); + mmuinvalidateaddr(va); + splx(s); + return (KMap*)va; +} + +KMap* +kmap(Page *p) +{ + return kmapp(p->pa); } +void +kunmap(KMap *k) +{ + int i; + uintptr va; + + coherence(); + va = (uintptr)k; + if(L1X(va) != L1X(KMAPADDR)) + return; + /* wasteful: only needed for text pages aliased within data cache */ + cachedwbse((void*)PPN(va), BY2PG); + i = L2X(va); + up->kmaptab[i] = 0; + m->kmapl2[i] = 0; + up->nkmap--; + cachedwbtlb(&m->kmapl2[i], sizeof(PTE)); + mmuinvalidateaddr(va); +} diff --git a/sys/src/9/bcm/pci.c b/sys/src/9/bcm/pci.c new file mode 100644 index 0000000000..f55801ae3b --- /dev/null +++ b/sys/src/9/bcm/pci.c @@ -0,0 +1,1136 @@ +/* + * from 9front + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "pci.h" + +#define PCIWIN 0x0600000000ULL + +/* bcmstb PCIe controller registers */ +enum{ + RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 = 0x0188/4, + RC_CFG_PRIV1_ID_VAL3 = 0x043c/4, + RC_DL_MDIO_ADDR = 0x1100/4, + RC_DL_MDIO_WR_DATA = 0x1104/4, + RC_DL_MDIO_RD_DATA = 0x1108/4, + MISC_MISC_CTRL = 0x4008/4, + MISC_CPU_2_PCIE_MEM_WIN0_LO = 0x400c/4, + MISC_CPU_2_PCIE_MEM_WIN0_HI = 0x4010/4, + MISC_RC_BAR1_CONFIG_LO = 0x402c/4, + MISC_RC_BAR2_CONFIG_LO = 0x4034/4, + MISC_RC_BAR2_CONFIG_HI = 0x4038/4, + MISC_RC_BAR3_CONFIG_LO = 0x403c/4, + MISC_MSI_BAR_CONFIG_LO = 0x4044/4, + MISC_MSI_BAR_CONFIG_HI = 0x4048/4, + MISC_MSI_DATA_CONFIG = 0x404c/4, + MISC_EOI_CTRL = 0x4060/4, + MISC_PCIE_CTRL = 0x4064/4, + MISC_PCIE_STATUS = 0x4068/4, + MISC_REVISION = 0x406c/4, + MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT = 0x4070/4, + MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI = 0x4080/4, + MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI = 0x4084/4, + MISC_HARD_PCIE_HARD_DEBUG = 0x4204/4, + + INTR2_CPU_BASE = 0x4300/4, + MSI_INTR2_BASE = 0x4500/4, + INTR_STATUS = 0, + INTR_SET, + INTR_CLR, + INTR_MASK_STATUS, + INTR_MASK_SET, + INTR_MASK_CLR, + + EXT_CFG_INDEX = 0x9000/4, + RGR1_SW_INIT_1 = 0x9210/4, + EXT_CFG_DATA = 0x8000/4, + +}; + +#define MSI_TARGET_ADDR 0xFFFFFFFFCULL + +static u32int *regs = (u32int*)(VIRTIO + 0x500000); + +static Lock pcicfglock; +static int pcimaxbno = 0; +static int pcimaxdno = 0; +static Pcidev* pciroot; +static Pcidev* pcilist; +static Pcidev* pcitail; + +typedef struct Pcisiz Pcisiz; +struct Pcisiz +{ + Pcidev* dev; + int siz; + int bar; +}; + +enum +{ + MaxFNO = 7, + MaxUBN = 255, +}; + +static char* bustypes[] = { + "CBUSI", + "CBUSII", + "EISA", + "FUTURE", + "INTERN", + "ISA", + "MBI", + "MBII", + "MCA", + "MPI", + "MPSA", + "NUBUS", + "PCI", + "PCMCIA", + "TC", + "VL", + "VME", + "XPRESS", +}; + +static int +tbdffmt(Fmt* fmt) +{ + char *p; + int l, r; + uint type, tbdf; + + if((p = malloc(READSTR)) == nil) + return fmtstrcpy(fmt, "(tbdfconv)"); + + switch(fmt->r){ + case 'T': + tbdf = va_arg(fmt->args, int); + if(tbdf == BUSUNKNOWN) + snprint(p, READSTR, "unknown"); + else{ + type = BUSTYPE(tbdf); + if(type < nelem(bustypes)) + l = snprint(p, READSTR, bustypes[type]); + else + l = snprint(p, READSTR, "%d", type); + snprint(p+l, READSTR-l, ".%d.%d.%d", + BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); + } + break; + + default: + snprint(p, READSTR, "(tbdfconv)"); + break; + } + r = fmtstrcpy(fmt, p); + free(p); + + return r; +} + +static void pcicfginit(void); + +static void* +cfgaddr(int tbdf, int rno) +{ + if(BUSBNO(tbdf) == 0 && BUSDNO(tbdf) == 0) + return (uchar*)regs + rno; + regs[EXT_CFG_INDEX] = BUSBNO(tbdf) << 20 | BUSDNO(tbdf) << 15 | BUSFNO(tbdf) << 12; + coherence(); + return ((uchar*)®s[EXT_CFG_DATA]) + rno; +} + +static int +pcicfgrw32(int tbdf, int rno, int data, int read) +{ + int x = -1; + u32int *p; + + ilock(&pcicfglock); + if((p = cfgaddr(tbdf, rno & ~3)) != nil){ + if(read) + x = *p; + else + *p = data; + } + iunlock(&pcicfglock); + return x; +} +static int +pcicfgrw16(int tbdf, int rno, int data, int read) +{ + int x = -1; + u16int *p; + + ilock(&pcicfglock); + if((p = cfgaddr(tbdf, rno & ~1)) != nil){ + if(read) + x = *p; + else + *p = data; + } + iunlock(&pcicfglock); + return x; +} +static int +pcicfgrw8(int tbdf, int rno, int data, int read) +{ + int x = -1; + u8int *p; + + ilock(&pcicfglock); + if((p = cfgaddr(tbdf, rno)) != nil){ + if(read) + x = *p; + else + *p = data; + } + iunlock(&pcicfglock); + return x; +} + +int +pcicfgr32(Pcidev* pcidev, int rno) +{ + return pcicfgrw32(pcidev->tbdf, rno, 0, 1); +} +void +pcicfgw32(Pcidev* pcidev, int rno, int data) +{ + pcicfgrw32(pcidev->tbdf, rno, data, 0); +} +int +pcicfgr16(Pcidev* pcidev, int rno) +{ + return pcicfgrw16(pcidev->tbdf, rno, 0, 1); +} +void +pcicfgw16(Pcidev* pcidev, int rno, int data) +{ + pcicfgrw16(pcidev->tbdf, rno, data, 0); +} +int +pcicfgr8(Pcidev* pcidev, int rno) +{ + return pcicfgrw8(pcidev->tbdf, rno, 0, 1); +} +void +pcicfgw8(Pcidev* pcidev, int rno, int data) +{ + pcicfgrw8(pcidev->tbdf, rno, data, 0); +} + +Pcidev* +pcimatch(Pcidev* prev, int vid, int did) +{ + if(prev == nil) + prev = pcilist; + else + prev = prev->list; + + while(prev != nil){ + if((vid == 0 || prev->vid == vid) + && (did == 0 || prev->did == did)) + break; + prev = prev->list; + } + return prev; +} + +Pcidev* +pcimatchtbdf(int tbdf) +{ + Pcidev *pcidev; + + for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { + if(pcidev->tbdf == tbdf) + break; + } + return pcidev; +} + +static u32int +pcibarsize(Pcidev *p, int rno) +{ + u32int v, size; + + v = pcicfgrw32(p->tbdf, rno, 0, 1); + pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); + size = pcicfgrw32(p->tbdf, rno, 0, 1); + if(v & 1) + size |= 0xFFFF0000; + pcicfgrw32(p->tbdf, rno, v, 0); + + return -(size & ~0x0F); +} + +static int +pcisizcmp(void *a, void *b) +{ + Pcisiz *aa, *bb; + + aa = a; + bb = b; + return aa->siz - bb->siz; +} + +static ulong +pcimask(ulong v) +{ + ulong m; + + m = BI2BY*sizeof(v); + for(m = 1<<(m-1); m != 0; m >>= 1) { + if(m & v) + break; + } + + m--; + if((v & m) == 0) + return v; + + v |= m; + return v+1; +} + +static void +pcibusmap(Pcidev *root, uintpci *pmema, uintpci *pioa, int wrreg) +{ + Pcidev *p; + int ntb, i, size, rno, hole; + uintpci v, mema, ioa, sioa, smema, base, limit; + Pcisiz *table, *tptr, *mtb, *itb; + + ioa = *pioa; + mema = *pmema; + + ntb = 0; + for(p = root; p != nil; p = p->link) + ntb++; + + ntb *= (PciCIS-PciBAR0)/4; + table = malloc(2*ntb*sizeof(Pcisiz)); + if(table == nil) + panic("pcibusmap: can't allocate memory"); + itb = table; + mtb = table+ntb; + + /* + * Build a table of sizes + */ + for(p = root; p != nil; p = p->link) { + if(p->ccrb == 0x06) { + if(p->ccru != 0x04 || p->bridge == nil) + continue; + + sioa = ioa; + smema = mema; + pcibusmap(p->bridge, &smema, &sioa, 0); + + hole = pcimask(smema-mema); + if(hole < (1<<20)) + hole = 1<<20; + p->mema.size = hole; + + hole = pcimask(sioa-ioa); + if(hole < (1<<12)) + hole = 1<<12; + + p->ioa.size = hole; + + itb->dev = p; + itb->bar = -1; + itb->siz = p->ioa.size; + itb++; + + mtb->dev = p; + mtb->bar = -1; + mtb->siz = p->mema.size; + mtb++; + continue; + } + + for(i = 0; i <= 5; i++) { + rno = PciBAR0 + i*4; + v = pcicfgrw32(p->tbdf, rno, 0, 1); + size = pcibarsize(p, rno); + if(size == 0) + continue; + + p->mem[i].size = size; + if(v & 1) { + itb->dev = p; + itb->bar = i; + itb->siz = size; + itb++; + } + else { + mtb->dev = p; + mtb->bar = i; + mtb->siz = size; + mtb++; + + if((v & 7) == 4) + i++; + } + } + } + + /* + * Sort both tables IO smallest first, Memory largest + */ + qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp); + tptr = table+ntb; + qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp); + + /* + * Allocate IO address space on this bus + */ + for(tptr = table; tptr < itb; tptr++) { + hole = tptr->siz; + if(tptr->bar == -1) + hole = 1<<12; + ioa = (ioa+hole-1) & ~(hole-1); + + p = tptr->dev; + if(tptr->bar == -1) + p->ioa.bar = ioa; + else { + p->pcr |= IOen; + p->mem[tptr->bar].bar = ioa|1; + if(wrreg) + pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0); + } + + ioa += tptr->siz; + } + + /* + * Allocate Memory address space on this bus + */ + for(tptr = table+ntb; tptr < mtb; tptr++) { + hole = tptr->siz; + if(tptr->bar == -1) + hole = 1<<20; + mema = (mema+hole-1) & ~(hole-1); + + p = tptr->dev; + if(tptr->bar == -1) + p->mema.bar = mema; + else { + p->pcr |= MEMen; + p->mem[tptr->bar].bar = mema; + if(wrreg){ + rno = PciBAR0+(tptr->bar*4); + if((mema >> 32) != 0){ + pcicfgrw32(p->tbdf, rno, mema|4, 0); + pcicfgrw32(p->tbdf, rno+4, mema >> 32, 0); + } else { + pcicfgrw32(p->tbdf, rno, mema, 0); + } + } + } + mema += tptr->siz; + } + + *pmema = mema; + *pioa = ioa; + free(table); + + if(wrreg == 0) + return; + + /* + * Finally set all the bridge addresses & registers + */ + for(p = root; p != nil; p = p->link) { + if(p->bridge == nil) { + if(p->cls == 0){ + p->cls = 64; + pcicfgw8(p, PciCLS, p->cls); + } + pcicfgrw8(p->tbdf, PciLTR, 64, 0); + p->pcr |= MASen; + pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0); + continue; + } + + if(p == pciroot){ + base = p->mema.bar; + limit = base+p->mema.size-1; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = base; + regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = base >> 32; + base >>= 20, limit >>= 20; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = (base & 0xFFF) << 4 | (limit & 0xFFF) << 20; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = base >> 12; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = limit >> 12; + } + + base = p->ioa.bar; + limit = base+p->ioa.size-1; + v = pcicfgrw32(p->tbdf, PciIBR, 0, 1); + v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8); + pcicfgrw32(p->tbdf, PciIBR, v, 0); + v = (limit & 0xFFFF0000)|(base>>16); + pcicfgrw32(p->tbdf, PciIUBR, v, 0); + + base = p->mema.bar; + limit = base+p->mema.size-1; + v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16); + pcicfgrw32(p->tbdf, PciMBR, v, 0); + + /* + * Disable memory prefetch + */ + pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0); + pcicfgrw8(p->tbdf, PciLTR, 64, 0); + + /* + * Enable the bridge + */ + p->pcr |= IOen|MEMen|MASen; + pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0); + + sioa = p->ioa.bar; + smema = p->mema.bar; + pcibusmap(p->bridge, &smema, &sioa, 1); + } +} + +static int +pcilscan(int bno, Pcidev** list, Pcidev *parent) +{ + Pcidev *p, *head, *tail; + int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; + + maxubn = bno; + head = nil; + tail = nil; + for(dno = 0; dno <= pcimaxdno; dno++){ + maxfno = 0; + for(fno = 0; fno <= maxfno; fno++){ + /* + * For this possible device, form the + * bus+device+function triplet needed to address it + * and try to read the vendor and device ID. + * If successful, allocate a device struct and + * start to fill it in with some useful information + * from the device's configuration space. + */ + tbdf = MKBUS(BusPCI, bno, dno, fno); + l = pcicfgrw32(tbdf, PciVID, 0, 1); + if(l == 0xFFFFFFFF || l == 0) + continue; + p = malloc(sizeof(*p)); + if(p == nil) + panic("pcilscan: no memory"); + p->tbdf = tbdf; + p->vid = l; + p->did = l>>16; + + if(pcilist != nil) + pcitail->list = p; + else + pcilist = p; + pcitail = p; + + p->pcr = pcicfgr16(p, PciPCR); + p->rid = pcicfgr8(p, PciRID); + p->ccrp = pcicfgr8(p, PciCCRp); + p->ccru = pcicfgr8(p, PciCCRu); + p->ccrb = pcicfgr8(p, PciCCRb); + p->cls = pcicfgr8(p, PciCLS); + p->ltr = pcicfgr8(p, PciLTR); + + p->intl = pcicfgr8(p, PciINTL); + + /* + * If the device is a multi-function device adjust the + * loop count so all possible functions are checked. + */ + hdt = pcicfgr8(p, PciHDT); + if(hdt & 0x80) + maxfno = MaxFNO; + + /* + * If appropriate, read the base address registers + * and work out the sizes. + */ + switch(p->ccrb) { + case 0x00: /* prehistoric */ + case 0x01: /* mass storage controller */ + case 0x02: /* network controller */ + case 0x03: /* display controller */ + case 0x04: /* multimedia device */ + case 0x07: /* simple comm. controllers */ + case 0x08: /* base system peripherals */ + case 0x09: /* input devices */ + case 0x0A: /* docking stations */ + case 0x0B: /* processors */ + case 0x0C: /* serial bus controllers */ + case 0x0D: /* wireless controllers */ + case 0x0E: /* intelligent I/O controllers */ + case 0x0F: /* sattelite communication controllers */ + case 0x10: /* encryption/decryption controllers */ + case 0x11: /* signal processing controllers */ + if((hdt & 0x7F) != 0) + break; + rno = PciBAR0; + for(i = 0; i <= 5; i++) { + p->mem[i].bar = pcicfgr32(p, rno); + p->mem[i].size = pcibarsize(p, rno); + if((p->mem[i].bar & 7) == 4 && i < 5){ + rno += 4; + p->mem[i].bar |= (uintpci)pcicfgr32(p, rno) << 32; + i++; + } + rno += 4; + } + break; + + case 0x05: /* memory controller */ + case 0x06: /* bridge device */ + default: + break; + } + + p->parent = parent; + if(head != nil) + tail->link = p; + else + head = p; + tail = p; + } + } + + *list = head; + for(p = head; p != nil; p = p->link){ + /* + * Find PCI-PCI bridges and recursively descend the tree. + */ + if(p->ccrb != 0x06 || p->ccru != 0x04) + continue; + + /* + * If the secondary or subordinate bus number is not + * initialised try to do what the PCI BIOS should have + * done and fill in the numbers as the tree is descended. + * On the way down the subordinate bus number is set to + * the maximum as it's not known how many buses are behind + * this one; the final value is set on the way back up. + */ + sbn = pcicfgr8(p, PciSBN); + ubn = pcicfgr8(p, PciUBN); + + if(sbn == 0 || ubn == 0) { + sbn = maxubn+1; + /* + * Make sure memory, I/O and master enables are + * off, set the primary, secondary and subordinate + * bus numbers and clear the secondary status before + * attempting to scan the secondary bus. + * + * Initialisation of the bridge should be done here. + */ + pcicfgw32(p, PciPCR, 0xFFFF0000); + l = (MaxUBN<<16)|(sbn<<8)|bno; + pcicfgw32(p, PciPBN, l); + pcicfgw16(p, PciSPSR, 0xFFFF); + maxubn = pcilscan(sbn, &p->bridge, p); + l = (maxubn<<16)|(sbn<<8)|bno; + + pcicfgw32(p, PciPBN, l); + } + else { + if(ubn > maxubn) + maxubn = ubn; + pcilscan(sbn, &p->bridge, p); + } + } + + return maxubn; +} + +static void +pcicfginit(void) +{ + uintpci mema, ioa; + + fmtinstall('T', tbdffmt); + + pcilscan(0, &pciroot, nil); + + /* + * Work out how big the top bus is + */ + ioa = 0; + mema = 0; + pcibusmap(pciroot, &mema, &ioa, 0); + + /* + * Align the windows and map it + */ + ioa = 0; + mema = PCIWIN; + pcibusmap(pciroot, &mema, &ioa, 1); +} + +static void +pcilhinv(Pcidev* p) +{ + int i; + Pcidev *t; + + if(p == nil) { + p = pciroot; + print("pci dev type vid did intl memory\n"); + } + for(t = p; t != nil; t = t->link) { + print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ", + BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf), + t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl); + + for(i = 0; i < nelem(p->mem); i++) { + if(t->mem[i].size == 0) + continue; + print("%d:%llux %d ", i, + (uvlong)t->mem[i].bar, t->mem[i].size); + } + if(t->bridge) + print("->%d", BUSBNO(t->bridge->tbdf)); + print("\n"); + } + while(p != nil) { + if(p->bridge != nil) + pcilhinv(p->bridge); + p = p->link; + } +} + +static void +pcihinv(Pcidev* p) +{ + pcilhinv(p); +} + +void +pcisetioe(Pcidev* p) +{ + p->pcr |= IOen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrioe(Pcidev* p) +{ + p->pcr &= ~IOen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pcisetbme(Pcidev* p) +{ + p->pcr |= MASen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrbme(Pcidev* p) +{ + p->pcr &= ~MASen; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pcisetmwi(Pcidev* p) +{ + p->pcr |= MemWrInv; + pcicfgw16(p, PciPCR, p->pcr); +} + +void +pciclrmwi(Pcidev* p) +{ + p->pcr &= ~MemWrInv; + pcicfgw16(p, PciPCR, p->pcr); +} + +static int +enumcaps(Pcidev *p, int (*fmatch)(Pcidev*, int, int, int), int arg) +{ + int i, r, cap, off; + + /* status register bit 4 has capabilities */ + if((pcicfgr16(p, PciPSR) & 1<<4) == 0) + return -1; + switch(pcicfgr8(p, PciHDT) & 0x7F){ + default: + return -1; + case 0: /* etc */ + case 1: /* pci to pci bridge */ + off = 0x34; + break; + case 2: /* cardbus bridge */ + off = 0x14; + break; + } + for(i = 48; i--;){ + off = pcicfgr8(p, off); + if(off < 0x40 || (off & 3)) + break; + off &= ~3; + cap = pcicfgr8(p, off); + if(cap == 0xff) + break; + r = (*fmatch)(p, cap, off, arg); + if(r < 0) + break; + if(r == 0) + return off; + off++; + } + return -1; +} + +static int +matchcap(Pcidev *, int cap, int, int arg) +{ + return cap != arg; +} + +static int +matchhtcap(Pcidev *p, int cap, int off, int arg) +{ + int mask; + + if(cap != PciCapHTC) + return 1; + if(arg == 0x00 || arg == 0x20) + mask = 0xE0; + else + mask = 0xF8; + cap = pcicfgr8(p, off+3); + return (cap & mask) != arg; +} + +int +pcicap(Pcidev *p, int cap) +{ + return enumcaps(p, matchcap, cap); +} + +int +pcinextcap(Pcidev *pci, int offset) +{ + if(offset == 0) { + if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0) + return 0; /* no capabilities */ + offset = PciCAP-1; + } + return pcicfgr8(pci, offset+1) & ~3; +} + +int +pcihtcap(Pcidev *p, int cap) +{ + return enumcaps(p, matchhtcap, cap); +} + +static int +pcigetpmrb(Pcidev* p) +{ + if(p->pmrb != 0) + return p->pmrb; + return p->pmrb = pcicap(p, PciCapPMG); +} + +int +pcigetpms(Pcidev* p) +{ + int pmcsr, ptr; + + if((ptr = pcigetpmrb(p)) == -1) + return -1; + + /* + * Power Management Register Block: + * offset 0: Capability ID + * 1: next item pointer + * 2: capabilities + * 4: control/status + * 6: bridge support extensions + * 7: data + */ + pmcsr = pcicfgr16(p, ptr+4); + + return pmcsr & 0x0003; +} + +int +pcisetpms(Pcidev* p, int state) +{ + int ostate, pmc, pmcsr, ptr; + + if((ptr = pcigetpmrb(p)) == -1) + return -1; + + pmc = pcicfgr16(p, ptr+2); + pmcsr = pcicfgr16(p, ptr+4); + ostate = pmcsr & 0x0003; + pmcsr &= ~0x0003; + + switch(state){ + default: + return -1; + case 0: + break; + case 1: + if(!(pmc & 0x0200)) + return -1; + break; + case 2: + if(!(pmc & 0x0400)) + return -1; + break; + case 3: + break; + } + pmcsr |= state; + pcicfgw16(p, ptr+4, pmcsr); + + return ostate; +} + +void +pcienable(Pcidev *p) +{ + uint pcr; + int i; + + if(p == nil) + return; + + pcienable(p->parent); + + switch(pcisetpms(p, 0)){ + case 1: + print("pcienable %T: wakeup from D1\n", p->tbdf); + break; + case 2: + print("pcienable %T: wakeup from D2\n", p->tbdf); + if(p->bridge != nil) + delay(100); /* B2: minimum delay 50ms */ + else + delay(1); /* D2: minimum delay 200µs */ + break; + case 3: + print("pcienable %T: wakeup from D3\n", p->tbdf); + delay(100); /* D3: minimum delay 50ms */ + + /* restore registers */ + for(i = 0; i < 6; i++) + pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar); + pcicfgw8(p, PciINTL, p->intl); + pcicfgw8(p, PciLTR, p->ltr); + pcicfgw8(p, PciCLS, p->cls); + pcicfgw16(p, PciPCR, p->pcr); + break; + } + + if(p->bridge != nil) + pcr = IOen|MEMen|MASen; + else { + pcr = 0; + for(i = 0; i < 6; i++){ + if(p->mem[i].size == 0) + continue; + if(p->mem[i].bar & 1) + pcr |= IOen; + else + pcr |= MEMen; + } + } + + if((p->pcr & pcr) != pcr){ + print("pcienable %T: pcr %ux->%ux\n", p->tbdf, p->pcr, p->pcr|pcr); + p->pcr |= pcr; + pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0); + } +} + +void +pcidisable(Pcidev *p) +{ + if(p == nil) + return; + pciclrbme(p); +} + +enum { + MSICtrl = 0x02, /* message control register (16 bit) */ + MSIAddr = 0x04, /* message address register (64 bit) */ + MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */ + MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */ +}; + +typedef struct Pciisr Pciisr; +struct Pciisr { + void (*f)(Ureg*, void*); + void *a; + Pcidev *p; +}; + +static Pciisr pciisr[32]; +static Lock pciisrlk; + +void +pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + int cap, ok64; + u32int dat; + u64int adr; + Pcidev *p; + Pciisr *isr; + + if((p = pcimatchtbdf(tbdf)) == nil){ + print("pciintrenable: %T: unknown device\n", tbdf); + return; + } + if((cap = pcicap(p, PciCapMSI)) < 0){ + print("pciintrenable: %T: no MSI cap\n", tbdf); + return; + } + + lock(&pciisrlk); + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p == p){ + isr->p = nil; + regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); + break; + } + } + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p == nil){ + isr->p = p; + isr->a = a; + isr->f = f; + regs[MSI_INTR2_BASE + INTR_CLR] = 1 << (isr-pciisr); + regs[MSI_INTR2_BASE + INTR_MASK_CLR] = 1 << (isr-pciisr); + break; + } + } + unlock(&pciisrlk); + + if(isr >= &pciisr[nelem(pciisr)]){ + print("pciintrenable: %T: out of isr slots\n", tbdf); + return; + } + + adr = MSI_TARGET_ADDR; + ok64 = (pcicfgr16(p, cap + MSICtrl) & (1<<7)) != 0; + pcicfgw32(p, cap + MSIAddr, adr); + if(ok64) pcicfgw32(p, cap + MSIAddr + 4, adr>>32); + dat = regs[MISC_MSI_DATA_CONFIG]; + dat = ((dat >> 16) & (dat & 0xFFFF)) | (isr-pciisr); + pcicfgw16(p, cap + (ok64 ? MSIData64 : MSIData32), dat); + pcicfgw16(p, cap + MSICtrl, 1); +} + +void +pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a) +{ + Pciisr *isr; + + lock(&pciisrlk); + for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){ + if(isr->p != nil && isr->p->tbdf == tbdf && isr->f == f && isr->a == a){ + regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr); + isr->p = nil; + isr->f = nil; + isr->a = nil; + break; + } + } + unlock(&pciisrlk); +} + +static void +pciinterrupt(Ureg *ureg, void*) +{ + Pciisr *isr; + u32int sts; + + sts = regs[MSI_INTR2_BASE + INTR_STATUS]; + if(sts == 0) + return; + regs[MSI_INTR2_BASE + INTR_CLR] = sts; + for(isr = pciisr; sts != 0 && isr < &pciisr[nelem(pciisr)]; isr++, sts>>=1){ + if((sts & 1) != 0 && isr->f != nil) + (*isr->f)(ureg, isr->a); + } + regs[MISC_EOI_CTRL] = 1; +} + +void +pcilink(void) +{ + int log2dmasize = 30; // 1GB + + regs[RGR1_SW_INIT_1] |= 3; + delay(200); + regs[RGR1_SW_INIT_1] &= ~2; + regs[MISC_PCIE_CTRL] &= ~5; + delay(200); + + regs[MISC_HARD_PCIE_HARD_DEBUG] &= ~0x08000000; + delay(200); + + regs[MSI_INTR2_BASE + INTR_CLR] = -1; + regs[MSI_INTR2_BASE + INTR_MASK_SET] = -1; + + regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = 0; + regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = 0; + + // SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE + regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27; + + regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15); + regs[MISC_RC_BAR2_CONFIG_HI] = 0; + + regs[MISC_RC_BAR1_CONFIG_LO] = 0; + regs[MISC_RC_BAR3_CONFIG_LO] = 0; + + regs[MISC_MSI_BAR_CONFIG_LO] = MSI_TARGET_ADDR | 1; + regs[MISC_MSI_BAR_CONFIG_HI] = MSI_TARGET_ADDR>>32; + regs[MISC_MSI_DATA_CONFIG] = 0xFFF86540; + intrenable(IRQpci, pciinterrupt, nil, BUSUNKNOWN, "pci"); + + // force to GEN2 + regs[(0xAC + 12)/4] = (regs[(0xAC + 12)/4] & ~15) | 2; // linkcap + regs[(0xAC + 48)/4] = (regs[(0xAC + 48)/4] & ~15) | 2; // linkctl2 + + regs[RGR1_SW_INIT_1] &= ~1; + delay(500); + + if((regs[MISC_PCIE_STATUS] & 0x30) != 0x30){ + print("pcireset: phy link is down\n"); + return; + } + + regs[RC_CFG_PRIV1_ID_VAL3] = 0x060400; + regs[RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1] &= ~0xC; + regs[MISC_HARD_PCIE_HARD_DEBUG] |= 2; + + pcicfginit(); + pcihinv(nil); +} diff --git a/sys/src/9/bcm/pci.h b/sys/src/9/bcm/pci.h new file mode 100644 index 0000000000..f67346ede9 --- /dev/null +++ b/sys/src/9/bcm/pci.h @@ -0,0 +1,241 @@ +/* + * PCI + */ +typedef unsigned long long uintpci; + +#define BUSUNKNOWN (-1) + +enum { + BusCBUS = 0, /* Corollary CBUS */ + BusCBUSII, /* Corollary CBUS II */ + BusEISA, /* Extended ISA */ + BusFUTURE, /* IEEE Futurebus */ + BusINTERN, /* Internal bus */ + BusISA, /* Industry Standard Architecture */ + BusMBI, /* Multibus I */ + BusMBII, /* Multibus II */ + BusMCA, /* Micro Channel Architecture */ + BusMPI, /* MPI */ + BusMPSA, /* MPSA */ + BusNUBUS, /* Apple Macintosh NuBus */ + BusPCI, /* Peripheral Component Interconnect */ + BusPCMCIA, /* PC Memory Card International Association */ + BusTC, /* DEC TurboChannel */ + BusVL, /* VESA Local bus */ + BusVME, /* VMEbus */ + BusXPRESS, /* Express System Bus */ +}; + +#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) +#define BUSFNO(tbdf) (((tbdf)>>8)&0x07) +#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) +#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) +#define BUSTYPE(tbdf) ((tbdf)>>24) +#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) + +enum { /* type 0 & type 1 pre-defined header */ + PciVID = 0x00, /* vendor ID */ + PciDID = 0x02, /* device ID */ + PciPCR = 0x04, /* command */ + PciPSR = 0x06, /* status */ + PciRID = 0x08, /* revision ID */ + PciCCRp = 0x09, /* programming interface class code */ + PciCCRu = 0x0A, /* sub-class code */ + PciCCRb = 0x0B, /* base class code */ + PciCLS = 0x0C, /* cache line size */ + PciLTR = 0x0D, /* latency timer */ + PciHDT = 0x0E, /* header type */ + PciBST = 0x0F, /* BIST */ + + PciBAR0 = 0x10, /* base address */ + PciBAR1 = 0x14, + + PciCAP = 0x34, /* capabilities pointer */ + PciINTL = 0x3C, /* interrupt line */ + PciINTP = 0x3D, /* interrupt pin */ +}; + +/* ccrb (base class code) values; controller types */ +enum { + Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ + Pcibcstore = 1, /* mass storage */ + Pcibcnet = 2, /* network */ + Pcibcdisp = 3, /* display */ + Pcibcmmedia = 4, /* multimedia */ + Pcibcmem = 5, /* memory */ + Pcibcbridge = 6, /* bridge */ + Pcibccomm = 7, /* simple comms (e.g., serial) */ + Pcibcbasesys = 8, /* base system */ + Pcibcinput = 9, /* input */ + Pcibcdock = 0xa, /* docking stations */ + Pcibcproc = 0xb, /* processors */ + Pcibcserial = 0xc, /* serial bus (e.g., USB) */ + Pcibcwireless = 0xd, /* wireless */ + Pcibcintell = 0xe, /* intelligent i/o */ + Pcibcsatcom = 0xf, /* satellite comms */ + Pcibccrypto = 0x10, /* encryption/decryption */ + Pcibcdacq = 0x11, /* data acquisition & signal proc. */ +}; + +/* ccru (sub-class code) values; common cases only */ +enum { + /* mass storage */ + Pciscscsi = 0, /* SCSI */ + Pciscide = 1, /* IDE (ATA) */ + Pciscsata = 6, /* SATA */ + + /* network */ + Pciscether = 0, /* Ethernet */ + + /* display */ + Pciscvga = 0, /* VGA */ + Pciscxga = 1, /* XGA */ + Pcisc3d = 2, /* 3D */ + + /* bridges */ + Pcischostpci = 0, /* host/pci */ + Pciscpcicpci = 1, /* pci/pci */ + + /* simple comms */ + Pciscserial = 0, /* 16450, etc. */ + Pciscmultiser = 1, /* multiport serial */ + + /* serial bus */ + Pciscusb = 3, /* USB */ +}; + +enum { /* type 0 pre-defined header */ + PciCIS = 0x28, /* cardbus CIS pointer */ + PciSVID = 0x2C, /* subsystem vendor ID */ + PciSID = 0x2E, /* subsystem ID */ + PciEBAR0 = 0x30, /* expansion ROM base address */ + PciMGNT = 0x3E, /* burst period length */ + PciMLT = 0x3F, /* maximum latency between bursts */ +}; + +enum { /* type 1 pre-defined header */ + PciPBN = 0x18, /* primary bus number */ + PciSBN = 0x19, /* secondary bus number */ + PciUBN = 0x1A, /* subordinate bus number */ + PciSLTR = 0x1B, /* secondary latency timer */ + PciIBR = 0x1C, /* I/O base */ + PciILR = 0x1D, /* I/O limit */ + PciSPSR = 0x1E, /* secondary status */ + PciMBR = 0x20, /* memory base */ + PciMLR = 0x22, /* memory limit */ + PciPMBR = 0x24, /* prefetchable memory base */ + PciPMLR = 0x26, /* prefetchable memory limit */ + PciPUBR = 0x28, /* prefetchable base upper 32 bits */ + PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ + PciIUBR = 0x30, /* I/O base upper 16 bits */ + PciIULR = 0x32, /* I/O limit upper 16 bits */ + PciEBAR1 = 0x28, /* expansion ROM base address */ + PciBCR = 0x3E, /* bridge control register */ +}; + +enum { /* type 2 pre-defined header */ + PciCBExCA = 0x10, + PciCBSPSR = 0x16, + PciCBPBN = 0x18, /* primary bus number */ + PciCBSBN = 0x19, /* secondary bus number */ + PciCBUBN = 0x1A, /* subordinate bus number */ + PciCBSLTR = 0x1B, /* secondary latency timer */ + PciCBMBR0 = 0x1C, + PciCBMLR0 = 0x20, + PciCBMBR1 = 0x24, + PciCBMLR1 = 0x28, + PciCBIBR0 = 0x2C, /* I/O base */ + PciCBILR0 = 0x30, /* I/O limit */ + PciCBIBR1 = 0x34, /* I/O base */ + PciCBILR1 = 0x38, /* I/O limit */ + PciCBSVID = 0x40, /* subsystem vendor ID */ + PciCBSID = 0x42, /* subsystem ID */ + PciCBLMBAR = 0x44, /* legacy mode base address */ +}; + +enum { + /* bar bits */ + Barioaddr = 1<<0, /* vs. memory addr */ + Barwidthshift = 1, + Barwidthmask = 3, + Barwidth32 = 0, + Barwidth64 = 2, + Barprefetch = 1<<3, +}; + +enum +{ /* command register */ + IOen = (1<<0), + MEMen = (1<<1), + MASen = (1<<2), + MemWrInv = (1<<4), + PErrEn = (1<<6), + SErrEn = (1<<8), +}; + +/* capabilities */ +enum { + PciCapPMG = 0x01, /* power management */ + PciCapAGP = 0x02, + PciCapVPD = 0x03, /* vital product data */ + PciCapSID = 0x04, /* slot id */ + PciCapMSI = 0x05, + PciCapCHS = 0x06, /* compact pci hot swap */ + PciCapPCIX = 0x07, + PciCapHTC = 0x08, /* hypertransport irq conf */ + PciCapVND = 0x09, /* vendor specific information */ + PciCapPCIe = 0x10, + PciCapMSIX = 0x11, + PciCapSATA = 0x12, + PciCapHSW = 0x0c, /* hot swap */ +}; + +typedef struct Pcidev Pcidev; +struct Pcidev +{ + int tbdf; /* type+bus+device+function */ + ushort vid; /* vendor ID */ + ushort did; /* device ID */ + + ushort pcr; + + uchar rid; + uchar ccrp; + uchar ccru; + uchar ccrb; + uchar cls; + uchar ltr; + + struct { + uintpci bar; /* base address */ + int size; + } mem[6]; + + uchar intl; /* interrupt line */ + + Pcidev* list; + Pcidev* link; /* next device on this bno */ + + Pcidev* parent; /* up a bus */ + Pcidev* bridge; /* down a bus */ + + int pmrb; /* power management register block */ + + struct { + uintpci bar; + int size; + } ioa, mema; +}; + +#define PCIWINDOW 0 +#define PCIWADDR(va) (PADDR(va)+PCIWINDOW) + +#pragma varargck type "T" int +#pragma varargck type "T" uint + +void pcienable(Pcidev *); +void pcidisable(Pcidev *); +void pcisetbme(Pcidev* ); +Pcidev* pcimatch(Pcidev* prev, int vid, int did); +void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a); +void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a); diff --git a/sys/src/9/bcm/pi b/sys/src/9/bcm/pi index 461c868c94..ad20a256fe 100644 --- a/sys/src/9/bcm/pi +++ b/sys/src/9/bcm/pi @@ -18,18 +18,26 @@ dev kbmap kbin kbd latin1 uart + gpio gpio + spi spi + i2c i2c fakertc +# rtc3231 i2c + ether netif sd usb - ether netif + aoe link archbcm loopbackmedium ethermedium + sdhost usbdwc etherusb + ether4330 emmc + pitft ip tcp @@ -40,11 +48,14 @@ ip ipmux misc - uartmini + armv6 + trap + uartmini gpio sdmmc emmc + sdaoe sdscsi dma vcore - vfp3 coproc + vfp3 port int cpuserver = 0; diff --git a/sys/src/9/bcm/pi2 b/sys/src/9/bcm/pi2 new file mode 100644 index 0000000000..63545da1b8 --- /dev/null +++ b/sys/src/9/bcm/pi2 @@ -0,0 +1,72 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + aoe + +link + archbcm2 + loopbackmedium + ethermedium + sdhost + usbdwc + etherusb + ether4330 emmc + pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap + uartmini gpio + sdmmc emmc + sdaoe sdscsi + dma + vcore + vfp3 + +port + int cpuserver = 0; + +boot boot #S/sdM0/ + local + tcp + +bootdir + boot$CONF.out boot + /arm/bin/ip/ipconfig + /arm/bin/auth/factotum + /arm/bin/fossil/fossil + /arm/bin/usb/usbd diff --git a/sys/src/9/bcm/pi2cpu b/sys/src/9/bcm/pi2cpu new file mode 100644 index 0000000000..a950880351 --- /dev/null +++ b/sys/src/9/bcm/pi2cpu @@ -0,0 +1,72 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + aoe + +link + archbcm2 + loopbackmedium + ethermedium + sdhost + usbdwc + etherusb + ether4330 emmc + pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap + uartmini gpio + sdmmc emmc + sdaoe sdscsi + dma + vcore + vfp3 + +port + int cpuserver = 1; + +boot cpu boot #S/sdM0/ + local + tcp + +bootdir + boot$CONF.out boot + /arm/bin/ip/ipconfig + /arm/bin/auth/factotum + /arm/bin/fossil/fossil + /arm/bin/usb/usbd diff --git a/sys/src/9/bcm/pi2wifi b/sys/src/9/bcm/pi2wifi new file mode 100644 index 0000000000..ad1e629f5c --- /dev/null +++ b/sys/src/9/bcm/pi2wifi @@ -0,0 +1,79 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + +link + archbcm2 + loopbackmedium + ethermedium + sdhost + usbdwc + etherusb + ether4330 emmc + pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap + uartmini gpio + sdmmc emmc + dma + vcore + vfp3 + +port + int cpuserver = 0; + +boot boot #S/sdM0/ + local + tcp + +bootdir + bootwifi.rc boot + /arm/bin/rc + /rc/lib/rcmain + /arm/bin/usb/usbd + /arm/bin/auth/factotum + /arm/bin/srv + /arm/bin/aux/wpa wpa + /arm/bin/ip/ipconfig + /arm/bin/mount + /arm/bin/bind + /arm/bin/echo + /arm/bin/read + /sys/lib/firmware/brcmfmac43430-sdio.bin + /sys/lib/firmware/brcmfmac43430-sdio.txt diff --git a/sys/src/9/bcm/pi4 b/sys/src/9/bcm/pi4 new file mode 100644 index 0000000000..88c2e888a5 --- /dev/null +++ b/sys/src/9/bcm/pi4 @@ -0,0 +1,76 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + aoe + +link + archbcm4 + pci + gisb + loopbackmedium + ethermedium +# sdhost + sdhc + usbxhci +# etherusb + ethergenet ethermii + ether4330 emmc +# pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap4 + uartmini gpio + sdmmc + sdaoe sdscsi + dma + vcore + vfp3 + +port + int cpuserver = 0; + +boot boot #S/sdM0/ + local + tcp + +bootdir + boot$CONF.out boot + /arm/bin/ip/ipconfig + /arm/bin/auth/factotum + /arm/bin/fossil/fossil + /arm/bin/usb/usbd diff --git a/sys/src/9/bcm/pi4cpu b/sys/src/9/bcm/pi4cpu new file mode 100644 index 0000000000..3104e07b91 --- /dev/null +++ b/sys/src/9/bcm/pi4cpu @@ -0,0 +1,76 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + aoe + +link + archbcm4 + pci + gisb + loopbackmedium + ethermedium +# sdhost + sdhc + usbxhci +# etherusb + ethergenet ethermii + ether4330 emmc +# pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap4 + uartmini gpio + sdmmc + sdaoe sdscsi + dma + vcore + vfp3 + +port + int cpuserver = 1; + +boot cpu boot #S/sdM0/ + local + tcp + +bootdir + boot$CONF.out boot + /arm/bin/ip/ipconfig + /arm/bin/auth/factotum + /arm/bin/fossil/fossil + /arm/bin/usb/usbd diff --git a/sys/src/9/bcm/pi4wifi b/sys/src/9/bcm/pi4wifi new file mode 100644 index 0000000000..a188cba17c --- /dev/null +++ b/sys/src/9/bcm/pi4wifi @@ -0,0 +1,86 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio +# spi spi +# i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + aoe + +link + archbcm4 + pci + gisb + loopbackmedium + ethermedium +# sdhost + sdhc + usbxhci +# etherusb + ethergenet ethermii + ether4330 emmc +# pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv7 + trap4 + uartmini gpio + sdmmc + sdaoe sdscsi + dma + vcore + vfp3 + +port + int cpuserver = 0; + +boot boot #S/sdM0/ + local + tcp + +bootdir + bootwifi.rc boot + /arm/bin/rc + /rc/lib/rcmain + /arm/bin/usb/usbd + /arm/bin/auth/factotum + /arm/bin/srv + /arm/bin/aux/wpa wpa + /arm/bin/ip/ipconfig + /arm/bin/mount + /arm/bin/bind + /arm/bin/echo + /arm/bin/read + /sys/lib/firmware/brcmfmac43455-sdio.bin + /sys/lib/firmware/brcmfmac43455-sdio.txt + /sys/lib/firmware/brcmfmac43455-sdio.clm_blob diff --git a/sys/src/9/bcm/picpu b/sys/src/9/bcm/picpu index fb316d5e22..b265639c08 100644 --- a/sys/src/9/bcm/picpu +++ b/sys/src/9/bcm/picpu @@ -18,18 +18,26 @@ dev kbmap kbin kbd latin1 uart + gpio gpio + spi spi + i2c i2c fakertc +# rtc3231 i2c + ether netif sd usb - ether netif + aoe link archbcm loopbackmedium ethermedium + sdhost usbdwc etherusb + ether4330 emmc + pitft ip tcp @@ -40,11 +48,14 @@ ip ipmux misc - uartmini + armv6 + trap + uartmini gpio sdmmc emmc + sdaoe sdscsi dma vcore - vfp3 coproc + vfp3 port int cpuserver = 1; diff --git a/sys/src/9/bcm/pifat b/sys/src/9/bcm/pifat index dd7d4018ad..90f7440175 100644 --- a/sys/src/9/bcm/pifat +++ b/sys/src/9/bcm/pifat @@ -33,10 +33,12 @@ ip ipmux misc - uartmini + armv6 + trap + uartmini gpio sdmmc emmc dma - vfp3 coproc + vfp3 port int cpuserver = 0; diff --git a/sys/src/9/bcm/pitft.c b/sys/src/9/bcm/pitft.c new file mode 100644 index 0000000000..580a36fb96 --- /dev/null +++ b/sys/src/9/bcm/pitft.c @@ -0,0 +1,277 @@ +/* + * Support for a SPI LCD panel from Adafruit + * based on HX8357D controller chip + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +enum { + TFTWidth = 480, + TFTHeight = 320, +}; + +static void pitftblank(int); +static void pitftdraw(Rectangle); +static long pitftread(Chan*, void*, long, vlong); +static long pitftwrite(Chan*, void*, long, vlong); +static void spicmd(uchar); +static void spidata(uchar *, int); +static void setwindow(int, int, int, int); +static void xpitftdraw(void *); + +extern Memimage xgscreen; +extern Lcd *lcd; + +static Lcd pitft = { + pitftdraw, + pitftblank, +}; + +static Queue *updateq = nil; + +void +pitftlink(void) +{ + addarchfile("pitft", 0666, pitftread, pitftwrite); +} + +static void +pitftsetup(void) +{ + uchar spibuf[32]; + + gpiosel(25, Output); + spirw(0, spibuf, 1); + spicmd(0x01); + delay(10); + spicmd(0x11); + delay(10); + spicmd(0x29); + spicmd(0x13); + spicmd(0x36); + spibuf[0] = 0xe8; + spidata(spibuf, 1); + spicmd(0x3a); + spibuf[0] = 0x05; + spidata(spibuf, 1); +} + +static long +pitftread(Chan *, void *, long, vlong) +{ + return 0; +} + +static long +pitftwrite(Chan *, void *a, long n, vlong) +{ + if(strncmp(a, "init", 4) == 0 && updateq == nil) { + /* + * The HX8357 datasheet shows minimum + * clock cycle time of 66nS but the clock high + * and low times as 15nS and it seems to + * work at around 32MHz. + */ + spiclock(32); + pitftsetup(); + updateq = qopen(16384, 1, nil, nil); + kproc("pitft", xpitftdraw, nil); + lcd = &pitft; + } + return n; +} + +static void +pitftblank(int blank) +{ + USED(blank); +} + +static void +pitftdraw(Rectangle r) +{ + if(updateq == nil) + return; + if(r.min.x > TFTWidth || r.min.y > TFTHeight) + return; + /* + * using qproduce to make sure we don't block + * but if we've got a lot on the queue, it means we're + * redrawing the same areas over and over; clear it + * out and just draw the whole screen once + */ + if(qproduce(updateq, &r, sizeof(Rectangle)) == -1) { + r = Rect(0, 0, TFTWidth, TFTHeight); + qflush(updateq); + qproduce(updateq, &r, sizeof(Rectangle)); + } +} + +int +overlap(Rectangle r1, Rectangle r2) +{ + if(r1.max.x < r2.min.x) + return 0; + if(r1.min.x > r2.max.x) + return 0; + if(r1.max.y < r2.min.y) + return 0; + if(r1.min.y > r2.max.y) + return 0; + return 1; +} + +int +min(int x, int y) +{ + if(x < y) + return x; + return y; +} + +int +max(int x, int y) +{ + if(x < y) + return y; + return x; +} + +/* + * Because everyone wants to be holding locks when + * they update the screen but we need to sleep in the + * SPI code, we're decoupling this into a separate kproc(). + */ +static void +xpitftdraw(void *) +{ + Rectangle rec, bb; + Point pt; + uchar *p; + int i, r, c, gotrec; + uchar spibuf[32]; + + gotrec = 0; + qread(updateq, &rec, sizeof(Rectangle)); + bb = Rect(0, 0, TFTWidth, TFTHeight); + while(1) { + setwindow(bb.min.x, bb.min.y, + bb.max.x-1, bb.max.y-1); + spicmd(0x2c); + for(r = bb.min.y; r < bb.max.y; ++r) { + for(c = bb.min.x; c < bb.max.x; c += 8) { + for(i = 0; i < 8; ++i) { + pt.y = r; + pt.x = c + i; + p = byteaddr(&xgscreen, pt); + switch(xgscreen.depth) { + case 16: // RGB16 + spibuf[i*2+1] = p[0]; + spibuf[i*2] = p[1]; + break; + case 24: // BGR24 + spibuf[i*2] = (p[2] & 0xf8) | + (p[1] >> 5); + spibuf[i*2+1] = (p[0] >> 3) | + (p[1] << 3); + break; + case 32: // ARGB32 + spibuf[i*2] = (p[0] & 0xf8) | + (p[1] >> 5); + spibuf[i*2+1] = (p[1] >> 3) | + (p[1] << 3); + break; + } + } + spidata(spibuf, 16); + } + } + bb.max.y = -1; + while(1) { + if(!gotrec) { + qread(updateq, &rec, sizeof(Rectangle)); + gotrec = 1; + } + if(bb.max.y != -1) { + if(!overlap(bb, rec)) + break; + rec.min.x = min(rec.min.x, bb.min.x); + rec.min.y = min(rec.min.y, bb.min.y); + rec.max.x = max(rec.max.x, bb.max.x); + rec.max.y = max(rec.max.y, bb.max.y); + } + gotrec = 0; + // Expand rows to 8 pixel alignment + bb.min.x = rec.min.x & ~7; + if(bb.min.x < 0) + bb.min.x = 0; + bb.max.x = (rec.max.x + 7) & ~7; + if(bb.max.x > TFTWidth) + bb.max.x = TFTWidth; + bb.min.y = rec.min.y; + if(bb.min.y < 0) + bb.min.y = 0; + bb.max.y = rec.max.y; + if(bb.max.y > TFTHeight) + bb.max.y = TFTHeight; + if(qcanread(updateq)) { + qread(updateq, &rec, sizeof(Rectangle)); + gotrec = 1; + } + else + break; + } + } +} + +static void +spicmd(uchar c) +{ + char buf; + + gpioout(25, 0); + buf = c; + spirw(0, &buf, 1); +} + +static void +spidata(uchar *p, int n) +{ + char buf[128]; + + if(n > 128) + n = 128; + gpioout(25, 1); + memmove(buf, p, n); + spirw(0, buf, n); + gpioout(25, 0); +} + +static void +setwindow(int minc, int minr, int maxc, int maxr) +{ + uchar spibuf[4]; + + spicmd(0x2a); + spibuf[0] = minc >> 8; + spibuf[1] = minc & 0xff; + spibuf[2] = maxc >> 8; + spibuf[3] = maxc & 0xff; + spidata(spibuf, 4); + spicmd(0x2b); + spibuf[0] = minr >> 8; + spibuf[1] = minr & 0xff; + spibuf[2] = maxr >> 8; + spibuf[3] = maxr & 0xff; + spidata(spibuf, 4); +} diff --git a/sys/src/9/bcm/piwifi b/sys/src/9/bcm/piwifi new file mode 100644 index 0000000000..3176f43d39 --- /dev/null +++ b/sys/src/9/bcm/piwifi @@ -0,0 +1,79 @@ +dev + root + cons + env + pipe + proc + mnt + srv + dup + arch + ssl + tls + cap + fs + ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno + draw screen + mouse mouse + kbmap + kbin kbd latin1 + uart + gpio gpio + spi spi + i2c i2c + + fakertc +# rtc3231 i2c + ether netif + sd + usb + +link + archbcm + loopbackmedium + ethermedium + ether4330 emmc + sdhost + usbdwc + etherusb + pitft + +ip + tcp + udp + ipifc + icmp + icmp6 + ipmux + +misc + armv6 + trap + uartmini gpio + sdmmc emmc + dma + vcore + vfp3 + +port + int cpuserver = 0; + +boot boot #S/sdM0/ + local + tcp + +bootdir + bootwifi.rc boot + /arm/bin/rc + /rc/lib/rcmain + /arm/bin/usb/usbd + /arm/bin/auth/factotum + /arm/bin/srv + /arm/bin/aux/wpa wpa + /arm/bin/ip/ipconfig + /arm/bin/mount + /arm/bin/bind + /arm/bin/echo + /arm/bin/read + /sys/lib/firmware/brcmfmac43430-sdio.bin + /sys/lib/firmware/brcmfmac43430-sdio.txt diff --git a/sys/src/9/bcm/rebootcode.s b/sys/src/9/bcm/rebootcode.s index 8e924ccfda..8fa8fdfd14 100644 --- a/sys/src/9/bcm/rebootcode.s +++ b/sys/src/9/bcm/rebootcode.s @@ -1,93 +1,152 @@ /* - * armv6 reboot code + * armv6/armv7 reboot code */ #include "arm.s" +#define PTEDRAM (Dom0|L1AP(Krw)|Section) + +#define WFI WORD $0xe320f003 /* wait for interrupt */ +#define WFE WORD $0xe320f002 /* wait for event */ + /* - * Turn off MMU, then copy the new kernel to its correct location - * in physical memory. Then jump to the start of the kernel. + * CPU0: + * main(PADDR(entry), PADDR(code), size); + * Copy the new kernel to its correct location in virtual memory. + * Then turn off the mmu and jump to the start of the kernel. + * + * Other CPUs: + * main(0, soc.armlocal, 0); + * Turn off the mmu, wait for a restart address from CPU0, and jump to it. */ -/* main(PADDR(entry), PADDR(code), size); */ +/* */ TEXT main(SB), 1, $-4 MOVW $setR12(SB), R12 /* copy in arguments before stack gets unmapped */ MOVW R0, R8 /* entry point */ - MOVW p2+4(FP), R9 /* source */ - MOVW n+8(FP), R10 /* byte count */ - - /* SVC mode, interrupts disabled */ - MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 - MOVW R1, CPSR + MOVW p2+4(FP), R7 /* source */ + MOVW n+8(FP), R6 /* byte count */ - /* prepare to turn off mmu */ - BL cachesoff(SB) + /* redo double map of first MiB PHYSDRAM = KZERO */ + MOVW 12(R(MACH)), R2 /* m->mmul1 (virtual addr) */ + MOVW $PTEDRAM, R1 /* PTE bits */ + MOVW R1, (R2) + DSB + MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwb), CpCACHEse - /* turn off mmu */ - MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl - BIC $CpCmmu, R1 - MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + /* invalidate stale TLBs */ + BARRIERS + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS - /* set up a tiny stack for local vars and memmove args */ - MOVW R8, SP /* stack top just before kernel dest */ - SUB $20, SP /* allocate stack frame */ + /* relocate PC to physical addressing */ + MOVW $_reloc(SB), R15 - /* copy the kernel to final destination */ - MOVW R8, 16(SP) /* save dest (entry point) */ - MOVW R8, R0 /* first arg is dest */ - MOVW R9, 8(SP) /* push src */ - MOVW R10, 12(SP) /* push size */ - BL memmove(SB) - MOVW 16(SP), R8 /* restore entry point */ - - /* jump to kernel physical entry point */ - B (R8) - B 0(PC) +TEXT _reloc(SB), $-4 + + /* continue with reboot only on cpu0 */ + CPUID(R2) + BEQ bootcpu -/* - * turn the caches off, double map PHYSDRAM & KZERO, invalidate TLBs, revert - * to tiny addresses. upon return, it will be safe to turn off the mmu. - * clobbers R0-R2, and returns with SP invalid. - */ -TEXT cachesoff(SB), 1, $-4 + /* other cpus wait for inter processor interrupt from cpu0 */ - /* write back and invalidate caches */ - BARRIERS + /* turn caches off, invalidate icache */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache), R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl MOVW $0, R0 - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall - - /* turn caches off */ + /* turn off mmu */ MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl - BIC $(CpCdcache|CpCicache|CpCpredict), R1 + BIC $CpCmmu, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + /* turn off SMP cache snooping */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + BIC $CpACsmp, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + ISB + DSB + /* turn icache back on */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + ORR $(CpCicache), R1 MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl - - /* invalidate stale TLBs before changing them */ - BARRIERS - MOVW $KZERO, R0 /* some valid virtual address */ - MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv BARRIERS - /* from here on, R0 is base of physical memory */ - MOVW $PHYSDRAM, R0 +dowfi: + WFE /* wait for event signal */ + MOVW $0xCC(R7), R1 /* inter-core .startcpu mailboxes */ + ADD R2<<4, R1 /* mailbox for this core */ + MOVW 0(R1), R8 /* content of mailbox */ + CMP $0, R8 + BEQ dowfi /* if zero, wait again */ + BL (R8) /* call received address */ + B dowfi /* shouldn't return */ - /* redo double map of first MiB PHYSDRAM = KZERO */ - MOVW $(L1+L1X(PHYSDRAM)), R2 /* address of PHYSDRAM's PTE */ - MOVW $PTEDRAM, R1 /* PTE bits */ - ORR R0, R1 /* dram base */ - MOVW R1, (R2) +bootcpu: + MOVW $PADDR(MACHADDR+MACHSIZE-4), SP - /* invalidate stale TLBs again */ - BARRIERS - MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + /* copy the kernel to final destination */ + MOVW R8, R9 /* save physical entry point */ + ADD $KZERO, R8 /* relocate dest to virtual */ + ADD $KZERO, R7 /* relocate src to virtual */ + ADD $3, R6 /* round length to words */ + BIC $3, R6 +memloop: + MOVM.IA.W (R7), [R1] + MOVM.IA.W [R1], (R8) + SUB.S $4, R6 + BNE memloop + + /* clean dcache using appropriate code for armv6 or armv7 */ + MRC CpSC, 0, R1, C(CpID), C(CpIDfeat), 7 /* Memory Model Feature Register 3 */ + TST $0xF, R1 /* hierarchical cache maintenance? */ + BNE l2wb + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEall + B l2wbx +l2wb: + BL cachedwb(SB) + BL l2cacheuwb(SB) +l2wbx: + + /* turn caches off, invalidate icache */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache|CpCpredict), R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall + DSB + /* turn off mmu */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $CpCmmu, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl BARRIERS + /* turn off SMP cache snooping */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + BIC $CpACsmp, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + + /* invalidate dcache using appropriate code for armv6 or armv7 */ + MRC CpSC, 0, R1, C(CpID), C(CpIDfeat), 7 /* Memory Model Feature Register 3 */ + TST $0xF, R1 /* hierarchical cache maintenance */ + BNE l2inv + DSB + MOVW $0, R0 + MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEall + B l2invx +l2inv: + BL cachedinv(SB) + BL l2cacheuinv(SB) +l2invx: + + /* jump to restart entry point */ + MOVW R9, R8 + MOVW $0, R9 + B (R8) - /* relocate SB and return address to PHYSDRAM addressing */ - MOVW $KSEGM, R1 /* clear segment bits */ - BIC R1, R12 /* adjust SB */ - ORR R0, R12 - BIC R1, R14 /* adjust return address */ - ORR R0, R14 - - RET +#define ICACHELINESZ 32 +#include "cache.v7.s" diff --git a/sys/src/9/bcm/screen.c b/sys/src/9/bcm/screen.c index e6c164f01f..1968594726 100644 --- a/sys/src/9/bcm/screen.c +++ b/sys/src/9/bcm/screen.c @@ -37,10 +37,11 @@ Cursor arrow = { }; Memimage *gscreen; +Lcd *lcd; static Memdata xgdata; -static Memimage xgscreen = +/*static*/ Memimage xgscreen = { { 0, 0, Wid, Ht }, /* r */ { 0, 0, Wid, Ht }, /* clipr */ @@ -287,18 +288,24 @@ hwdraw(Memdrawparam *par) if(mask->data->bdata == xgdata.bdata) swcursoravoid(par->mr); + if(lcd) + lcd->draw(par->r); + return 0; } static int screensize(void) { - char *p; + char *p, buf[32]; char *f[3]; int width, height, depth; p = getconf("vgasize"); - if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) || + if(p == nil || memccpy(buf, p, '\0', sizeof buf) == nil) + return -1; + + if(getfields(buf, f, nelem(f), 0, "x") != nelem(f) || (width = atoi(f[0])) < 16 || (height = atoi(f[1])) <= 0 || (depth = atoi(f[2])) <= 0) @@ -312,16 +319,23 @@ void screeninit(void) { uchar *fb; - int set; + char *p; + int set, rgbswap; ulong chan; set = screensize() == 0; fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth); + if(fb == nil){ + xgscreen.r.max = Pt(640, 480); + xgscreen.depth = 16; + fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth); + } if(fb == nil){ print("can't initialise %dx%dx%d framebuffer \n", xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth); return; } + rgbswap = ((p = getconf("bcm2708_fb.fbswap")) != nil && *p == '1'); xgscreen.clipr = xgscreen.r; switch(xgscreen.depth){ default: @@ -332,10 +346,10 @@ screeninit(void) chan = RGB16; break; case 24: - chan = BGR24; + chan = rgbswap? RGB24 : BGR24; break; case 32: - chan = ARGB32; + chan = rgbswap? XRGB32 : XBGR32; break; } memsetchan(&xgscreen, chan); @@ -385,6 +399,8 @@ void blankscreen(int blank) { fbblank(blank); + if(lcd) + lcd->blank(blank); } static void @@ -471,9 +487,13 @@ scroll(void) p = Pt(window.min.x, window.min.y+o); memimagedraw(gscreen, r, gscreen, p, nil, p, S); flushmemscreen(r); + if(lcd) + lcd->draw(r); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(gscreen, r, back, ZP, nil, ZP, S); flushmemscreen(r); + if(lcd) + lcd->draw(r); curpos.y -= o; } diff --git a/sys/src/9/bcm/screen.h b/sys/src/9/bcm/screen.h index 285478c945..b79f33b01d 100644 --- a/sys/src/9/bcm/screen.h +++ b/sys/src/9/bcm/screen.h @@ -1,10 +1,17 @@ typedef struct Cursor Cursor; typedef struct Cursorinfo Cursorinfo; +typedef struct Lcd Lcd; + struct Cursorinfo { Cursor; Lock; }; +struct Lcd { + void (*draw)(Rectangle); + void (*blank)(int); +}; + /* devmouse.c */ extern void mousetrack(int, int, int, int); extern Point mousexy(void); diff --git a/sys/src/9/bcm/sdhc.c b/sys/src/9/bcm/sdhc.c new file mode 100644 index 0000000000..cd34f40d11 --- /dev/null +++ b/sys/src/9/bcm/sdhc.c @@ -0,0 +1,579 @@ +/* + * bcm2711 sd host controller + * + * Copyright © 2012,2019 Richard Miller + * + * adapted from emmc.c - the two should really be merged + */ + +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/sd.h" + +extern SDio *sdcardlink; +#define EMMCREGS (VIRTIO+0x340000) +#define ClkEmmc2 12 + +enum { + Extfreq = 100*Mhz, /* guess external clock frequency if */ + /* not available from vcore */ + Initfreq = 400000, /* initialisation frequency for MMC */ + SDfreq = 25*Mhz, /* standard SD frequency */ + SDfreqhs = 50*Mhz, /* high speed frequency */ + DTO = 14, /* data timeout exponent (guesswork) */ + + GoIdle = 0, /* mmc/sdio go idle state */ + MMCSelect = 7, /* mmc/sd card select command */ + Setbuswidth = 6, /* mmc/sd set bus width command */ + Switchfunc = 6, /* mmc/sd switch function command */ + Voltageswitch = 11, /* md/sdio switch to 1.8V */ + IORWdirect = 52, /* sdio read/write direct command */ + IORWextended = 53, /* sdio read/write extended command */ + Appcmd = 55, /* mmc/sd application command prefix */ +}; + +enum { + /* Controller registers */ + SDMAaddr = 0x00>>2, + Blksizecnt = 0x04>>2, + Arg1 = 0x08>>2, + Cmdtm = 0x0c>>2, + Resp0 = 0x10>>2, + Resp1 = 0x14>>2, + Resp2 = 0x18>>2, + Resp3 = 0x1c>>2, + Data = 0x20>>2, + Status = 0x24>>2, + Control0 = 0x28>>2, + Control1 = 0x2c>>2, + Interrupt = 0x30>>2, + Irptmask = 0x34>>2, + Irpten = 0x38>>2, + Control2 = 0x3c>>2, + Capability = 0x40>>2, + Forceirpt = 0x50>>2, + Dmadesc = 0x58>>2, + Boottimeout = 0x70>>2, + Dbgsel = 0x74>>2, + Exrdfifocfg = 0x80>>2, + Exrdfifoen = 0x84>>2, + Tunestep = 0x88>>2, + Tunestepsstd = 0x8c>>2, + Tunestepsddr = 0x90>>2, + Spiintspt = 0xf0>>2, + Slotisrver = 0xfc>>2, + + /* Control0 */ + Busvoltage = 7<<9, + V1_8 = 5<<9, + V3_0 = 6<<9, + V3_3 = 7<<9, + Buspower = 1<<8, + Dwidth8 = 1<<5, + Dmaselect = 3<<3, + DmaSDMA = 0<<3, + DmaADMA1 = 1<<3, + DmaADMA2 = 2<<3, + Hispeed = 1<<2, + Dwidth4 = 1<<1, + Dwidth1 = 0<<1, + LED = 1<<0, + + /* Control1 */ + Srstdata = 1<<26, /* reset data circuit */ + Srstcmd = 1<<25, /* reset command circuit */ + Srsthc = 1<<24, /* reset complete host controller */ + Datatoshift = 16, /* data timeout unit exponent */ + Datatomask = 0xF0000, + Clkfreq8shift = 8, /* SD clock base divider LSBs */ + Clkfreq8mask = 0xFF00, + Clkfreqms2shift = 6, /* SD clock base divider MSBs */ + Clkfreqms2mask = 0xC0, + Clkgendiv = 0<<5, /* SD clock divided */ + Clkgenprog = 1<<5, /* SD clock programmable */ + Clken = 1<<2, /* SD clock enable */ + Clkstable = 1<<1, + Clkintlen = 1<<0, /* enable internal EMMC clocks */ + + /* Cmdtm */ + Indexshift = 24, + Suspend = 1<<22, + Resume = 2<<22, + Abort = 3<<22, + Isdata = 1<<21, + Ixchken = 1<<20, + Crcchken = 1<<19, + Respmask = 3<<16, + Respnone = 0<<16, + Resp136 = 1<<16, + Resp48 = 2<<16, + Resp48busy = 3<<16, + Multiblock = 1<<5, + Host2card = 0<<4, + Card2host = 1<<4, + Autocmd12 = 1<<2, + Autocmd23 = 2<<2, + Blkcnten = 1<<1, + Dmaen = 1<<0, + + /* Interrupt */ + Admaerr = 1<<25, + Acmderr = 1<<24, + Denderr = 1<<22, + Dcrcerr = 1<<21, + Dtoerr = 1<<20, + Cbaderr = 1<<19, + Cenderr = 1<<18, + Ccrcerr = 1<<17, + Ctoerr = 1<<16, + Err = 1<<15, + Cardintr = 1<<8, + Cardinsert = 1<<6, /* not in Broadcom datasheet */ + Readrdy = 1<<5, + Writerdy = 1<<4, + Dmaintr = 1<<3, + Datadone = 1<<1, + Cmddone = 1<<0, + + /* Status */ + Bufread = 1<<11, /* not in Broadcom datasheet */ + Bufwrite = 1<<10, /* not in Broadcom datasheet */ + Readtrans = 1<<9, + Writetrans = 1<<8, + Datactive = 1<<2, + Datinhibit = 1<<1, + Cmdinhibit = 1<<0, +}; + +static int cmdinfo[64] = { +[0] Ixchken, +[2] Resp136, +[3] Resp48 | Ixchken | Crcchken, +[5] Resp48, +[6] Resp48 | Ixchken | Crcchken, +[7] Resp48busy | Ixchken | Crcchken, +[8] Resp48 | Ixchken | Crcchken, +[9] Resp136, +[11] Resp48 | Ixchken | Crcchken, +[12] Resp48busy | Ixchken | Crcchken, +[13] Resp48 | Ixchken | Crcchken, +[16] Resp48, +[17] Resp48 | Isdata | Card2host | Ixchken | Crcchken, +[18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken, +[24] Resp48 | Isdata | Host2card | Ixchken | Crcchken, +[25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken, +[41] Resp48, +[52] Resp48 | Ixchken | Crcchken, +[53] Resp48 | Ixchken | Crcchken | Isdata, +[55] Resp48 | Ixchken | Crcchken, +}; + +typedef struct Adma Adma; +typedef struct Ctlr Ctlr; + +/* + * ADMA2 descriptor + * See SD Host Controller Simplified Specification Version 2.00 + */ + +struct Adma { + u32int desc; + u32int addr; +}; + +enum { + /* desc fields */ + Valid = 1<<0, + End = 1<<1, + Int = 1<<2, + Nop = 0<<4, + Tran = 2<<4, + Link = 3<<4, + OLength = 16, + /* maximum value for Length field */ + Maxdma = ((1<<16) - 4), +}; + +struct Ctlr { + Rendez r; + Rendez cardr; + int fastclock; + ulong extclk; + int appcmd; + Adma *dma; +}; + +static Ctlr emmc; + +static void mmcinterrupt(Ureg*, void*); + +static void +WR(int reg, u32int val) +{ + u32int *r = (u32int*)EMMCREGS; + + if(0)print("WR %2.2ux %ux\n", reg<<2, val); + coherence(); + r[reg] = val; +} + +static uint +clkdiv(uint d) +{ + uint v; + + assert(d < 1<<10); + v = (d << Clkfreq8shift) & Clkfreq8mask; + v |= ((d >> 8) << Clkfreqms2shift) & Clkfreqms2mask; + return v; +} + +static Adma* +dmaalloc(void *addr, int len) +{ + int n; + uintptr a; + Adma *adma, *p; + + a = (uintptr)addr; + n = HOWMANY(len, Maxdma); + adma = sdmalloc(n * sizeof(Adma)); + for(p = adma; len > 0; p++){ + p->desc = Valid | Tran; + if(n == 1) + p->desc |= len<desc |= Maxdma<addr = dmaaddr((void*)a); + a += Maxdma; + len -= Maxdma; + n--; + } + cachedwbse(adma, (char*)p - (char*)adma); + return adma; +} + +static void +emmcclk(uint freq) +{ + u32int *r; + uint div; + int i; + + r = (u32int*)EMMCREGS; + div = emmc.extclk / (freq<<1); + if(emmc.extclk / (div<<1) > freq) + div++; + WR(Control1, clkdiv(div) | + DTO<> 16; + return snprint(inquiry, inqlen, + "BCM SD Host Controller %2.2x Version %2.2x", + ver&0xFF, ver>>8); +} + +static void +emmcenable(void) +{ + + WR(Control0, 0); + delay(1); + WR(Control0, V3_3 | Buspower | Dwidth1 | DmaADMA2); + WR(Control1, 0); + delay(1); + emmcclk(Initfreq); + WR(Irpten, 0); + WR(Irptmask, ~(Cardintr|Dmaintr)); + WR(Interrupt, ~0); + intrenable(IRQmmc, mmcinterrupt, nil, 0, "sdhc"); +} + +static int +emmccmd(u32int cmd, u32int arg, u32int *resp) +{ + u32int *r; + u32int c; + int i; + ulong now; + + r = (u32int*)EMMCREGS; + assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0); + c = (cmd << Indexshift) | cmdinfo[cmd]; + /* + * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix + */ + if(cmd == Switchfunc && !emmc.appcmd) + c |= Isdata|Card2host; + if(c & Isdata) + c |= Dmaen; + if(cmd == IORWextended){ + if(arg & (1<<31)) + c |= Host2card; + else + c |= Card2host; + if((r[Blksizecnt]&0xFFFF0000) != 0x10000) + c |= Multiblock | Blkcnten; + } + /* + * GoIdle indicates new card insertion: reset bus width & speed + */ + if(cmd == GoIdle){ + WR(Control0, r[Control0] & ~(Dwidth4|Hispeed)); + emmcclk(Initfreq); + } + if(r[Status] & Cmdinhibit){ + print("sdhc: need to reset Cmdinhibit intr %ux stat %ux\n", + r[Interrupt], r[Status]); + WR(Control1, r[Control1] | Srstcmd); + while(r[Control1] & Srstcmd) + ; + while(r[Status] & Cmdinhibit) + ; + } + if((r[Status] & Datinhibit) && + ((c & Isdata) || (c & Respmask) == Resp48busy)){ + print("sdhc: need to reset Datinhibit intr %ux stat %ux\n", + r[Interrupt], r[Status]); + WR(Control1, r[Control1] | Srstdata); + while(r[Control1] & Srstdata) + ; + while(r[Status] & Datinhibit) + ; + } + WR(Arg1, arg); + if((i = (r[Interrupt] & ~Cardintr)) != 0){ + if(i != Cardinsert) + print("sdhc: before command, intr was %ux\n", i); + WR(Interrupt, i); + } + WR(Cmdtm, c); + now = m->ticks; + while(((i=r[Interrupt])&(Cmddone|Err)) == 0) + if(m->ticks-now > HZ) + break; + if((i&(Cmddone|Err)) != Cmddone){ + if((i&~(Err|Cardintr)) != Ctoerr) + print("sdhc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); + WR(Interrupt, i); + if(r[Status]&Cmdinhibit){ + WR(Control1, r[Control1]|Srstcmd); + while(r[Control1]&Srstcmd) + ; + } + error(Eio); + } + WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy)); + switch(c & Respmask){ + case Resp136: + resp[0] = r[Resp0]<<8; + resp[1] = r[Resp0]>>24 | r[Resp1]<<8; + resp[2] = r[Resp1]>>24 | r[Resp2]<<8; + resp[3] = r[Resp2]>>24 | r[Resp3]<<8; + break; + case Resp48: + case Resp48busy: + resp[0] = r[Resp0]; + break; + case Respnone: + resp[0] = 0; + break; + } + if((c & Respmask) == Resp48busy){ + WR(Irpten, r[Irpten]|Datadone|Err); + tsleep(&emmc.r, datadone, 0, 3000); + i = r[Interrupt]; + if((i & Datadone) == 0) + print("sdhc: no Datadone after CMD%d\n", cmd); + if(i & Err) + print("sdhc: CMD%d error interrupt %ux\n", + cmd, r[Interrupt]); + WR(Interrupt, i); + } + /* + * Once card is selected, use faster clock + */ + if(cmd == MMCSelect){ + delay(1); + emmcclk(SDfreq); + delay(1); + emmc.fastclock = 1; + } + if(cmd == Setbuswidth){ + if(emmc.appcmd){ + /* + * If card bus width changes, change host bus width + */ + switch(arg){ + case 0: + WR(Control0, r[Control0] & ~Dwidth4); + break; + case 2: + WR(Control0, r[Control0] | Dwidth4); + break; + } + }else{ + /* + * If card switched into high speed mode, increase clock speed + */ + if((arg&0x8000000F) == 0x80000001){ + delay(1); + emmcclk(SDfreqhs); + delay(1); + } + } + }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ + switch(arg & 0x3){ + case 0: + WR(Control0, r[Control0] & ~Dwidth4); + break; + case 2: + WR(Control0, r[Control0] | Dwidth4); + //WR(Control0, r[Control0] | Hispeed); + break; + } + } + emmc.appcmd = (cmd == Appcmd); + return 0; +} + +static void +emmciosetup(int write, void *buf, int bsize, int bcount) +{ + int len; + + len = bsize * bcount; + assert(((uintptr)buf&3) == 0); + assert((len&3) == 0); + assert(bsize <= 2048); + WR(Blksizecnt, bcount<<16 | bsize); + if(emmc.dma) + sdfree(emmc.dma); + emmc.dma = dmaalloc(buf, len); + if(write) + cachedwbse(buf, len); + else + cachedwbinvse(buf, len); + WR(Dmadesc, dmaaddr(emmc.dma)); + okay(1); +} + +static void +emmcio(int write, uchar *buf, int len) +{ + u32int *r; + int i; + + r = (u32int*)EMMCREGS; + if(waserror()){ + okay(0); + nexterror(); + } + WR(Irpten, r[Irpten] | Datadone|Err); + tsleep(&emmc.r, datadone, 0, 3000); + WR(Irpten, r[Irpten] & ~(Datadone|Err)); + i = r[Interrupt]; + if((i & (Datadone|Err)) != Datadone){ + print("sdhc: %s error intr %ux stat %ux\n", + write? "write" : "read", i, r[Status]); + if(r[Status] & Datinhibit) + WR(Control1, r[Control1] | Srstdata); + while(r[Control1] & Srstdata) + ; + while(r[Status] & Datinhibit) + ; + WR(Interrupt, i); + error(Eio); + } + WR(Interrupt, i); + if(!write) + cachedinvse(buf, len); + poperror(); + okay(0); +} + +static void +mmcinterrupt(Ureg*, void*) +{ + u32int *r; + int i; + + r = (u32int*)EMMCREGS; + i = r[Interrupt]; + if(i&(Datadone|Err)) + wakeup(&emmc.r); + if(i&Cardintr) + wakeup(&emmc.cardr); + WR(Irpten, r[Irpten] & ~i); +} + +SDio sdiohc = { + "sdhc", + emmcinit, + emmcenable, + emmcinquiry, + emmccmd, + emmciosetup, + emmcio, +}; + +void +sdhclink(void) +{ + sdcardlink = &sdiohc; +} diff --git a/sys/src/9/bcm/sdhost.c b/sys/src/9/bcm/sdhost.c new file mode 100644 index 0000000000..1417fc758f --- /dev/null +++ b/sys/src/9/bcm/sdhost.c @@ -0,0 +1,389 @@ +/* + * bcm2835 sdhost controller + * + * Copyright © 2016 Richard Miller + */ + +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/sd.h" + +extern SDio *sdcardlink; + +#define SDHOSTREGS (VIRTIO+0x202000) + +enum { + Extfreq = 250*Mhz, /* guess external clock frequency if vcore doesn't say */ + Initfreq = 400000, /* initialisation frequency for MMC */ + SDfreq = 25*Mhz, /* standard SD frequency */ + SDfreqhs = 50*Mhz, /* SD high speed frequency */ + FifoDepth = 4, /* "Limit fifo usage due to silicon bug" (linux driver) */ + + GoIdle = 0, /* mmc/sdio go idle state */ + MMCSelect = 7, /* mmc/sd card select command */ + Setbuswidth = 6, /* mmc/sd set bus width command */ + Switchfunc = 6, /* mmc/sd switch function command */ + Stoptransmission = 12, /* mmc/sd stop transmission command */ + Appcmd = 55, /* mmc/sd application command prefix */ +}; + +enum { + /* Controller registers */ + Cmd = 0x00>>2, + Arg = 0x04>>2, + Timeout = 0x08>>2, + Clkdiv = 0x0c>>2, + + Resp0 = 0x10>>2, + Resp1 = 0x14>>2, + Resp2 = 0x18>>2, + Resp3 = 0x1c>>2, + + Status = 0x20>>2, + Poweron = 0x30>>2, + Dbgmode = 0x34>>2, + Hconfig = 0x38>>2, + Blksize = 0x3c>>2, + Data = 0x40>>2, + Blkcount = 0x50>>2, + + /* Cmd */ + Start = 1<<15, + Failed = 1<<14, + Respmask = 7<<9, + Resp48busy = 4<<9, + Respnone = 2<<9, + Resp136 = 1<<9, + Resp48 = 0<<9, + Host2card = 1<<7, + Card2host = 1<<6, + + /* Status */ + Busyint = 1<<10, + Blkint = 1<<9, + Sdioint = 1<<8, + Rewtimeout = 1<<7, + Cmdtimeout = 1<<6, + Crcerror = 3<<4, + Fifoerror = 1<<3, + Dataflag = 1<<0, + Intstatus = (Busyint|Blkint|Sdioint|Dataflag), + Errstatus = (Rewtimeout|Cmdtimeout|Crcerror|Fifoerror), + + /* Hconfig */ + BusyintEn = 1<<10, + BlkintEn = 1<<8, + SdiointEn = 1<<5, + DataintEn = 1<<4, + Slowcard = 1<<3, + Extbus4 = 1<<2, + Intbuswide = 1<<1, + Cmdrelease = 1<<0, +}; + +static int cmdinfo[64] = { +[0] Start | Respnone, +[2] Start | Resp136, +[3] Start | Resp48, +[5] Start | Resp48, +[6] Start | Resp48, +[63] Start | Resp48 | Card2host, +[7] Start | Resp48busy, +[8] Start | Resp48, +[9] Start | Resp136, +[11] Start | Resp48, +[12] Start | Resp48busy, +[13] Start | Resp48, +[16] Start | Resp48, +[17] Start | Resp48 | Card2host, +[18] Start | Resp48 | Card2host, +[24] Start | Resp48 | Host2card, +[25] Start | Resp48 | Host2card, +[41] Start | Resp48, +[52] Start | Resp48, +[53] Start | Resp48, +[55] Start | Resp48, +}; + +typedef struct Ctlr Ctlr; + +struct Ctlr { + Rendez r; + int bcount; + int done; + ulong extclk; + int appcmd; +}; + +static Ctlr sdhost; + +static void sdhostinterrupt(Ureg*, void*); + +static void +WR(int reg, u32int val) +{ + u32int *r = (u32int*)SDHOSTREGS; + + if(0)print("WR %2.2ux %ux\n", reg<<2, val); + r[reg] = val; +} + +static int +datadone(void*) +{ + return sdhost.done; +} + +static void +sdhostclock(uint freq) +{ + uint div; + + div = sdhost.extclk / freq; + if(sdhost.extclk / freq > freq) + div++; + if(div < 2) + div = 2; + WR(Clkdiv, div - 2); +} + +static int +sdhostinit(void) +{ + u32int *r; + ulong clk; + int i; + + /* disconnect emmc and connect sdhost to SD card gpio pins */ + for(i = 48; i <= 53; i++) + gpiosel(i, Alt0); + clk = getclkrate(ClkCore); + if(clk == 0){ + clk = Extfreq; + print("sdhost: assuming external clock %lud Mhz\n", clk/1000000); + } + sdhost.extclk = clk; + sdhostclock(Initfreq); + r = (u32int*)SDHOSTREGS; + WR(Poweron, 0); + WR(Timeout, 0xF00000); + WR(Dbgmode, FINS(r[Dbgmode], 9, 10, (FifoDepth | FifoDepth<<5))); + return 0; +} + +static int +sdhostinquiry(char *inquiry, int inqlen) +{ + return snprint(inquiry, inqlen, "BCM SDHost Controller"); +} + +static void +sdhostenable(void) +{ + u32int *r; + + r = (u32int*)SDHOSTREGS; + USED(r); + WR(Poweron, 1); + delay(10); + WR(Hconfig, Intbuswide | Slowcard | BusyintEn); + WR(Clkdiv, 0x7FF); + intrenable(IRQsdhost, sdhostinterrupt, nil, 0, "sdhost"); +} + +static int +sdhostcmd(u32int cmd, u32int arg, u32int *resp) +{ + u32int *r; + u32int c; + int i; + ulong now; + + r = (u32int*)SDHOSTREGS; + assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0); + c = cmd | cmdinfo[cmd]; + /* + * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix + */ + if(cmd == Switchfunc && !sdhost.appcmd) + c |= Card2host; + if(cmd != Stoptransmission && (i = (r[Dbgmode] & 0xF)) > 2){ + print("sdhost: previous command stuck: Dbg=%d Cmd=%ux\n", i, r[Cmd]); + error(Eio); + } + /* + * GoIdle indicates new card insertion: reset bus width & speed + */ + if(cmd == GoIdle){ + WR(Hconfig, r[Hconfig] & ~Extbus4); + sdhostclock(Initfreq); + } + + if(r[Status] & (Errstatus|Dataflag)) + WR(Status, Errstatus|Dataflag); + sdhost.done = 0; + WR(Arg, arg); + WR(Cmd, c); + now = m->ticks; + while(((i=r[Cmd])&(Start|Failed)) == Start) + if(m->ticks-now > HZ) + break; + if((i&(Start|Failed)) != 0){ + if(r[Status] != Cmdtimeout) + print("sdhost: cmd %ux arg %ux error stat %ux\n", i, arg, r[Status]); + i = r[Status]; + WR(Status, i); + error(Eio); + } + switch(c & Respmask){ + case Resp136: + resp[0] = r[Resp0]; + resp[1] = r[Resp1]; + resp[2] = r[Resp2]; + resp[3] = r[Resp3]; + break; + case Resp48: + case Resp48busy: + resp[0] = r[Resp0]; + break; + case Respnone: + resp[0] = 0; + break; + } + if((c & Respmask) == Resp48busy){ + tsleep(&sdhost.r, datadone, 0, 3000); + } + switch(cmd) { + case MMCSelect: + /* + * Once card is selected, use faster clock + */ + delay(1); + sdhostclock(SDfreq); + delay(1); + break; + case Setbuswidth: + if(sdhost.appcmd){ + /* + * If card bus width changes, change host bus width + */ + switch(arg){ + case 0: + WR(Hconfig, r[Hconfig] & ~Extbus4); + break; + case 2: + WR(Hconfig, r[Hconfig] | Extbus4); + break; + } + }else{ + /* + * If card switched into high speed mode, increase clock speed + */ + if((arg&0x8000000F) == 0x80000001){ + delay(1); + sdhostclock(SDfreqhs); + delay(1); + } + } + break; + } + sdhost.appcmd = (cmd == Appcmd); + return 0; +} + +void +sdhostiosetup(int write, void *buf, int bsize, int bcount) +{ + USED(write); + USED(buf); + + sdhost.bcount = bcount; + WR(Blksize, bsize); + WR(Blkcount, bcount); +} + +static void +sdhostio(int write, uchar *buf, int len) +{ + u32int *r; + int piolen; + u32int w; + + r = (u32int*)SDHOSTREGS; + assert((len&3) == 0); + assert((PTR2UINT(buf)&3) == 0); + okay(1); + if(waserror()){ + okay(0); + nexterror(); + } + /* + * According to comments in the linux driver, the hardware "doesn't + * manage the FIFO DREQs properly for multi-block transfers" on input, + * so the dma must be stopped early and the last 3 words fetched with pio + */ + piolen = 0; + if(!write && sdhost.bcount > 1){ + piolen = (FifoDepth-1) * sizeof(u32int); + len -= piolen; + } + if(write) + dmastart(DmaChanSdhost, DmaDevSdhost, DmaM2D, + buf, &r[Data], len); + else + dmastart(DmaChanSdhost, DmaDevSdhost, DmaD2M, + &r[Data], buf, len); + if(dmawait(DmaChanSdhost) < 0) + error(Eio); + if(!write){ + cachedinvse(buf, len); + buf += len; + for(; piolen > 0; piolen -= sizeof(u32int)){ + if((r[Dbgmode] & 0x1F00) == 0){ + print("sdhost: FIFO empty after short dma read\n"); + error(Eio); + } + w = r[Data]; + *((u32int*)buf) = w; + buf += sizeof(u32int); + } + } + poperror(); + okay(0); +} + +static void +sdhostinterrupt(Ureg*, void*) +{ + u32int *r; + int i; + + r = (u32int*)SDHOSTREGS; + i = r[Status]; + WR(Status, i); + if(i & Busyint){ + sdhost.done = 1; + wakeup(&sdhost.r); + } +} + +SDio sdiohost = { + "sdhost", + sdhostinit, + sdhostenable, + sdhostinquiry, + sdhostcmd, + sdhostiosetup, + sdhostio, +}; + +void +sdhostlink(void) +{ + sdcardlink = &sdiohost; +} diff --git a/sys/src/9/bcm/sdmmc.c b/sys/src/9/bcm/sdmmc.c new file mode 100644 index 0000000000..580729464c --- /dev/null +++ b/sys/src/9/bcm/sdmmc.c @@ -0,0 +1,355 @@ +/* + * mmc / sd memory card + * + * Copyright © 2012 Richard Miller + * + * Assumes only one card on the bus + */ + +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include "../port/sd.h" + +#define CSD(end, start) rbits(csd, start, (end)-(start)+1) + +typedef struct Ctlr Ctlr; + +enum { + Inittimeout = 15, + Multiblock = 1, + + /* Commands */ + GO_IDLE_STATE = 0, + ALL_SEND_CID = 2, + SEND_RELATIVE_ADDR= 3, + SWITCH_FUNC = 6, + SELECT_CARD = 7, + SD_SEND_IF_COND = 8, + SEND_CSD = 9, + STOP_TRANSMISSION= 12, + SEND_STATUS = 13, + SET_BLOCKLEN = 16, + READ_SINGLE_BLOCK= 17, + READ_MULTIPLE_BLOCK= 18, + WRITE_BLOCK = 24, + WRITE_MULTIPLE_BLOCK= 25, + APP_CMD = 55, /* prefix for following app-specific commands */ + SET_BUS_WIDTH = 6, + SD_SEND_OP_COND = 41, + + /* Command arguments */ + /* SD_SEND_IF_COND */ + Voltage = 1<<8, + Checkpattern = 0x42, + + /* SELECT_CARD */ + Rcashift = 16, + + /* SD_SEND_OP_COND */ + Hcs = 1<<30, /* host supports SDHC & SDXC */ + Ccs = 1<<30, /* card is SDHC or SDXC */ + V3_3 = 3<<20, /* 3.2-3.4 volts */ + + /* SET_BUS_WIDTH */ + Width1 = 0<<0, + Width4 = 2<<0, + + /* SWITCH_FUNC */ + Dfltspeed = 0<<0, + Hispeed = 1<<0, + Checkfunc = 0x00FFFFF0, + Setfunc = 0x80FFFFF0, + Funcbytes = 64, + + /* OCR (operating conditions register) */ + Powerup = 1<<31, +}; + +struct Ctlr { + SDev *dev; + SDio *io; + /* SD card registers */ + u16int rca; + u32int ocr; + u32int cid[4]; + u32int csd[4]; +}; + +SDio *sdcardlink; + +extern SDifc sdmmcifc; + +static uint +rbits(u32int *p, uint start, uint len) +{ + uint w, off, v; + + w = start / 32; + off = start % 32; + if(off == 0) + v = p[w]; + else + v = p[w] >> off | p[w+1] << (32-off); + if(len < 32) + return v & ((1<secsize = 1 << CSD(83, 80); + switch(CSD(127, 126)){ + case 0: /* CSD version 1 */ + csize = CSD(73, 62); + mult = CSD(49, 47); + unit->sectors = (csize+1) * (1<<(mult+2)); + break; + case 1: /* CSD version 2 */ + csize = CSD(69, 48); + unit->sectors = (csize+1) * 512LL*KiB / unit->secsize; + break; + } + if(unit->secsize == 1024){ + unit->sectors <<= 1; + unit->secsize = 512; + } +} + +static SDev* +mmcpnp(void) +{ + SDev *sdev; + Ctlr *ctl; + + if(sdcardlink == nil) + sdcardlink = &sdio; + if(sdcardlink->init() < 0) + return nil; + sdev = malloc(sizeof(SDev)); + if(sdev == nil) + return nil; + ctl = malloc(sizeof(Ctlr)); + if(ctl == nil){ + free(sdev); + return nil; + } + sdev->idno = 'M'; + sdev->ifc = &sdmmcifc; + sdev->nunit = 1; + sdev->ctlr = ctl; + ctl->dev = sdev; + ctl->io = sdcardlink; + return sdev; +} + +static int +mmcverify(SDunit *unit) +{ + int n; + Ctlr *ctl; + + ctl = unit->dev->ctlr; + n = ctl->io->inquiry((char*)&unit->inquiry[8], sizeof(unit->inquiry)-8); + if(n < 0) + return 0; + unit->inquiry[0] = SDperdisk; + unit->inquiry[1] = SDinq1removable; + unit->inquiry[4] = sizeof(unit->inquiry)-4; + return 1; +} + +static int +mmcenable(SDev* dev) +{ + Ctlr *ctl; + + ctl = dev->ctlr; + ctl->io->enable(); + return 1; +} + +static void +mmcswitchfunc(SDio *io, int arg) +{ + uchar *buf; + int n; + u32int r[4]; + + n = Funcbytes; + buf = sdmalloc(n); + if(waserror()){ + print("mmcswitchfunc error\n"); + sdfree(buf); + nexterror(); + } + io->iosetup(0, buf, n, 1); + io->cmd(SWITCH_FUNC, arg, r); + io->io(0, buf, n); + sdfree(buf); + poperror(); +} + +static int +mmconline(SDunit *unit) +{ + int hcs, i; + u32int r[4]; + Ctlr *ctl; + SDio *io; + + ctl = unit->dev->ctlr; + io = ctl->io; + assert(unit->subno == 0); + + if(waserror()){ + unit->sectors = 0; + return 0; + } + if(unit->sectors != 0){ + io->cmd(SEND_STATUS, ctl->rca<sectors = 0; + poperror(); + return 2; + } + io->cmd(GO_IDLE_STATE, 0, r); + hcs = 0; + if(!waserror()){ + io->cmd(SD_SEND_IF_COND, Voltage|Checkpattern, r); + if(r[0] == (Voltage|Checkpattern)) /* SD 2.0 or above */ + hcs = Hcs; + poperror(); + } + for(i = 0; i < Inittimeout; i++){ + delay(100); + io->cmd(APP_CMD, 0, r); + io->cmd(SD_SEND_OP_COND, hcs|V3_3, r); + if(r[0] & Powerup) + break; + } + if(i == Inittimeout){ + print("sdmmc: card won't power up\n"); + error(Eio); + } + poperror(); + ctl->ocr = r[0]; + io->cmd(ALL_SEND_CID, 0, r); + memmove(ctl->cid, r, sizeof ctl->cid); + io->cmd(SEND_RELATIVE_ADDR, 0, r); + ctl->rca = r[0]>>16; + io->cmd(SEND_CSD, ctl->rca<csd, r, sizeof ctl->csd); + identify(unit, ctl->csd); + io->cmd(SELECT_CARD, ctl->rca<cmd(SET_BLOCKLEN, unit->secsize, r); + io->cmd(APP_CMD, ctl->rca<cmd(SET_BUS_WIDTH, Width4, r); + if(!waserror()){ + mmcswitchfunc(io, Hispeed|Setfunc); + poperror(); + } + poperror(); + return 1; +} + +static int +mmcrctl(SDunit *unit, char *p, int l) +{ + Ctlr *ctl; + int i, n; + + ctl = unit->dev->ctlr; + assert(unit->subno == 0); + if(unit->sectors == 0){ + mmconline(unit); + if(unit->sectors == 0) + return 0; + } + n = snprint(p, l, "rca %4.4ux ocr %8.8ux\ncid ", ctl->rca, ctl->ocr); + for(i = nelem(ctl->cid)-1; i >= 0; i--) + n += snprint(p+n, l-n, "%8.8ux", ctl->cid[i]); + n += snprint(p+n, l-n, " csd "); + for(i = nelem(ctl->csd)-1; i >= 0; i--) + n += snprint(p+n, l-n, "%8.8ux", ctl->csd[i]); + n += snprint(p+n, l-n, "\ngeometry %llud %ld %lld 255 63\n", + unit->sectors, unit->secsize, unit->sectors / (255*63)); + return n; +} + +static long +mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno) +{ + int len, tries; + ulong b; + u32int r[4]; + uchar *buf; + Ctlr *ctl; + SDio *io; + + USED(lun); + ctl = unit->dev->ctlr; + io = ctl->io; + assert(unit->subno == 0); + if(unit->sectors == 0) + error("media change"); + buf = data; + len = unit->secsize; + if(Multiblock){ + b = bno; + tries = 0; + while(waserror()) + if(++tries == 3) + nexterror(); + io->iosetup(write, buf, len, nb); + if(waserror()){ + io->cmd(STOP_TRANSMISSION, 0, r); + nexterror(); + } + io->cmd(write? WRITE_MULTIPLE_BLOCK: READ_MULTIPLE_BLOCK, + ctl->ocr & Ccs? b: b * len, r); + io->io(write, buf, nb * len); + poperror(); + io->cmd(STOP_TRANSMISSION, 0, r); + poperror(); + b += nb; + }else{ + for(b = bno; b < bno + nb; b++){ + io->iosetup(write, buf, len, 1); + io->cmd(write? WRITE_BLOCK : READ_SINGLE_BLOCK, + ctl->ocr & Ccs? b: b * len, r); + io->io(write, buf, len); + buf += len; + } + } + return (b - bno) * len; +} + +static int +mmcrio(SDreq*) +{ + return -1; +} + +SDifc sdmmcifc = { + .name = "mmc", + .pnp = mmcpnp, + .enable = mmcenable, + .verify = mmcverify, + .online = mmconline, + .rctl = mmcrctl, + .bio = mmcbio, + .rio = mmcrio, +}; diff --git a/sys/src/9/bcm/spi.c b/sys/src/9/bcm/spi.c new file mode 100644 index 0000000000..1abc6dcad5 --- /dev/null +++ b/sys/src/9/bcm/spi.c @@ -0,0 +1,149 @@ +/* + * bcm2835 spi controller + */ + +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#define SPIREGS (VIRTIO+0x204000) +#define SPI0_CE1_N 7 /* P1 pin 26 */ +#define SPI0_CE0_N 8 /* P1 pin 24 */ +#define SPI0_MISO 9 /* P1 pin 21 */ +#define SPI0_MOSI 10 /* P1 pin 19 */ +#define SPI0_SCLK 11 /* P1 pin 23 */ + +typedef struct Ctlr Ctlr; +typedef struct Spiregs Spiregs; + +/* + * Registers for main SPI controller + */ +struct Spiregs { + u32int cs; /* control and status */ + u32int data; + u32int clkdiv; + u32int dlen; + u32int lossitoh; + u32int dmactl; +}; + +/* + * Per-controller info + */ +struct Ctlr { + Spiregs *regs; + QLock lock; + Lock reglock; + Rendez r; +}; + +static Ctlr spi; + +enum { + /* cs */ + Lossi32bit = 1<<25, + Lossidma = 1<<24, + Cspol2 = 1<<23, + Cspol1 = 1<<22, + Cspol0 = 1<<21, + Rxf = 1<<20, + Rxr = 1<<19, + Txd = 1<<18, + Rxd = 1<<17, + Done = 1<<16, + Lossi = 1<<13, + Ren = 1<<12, + Adcs = 1<<11, /* automatically deassert chip select (dma) */ + Intr = 1<<10, + Intd = 1<<9, + Dmaen = 1<<8, + Ta = 1<<7, + Cspol = 1<<6, + Rxclear = 1<<5, + Txclear = 1<<4, + Cpol = 1<<3, + Cpha = 1<<2, + Csmask = 3<<0, + Csshift = 0, + + /* dmactl */ + Rpanicshift = 24, + Rdreqshift = 16, + Tpanicshift = 8, + Tdreqshift = 0, +}; + +static void +spiinit(void) +{ + spi.regs = (Spiregs*)SPIREGS; + spi.regs->clkdiv = 250; /* 1 MHz */ + gpiosel(SPI0_MISO, Alt0); + gpiosel(SPI0_MOSI, Alt0); + gpiosel(SPI0_SCLK, Alt0); + gpiosel(SPI0_CE0_N, Alt0); + gpiosel(SPI0_CE1_N, Alt0); +} + +void +spimode(int mode) +{ + if(spi.regs == 0) + spiinit(); + spi.regs->cs = (spi.regs->cs & ~(Cpha | Cpol)) | (mode << 2); +} + +/* + * According the Broadcom docs, the divisor has to + * be a power of 2, but an errata says that should + * be multiple of 2 and scope observations confirm + * that restricting it to a power of 2 is unnecessary. + */ +void +spiclock(uint mhz) +{ + if(spi.regs == 0) + spiinit(); + if(mhz == 0) { + spi.regs->clkdiv = 32768; /* about 8 KHz */ + return; + } + spi.regs->clkdiv = 2 * ((125 + (mhz - 1)) / mhz); +} + +void +spirw(uint cs, void *buf, int len) +{ + Spiregs *r; + + assert(cs <= 2); + assert(len < (1<<16)); + qlock(&spi.lock); + if(waserror()){ + qunlock(&spi.lock); + nexterror(); + } + if(spi.regs == 0) + spiinit(); + r = spi.regs; + r->dlen = len; + r->cs = (r->cs & (Cpha | Cpol)) | (cs << Csshift) | Rxclear | Txclear | Dmaen | Adcs | Ta; + /* + * Start write channel before read channel - cache wb before inv + */ + dmastart(DmaChanSpiTx, DmaDevSpiTx, DmaM2D, + buf, &r->data, len); + dmastart(DmaChanSpiRx, DmaDevSpiRx, DmaD2M, + &r->data, buf, len); + if(dmawait(DmaChanSpiRx) < 0) + error(Eio); + cachedinvse(buf, len); + r->cs &= (Cpha | Cpol); + qunlock(&spi.lock); + poperror(); +} diff --git a/sys/src/9/bcm/trap.c b/sys/src/9/bcm/trap.c index d785096184..310971b751 100644 --- a/sys/src/9/bcm/trap.c +++ b/sys/src/9/bcm/trap.c @@ -13,6 +13,7 @@ #include "arm.h" #define INTREGS (VIRTIO+0xB200) +#define LOCALREGS (VIRTIO+IOSIZE) typedef struct Intregs Intregs; typedef struct Vctl Vctl; @@ -22,6 +23,10 @@ enum { Nvec = 8, /* # of vectors at start of lexception.s */ Fiqenable = 1<<7, + + Localtimerint = 0x40, + Localmboxint = 0x50, + Localintpending = 0x60, }; /* @@ -48,12 +53,14 @@ struct Intregs { struct Vctl { Vctl *next; int irq; + int cpu; u32int *reg; u32int mask; void (*f)(Ureg*, void*); void *a; }; +static Lock vctllock; static Vctl *vctl, *vfiq; static char *trapnames[PsrMask+1] = { @@ -77,14 +84,16 @@ trapinit(void) { Vpage0 *vpage0; - /* disable everything */ - intrsoff(); - - /* set up the exception vectors */ - vpage0 = (Vpage0*)HVECTORS; - memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); - memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); - cacheuwbinv(); + if (m->machno == 0) { + /* disable everything */ + intrsoff(); + /* set up the exception vectors */ + vpage0 = (Vpage0*)HVECTORS; + memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); + memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); + cacheuwbinv(); + l2cacheuwbinv(); + } /* set up the stacks for the interrupt modes */ setr13(PsrMfiq, (u32int*)(FIQSTKTOP)); @@ -96,6 +105,21 @@ trapinit(void) coherence(); } +void +intrcpushutdown(void) +{ + u32int *enable; + + if(soc.armlocal == 0) + return; + enable = (u32int*)(LOCALREGS + Localtimerint) + m->machno; + *enable = 0; + if(m->machno){ + enable = (u32int*)(LOCALREGS + Localmboxint) + m->machno; + *enable = 1; + } +} + void intrsoff(void) { @@ -110,6 +134,30 @@ intrsoff(void) ip->FIQctl = 0; } +/* called from cpu0 after other cpus are shutdown */ +void +intrshutdown(void) +{ + intrsoff(); + intrcpushutdown(); +} + +static void +intrtime(void) +{ + ulong diff; + ulong x; + + x = perfticks(); + diff = x - m->perf.intrts; + m->perf.intrts = 0; + + m->perf.inintr += diff; + if(up == nil && m->perf.inidle > diff) + m->perf.inidle -= diff; +} + + /* * called by trap to handle irq interrupts. * returns true iff a clock interrupt, thus maybe reschedule. @@ -119,16 +167,23 @@ irq(Ureg* ureg) { Vctl *v; int clockintr; + int found; + m->perf.intrts = perfticks(); clockintr = 0; + found = 0; for(v = vctl; v; v = v->next) - if(*v->reg & v->mask){ + if(v->cpu == m->machno && (*v->reg & v->mask) != 0){ + found = 1; coherence(); v->f(ureg, v->a); coherence(); - if(v->irq == IRQclock) + if(v->irq == IRQclock || v->irq == IRQcntps || v->irq == IRQcntpns) clockintr = 1; } + if(!found) + m->spuriousintr++; + intrtime(); return clockintr; } @@ -139,15 +194,24 @@ void fiq(Ureg *ureg) { Vctl *v; + int inintr; + if(m->perf.intrts) + inintr = 1; + else{ + inintr = 0; + m->perf.intrts = perfticks(); + } v = vfiq; if(v == nil) - panic("unexpected item in bagging area"); + panic("cpu%d: unexpected item in bagging area", m->machno); m->intr++; ureg->pc -= 4; coherence(); v->f(ureg, v->a); coherence(); + if(!inintr) + intrtime(); } void @@ -162,7 +226,16 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) if(v == nil) panic("irqenable: no mem"); v->irq = irq; - if(irq >= IRQbasic){ + v->cpu = 0; + if(irq >= IRQlocal){ + v->reg = (u32int*)(LOCALREGS + Localintpending) + m->machno; + if(irq >= IRQmbox0) + enable = (u32int*)(LOCALREGS + Localmboxint) + m->machno; + else + enable = (u32int*)(LOCALREGS + Localtimerint) + m->machno; + v->mask = 1 << (irq - IRQlocal); + v->cpu = m->machno; + }else if(irq >= IRQbasic){ enable = &ip->ARMenable; v->reg = &ip->ARMpending; v->mask = 1 << (irq - IRQbasic); @@ -173,6 +246,7 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) } v->f = f; v->a = a; + lock(&vctllock); if(irq == IRQfiq){ assert((ip->FIQctl & Fiqenable) == 0); assert((*enable & v->mask) == 0); @@ -181,8 +255,15 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) }else{ v->next = vctl; vctl = v; - *enable = v->mask; + if(irq >= IRQmbox0){ + if(irq <= IRQmbox3) + *enable |= 1 << (irq - IRQmbox0); + }else if(irq >= IRQlocal) + *enable |= 1 << (irq - IRQlocal); + else + *enable = v->mask; } + unlock(&vctllock); } static char * @@ -226,8 +307,8 @@ faultarm(Ureg *ureg, uintptr va, int user, int read) char buf[ERRMAX]; if(up == nil) { - dumpregs(ureg); - panic("fault: nil up in faultarm, accessing %#p", va); + //dumpregs(ureg); + panic("fault: nil up in faultarm, pc %#p accessing %#p", ureg->pc, va); } insyscall = up->insyscall; up->insyscall = 1; @@ -308,8 +389,8 @@ trap(Ureg *ureg) clockintr = 0; /* if set, may call sched() before return */ switch(ureg->type){ default: - panic("unknown trap; type %#lux, psr mode %#lux", ureg->type, - ureg->psr & PsrMask); + panic("unknown trap; type %#lux, psr mode %#lux pc %lux", ureg->type, + ureg->psr & PsrMask, ureg->pc); break; case PsrMirq: clockintr = irq(ureg); @@ -320,10 +401,9 @@ trap(Ureg *ureg) fsr = (x>>7) & 0x8 | x & 0x7; switch(fsr){ case 0x02: /* instruction debug event (BKPT) */ - if(user){ - snprint(buf, sizeof buf, "sys: breakpoint"); - postnote(up, 1, buf, NDebug); - }else{ + if(user) + postnote(up, 1, "sys: breakpoint", NDebug); + else{ iprint("kernel bkpt: pc %#lux inst %#ux\n", ureg->pc, *(u32int*)ureg->pc); panic("kernel bkpt"); @@ -352,8 +432,7 @@ trap(Ureg *ureg) case 0x3: /* access flag fault (section) */ if(user){ snprint(buf, sizeof buf, - "sys: alignment: pc %#lux va %#p\n", - ureg->pc, va); + "sys: alignment: va %#p", va); postnote(up, 1, buf, NDebug); } else panic("kernel alignment: pc %#lux va %#p", ureg->pc, va); @@ -389,8 +468,7 @@ trap(Ureg *ureg) /* domain fault, accessing something we shouldn't */ if(user){ snprint(buf, sizeof buf, - "sys: access violation: pc %#lux va %#p\n", - ureg->pc, va); + "sys: access violation: va %#p", va); postnote(up, 1, buf, NDebug); } else panic("kernel access violation: pc %#lux va %#p", @@ -411,12 +489,8 @@ trap(Ureg *ureg) else{ /* look for floating point instructions to interpret */ rv = fpuemu(ureg); - if(rv == 0){ - snprint(buf, sizeof buf, - "undefined instruction: pc %#lux\n", - ureg->pc); - postnote(up, 1, buf, NDebug); - } + if(rv == 0) + postnote(up, 1, "sys: undefined instruction", NDebug); } }else{ if (ureg->pc & 3) { @@ -524,13 +598,21 @@ dumpstackwithureg(Ureg *ureg) * Fill in enough of Ureg to get a stack trace, and call a function. * Used by debugging interface rdb. */ + +static void +getpcsp(ulong *pc, ulong *sp) +{ + *pc = getcallerpc(&pc); + *sp = (ulong)&pc-4; +} + void callwithureg(void (*fn)(Ureg*)) { Ureg ureg; - ureg.pc = getcallerpc(&fn); - ureg.sp = PTR2UINT(&fn); + getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp); + ureg.r14 = getcallerpc(&fn); fn(&ureg); } diff --git a/sys/src/9/bcm/trap4.c b/sys/src/9/bcm/trap4.c new file mode 100644 index 0000000000..ca53cb2b92 --- /dev/null +++ b/sys/src/9/bcm/trap4.c @@ -0,0 +1,993 @@ +/* + * Adapted from ../teg2/trap.c + * + * arm mpcore generic interrupt controller (gic) v1 + * traps, exceptions, interrupts, system calls. + * + * there are two pieces: the interrupt distributor and the cpu interface. + * + * memset or memmove on any of the distributor registers generates an + * exception like this one: + * panic: external abort 0x28 pc 0xc048bf68 addr 0x50041800 + * + * we use l1 and l2 cache ops to force vectors to be visible everywhere. + * + * apparently irqs 0—15 (SGIs) are always enabled. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#include "ureg.h" +#include "arm.h" + +#define IRQLOCAL(irq) ((irq) - IRQlocal + 13 + 16) +#define IRQGLOBAL(irq) ((irq) + 64 + 32) + +#define ISSGI(irq) ((uint)(irq) < Nppi) + +enum { + Debug = 0, + + Intrdist = 0x41000, + Intrcpu = 0x42000, + + Nvec = 8, /* # of vectors at start of lexception.s */ + Bi2long = BI2BY * sizeof(long), + Nirqs = 1024, + Nsgi = 16, /* software-generated (inter-processor) intrs */ + Nppi = 32, /* sgis + other private peripheral intrs */ +}; + +typedef struct Intrcpuregs Intrcpuregs; +typedef struct Intrdistregs Intrdistregs; + +/* + * almost this entire register set is buggered. + * the distributor is supposed to be per-system, not per-cpu, + * yet some registers are banked per-cpu, as marked. + */ +struct Intrdistregs { /* distributor */ + ulong ctl; + ulong ctlrtype; + ulong distid; + uchar _pad0[0x80 - 0xc]; + + /* botch: *[0] are banked per-cpu from here */ + /* bit maps */ + ulong grp[32]; /* in group 1 (non-secure) */ + ulong setena[32]; /* forward to cpu interfaces */ + ulong clrena[32]; + ulong setpend[32]; + ulong clrpend[32]; + ulong setact[32]; /* active? */ + ulong clract[32]; + /* botch: *[0] are banked per-cpu until here */ + + uchar pri[1020]; /* botch: pri[0] — pri[7] are banked per-cpu */ + ulong _rsrvd1; + /* botch: targ[0] through targ[7] are banked per-cpu and RO */ + uchar targ[1020]; /* byte bit maps: cpu targets indexed by intr */ + ulong _rsrvd2; + /* botch: cfg[1] is banked per-cpu */ + ulong cfg[64]; /* bit pairs: edge? 1-N? */ + ulong _pad1[64]; + ulong nsac[64]; /* bit pairs (v2 only) */ + + /* software-generated intrs (a.k.a. sgi) */ + ulong swgen; /* intr targets */ + uchar _pad2[0xf10 - 0xf04]; + uchar clrsgipend[16]; /* bit map (v2 only) */ + uchar setsgipend[16]; /* bit map (v2 only) */ +}; + +enum { + /* ctl bits */ + Forw2cpuif = 1, + + /* ctlrtype bits */ + Cpunoshft = 5, + Cpunomask = MASK(3), + Intrlines = MASK(5), + + /* cfg bits */ + Level = 0<<1, + Edge = 1<<1, /* edge-, not level-sensitive */ + Toall = 0<<0, + To1 = 1<<0, /* vs. to all */ + + /* swgen bits */ + Totargets = 0, + Tonotme = 1<<24, + Tome = 2<<24, +}; + +/* each cpu sees its own registers at the same base address ((ARMLOCAL+Intrcpu)) */ +struct Intrcpuregs { + ulong ctl; + ulong primask; + + ulong binpt; /* group pri vs subpri split */ + ulong ack; + ulong end; + ulong runpri; + ulong hipripend; + + /* aliased regs (secure, for group 1) */ + ulong alibinpt; + ulong aliack; /* (v2 only) */ + ulong aliend; /* (v2 only) */ + ulong alihipripend; /* (v2 only) */ + + uchar _pad0[0xd0 - 0x2c]; + ulong actpri[4]; /* (v2 only) */ + ulong nsactpri[4]; /* (v2 only) */ + + uchar _pad0[0xfc - 0xf0]; + ulong ifid; /* ro */ + + uchar _pad0[0x1000 - 0x100]; + ulong deact; /* wo (v2 only) */ +}; + +enum { + /* ctl bits */ + Enable = 1, + Eoinodeact = 1<<9, /* (v2 only) */ + + /* (ali) ack/end/hipriend/deact bits */ + Intrmask = MASK(10), + Cpuidshift = 10, + Cpuidmask = MASK(3), + + /* ifid bits */ + Archversshift = 16, + Archversmask = MASK(4), +}; + +typedef struct Vctl Vctl; +typedef struct Vctl { + Vctl* next; /* handlers on this vector */ + char *name; /* of driver, xallocated */ + void (*f)(Ureg*, void*); /* handler to call */ + void* a; /* argument to call it with */ +} Vctl; + +static Lock vctllock; +static Vctl* vctl[Nirqs]; + +/* + * Layout at virtual address 0. + */ +typedef struct Vpage0 { + void (*vectors[Nvec])(void); + u32int vtable[Nvec]; +} Vpage0; + +enum +{ + Ntimevec = 20 /* number of time buckets for each intr */ +}; +ulong intrtimes[Nirqs][Ntimevec]; + +int irqtooearly = 0; + +static ulong shadena[32]; /* copy of enable bits, saved by intcmaskall */ +static Lock distlock; + +extern int notify(Ureg*); + +static void dumpstackwithureg(Ureg *ureg); + +void +printrs(int base, ulong word) +{ + int bit; + + for (bit = 0; word; bit++, word >>= 1) + if (word & 1) + iprint(" %d", base + bit); +} + +void +dumpintrs(char *what, ulong *bits) +{ + int i, first, some; + ulong word; + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + first = 1; + some = 0; + USED(idp); + for (i = 0; i < nelem(idp->setpend); i++) { + word = bits[i]; + if (word) { + if (first) { + first = 0; + iprint("%s", what); + } + some = 1; + printrs(i * Bi2long, word); + } + } + if (!some) + iprint("%s none", what); + iprint("\n"); +} + +void +dumpintrpend(void) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + iprint("\ncpu%d gic regs:\n", m->machno); + dumpintrs("group 1", idp->grp); + dumpintrs("enabled", idp->setena); + dumpintrs("pending", idp->setpend); + dumpintrs("active ", idp->setact); +} + +/* + * keep histogram of interrupt service times + */ +void +intrtime(Mach*, int vno) +{ + ulong diff; + ulong x; + + x = perfticks(); + diff = x - m->perf.intrts; + m->perf.intrts = x; + + m->perf.inintr += diff; + if(up == nil && m->perf.inidle > diff) + m->perf.inidle -= diff; + + if (m->cpumhz == 0) + return; /* don't divide by zero */ + diff /= m->cpumhz*100; /* quantum = 100µsec */ + if(diff >= Ntimevec) + diff = Ntimevec-1; + if ((uint)vno >= Nirqs) + vno = Nirqs-1; + intrtimes[vno][diff]++; +} + +static ulong +intack(Intrcpuregs *icp) +{ + return icp->ack & Intrmask; +} + +static void +intdismiss(Intrcpuregs *icp, ulong ack) +{ + icp->end = ack; + coherence(); +} + +static int +irqinuse(uint irq) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + return idp->setena[irq / Bi2long] & (1 << (irq % Bi2long)); +} + +void +intcunmask(uint irq) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + ilock(&distlock); + idp->setena[irq / Bi2long] = 1 << (irq % Bi2long); + iunlock(&distlock); +} + +void +intcmask(uint irq) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + ilock(&distlock); + idp->clrena[irq / Bi2long] = 1 << (irq % Bi2long); + iunlock(&distlock); +} + +static void +intcmaskall(Intrdistregs *idp) /* mask all intrs for all cpus */ +{ + int i; + + for (i = 0; i < nelem(idp->setena); i++) + shadena[i] = idp->setena[i]; + for (i = 0; i < nelem(idp->clrena); i++) + idp->clrena[i] = ~0; + coherence(); +} + +static void +intcunmaskall(Intrdistregs *idp) /* unused */ +{ + int i; + + for (i = 0; i < nelem(idp->setena); i++) + idp->setena[i] = shadena[i]; + coherence(); +} + +static ulong +permintrs(Intrdistregs *idp, int base, int r) +{ + ulong perms; + + idp->clrena[r] = ~0; /* disable all */ + coherence(); + perms = idp->clrena[r]; + if (perms) { + iprint("perm intrs:"); + printrs(base, perms); + iprint("\n"); + } + return perms; +} + +static void +intrcfg(Intrdistregs *idp) +{ + int i, cpumask; + ulong pat; + + /* set up all interrupts as level-sensitive, to one cpu (0) */ + pat = 0; + for (i = 0; i < Bi2long; i += 2) + pat |= (Level | To1) << i; + + if (m->machno == 0) { /* system-wide & cpu0 cfg */ + for (i = 0; i < nelem(idp->grp); i++) + idp->grp[i] = 0; /* secure */ + for (i = 0; i < nelem(idp->pri); i++) + idp->pri[i] = 0; /* highest priority */ + /* set up all interrupts as level-sensitive, to one cpu (0) */ + for (i = 0; i < nelem(idp->cfg); i++) + idp->cfg[i] = pat; + /* first Nppi are read-only for SGIs and PPIs */ + cpumask = 1<<0; /* just cpu 0 */ + for (i = Nppi; i < sizeof idp->targ; i++) + idp->targ[i] = cpumask; + coherence(); + + intcmaskall(idp); + for (i = 0; i < nelem(idp->clrena); i++) { + // permintrs(idp, i * Bi2long, i); + idp->clrpend[i] = idp->clract[i] = idp->clrena[i] = ~0; + } + } else { /* per-cpu config */ + idp->grp[0] = 0; /* secure */ + for (i = 0; i < 8; i++) + idp->pri[i] = 0; /* highest priority */ + /* idp->targ[0 through Nppi-1] are supposed to be read-only */ + for (i = 0; i < Nppi; i++) + idp->targ[i] = 1<machno; + idp->cfg[1] = pat; + coherence(); + + // permintrs(idp, i * Bi2long, i); + idp->clrpend[0] = idp->clract[0] = idp->clrena[0] = ~0; + /* on cpu1, irq Extpmuirq (118) is always pending here */ + } + coherence(); +} + +void +intrto(int cpu, int irq) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + /* first Nppi are read-only for SGIs and the like */ + ilock(&distlock); + idp->targ[irq] = 1 << cpu; + iunlock(&distlock); +} + +void +intrsto(int cpu) /* unused */ +{ + int i; + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + /* first Nppi are read-only for SGIs and the like */ + for (i = Nppi; i < sizeof idp->targ; i++) + intrto(cpu, i); + USED(idp); +} + +void +intrcpu(int cpu) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + ilock(&distlock); + idp->swgen = Totargets | 1 << (cpu + 16) | m->machno; + iunlock(&distlock); +} + +/* + * set up for exceptions + */ +void +trapinit(void) +{ + int s; + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + Intrcpuregs *icp = (Intrcpuregs *)(ARMLOCAL+Intrcpu); + Vpage0 *vpage0; + enum { Vecsize = sizeof vpage0->vectors + sizeof vpage0->vtable, }; + + /* + * set up the exception vectors, high and low. + * + * we can't use cache ops on HVECTORS address, since they + * work on virtual addresses, and only those that have a + * physical address == PADDR(virtual). + */ + if (m->machno == 0) { + vpage0 = (Vpage0*)HVECTORS; + memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); + memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); + + vpage0 = (Vpage0*)KADDR(0); + memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); + memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); + + cacheuwbinv(); + l2cacheuwbinv(); + } + + /* + * set up the stack pointers for the exception modes for this cpu. + * they point to small `save areas' in Mach, not actual stacks. + */ + s = splhi(); /* make these modes ignore intrs too */ + setr13(PsrMfiq, (u32int*)(FIQSTKTOP)); + setr13(PsrMirq, m->sirq); + setr13(PsrMabt, m->sabt); + setr13(PsrMund, m->sund); + setr13(PsrMsys, m->ssys); + splx(s); + + assert((idp->distid & MASK(12)) == 0x43b); /* made by arm */ + assert((icp->ifid & MASK(12)) == 0x43b); /* made by arm */ + + ilock(&distlock); + idp->ctl = 0; + icp->ctl = 0; + coherence(); + + intrcfg(idp); /* some per-cpu cfg here */ + + icp->ctl = Enable; + icp->primask = (uchar)~0; /* let all priorities through */ + coherence(); + + idp->ctl = Forw2cpuif; + iunlock(&distlock); +} + +void +intrsoff(void) +{ + ilock(&distlock); + intcmaskall((Intrdistregs *)(ARMLOCAL+Intrdist)); + iunlock(&distlock); +} + +void +intrcpushutdown(void) +{ + Intrcpuregs *icp = (Intrcpuregs *)(ARMLOCAL+Intrcpu); + + icp->ctl = 0; + icp->primask = 0; /* let no priorities through */ + coherence(); +} + +/* called from cpu0 after other cpus are shutdown */ +void +intrshutdown(void) +{ + Intrdistregs *idp = (Intrdistregs *)(ARMLOCAL+Intrdist); + + intrsoff(); + idp->ctl = 0; + intrcpushutdown(); +} + +/* + * enable an irq interrupt + * note that the same private interrupt may be enabled on multiple cpus + */ +void +irqenable(int irq, void (*f)(Ureg*, void*), void* a) +{ + Vctl *v; + int ena; + static char name[] = "anon"; + + /* permute irq numbers for pi4 */ + if(irq >= IRQlocal) + irq = IRQLOCAL(irq); + else + irq = IRQGLOBAL(irq); + if(irq >= nelem(vctl)) + panic("irqenable irq %d", irq); + + if (irqtooearly) { + iprint("irqenable for %d %s called too early\n", irq, name); + return; + } + + /* + * if in use, could be a private interrupt on a secondary cpu, + * or a shared irq number (eg emmc and sdhc) + */ + ena = 1; + if(!ISSGI(irq) || vctl[irq] == nil) { + v = malloc(sizeof(Vctl)); + if (v == nil) + panic("irqenable: malloc Vctl"); + v->f = f; + v->a = a; + v->name = malloc(strlen(name)+1); + if (v->name == nil) + panic("irqenable: malloc name"); + strcpy(v->name, name); + + lock(&vctllock); + v->next = vctl[irq]; + if (v->next == nil) + vctl[irq] = v; + else if (!ISSGI(irq)) { + /* shared irq number */ + vctl[irq] = v; + ena = 0; + } else { + /* allocation race: someone else did it first */ + free(v->name); + free(v); + } + unlock(&vctllock); + } + if (ena) { + intdismiss((Intrcpuregs *)(ARMLOCAL+Intrcpu), irq); + intcunmask(irq); + } +} + +/* + * called by trap to handle access faults + */ +static void +faultarm(Ureg *ureg, uintptr va, int user, int read) +{ + int n, insyscall; + + if(up == nil) { + dumpstackwithureg(ureg); + panic("faultarm: cpu%d: nil up, %sing %#p at %#p", + m->machno, (read? "read": "writ"), va, ureg->pc); + } + insyscall = up->insyscall; + up->insyscall = 1; + + n = fault(va, read); /* goes spllo */ + splhi(); + if(n < 0){ + char buf[ERRMAX]; + + if(!user){ + dumpstackwithureg(ureg); + panic("fault: cpu%d: kernel %sing %#p at %#p", + m->machno, read? "read": "writ", va, ureg->pc); + } + /* don't dump registers; programs suicide all the time */ + snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p", + read? "read": "write", va); + postnote(up, 1, buf, NDebug); + } + up->insyscall = insyscall; +} + +/* + * called by trap to handle interrupts. + * returns true iff a clock interrupt, thus maybe reschedule. + */ +static int +irq(Ureg* ureg) +{ + int clockintr, ack; + uint irqno, handled; + Intrcpuregs *icp = (Intrcpuregs *)(ARMLOCAL+Intrcpu); + Vctl *v; + + clockintr = 0; +again: + ack = intack(icp); + irqno = ack & Intrmask; + + if(irqno == 1023) + return clockintr; + if(irqno == IRQGLOBAL(IRQclock) || irqno == IRQLOCAL(IRQcntpns)) + clockintr = 1; + + handled = 0; + for(v = vctl[irqno]; v != nil; v = v->next) + if (v->f) { + if (islo()) + panic("trap: pl0 before trap handler for %s", + v->name); + coherence(); + v->f(ureg, v->a); + coherence(); + if (islo()) + panic("trap: %s lowered pl", v->name); +// splhi(); /* in case v->f lowered pl */ + handled++; + } + if(!handled){ + if (irqno >= 1022){ + iprint("cpu%d: ignoring spurious interrupt\n", m->machno); + return clockintr; + }else { + intcmask(irqno); + iprint("cpu%d: unexpected interrupt %d, now masked\n", + m->machno, irqno); + } + } + + intdismiss(icp, ack); + intrtime(m, irqno); + goto again; +} + +/* + * returns 1 if the instruction writes memory, 0 otherwise + */ +int +writetomem(ulong inst) +{ + /* swap always write memory */ + if((inst & 0x0FC00000) == 0x01000000) + return 1; + + /* loads and stores are distinguished by bit 20 */ + if(inst & (1<<20)) + return 0; + + return 1; +} + +static void +datafault(Ureg *ureg, int user) +{ + int x; + ulong inst, fsr; + uintptr va; + + va = farget(); + + inst = *(ulong*)(ureg->pc); + /* bits 12 and 10 have to be concatenated with status */ + x = fsrget(); + fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf; + switch(fsr){ + default: + case 0xa: /* ? was under external abort */ + panic("unknown data fault, 6b fsr %#lux", fsr); + break; + case 0x0: + panic("vector exception at %#lux", ureg->pc); + break; + case 0x1: /* alignment fault */ + case 0x3: /* access flag fault (section) */ + if(user){ + char buf[ERRMAX]; + + snprint(buf, sizeof buf, + "sys: alignment: pc %#lux va %#p\n", + ureg->pc, va); + postnote(up, 1, buf, NDebug); + } else { + dumpstackwithureg(ureg); + panic("kernel alignment: pc %#lux va %#p", ureg->pc, va); + } + break; + case 0x2: + panic("terminal exception at %#lux", ureg->pc); + break; + case 0x4: /* icache maint fault */ + case 0x6: /* access flag fault (page) */ + case 0x8: /* precise external abort, non-xlat'n */ + case 0x28: + case 0x16: /* imprecise ext. abort, non-xlt'n */ + case 0x36: + panic("external non-translation abort %#lux pc %#lux addr %#p", + fsr, ureg->pc, va); + break; + case 0xc: /* l1 translation, precise ext. abort */ + case 0x2c: + case 0xe: /* l2 translation, precise ext. abort */ + case 0x2e: + panic("external translation abort %#lux pc %#lux addr %#p", + fsr, ureg->pc, va); + break; + case 0x1c: /* l1 translation, precise parity err */ + case 0x1e: /* l2 translation, precise parity err */ + case 0x18: /* imprecise parity or ecc err */ + panic("translation parity error %#lux pc %#lux addr %#p", + fsr, ureg->pc, va); + break; + case 0x5: /* translation fault, no section entry */ + case 0x7: /* translation fault, no page entry */ + faultarm(ureg, va, user, !writetomem(inst)); + break; + case 0x9: + case 0xb: + /* domain fault, accessing something we shouldn't */ + if(user){ + char buf[ERRMAX]; + + snprint(buf, sizeof buf, + "sys: access violation: pc %#lux va %#p\n", + ureg->pc, va); + postnote(up, 1, buf, NDebug); + } else + panic("kernel access violation: pc %#lux va %#p", + ureg->pc, va); + break; + case 0xd: + case 0xf: + /* permission error, copy on write or real permission error */ + faultarm(ureg, va, user, !writetomem(inst)); + break; + } +} + +/* + * here on all exceptions other than syscall (SWI) and reset + */ +void +trap(Ureg *ureg) +{ + int clockintr, user, rem; + uintptr va, ifsr; + + splhi(); /* paranoia */ + if(up != nil) + rem = ((char*)ureg)-up->kstack; + else + rem = ((char*)ureg)-((char*)m+sizeof(Mach)); + if(rem < 1024) { + iprint("trap: %d stack bytes left, up %#p ureg %#p m %#p cpu%d at pc %#lux\n", + rem, up, ureg, m, m->machno, ureg->pc); + dumpstackwithureg(ureg); + panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux", + rem, up, ureg, ureg->pc); + } + + m->perf.intrts = perfticks(); + user = (ureg->psr & PsrMask) == PsrMusr; + if(user){ + up->dbgreg = ureg; + cycles(&up->kentry); + } + + /* + * All interrupts/exceptions should be resumed at ureg->pc-4, + * except for Data Abort which resumes at ureg->pc-8. + */ + if(ureg->type == (PsrMabt+1)) + ureg->pc -= 8; + else + ureg->pc -= 4; + + clockintr = 0; /* if set, may call sched() before return */ + switch(ureg->type){ + default: + panic("unknown trap; type %#lux, psr mode %#lux", ureg->type, + ureg->psr & PsrMask); + break; + case PsrMirq: + m->intr++; + clockintr = irq(ureg); + if(0 && up && !clockintr) + preempted(); /* this causes spurious suicides */ + break; + case PsrMabt: /* prefetch (instruction) fault */ + va = ureg->pc; + ifsr = ifsrget(); + ifsr = (ifsr>>7) & 0x8 | ifsr & 0x7; + switch(ifsr){ + case 0x02: /* instruction debug event (BKPT) */ + if(user) + postnote(up, 1, "sys: breakpoint", NDebug); + else{ + iprint("kernel bkpt: pc %#lux inst %#ux\n", + va, *(u32int*)va); + panic("kernel bkpt"); + } + break; + default: + faultarm(ureg, va, user, 1); + break; + } + break; + case PsrMabt+1: /* data fault */ + datafault(ureg, user); + break; + case PsrMund: /* undefined instruction */ + if(!user) { + if (ureg->pc & 3) { + iprint("rounding fault pc %#lux down to word\n", + ureg->pc); + ureg->pc &= ~3; + } + if (Debug) + iprint("mathemu: cpu%d fpon %d instr %#8.8lux at %#p\n", + m->machno, m->fpon, *(ulong *)ureg->pc, + ureg->pc); + dumpstackwithureg(ureg); + panic("cpu%d: undefined instruction: pc %#lux inst %#ux", + m->machno, ureg->pc, ((u32int*)ureg->pc)[0]); + } else if(seg(up, ureg->pc, 0) != nil && + *(u32int*)ureg->pc == 0xD1200070) + postnote(up, 1, "sys: breakpoint", NDebug); + else if(fpuemu(ureg) == 0){ /* didn't find any FP instrs? */ + char buf[ERRMAX]; + + snprint(buf, sizeof buf, + "undefined instruction: pc %#lux instr %#8.8lux\n", + ureg->pc, *(ulong *)ureg->pc); + postnote(up, 1, buf, NDebug); + } + break; + } + splhi(); + + /* delaysched set because we held a lock or because our quantum ended */ + if(up && up->delaysched && clockintr){ + sched(); /* can cause more traps */ + splhi(); + } + + if(user){ + if(up->procctl || up->nnote) + notify(ureg); + kexit(ureg); + } +} + +/* + * Fill in enough of Ureg to get a stack trace, and call a function. + * Used by debugging interface rdb. + */ +void +callwithureg(void (*fn)(Ureg*)) +{ + Ureg ureg; + + memset(&ureg, 0, sizeof ureg); + ureg.pc = getcallerpc(&fn); + ureg.sp = PTR2UINT(&fn); + fn(&ureg); +} + +static void +dumpstackwithureg(Ureg *ureg) +{ + int x; + uintptr l, v, i, estack; + char *s; + + dumpregs(ureg); + if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){ + iprint("dumpstack disabled\n"); + return; + } + delay(1000); + iprint("dumpstack\n"); + + x = 0; + x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n", + ureg->pc, ureg->sp, ureg->r14); + delay(20); + i = 0; + if(up + && (uintptr)&l >= (uintptr)up->kstack + && (uintptr)&l <= (uintptr)up->kstack+KSTACK) + estack = (uintptr)up->kstack+KSTACK; + else if((uintptr)&l >= (uintptr)m->stack + && (uintptr)&l <= (uintptr)m+MACHSIZE) + estack = (uintptr)m+MACHSIZE; + else + return; + x += iprint("estackx %p\n", estack); + + for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){ + v = *(uintptr*)l; + if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){ + x += iprint("%.8p ", v); + delay(20); + i++; + } + if(i == 8){ + i = 0; + x += iprint("\n"); + delay(20); + } + } + if(i) + iprint("\n"); + delay(3000); +} + +void +dumpstack(void) +{ + callwithureg(dumpstackwithureg); +} + +/* + * dump general registers + */ +static void +dumpgpr(Ureg* ureg) +{ + if(up != nil) + iprint("cpu%d: registers for %s %lud\n", + m->machno, up->text, up->pid); + else + iprint("cpu%d: registers for kernel\n", m->machno); + + delay(20); + iprint("%#8.8lux\tr0\n", ureg->r0); + iprint("%#8.8lux\tr1\n", ureg->r1); + iprint("%#8.8lux\tr2\n", ureg->r2); + delay(20); + iprint("%#8.8lux\tr3\n", ureg->r3); + iprint("%#8.8lux\tr4\n", ureg->r4); + iprint("%#8.8lux\tr5\n", ureg->r5); + delay(20); + iprint("%#8.8lux\tr6\n", ureg->r6); + iprint("%#8.8lux\tr7\n", ureg->r7); + iprint("%#8.8lux\tr8\n", ureg->r8); + delay(20); + iprint("%#8.8lux\tr9 (up)\n", ureg->r9); + iprint("%#8.8lux\tr10 (m)\n", ureg->r10); + iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11); + iprint("%#8.8lux\tr12 (SB)\n", ureg->r12); + delay(20); + iprint("%#8.8lux\tr13 (sp)\n", ureg->r13); + iprint("%#8.8lux\tr14 (link)\n", ureg->r14); + iprint("%#8.8lux\tr15 (pc)\n", ureg->pc); + delay(20); + iprint("%10.10lud\ttype\n", ureg->type); + iprint("%#8.8lux\tpsr\n", ureg->psr); + delay(500); +} + +void +dumpregs(Ureg* ureg) +{ + dumpgpr(ureg); +} + +void +fiq(Ureg *) +{ +} diff --git a/sys/src/9/bcm/uartmini.c b/sys/src/9/bcm/uartmini.c index f7d4149911..db13e13103 100644 --- a/sys/src/9/bcm/uartmini.c +++ b/sys/src/9/bcm/uartmini.c @@ -10,35 +10,11 @@ #include "fns.h" #include "io.h" -#define GPIOREGS (VIRTIO+0x200000) #define AUXREGS (VIRTIO+0x215000) #define OkLed 16 #define TxPin 14 #define RxPin 15 -/* GPIO regs */ -enum { - Fsel0 = 0x00>>2, - FuncMask= 0x7, - Input = 0x0, - Output = 0x1, - Alt0 = 0x4, - Alt1 = 0x5, - Alt2 = 0x6, - Alt3 = 0x7, - Alt4 = 0x3, - Alt5 = 0x2, - Set0 = 0x1c>>2, - Clr0 = 0x28>>2, - Lev0 = 0x34>>2, - PUD = 0x94>>2, - Off = 0x0, - Pulldown= 0x1, - Pullup = 0x2, - PUDclk0 = 0x98>>2, - PUDclk1 = 0x9c>>2, -}; - /* AUX regs */ enum { Irq = 0x00>>2, @@ -73,56 +49,11 @@ static Uart miniuart = { .regs = (u32int*)AUXREGS, .name = "uart0", .freq = 250000000, + .baud = 115200, .phys = &miniphysuart, }; -void -gpiosel(uint pin, int func) -{ - u32int *gp, *fsel; - int off; - - gp = (u32int*)GPIOREGS; - fsel = &gp[Fsel0 + pin/10]; - off = (pin % 10) * 3; - *fsel = (*fsel & ~(FuncMask<baud); if(ie){ intrenable(IRQaux, interrupt, uart, 0, "uart"); ap[MuIer] = RxIen|TxIen; @@ -385,7 +316,7 @@ uartconsinit(void) if(!uart->enabled) (*uart->phys->enable)(uart, 0); - uartctl(uart, "b9600 l8 pn s1"); + uartctl(uart, "l8 pn s1"); if(*cmd != '\0') uartctl(uart, cmd); @@ -417,8 +348,26 @@ void okay(int on) { static int first; + static int okled, polarity; + char *p; - if(!first++) - gpiosel(OkLed, Output); - gpioout(OkLed, !on); + if(!first++){ + p = getconf("bcm2709.disk_led_gpio"); + if(p == nil) + p = getconf("bcm2708.disk_led_gpio"); + if(p != nil) + okled = strtol(p, 0, 0); + else + okled = 'v'; + p = getconf("bcm2709.disk_led_active_low"); + if(p == nil) + p = getconf("bcm2708.disk_led_active_low"); + polarity = (p == nil || *p == '1'); + if(okled != 'v') + gpiosel(okled, Output); + } + if(okled == 'v') + vgpset(0, on); + else if(okled != 0) + gpioout(okled, on^polarity); } diff --git a/sys/src/9/bcm/usb.h b/sys/src/9/bcm/usb.h new file mode 100644 index 0000000000..9b243b43e7 --- /dev/null +++ b/sys/src/9/bcm/usb.h @@ -0,0 +1,205 @@ +/* + * common USB definitions. + */ +#define dprint if(debug)print +#define ddprint if(debug>1)print +#define deprint if(debug || ep->debug)print +#define ddeprint if(debug>1 || ep->debug>1)print + +#define GET2(p) ((((p)[1]&0xFF)<<8)|((p)[0]&0xFF)) +#define PUT2(p,v) {((p)[0] = (v)); ((p)[1] = (v)>>8);} + +typedef struct Udev Udev; /* USB device */ +typedef struct Ep Ep; /* Endpoint */ +typedef struct Hci Hci; /* Host Controller Interface */ +typedef struct Hciimpl Hciimpl; /* Link to the controller impl. */ + +enum +{ + /* fundamental constants */ + Ndeveps = 16, /* max nb. of endpoints per device */ + + /* tunable parameters */ + Nhcis = 16, /* max nb. of HCIs */ + Neps = 128, /* max nb. of endpoints */ + Maxctllen = 32*1024, /* max allowed sized for ctl. xfers; see Maxdevconf */ + Xfertmout = 2000, /* default request time out (ms) */ + + /* transfer types. keep this order */ + Tnone = 0, /* no tranfer type configured */ + Tctl, /* wr req + rd/wr data + wr/rd sts */ + Tiso, /* stream rd or wr (real time) */ + Tbulk, /* stream rd or wr */ + Tintr, /* msg rd or wr */ + Nttypes, /* number of transfer types */ + + Epmax = 0xF, /* max ep. addr */ + Devmax = 0x7F, /* max dev. addr */ + + /* Speeds */ + Fullspeed = 0, + Lowspeed, + Highspeed, + Nospeed, + Superspeed, + + /* request type */ + Rh2d = 0<<7, + Rd2h = 1<<7, + Rstd = 0<<5, + Rclass = 1<<5, + Rdev = 0, + Rep = 2, + Rother = 3, + + /* req offsets */ + Rtype = 0, + Rreq = 1, + Rvalue = 2, + Rindex = 4, + Rcount = 6, + Rsetuplen = 8, + + /* standard requests */ + Rgetstatus = 0, + Rclearfeature = 1, + Rsetfeature = 3, + Rsetaddr = 5, + Rgetdesc = 6, + + /* device states */ + Dconfig = 0, /* configuration in progress */ + Denabled, /* address assigned */ + Ddetach, /* device is detached */ + Dreset, /* its port is being reset */ + + /* (root) Hub reply to port status (reported to usbd) */ + HPpresent = 0x1, + HPenable = 0x2, + HPsuspend = 0x4, + HPovercurrent = 0x8, + HPreset = 0x10, + HPpower = 0x100, + HPslow = 0x200, + HPhigh = 0x400, + HPstatuschg = 0x10000, + HPchange = 0x20000, +}; + +/* + * Services provided by the driver. + * epopen allocates hardware structures to prepare the endpoint + * for I/O. This happens when the user opens the data file. + * epclose releases them. This happens when the data file is closed. + * epwrite tries to write the given bytes, waiting until all of them + * have been written (or failed) before returning; but not for Iso. + * epread does the same for reading. + * It can be assumed that endpoints are DMEXCL but concurrent + * read/writes may be issued and the controller must take care. + * For control endpoints, device-to-host requests must be followed by + * a read of the expected length if needed. + * The port requests are called when usbd issues commands for root + * hubs. Port status must return bits as a hub request would do. + * Toggle handling and other details are left for the controller driver + * to avoid mixing too much the controller and the comon device. + * While an endpoint is closed, its toggles are saved in the Ep struct. + */ +struct Hciimpl +{ + void *aux; /* for controller info */ + void (*init)(Hci*); /* init. controller */ + void (*dump)(Hci*); /* debug */ + void (*interrupt)(Ureg*, void*); /* service interrupt */ + void (*epopen)(Ep*); /* prepare ep. for I/O */ + void (*epclose)(Ep*); /* terminate I/O on ep. */ + long (*epread)(Ep*,void*,long); /* transmit data for ep */ + long (*epwrite)(Ep*,void*,long); /* receive data for ep */ + char* (*seprintep)(char*,char*,Ep*); /* debug */ + int (*portenable)(Hci*, int, int); /* enable/disable port */ + int (*portreset)(Hci*, int, int); /* set/clear port reset */ + int (*portstatus)(Hci*, int); /* get port status */ + void (*shutdown)(Hci*); /* shutdown for reboot */ + void (*debug)(Hci*, int); /* set/clear debug flag */ +}; + +struct Hci +{ + ISAConf; /* hardware info */ + int tbdf; /* type+busno+devno+funcno */ + int ctlrno; /* controller number */ + int nports; /* number of ports in hub */ + int highspeed; + uint superspeed; /* bitmap of superspeed ports */ + Hciimpl; /* HCI driver */ +}; + +/* + * USB endpoint. + * All endpoints are kept in a global array. The first + * block of fields is constant after endpoint creation. + * The rest is configuration information given to all controllers. + * The first endpoint for a device (known as ep0) represents the + * device and is used to configure it and create other endpoints. + * Its QLock also protects per-device data in dev. + * See Hciimpl for clues regarding how this is used by controllers. + */ +struct Ep +{ + Ref; /* one per fid (and per dev ep for ep0s) */ + + /* const once inited. */ + int idx; /* index in global eps array */ + int nb; /* endpoint number in device */ + Hci* hp; /* HCI it belongs to */ + Udev* dev; /* device for the endpoint */ + Ep* ep0; /* control endpoint for its device */ + + QLock; /* protect fields below */ + char* name; /* for ep file names at #u/ */ + int inuse; /* endpoint is open */ + int mode; /* OREAD, OWRITE, or ORDWR */ + int clrhalt; /* true if halt was cleared on ep. */ + int debug; /* per endpoint debug flag */ + char* info; /* for humans to read */ + long maxpkt; /* maximum packet size */ + int ttype; /* tranfer type */ + ulong load; /* in µs, for a fransfer of maxpkt bytes */ + void* aux; /* for controller specific info */ + u64int rhrepl; /* fake root hub replies */ + int toggle[2]; /* saved toggles (while ep is not in use) */ + long pollival; /* poll interval ([µ]frames; intr/iso) */ + long hz; /* poll frequency (iso) */ + long samplesz; /* sample size (iso) */ + int ntds; /* nb. of Tds per µframe */ + int tmout; /* 0 or timeout for transfers (ms) */ +}; + +/* + * Per-device configuration and cached list of endpoints. + * eps[0]->QLock protects it. + */ +struct Udev +{ + int nb; /* USB device number */ + int state; /* state for the device */ + int ishub; /* hubs can allocate devices */ + int isroot; /* is a root hub */ + int speed; /* Full/Low/High/No -speed */ + int hub; /* dev number for the parent hub */ + int port; /* port number in the parent hub */ + Ep* eps[Ndeveps]; /* end points for this device (cached) */ + int addr; /* device address */ + int depth; /* hub depth from root port */ + int rootport; /* port number on root hub */ + int routestr; /* route string */ + + void *aux; + void (*free)(void*); + +}; + +void addhcitype(char *type, int (*reset)(Hci*)); + +extern char *usbmodename[]; + +extern char *seprintdata(char*,char*,uchar*,int); diff --git a/sys/src/9/bcm/usbdwc.c b/sys/src/9/bcm/usbdwc.c index a5479ae538..a8c281336f 100644 --- a/sys/src/9/bcm/usbdwc.c +++ b/sys/src/9/bcm/usbdwc.c @@ -20,7 +20,7 @@ #include "fns.h" #include "io.h" #include "../port/error.h" -#include "../port/usb.h" +#include "usb.h" #include "dwcotg.h" @@ -33,12 +33,25 @@ enum Read = 0, Write = 1, + + /* + * Workaround for an unexplained glitch where an Ack interrupt + * is received without Chhltd, whereupon all channels remain + * permanently busy and can't be halted. This was only seen + * when the controller is reading a sequence of bulk input + * packets in DMA mode. Setting Slowbulkin=1 will avoid the + * lockup by reading packets individually with an interrupt + * after each. More recent chips don't seem to exhibit the + * problem, so it's probably safe to leave this off now. + */ + Slowbulkin = 0, }; typedef struct Ctlr Ctlr; typedef struct Epio Epio; struct Ctlr { + Lock; Dwcregs *regs; /* controller registers */ int nchan; /* number of host channels */ ulong chanbusy; /* bitmap of in-use channels */ @@ -52,7 +65,11 @@ struct Ctlr { }; struct Epio { - QLock; + union { + QLock rlock; + QLock ctllock; + }; + QLock wlock; Block *cb; ulong lastpoll; }; @@ -65,13 +82,31 @@ static char Ebadlen[] = "bad usb request length"; static void clog(Ep *ep, Hostchan *hc); static void logdump(Ep *ep); +static void +filock(Lock *l) +{ + int x; + + x = splfhi(); + ilock(l); + l->sr = x; +} + +static void +fiunlock(Lock *l) +{ + iunlock(l); +} + static Hostchan* chanalloc(Ep *ep) { Ctlr *ctlr; int bitmap, i; + static int first; ctlr = ep->hp->aux; +retry: qlock(&ctlr->chanlock); bitmap = ctlr->chanbusy; for(i = 0; i < ctlr->nchan; i++) @@ -81,8 +116,10 @@ chanalloc(Ep *ep) return &ctlr->regs->hchan[i]; } qunlock(&ctlr->chanlock); - panic("miller is a lazy git"); - return nil; + if(!first++) + print("usbdwc: all host channels busy - retrying\n"); + tsleep(&up->sleep, return0, 0, 1); + goto retry; } static void @@ -157,23 +194,22 @@ sofdone(void *a) Dwcregs *r; r = a; - return r->gintsts & Sofintr; + return (r->gintmsk & Sofintr) == 0; } static void sofwait(Ctlr *ctlr, int n) { Dwcregs *r; - int x; r = ctlr->regs; do{ + filock(ctlr); r->gintsts = Sofintr; - x = splfhi(); ctlr->sofchan |= 1<gintmsk |= Sofintr; + fiunlock(ctlr); sleep(&ctlr->chanintr[n], sofdone, r); - splx(x); }while((r->hfnum & 7) == 6); } @@ -191,7 +227,7 @@ chandone(void *a) static int chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask) { - int intr, n, x, ointr; + int intr, n, ointr; ulong start, now; Dwcregs *r; @@ -199,13 +235,14 @@ chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask) n = hc - r->hchan; for(;;){ restart: - x = splfhi(); + filock(ctlr); r->haintmsk |= 1<hcintmsk = mask; - sleep(&ctlr->chanintr[n], chandone, hc); + fiunlock(ctlr); + tsleep(&ctlr->chanintr[n], chandone, hc, 1000); + if((intr = hc->hcint) == 0) + goto restart; hc->hcintmsk = 0; - splx(x); - intr = hc->hcint; if(intr & Chhltd) return intr; start = fastticks(0); @@ -217,13 +254,14 @@ chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask) if((ointr != Ack && ointr != (Ack|Xfercomp)) || intr != (Ack|Chhltd|Xfercomp) || (now - start) > 60) - dprint("await %x after %ld %x -> %x\n", + dprint("await %x after %ldµs %x -> %x\n", mask, now - start, ointr, intr); return intr; } if((intr & mask) == 0){ - dprint("ep%d.%d await %x intr %x -> %x\n", - ep->dev->nb, ep->nb, mask, ointr, intr); + if(intr != Nak) + dprint("ep%d.%d await %x after %ldµs intr %x -> %x\n", + ep->dev->nb, ep->nb, mask, now - start, ointr, intr); goto restart; } now = fastticks(0); @@ -253,6 +291,8 @@ chanintr(Ctlr *ctlr, int n) int i; hc = &ctlr->regs->hchan[n]; + if((hc->hcint & hc->hcintmsk) == 0) + return 1; if(ctlr->debugchan & (1<hcsplt & Spltena) == 0) @@ -346,7 +386,7 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len) else n = len; hc->hctsiz = n | npkt<hcdma = PADDR(a); + hc->hcdma = dmaaddr(a); nleft = len; logstart(ep); @@ -377,13 +417,19 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len) } hc->hcchar = (hc->hcchar &~ Chdis) | Chen; clog(ep, hc); +wait: if(ep->ttype == Tbulk && dir == Epin) - i = chanwait(ep, ctlr, hc, /* Ack| */ Chhltd); + i = chanwait(ep, ctlr, hc, Chhltd); else if(ep->ttype == Tintr && (hc->hcsplt & Spltena)) i = chanwait(ep, ctlr, hc, Chhltd); else i = chanwait(ep, ctlr, hc, Chhltd|Nak); clog(ep, hc); + if(hc->hcint != i){ + dprint("chanwait intr %ux->%ux\n", i, hc->hcint); + if((i = hc->hcint) == 0) + goto wait; + } hc->hcint = i; if(hc->hcsplt & Spltena){ @@ -404,12 +450,12 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len) continue; } logdump(ep); - print("usbotg: ep%d.%d error intr %8.8ux\n", + print("usbdwc: ep%d.%d error intr %8.8ux\n", ep->dev->nb, ep->nb, i); if(i & ~(Chhltd|Ack)) error(Eio); if(hc->hcdma != hcdma) - print("usbotg: weird hcdma %x->%x intr %x->%x\n", + print("usbdwc: weird hcdma %ux->%ux intr %ux->%ux\n", hcdma, hc->hcdma, i, hc->hcint); } n = hc->hcdma - hcdma; @@ -419,13 +465,13 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len) else continue; } - if(dir == Epin && ep->ttype == Tbulk && n == nleft){ + if(dir == Epin && ep->ttype == Tbulk){ nt = (hctsiz & Xfersize) - (hc->hctsiz & Xfersize); if(nt != n){ if(n == ROUND(nt, 4)) n = nt; else - print("usbotg: intr %8.8ux " + print("usbdwc: intr %8.8ux " "dma %8.8ux-%8.8ux " "hctsiz %8.8ux-%8.ux\n", i, hcdma, hc->hcdma, hctsiz, @@ -490,7 +536,7 @@ eptrans(Ep *ep, int rw, void *a, long n) nexterror(); } chansetup(hc, ep); - if(rw == Read && ep->ttype == Tbulk) + if(Slowbulkin && rw == Read && ep->ttype == Tbulk) n = multitrans(ep, hc, rw, a, n); else{ n = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw], @@ -523,8 +569,8 @@ ctltrans(Ep *ep, uchar *req, long n) if(datalen <= 0 || datalen > Maxctllen) error(Ebadlen); /* XXX cache madness */ - epio->cb = b = allocb(ROUND(datalen, ep->maxpkt) + CACHELINESZ); - b->wp = (uchar*)ROUND((uintptr)b->wp, CACHELINESZ); + epio->cb = b = allocb(ROUND(datalen, ep->maxpkt)); + assert(((uintptr)b->wp & (BLOCKALIGN-1)) == 0); memset(b->wp, 0x55, b->lim - b->wp); cachedwbinvse(b->wp, b->lim - b->wp); data = b->wp; @@ -549,6 +595,7 @@ ctltrans(Ep *ep, uchar *req, long n) }else b->wp += chanio(ep, hc, Epin, DATA1, data, datalen); chanio(ep, hc, Epout, DATA1, nil, 0); + cachedinvse(b->rp, BLEN(b)); n = Rsetuplen; }else{ if(datalen > 0) @@ -626,7 +673,7 @@ init(Hci *hp) greset(r, Rxfflsh); r->grstctl = TXF_ALL; greset(r, Txfflsh); - dprint("usbotg: FIFO depth %d sizes rx/nptx/ptx %8.8ux %8.8ux %8.8ux\n", + dprint("usbdwc: FIFO depth %d sizes rx/nptx/ptx %8.8ux %8.8ux %8.8ux\n", n, r->grxfsiz, r->gnptxfsiz, r->hptxfsiz); r->hport0 = Prtpwr|Prtconndet|Prtenchng|Prtovrcurrchng; @@ -653,6 +700,7 @@ fiqintr(Ureg*, void *a) ctlr = hp->aux; r = ctlr->regs; wakechan = 0; + filock(ctlr); intr = r->gintsts; if(intr & Hcintr){ haint = r->haint & r->haintmsk; @@ -678,6 +726,7 @@ fiqintr(Ureg*, void *a) ctlr->wakechan |= wakechan; armtimerset(1); } + fiunlock(ctlr); } static void @@ -685,14 +734,14 @@ irqintr(Ureg*, void *a) { Ctlr *ctlr; uint wakechan; - int i, x; + int i; ctlr = a; - x = splfhi(); + filock(ctlr); armtimerset(0); wakechan = ctlr->wakechan; ctlr->wakechan = 0; - splx(x); + fiunlock(ctlr); for(i = 0; wakechan; i++){ if(wakechan & 1) wakeup(&ctlr->chanintr[i]); @@ -703,7 +752,7 @@ irqintr(Ureg*, void *a) static void epopen(Ep *ep) { - ddprint("usbotg: epopen ep%d.%d ttype %d\n", + ddprint("usbdwc: epopen ep%d.%d ttype %d\n", ep->dev->nb, ep->nb, ep->ttype); switch(ep->ttype){ case Tnone: @@ -726,7 +775,7 @@ epopen(Ep *ep) static void epclose(Ep *ep) { - ddprint("usbotg: epclose ep%d.%d ttype %d\n", + ddprint("usbdwc: epclose ep%d.%d ttype %d\n", ep->dev->nb, ep->nb, ep->ttype); switch(ep->ttype){ case Tctl: @@ -742,6 +791,7 @@ static long epread(Ep *ep, void *a, long n) { Epio *epio; + QLock *q; Block *b; uchar *p; ulong elapsed; @@ -749,10 +799,11 @@ epread(Ep *ep, void *a, long n) ddprint("epread ep%d.%d %ld\n", ep->dev->nb, ep->nb, n); epio = ep->aux; + q = ep->ttype == Tctl? &epio->ctllock : &epio->rlock; b = nil; - qlock(epio); + qlock(q); if(waserror()){ - qunlock(epio); + qunlock(q); if(b) freeb(b); nexterror(); @@ -762,7 +813,7 @@ epread(Ep *ep, void *a, long n) error(Egreg); case Tctl: nr = ctldata(ep, a, n); - qunlock(epio); + qunlock(q); poperror(); return nr; case Tintr: @@ -772,13 +823,15 @@ epread(Ep *ep, void *a, long n) /* fall through */ case Tbulk: /* XXX cache madness */ - b = allocb(ROUND(n, ep->maxpkt) + CACHELINESZ); - p = (uchar*)ROUND((uintptr)b->base, CACHELINESZ); - cachedwbinvse(p, n); + b = allocb(ROUND(n, ep->maxpkt)); + p = b->rp; + assert(((uintptr)p & (BLOCKALIGN-1)) == 0); + cachedinvse(p, n); nr = eptrans(ep, Read, p, n); + cachedinvse(p, nr); epio->lastpoll = TK2MS(m->ticks); memmove(a, p, nr); - qunlock(epio); + qunlock(q); freeb(b); poperror(); return nr; @@ -789,16 +842,18 @@ static long epwrite(Ep *ep, void *a, long n) { Epio *epio; + QLock *q; Block *b; uchar *p; ulong elapsed; ddprint("epwrite ep%d.%d %ld\n", ep->dev->nb, ep->nb, n); epio = ep->aux; + q = ep->ttype == Tctl? &epio->ctllock : &epio->wlock; b = nil; - qlock(epio); + qlock(q); if(waserror()){ - qunlock(epio); + qunlock(q); if(b) freeb(b); nexterror(); @@ -814,8 +869,9 @@ epwrite(Ep *ep, void *a, long n) case Tctl: case Tbulk: /* XXX cache madness */ - b = allocb(n + CACHELINESZ); - p = (uchar*)ROUND((uintptr)b->base, CACHELINESZ); + b = allocb(n); + p = b->wp; + assert(((uintptr)p & (BLOCKALIGN-1)) == 0); memmove(p, a, n); cachedwbse(p, n); if(ep->ttype == Tctl) @@ -824,7 +880,7 @@ epwrite(Ep *ep, void *a, long n) n = eptrans(ep, Write, p, n); epio->lastpoll = TK2MS(m->ticks); } - qunlock(epio); + qunlock(q); freeb(b); poperror(); return n; @@ -846,11 +902,11 @@ portenable(Hci *hp, int port, int on) assert(port == 1); ctlr = hp->aux; r = ctlr->regs; - dprint("usbotg enable=%d; sts %#x\n", on, r->hport0); + dprint("usbdwc enable=%d; sts %#x\n", on, r->hport0); if(!on) r->hport0 = Prtpwr | Prtena; tsleep(&up->sleep, return0, 0, Enabledelay); - dprint("usbotg enable=%d; sts %#x\n", on, r->hport0); + dprint("usbdwc enable=%d; sts %#x\n", on, r->hport0); return 0; } @@ -864,7 +920,7 @@ portreset(Hci *hp, int port, int on) assert(port == 1); ctlr = hp->aux; r = ctlr->regs; - dprint("usbotg reset=%d; sts %#x\n", on, r->hport0); + dprint("usbdwc reset=%d; sts %#x\n", on, r->hport0); if(!on) return 0; r->hport0 = Prtpwr | Prtrst; @@ -875,9 +931,9 @@ portreset(Hci *hp, int port, int on) b = s & (Prtconndet|Prtenchng|Prtovrcurrchng); if(b != 0) r->hport0 = Prtpwr | b; - dprint("usbotg reset=%d; sts %#x\n", on, s); + dprint("usbdwc reset=%d; sts %#x\n", on, s); if((s & Prtena) == 0) - print("usbotg: host port not enabled after reset"); + print("usbdwc: host port not enabled after reset"); return 0; } @@ -947,7 +1003,7 @@ reset(Hci *hp) id = ctlr->regs->gsnpsid; if((id>>16) != ('O'<<8 | 'T')) return -1; - dprint("usbotg: rev %d.%3.3x\n", (id>>12)&0xF, id&0xFFF); + dprint("usbdwc: rev %d.%3.3x\n", (id>>12)&0xF, id&0xFFF); intrenable(IRQtimerArm, irqintr, ctlr, 0, "dwc"); diff --git a/sys/src/9/bcm/usbxhci.c b/sys/src/9/bcm/usbxhci.c new file mode 100644 index 0000000000..f783c8b31a --- /dev/null +++ b/sys/src/9/bcm/usbxhci.c @@ -0,0 +1,1837 @@ +/* + * from 9front ../port/usbxhci.c + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "pci.h" +#include "../port/error.h" +#include "usb.h" + +extern void dmaflush(int, void*, ulong); + +enum { + /* Capability Registers */ + CAPLENGTH = 0x00/4, // 1 + HCIVERSION = 0x02/4, // 2 + HCSPARAMS1 = 0x04/4, + HCSPARAMS2 = 0x08/4, + HCSPARAMS3 = 0x0C/4, + + HCCPARAMS = 0x10/4, + AC64 = 1<<0, + BNC = 1<<1, + CSZ = 1<<2, + PPC = 1<<3, + PIND = 1<<4, + LHRC = 1<<5, + LTC = 1<<6, + NSS = 1<<7, + + DBOFF = 0x14/4, + RTSOFF = 0x18/4, + + HCCPARAMS2 = 0x1C/4, + + /* Operational Registers */ + USBCMD = 0x00/4, /* USB Command Register */ + RUNSTOP = 1<<0, /* Run/Stop - RW */ + HCRST = 1<<1, /* Host Controller Reset - RW */ + INTE = 1<<2, /* Interrupter Enable - RW */ + HSEE = 1<<3, /* Host System Error Enable - RW */ + LHCRST = 1<<7, /* Light Host Controller Reset - RO/RW */ + CSS = 1<<8, /* Controller Save State - RW */ + CRS = 1<<9, /* Controller Restore State - RW */ + EWE = 1<<10, /* Enable Wrap Event - RW */ + EU3S = 1<<11, /* Enable U3 MFINDEX Stop - RW */ + + USBSTS = 0x04/4, /* USB Status Register */ + HCH = 1<<0, /* HCHalted - RO */ + HSE = 1<<2, /* Host System Error - RW1C */ + EINT = 1<<3, /* Event Interrupt - RW1C */ + PCD = 1<<4, /* Port Change Detect - RW1C */ + SSS = 1<<8, /* Save State Status - RO */ + RSS = 1<<9, /* Restore State Status - RO */ + SRE = 1<<10, /* Save/Restore Error - RW1C */ + CNR = 1<<11, /* Controller Not Ready - RO */ + HCE = 1<<12, /* Host Controller Error - RO */ + + PAGESIZE = 0x08/4, /* Page Size - RO */ + + DNCTRL = 0x14/4, /* Device Notification Control Register - RW */ + + CRCR = 0x18/4, /* Command Ring Control Register - RW */ + RCS = 1<<0, /* Ring Cycle State - RW */ + CS = 1<<1, /* Command Stop - RW1S */ + CA = 1<<2, /* Command Abort - RW1S */ + CRR = 1<<3, /* Command Ring Running - RO */ + + DCBAAP = 0x30/4, // 8 + + CONFIG = 0x38/4, /* Configure Register (MaxSlotEn[7:0]) */ + + /* Port Register Set */ + PORTSC = 0x00/4, /* Port status and Control Register */ + CCS = 1<<0, /* Current Connect Status - ROS */ + PED = 1<<1, /* Port Enable/Disabled - RW1CS */ + OCA = 1<<3, /* Over-current Active - RO */ + PR = 1<<4, /* Port Reset - RW1S */ + PLS = 15<<5, /* Port Link State - RWS */ + PP = 1<<9, /* Port Power - RWS */ + PS = 15<<10, /* Port Speed - ROS */ + PIC = 3<<14, /* Port Indicator Control - RWS */ + LWS = 1<<16, /* Port Link Write Strobe - RW */ + CSC = 1<<17, /* Connect Status Change - RW1CS */ + PEC = 1<<18, /* Port Enabled/Disabled Change - RW1CS */ + WRC = 1<<19, /* Warm Port Reset Change - RW1CS */ + OCC = 1<<20, /* Over-current Change - RW1CS */ + PRC = 1<<21, /* Port Reset Change - RW1CS */ + PLC = 1<<22, /* Port Link State Change - RW1CS */ + CEC = 1<<23, /* Port Config Error Change - RW1CS */ + CAS = 1<<24, /* Cold Attach Status - RO */ + WCE = 1<<25, /* Wake on Connect Enable - RWS */ + WDE = 1<<26, /* Wake on Disconnect Enable - RWS */ + WOE = 1<<27, /* Wake on Over-current Enable - RWS */ + DR = 1<<30, /* Device Removable - RO */ + WPR = 1<<31, /* Warm Port Reset - RW1S */ + + PORTPMSC = 0x04/4, + PORTLI = 0x08/4, + + /* Host Controller Runtime Register */ + MFINDEX = 0x0000/4, /* Microframe Index */ + IR0 = 0x0020/4, /* Interrupt Register Set 0 */ + + /* Interrupter Registers */ + IMAN = 0x00/4, /* Interrupter Management */ + IMOD = 0x04/4, /* Interrupter Moderation */ + ERSTSZ = 0x08/4, /* Event Ring Segment Table Size */ + ERSTBA = 0x10/4, /* Event Ring Segment Table Base Address */ + ERDP = 0x18/4, /* Event Ring Dequeue Pointer */ + + /* TRB flags */ + TR_ENT = 1<<1, + TR_ISP = 1<<2, + TR_NS = 1<<3, + TR_CH = 1<<4, + TR_IOC = 1<<5, + TR_IDT = 1<<6, + TR_BEI = 1<<9, + + /* TRB types */ + TR_RESERVED = 0<<10, + TR_NORMAL = 1<<10, + TR_SETUPSTAGE = 2<<10, + TR_DATASTAGE = 3<<10, + TR_STATUSSTAGE = 4<<10, + TR_ISOCH = 5<<10, + TR_LINK = 6<<10, + TR_EVENTDATA = 7<<10, + TR_NOOP = 8<<10, + + CR_ENABLESLOT = 9<<10, + CR_DISABLESLOT = 10<<10, + CR_ADDRESSDEV = 11<<10, + CR_CONFIGEP = 12<<10, + CR_EVALCTX = 13<<10, + CR_RESETEP = 14<<10, + CR_STOPEP = 15<<10, + CR_SETTRDQP = 16<<10, + CR_RESETDEV = 17<<10, + CR_FORCECMD = 18<<10, + CR_NEGBW = 19<<10, + CR_SETLAT = 20<<10, + CR_GETPORTBW = 21<<10, + CR_FORCEHDR = 22<<10, + CR_NOOP = 23<<10, + + ER_TRANSFER = 32<<10, + ER_CMDCOMPL = 33<<10, + ER_PORTSC = 34<<10, + ER_BWREQ = 35<<10, + ER_DOORBELL = 36<<10, + ER_HCE = 37<<10, + ER_DEVNOTE = 38<<10, + ER_MFINDEXWRAP = 39<<10, +}; + +typedef struct Ctlr Ctlr; +typedef struct Wait Wait; +typedef struct Ring Ring; +typedef struct Slot Slot; +typedef struct Epio Epio; +typedef struct Port Port; + +struct Wait +{ + Wait *next; + Ring *ring; + u32int *td; + u32int er[4]; + Rendez *z; +}; + +struct Ring +{ + int id; + + Slot *slot; + + u32int *base; + + u32int mask; + u32int shift; + + u32int rp; + u32int wp; + + u32int *ctx; + u32int *doorbell; + + int stopped; + + Wait *pending; + Lock; +}; + +struct Slot +{ + int id; + + int confval; // bConfigurationValue of SET_CONFIGURATION + int iface; // bInterfaceNumber of SET_INTERFACE + int altc; // bAlternateSetting of SET_INTERFACE + + Ctlr *ctlr; + Udev *dev; + + u32int *ibase; + u32int *obase; + + /* endpoint rings */ + int nep; + Ring epr[32]; +}; + +struct Port +{ + char spec[4]; + int proto; + + u32int *reg; +}; + +struct Ctlr +{ + Pcidev *pcidev; + + u32int *mmio; + + u32int *opr; /* operational registers */ + u32int *rts; /* runtime registers */ + u32int *dba; /* doorbell array */ + + u64int *dcba; /* device context base array */ + + u64int *sba; /* scratchpad buffer array */ + void *sbp; /* scratchpad buffer pages */ + + u32int *erst[1]; /* event ring segment table */ + Ring er[1]; /* event ring segment */ + Ring cr[1]; /* command ring segment */ + QLock cmdlock; + + u32int µframe; + + QLock slotlock; + Slot **slot; /* slots by slot id */ + Port *port; + + u32int hccparams; + + int csz; + int pagesize; + int nscratch; + int nintrs; + int nslots; + + Rendez recover; + void *active; + uintptr base; +}; + +struct Epio +{ + QLock; + + Ring *ring; + Block *b; + + /* iso */ + u32int frame; + u32int period; + u32int incr; + u32int tdsz; + + int nleft; +}; + +static char Ebadlen[] = "bad usb request length"; +static char Enotconfig[] = "usb endpoint not configured"; +static char Erecover[] = "xhci controller needs reset"; + +static char* +ctlrcmd(Ctlr *ctlr, u32int c, u32int s, u64int p, u32int *er); + +static void +setrptr(u32int *reg, u64int pa) +{ + coherence(); + reg[0] = pa; + reg[1] = pa>>32; +} + +static u32int +µframe(Ctlr *ctlr) +{ + u32int µ; + do { + µ = (ctlr->rts[MFINDEX] & (1<<14)-1) | + (ctlr->µframe & ~((1<<14)-1)); + } while((int)(µ - ctlr->µframe) < 0); + return µ; +} + +static void +freering(Ring *r) +{ + if(r == nil) + return; + if(r->base != nil){ + dmaflush(0, r->base, 4*4<shift); + free(r->base); + } + memset(r, 0, sizeof(*r)); +} + +static Ring* +initring(Ring *r, int shift) +{ + r->id = 0; + r->ctx = nil; + r->slot = nil; + r->doorbell = nil; + r->pending = nil; + r->stopped = 0; + r->shift = shift; + r->mask = (1<rp = r->wp = 0; + r->base = mallocalign(4*4<base == nil){ + freering(r); + error(Enomem); + } + dmaflush(1, r->base, 4*4<pending) != nil){ + r->pending = w->next; + w->next = nil; + if((z = w->z) != nil){ + w->z = nil; + wakeup(z); + } + } +} + +static u64int +resetring(Ring *r) +{ + u64int pa; + + ilock(r); + flushring(r); + r->rp = r->wp; + pa = PCIWADDR(&r->base[4*(r->wp & r->mask)]) | ((~r->wp>>r->shift) & 1); + iunlock(r); + + return pa; +} + +static u32int* +xecp(Ctlr *ctlr, uchar id, u32int *p) +{ + u32int x, *e; + + e = &ctlr->mmio[ctlr->pcidev->mem[0].size/4]; + if(p == nil){ + p = ctlr->mmio; + x = ctlr->hccparams>>16; + } else { + assert(p < e); + x = (*p>>8) & 255; + } + while(x != 0){ + p += x; + if(p >= e) + break; + x = *p; + if((x & 255) == id) + return p; + x >>= 8; + x &= 255; + } + return nil; +} + +static void +handoff(Ctlr *ctlr) +{ + u32int *r; + int i; + + if((r = xecp(ctlr, 1, nil)) == nil) + return; + if(getconf("*noxhcihandoff") == nil){ + r[0] |= 1<<24; /* request ownership */ + for(i = 0; (r[0] & (1<<16)) != 0 && i<100; i++) + tsleep(&up->sleep, return0, nil, 10); + } + /* disable SMI interrupts */ + r[1] &= 7<<1 | 255<<5 | 7<<17 | 7<<29; + + /* clear BIOS ownership in case of timeout */ + r[0] &= ~(1<<16); +} + +static void +shutdown(Hci *hp) +{ + Ctlr *ctlr = hp->aux; + int i; + + ctlr->opr[USBCMD] = 0; + for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++) + delay(10); + pciintrdisable(ctlr->pcidev->tbdf, hp->interrupt, hp); + pcidisable(ctlr->pcidev); +} + +static void +release(Ctlr *ctlr) +{ + int i; + + freering(ctlr->cr); + for(i=0; ier); i++){ + freering(&ctlr->er[i]); + free(ctlr->erst[i]); + ctlr->erst[i] = nil; + } + free(ctlr->port), ctlr->port = nil; + free(ctlr->slot), ctlr->slot = nil; + free(ctlr->dcba), ctlr->dcba = nil; + free(ctlr->sba), ctlr->sba = nil; + if(ctlr->sbp != nil){ + dmaflush(0, ctlr->sbp, ctlr->nscratch*ctlr->pagesize); + free(ctlr->sbp); + ctlr->sbp = nil; + } +} + +static void recover(void *arg); + +static void +init(Hci *hp) +{ + Ctlr *ctlr; + Port *pp; + u32int *x; + uchar *p; + int i, j; + + ctlr = hp->aux; + pcienable(ctlr->pcidev); + if(ctlr->mmio[CAPLENGTH] == -1){ + pcidisable(ctlr->pcidev); + error("controller vanished"); + } + + ctlr->opr = &ctlr->mmio[(ctlr->mmio[CAPLENGTH]&0xFF)/4]; + ctlr->dba = &ctlr->mmio[ctlr->mmio[DBOFF]/4]; + ctlr->rts = &ctlr->mmio[ctlr->mmio[RTSOFF]/4]; + + ctlr->hccparams = ctlr->mmio[HCCPARAMS]; + handoff(ctlr); + xhcireset(BUSBNO(hp->tbdf)<<20 | BUSDNO(hp->tbdf)<<15 | BUSFNO(hp->tbdf)<<12); + + for(i=0; (ctlr->opr[USBSTS] & CNR) != 0 && i<100; i++) + tsleep(&up->sleep, return0, nil, 10); + if(i == 100) + print("%s: controller not ready, status %ux\n", hp->type, ctlr->opr[USBSTS]); + + ctlr->opr[USBCMD] = HCRST; + delay(1); + for(i=0; (ctlr->opr[USBSTS] & (CNR|HCH)) != HCH && i<100; i++) + tsleep(&up->sleep, return0, nil, 10); + if(i == 100) + print("%s: controller not halted, status %ux\n", hp->type, ctlr->opr[USBSTS]); + + pcisetbme(ctlr->pcidev); + pciintrenable(ctlr->pcidev->tbdf, hp->interrupt, hp); + + if(waserror()){ + shutdown(hp); + release(ctlr); + nexterror(); + } + + ctlr->csz = (ctlr->hccparams & CSZ) != 0; + ctlr->pagesize = (ctlr->opr[PAGESIZE] & 0xFFFF) << 12; + + ctlr->nscratch = (ctlr->mmio[HCSPARAMS2] >> 27) & 0x1F | (ctlr->mmio[HCSPARAMS2] >> 16) & 0x3E0; + ctlr->nintrs = (ctlr->mmio[HCSPARAMS1] >> 8) & 0x7FF; + ctlr->nslots = (ctlr->mmio[HCSPARAMS1] >> 0) & 0xFF; + + hp->highspeed = 1; + hp->superspeed = 0; + hp->nports = (ctlr->mmio[HCSPARAMS1] >> 24) & 0xFF; + ctlr->port = malloc(hp->nports * sizeof(Port)); + if(ctlr->port == nil) + error(Enomem); + for(i=0; inports; i++) + ctlr->port[i].reg = &ctlr->opr[0x400/4 + i*4]; + + x = nil; + while((x = xecp(ctlr, 2, x)) != nil){ + i = x[2]&255; + j = (x[2]>>8)&255; + while(j--){ + if(i < 1 || i > hp->nports) + break; + pp = &ctlr->port[i-1]; + pp->proto = x[0]>>16; + memmove(pp->spec, &x[1], 4); + if(memcmp(pp->spec, "USB ", 4) == 0 && pp->proto >= 0x0300) + hp->superspeed |= 1<<(i-1); + i++; + } + } + + ctlr->slot = malloc((1+ctlr->nslots)*sizeof(ctlr->slot[0])); + ctlr->dcba = mallocalign((1+ctlr->nslots)*sizeof(ctlr->dcba[0]), 64, 0, ctlr->pagesize); + if(ctlr->slot == nil || ctlr->dcba == nil) + error(Enomem); + if(ctlr->nscratch != 0){ + ctlr->sba = mallocalign(ctlr->nscratch*8, 64, 0, ctlr->pagesize); + ctlr->sbp = mallocalign(ctlr->nscratch*ctlr->pagesize, ctlr->pagesize, 0, 0); + if(ctlr->sba == nil || ctlr->sbp == nil) + error(Enomem); + for(i=0, p = ctlr->sbp; inscratch; i++, p += ctlr->pagesize){ + memset(p, 0, ctlr->pagesize); + ctlr->sba[i] = PCIWADDR(p); + } + dmaflush(1, ctlr->sbp, ctlr->nscratch*ctlr->pagesize); + dmaflush(1, ctlr->sba, ctlr->nscratch*8); + ctlr->dcba[0] = PCIWADDR(ctlr->sba); + } else { + ctlr->dcba[0] = 0; + } + for(i=1; i<=ctlr->nslots; i++) + ctlr->dcba[i] = 0; + + ctlr->opr[CONFIG] = (ctlr->opr[CONFIG] & 0xFFFFFC00) | ctlr->nslots; /* MaxSlotsEn */ + + dmaflush(1, ctlr->dcba, (1+ctlr->nslots)*sizeof(ctlr->dcba[0])); + setrptr(&ctlr->opr[DCBAAP], PCIWADDR(ctlr->dcba)); + + initring(ctlr->cr, 8); /* 256 entries */ + ctlr->cr->id = 0; + ctlr->cr->doorbell = &ctlr->dba[0]; + setrptr(&ctlr->opr[CRCR], resetring(ctlr->cr)); + + for(i=0; inintrs; i++){ + u32int *irs = &ctlr->rts[IR0 + i*8]; + + if(i >= nelem(ctlr->er)){ + irs[ERSTSZ] = 0; /* disable ring */ + irs[IMAN] = 1; + irs[IMOD] = 0; + setrptr(&irs[ERSTBA], 0); + setrptr(&irs[ERDP], 0); + continue; + } + + /* allocate and link into event ring segment table */ + initring(&ctlr->er[i], 8); /* 256 entries */ + ctlr->erst[i] = mallocalign(4*4, 64, 0, 0); + if(ctlr->erst[i] == nil) + error(Enomem); + *((u64int*)ctlr->erst[i]) = PCIWADDR(ctlr->er[i].base); + ctlr->erst[i][2] = ctlr->er[i].mask+1; + ctlr->erst[i][3] = 0; + dmaflush(1, ctlr->erst[i], 4*4); + + irs[ERSTSZ] = 1; /* just one segment */ + irs[IMAN] = 3; + irs[IMOD] = 0; + setrptr(&irs[ERSTBA], PCIWADDR(ctlr->erst[i])); + setrptr(&irs[ERDP], PCIWADDR(ctlr->er[i].base) | (1<<3)); + } + poperror(); + + ctlr->µframe = 0; + ctlr->opr[USBSTS] = ctlr->opr[USBSTS] & (HSE|EINT|PCD|SRE); + coherence(); + + ctlr->opr[USBCMD] = RUNSTOP|INTE|HSEE|EWE; + for(i=0; (ctlr->opr[USBSTS] & (CNR|HCH)) != 0 && i<100; i++) + tsleep(&up->sleep, return0, nil, 10); + + kproc("xhcirecover", recover, hp); +} + +static int +needrecover(void *arg) +{ + Ctlr *ctlr = arg; + return ctlr->er->stopped || + (ctlr->opr[USBSTS] & (HCH|HCE|HSE)) != 0; +} + +static void +recover(void *arg) +{ + Hci *hp = arg; + Ctlr *ctlr = hp->aux; + + while(waserror()) + ; + while(!needrecover(ctlr)) + tsleep(&ctlr->recover, needrecover, ctlr, 10); + shutdown(hp); + + /* + * flush all transactions and wait until all devices have + * been detached by usbd. + */ + for(;;){ + int i, j, active; + + ilock(ctlr->cr); + ctlr->cr->stopped = 1; + flushring(ctlr->cr); + iunlock(ctlr->cr); + + active = 0; + qlock(&ctlr->slotlock); + for(i=1; i<=ctlr->nslots; i++){ + Slot *slot = ctlr->slot[i]; + if(slot == nil) + continue; + active++; + for(j=0; j < slot->nep; j++){ + Ring *ring = &slot->epr[j]; + if(ring->base == nil) + continue; + ilock(ring); + ring->stopped = 1; + flushring(ring); + iunlock(ring); + } + } + qunlock(&ctlr->slotlock); + if(active == 0) + break; + + tsleep(&up->sleep, return0, nil, 100); + } + + qlock(&ctlr->slotlock); + qlock(&ctlr->cmdlock); + + release(ctlr); + if(waserror()) { + print("xhci recovery failed: %s\n", up->errstr); + } else { + init(hp); + poperror(); + } + + qunlock(&ctlr->cmdlock); + qunlock(&ctlr->slotlock); + + pexit("", 1); +} + +static void +dump(Hci *) +{ +} + +static void +queuetd(Ring *r, u32int c, u32int s, u64int p, Wait *w) +{ + u32int *td, x; + + x = r->wp++; + if((x & r->mask) == r->mask){ + td = r->base + 4*(x & r->mask); + *(u64int*)td = PCIWADDR(r->base); + td[2] = 0; + td[3] = ((~x>>r->shift)&1) | (1<<1) | TR_LINK; + dmaflush(1, td, 4*4); + x = r->wp++; + } + td = r->base + 4*(x & r->mask); + if(w != nil){ + w->er[0] = w->er[1] = w->er[2] = w->er[3] = 0; + w->ring = r; + w->td = td; + w->z = &up->sleep; + + ilock(r); + w->next = r->pending; + r->pending = w; + iunlock(r); + } + coherence(); + *(u64int*)td = p; + td[2] = s; + td[3] = ((~x>>r->shift)&1) | c; + dmaflush(1, td, 4*4); +} + +static char *ccerrtab[] = { +[2] "Data Buffer Error", +[3] "Babble Detected Error", +[4] "USB Transaction Error", +[5] "TRB Error", +[6] "Stall Error", +[7] "Resume Error", +[8] "Bandwidth Error", +[9] "No Slots Available", +[10] "Invalid Stream Type", +[11] "Slot Not Enabled", +[12] "Endpoint Not Enabled", +[13] "Short Packet", +[14] "Ring Underrun", +[15] "Ring Overrun", +[16] "VF Event Ring Full", +[17] "Parameter Error", +[18] "Bandwidth Overrun Error", +[19] "Context State Error", +[20] "No Ping Response", +[21] "Event Ring Full", +[22] "Incompatible Device", +[23] "Missed Service Error", +[24] "Command Ring Stopped", +[25] "Command Aborted", +[26] "Stopped", +[27] "Stopped - Length Invalid", +[29] "Max Exit Latency Too Large", +[31] "Isoch Buffer Overrun", +[32] "Event Lost Error", +[33] "Undefined Error", +[34] "Invalid Stream ID", +[35] "Secondary Bandwidth Error", +[36] "Split Transaction Error", +}; + +static char* +ccerrstr(u32int cc) +{ + char *s; + + if(cc == 1 || cc == 13) + return nil; + if(cc < nelem(ccerrtab) && ccerrtab[cc] != nil) + s = ccerrtab[cc]; + else + s = "???"; + return s; +} + +static int +waitdone(void *a) +{ + return ((Wait*)a)->z == nil; +} + +static char* +waittd(Ctlr *ctlr, Wait *w, int tmout) +{ + Ring *r = w->ring; + + coherence(); + *r->doorbell = r->id; + + while(waserror()){ + if(r->stopped) { + ctlr->er->stopped = 1; + wakeup(&ctlr->recover); + + /* wait for rescue */ + tmout = 0; + continue; + } + + if(r == ctlr->cr) + ctlr->opr[CRCR] |= CA; + else + ctlrcmd(ctlr, CR_STOPEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); + r->stopped = 1; + + /* time to abort the transaction */ + tmout = 5000; + } + if(tmout > 0){ + tsleep(&up->sleep, waitdone, w, tmout); + if(!waitdone(w)) + error("timed out"); + } else { + while(!waitdone(w)) + sleep(&up->sleep, waitdone, w); + } + poperror(); + return ccerrstr(w->er[2]>>24); +} + +static char* +ctlrcmd(Ctlr *ctlr, u32int c, u32int s, u64int p, u32int *er) +{ + Wait w[1]; + char *err; + + qlock(&ctlr->cmdlock); + if(needrecover(ctlr)){ + qunlock(&ctlr->cmdlock); + return Erecover; + } + ctlr->cr->stopped = 0; + queuetd(ctlr->cr, c, s, p, w); + err = waittd(ctlr, w, 5000); + qunlock(&ctlr->cmdlock); + + if(er != nil) + memmove(er, w->er, 4*4); + + return err; +} + +static void +completering(Ring *r, u32int *er) +{ + Wait *w, **wp; + u32int *td, x; + u64int pa; + + pa = (*(u64int*)er) & ~15ULL; + ilock(r); + + for(x = r->rp; (int)(r->wp - x) > 0;){ + td = &r->base[4*(x++ & r->mask)]; + if((u64int)PCIWADDR(td) == pa){ + r->rp = x; + break; + } + } + + wp = &r->pending; + while(w = *wp){ + if((u64int)PCIWADDR(w->td) == pa){ + Rendez *z = w->z; + + memmove(w->er, er, 4*4); + *wp = w->next; + w->next = nil; + + if(z != nil){ + w->z = nil; + wakeup(z); + } + break; + } else { + wp = &w->next; + } + } + + iunlock(r); +} + +static void +interrupt(Ureg*, void *arg) +{ + Hci *hp = arg; + Ctlr *ctlr = hp->aux; + Ring *ring = ctlr->er; + Slot *slot; + u32int *irs, *td, x; + + if(ring->base == nil) + return; + + irs = &ctlr->rts[IR0]; + x = irs[IMAN]; + if(x & 1) irs[IMAN] = x & 3; + + for(x = ring->rp;; x=++ring->rp){ + td = ring->base + 4*(x & ring->mask); + dmaflush(0, td, 4*4); + + if((((x>>ring->shift)^td[3])&1) == 0) + break; + + switch(td[3] & 0xFC00){ + case ER_CMDCOMPL: + completering(ctlr->cr, td); + break; + case ER_TRANSFER: + x = td[3]>>24; + if(x == 0 || x > ctlr->nslots) + break; + slot = ctlr->slot[x]; + if(slot == nil) + break; + completering(&slot->epr[(td[3]>>16)-1&31], td); + break; + case ER_MFINDEXWRAP: + ctlr->µframe = (ctlr->rts[MFINDEX] & (1<<14)-1) | + (ctlr->µframe+(1<<14) & ~((1<<14)-1)); + break; + case ER_HCE: + iprint("xhci: host controller error: %ux %ux %ux %ux\n", + td[0], td[1], td[2], td[3]); + ctlr->er->stopped = 1; + wakeup(&ctlr->recover); + return; + case ER_PORTSC: + break; + case ER_BWREQ: + case ER_DOORBELL: + case ER_DEVNOTE: + default: + iprint("xhci: event %ud: %ux %ux %ux %ux\n", + x, td[0], td[1], td[2], td[3]); + } + } + + setrptr(&irs[ERDP], PCIWADDR(td) | (1<<3)); +} + +static void +freeslot(void *arg) +{ + Slot *slot; + + if(arg == nil) + return; + slot = arg; + if(slot->id != 0){ + Ctlr *ctlr = slot->ctlr; + qlock(&ctlr->slotlock); + if(ctlr->slot != nil && ctlr->slot[slot->id] == slot){ + ctlrcmd(ctlr, CR_DISABLESLOT | (slot->id<<24), 0, 0, nil); + dmaflush(0, slot->obase, 32*32 << ctlr->csz); + ctlr->dcba[slot->id] = 0; + dmaflush(1, &ctlr->dcba[slot->id], sizeof(ctlr->dcba[0])); + ctlr->slot[slot->id] = nil; + } + qunlock(&ctlr->slotlock); + } + freering(&slot->epr[0]); + free(slot->ibase); + free(slot->obase); + free(slot); +} + +static Slot* +allocslot(Ctlr *ctlr, Udev *dev) +{ + u32int r[4]; + Slot *slot; + char *err; + + slot = malloc(sizeof(Slot)); + if(slot == nil) + error(Enomem); + + slot->ctlr = ctlr; + slot->dev = dev; + slot->nep = 0; + slot->id = 0; + + slot->confval = 0; + slot->iface = 0; + slot->altc = 0; + + qlock(&ctlr->slotlock); + if(waserror()){ + qunlock(&ctlr->slotlock); + freeslot(slot); + nexterror(); + } + if(ctlr->slot == nil) + error(Erecover); + slot->ibase = mallocalign(32*33 << ctlr->csz, 64, 0, ctlr->pagesize); + slot->obase = mallocalign(32*32 << ctlr->csz, 64, 0, ctlr->pagesize); + if(slot->ibase == nil || slot->obase == nil) + error(Enomem); + + if((err = ctlrcmd(ctlr, CR_ENABLESLOT, 0, 0, r)) != nil) + error(err); + slot->id = r[3]>>24; + if(slot->id <= 0 || slot->id > ctlr->nslots || ctlr->slot[slot->id] != nil){ + slot->id = 0; + error("bad slot id from controller"); + } + poperror(); + + dmaflush(1, slot->obase, 32*32 << ctlr->csz); + ctlr->dcba[slot->id] = PCIWADDR(slot->obase); + dmaflush(1, &ctlr->dcba[slot->id], sizeof(ctlr->dcba[0])); + + ctlr->slot[slot->id] = slot; + + qunlock(&ctlr->slotlock); + + return slot; +} + +static void +setdebug(Hci *, int) +{ +} + +static void +epclose(Ep *ep) +{ + Ctlr *ctlr; + Slot *slot; + Ring *ring; + Epio *io; + + if(ep->dev->isroot) + return; + + io = ep->aux; + if(io == nil) + return; + ep->aux = nil; + + ctlr = ep->hp->aux; + slot = ep->dev->aux; + + if(ep->nb > 0 && (io[OREAD].ring != nil || io[OWRITE].ring != nil)){ + u32int *w; + + /* input control context */ + w = slot->ibase; + memset(w, 0, 32<csz); + w[1] = 1; + if((ring = io[OREAD].ring) != nil){ + w[0] |= 1 << ring->id; + if(ring->id == slot->nep) + slot->nep--; + ctlrcmd(ctlr, CR_STOPEP | (ring->id<<16) | (slot->id<<24), 0, 0, nil); + } + if((ring = io[OWRITE].ring) != nil){ + w[0] |= 1 << ring->id; + if(ring->id == slot->nep) + slot->nep--; + ctlrcmd(ctlr, CR_STOPEP | (ring->id<<16) | (slot->id<<24), 0, 0, nil); + } + + /* (input) slot context */ + w += 8<csz; + w[0] = (w[0] & ~(0x1F<<27)) | slot->nep<<27; + + /* (input) ep context */ + w += ep->nb*2*8<csz; + memset(w, 0, 2*32<csz); + + dmaflush(1, slot->ibase, 32*33 << ctlr->csz); + ctlrcmd(ctlr, CR_CONFIGEP | (slot->id<<24), 0, PCIWADDR(slot->ibase), nil); + dmaflush(0, slot->obase, 32*32 << ctlr->csz); + + freering(io[OREAD].ring); + freering(io[OWRITE].ring); + } + freeb(io[OREAD].b); + freeb(io[OWRITE].b); + free(io); +} + +static void +initepctx(u32int *w, Ring *r, Ep *ep) +{ + int ival; + + if(ep->dev->speed == Lowspeed || ep->dev->speed == Fullspeed){ + for(ival=3; ival < 11 && (1<pollival; ival++) + ; + } else { + for(ival=0; ival < 15 && (1<pollival; ival++) + ; + } + w[0] = ival<<16; + w[1] = ((ep->ttype-Tctl) | (r->id&1)<<2)<<3 | (ep->ntds-1)<<8 | ep->maxpkt<<16; + if(ep->ttype != Tiso) + w[1] |= 3<<1; + *((u64int*)&w[2]) = PCIWADDR(r->base) | 1; + w[4] = 2*ep->maxpkt; + if(ep->ttype == Tintr || ep->ttype == Tiso) + w[4] |= (ep->maxpkt*ep->ntds)<<16; +} + +static void +initisoio(Epio *io, Ep *ep) +{ + if(io->ring == nil) + return; + io->frame = 0; + io->period = ep->pollival<<3*(ep->dev->speed == Fullspeed); + io->incr = (ep->hz*io->period<<8)/8000; + io->tdsz = (io->incr+255>>8)*ep->samplesz; + io->b = allocb((io->ring->mask+1)*io->tdsz); +} + +static void +initep(Ep *ep) +{ + Epio *io; + Ctlr *ctlr; + Slot *slot; + Ring *ring; + u32int *w; + char *err; + + io = ep->aux; + ctlr = ep->hp->aux; + slot = ep->dev->aux; + + io[OREAD].ring = io[OWRITE].ring = nil; + if(ep->nb == 0){ + io[OWRITE].ring = &slot->epr[0]; + return; + } + + /* (input) control context */ + w = slot->ibase; + memset(w, 0, 32<csz); + w[1] = 1; + w[31] = slot->altc<<16 | slot->iface<<8 | slot->confval; + + if(waserror()){ + freering(io[OWRITE].ring), io[OWRITE].ring = nil; + freering(io[OREAD].ring), io[OREAD].ring = nil; + nexterror(); + } + if(ep->mode != OREAD){ + ring = initring(io[OWRITE].ring = &slot->epr[ep->nb*2-1], 8); + ring->id = ep->nb*2; + if(ring->id > slot->nep) + slot->nep = ring->id; + ring->slot = slot; + ring->doorbell = &ctlr->dba[slot->id]; + ring->ctx = &slot->obase[ring->id*8<csz]; + w[1] |= 1 << ring->id; + } + if(ep->mode != OWRITE){ + ring = initring(io[OREAD].ring = &slot->epr[ep->nb*2], 8); + ring->id = ep->nb*2+1; + if(ring->id > slot->nep) + slot->nep = ring->id; + ring->slot = slot; + ring->doorbell = &ctlr->dba[slot->id]; + ring->ctx = &slot->obase[ring->id*8<csz]; + w[1] |= 1 << ring->id; + } + + /* (input) slot context */ + w += 8<csz; + w[0] = (w[0] & ~(0x1F<<27)) | slot->nep<<27; + if(!ep->dev->ishub) + w[0] &= ~(1<<25); // MTT + + /* (input) ep context */ + w += ep->nb*2*8<csz; + if(io[OWRITE].ring != nil){ + memset(w, 0, 5*4); + initepctx(w, io[OWRITE].ring, ep); + } + + w += 8<csz; + if(io[OREAD].ring != nil){ + memset(w, 0, 5*4); + initepctx(w, io[OREAD].ring, ep); + } + + dmaflush(1, slot->ibase, 32*33 << ctlr->csz); + err = ctlrcmd(ctlr, CR_CONFIGEP | (slot->id<<24), 0, PCIWADDR(slot->ibase), nil); + dmaflush(0, slot->obase, 32*32 << ctlr->csz); + if(err != nil) + error(err); + + if(ep->ttype == Tiso){ + initisoio(io+OWRITE, ep); + initisoio(io+OREAD, ep); + } + poperror(); +} + +static int +speedid(int speed) +{ + switch(speed){ + case Fullspeed: return 1; + case Lowspeed: return 2; + case Highspeed: return 3; + case Superspeed: return 4; + } + return 0; +} + +static void +epopen(Ep *ep) +{ + Ctlr *ctlr = ep->hp->aux; + Slot *slot, *hub; + Ring *ring; + Epio *io; + Udev *dev; + char *err; + u32int *w; + int i; + + if(ep->dev->isroot) + return; + if(needrecover(ctlr)) + error(Erecover); + io = malloc(sizeof(Epio)*2); + if(io == nil) + error(Enomem); + ep->aux = io; + if(waserror()){ + epclose(ep); + nexterror(); + } + dev = ep->dev; + slot = dev->aux; + if(slot != nil && slot->dev == dev){ + initep(ep); + poperror(); + return; + } + + /* first open has to be control endpoint */ + if(ep->nb != 0) + error(Egreg); + + slot = allocslot(ctlr, dev); + if(waserror()){ + freeslot(slot); + nexterror(); + } + + /* allocate control ep 0 ring */ + ring = initring(io[OWRITE].ring = &slot->epr[0], 4); + ring->id = 1; + slot->nep = 1; + ring->slot = slot; + ring->doorbell = &ctlr->dba[slot->id]; + ring->ctx = &slot->obase[8]; + + /* (input) control context */ + w = slot->ibase; + memset(w, 0, 3*32<csz); + w[1] = 3; /* A0, A1 */ + + /* (input) slot context */ + w += 8<csz; + w[2] = w[3] = 0; + w[0] = dev->routestr | speedid(dev->speed)<<20 | + (dev->speed == Highspeed && dev->ishub != 0)<<25 | // MTT + (dev->ishub != 0)<<26 | slot->nep<<27; + w[1] = dev->rootport<<16; + + /* find the parent hub that this device is conected to */ + qlock(&ctlr->slotlock); + for(i=1; i<=ctlr->nslots; i++){ + hub = ctlr->slot[i]; + if(hub == nil || hub->dev == nil || hub->dev->aux != hub) + continue; + if(hub == slot || hub->dev == dev) + continue; + if(!hub->dev->ishub) + continue; + if(hub->dev->addr != dev->hub) + continue; + if(hub->dev->rootport != dev->rootport) + continue; + + if(dev->speed < Highspeed && hub->dev->speed == Highspeed){ + w[0] |= 1<<25; // MTT + w[2] = hub->id | dev->port<<8; + } + break; + } + qunlock(&ctlr->slotlock); + + /* (input) ep context 0 */ + w += 8<csz; + initepctx(w, io[OWRITE].ring, ep); + + dmaflush(1, slot->ibase, 32*33 << ctlr->csz); + err = ctlrcmd(ctlr, CR_ADDRESSDEV | (slot->id<<24), 0, PCIWADDR(slot->ibase), nil); + dmaflush(0, slot->obase, 32*32 << ctlr->csz); + if(err != nil) + error(err); + + /* (output) slot context */ + w = slot->obase; + + dev->addr = w[3] & 0xFF; + + dev->aux = slot; + dev->free = freeslot; + + poperror(); + poperror(); +} + +static long +isoread(Ep *, uchar *, long) +{ + error(Egreg); + return 0; +} + +static long +isowrite(Ep *ep, uchar *p, long n) +{ + uchar *s, *d; + Ctlr *ctlr; + Epio *io; + u32int i, µ; + long m; + + s = p; + io = (Epio*)ep->aux + OWRITE; + qlock(io); + if(waserror()){ + qunlock(io); + nexterror(); + } + µ = io->period; + ctlr = ep->hp->aux; + if(needrecover(ctlr)) + error(Erecover); + for(i = io->frame;; i++){ + for(;;){ + m = (int)(io->ring->wp - io->ring->rp); + if(m <= 0) + i = (80 + µframe(ctlr))/µ; + if(m < io->ring->mask) + break; + *io->ring->doorbell = io->ring->id; + tsleep(&up->sleep, return0, nil, 5); + } + m = ((io->incr + (i*io->incr&255))>>8)*ep->samplesz; + d = io->b->rp + (i&io->ring->mask)*io->tdsz; + m -= io->nleft, d += io->nleft; + if(n < m){ + memmove(d, p, n); + p += n; + io->nleft += n; + break; + } + memmove(d, p, m); + p += m, n -= m; + m += io->nleft, d -= io->nleft; + io->nleft = 0; + dmaflush(1, d, m); + queuetd(io->ring, TR_ISOCH | (i*µ/8 & 0x7ff)<<20 | TR_IOC, m, PCIWADDR(d), nil); + } + io->frame = i; + while(io->ring->rp != io->ring->wp){ + int d = (int)(i*µ - µframe(ctlr))/8; + //d -= ep->sampledelay*1000 / ep->hz; + if(d < 5) + break; + *io->ring->doorbell = io->ring->id; + tsleep(&up->sleep, return0, nil, d); + } + qunlock(io); + poperror(); + + return p - s; +} + +static char* +unstall(Ep *ep, Ring *r) +{ + char *err; + + switch(r->ctx[0]&7){ + case 2: /* halted */ + case 4: /* error */ + ep->clrhalt = 1; + } + if(ep->clrhalt){ + ep->clrhalt = 0; + err = ctlrcmd(r->slot->ctlr, CR_RESETEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); + dmaflush(0, r->ctx, 8*4 << r->slot->ctlr->csz); + if(err != nil) + return err; + r->stopped = 1; + } + if(r->stopped){ + err = ctlrcmd(r->slot->ctlr, CR_SETTRDQP | (r->id<<16) | (r->slot->id<<24), 0, resetring(r), nil); + dmaflush(0, r->ctx, 8*4 << r->slot->ctlr->csz); + if(err != nil) + return err; + r->stopped = 0; + } + if(r->wp - r->rp >= r->mask) + return "Ring Full"; + return nil; +} + +static long +epread(Ep *ep, void *va, long n) +{ + Epio *io; + Ctlr *ctlr; + uchar *p; + char *err; + Wait w[1]; + + if(ep->dev->isroot) + error(Egreg); + + p = va; + if(ep->ttype == Tctl){ + io = (Epio*)ep->aux + OREAD; + qlock(io); + if(io->b == nil || BLEN(io->b) == 0){ + qunlock(io); + return 0; + } + if(n > BLEN(io->b)) + n = BLEN(io->b); + memmove(p, io->b->rp, n); + io->b->rp += n; + qunlock(io); + return n; + } else if(ep->ttype == Tiso) + return isoread(ep, p, n); + + if((uintptr)p <= KZERO){ + Block *b; + + b = allocb(n); + if(waserror()){ + freeb(b); + nexterror(); + } + n = epread(ep, b->rp, n); + memmove(p, b->rp, n); + freeb(b); + poperror(); + return n; + } + + ctlr = (Ctlr*)ep->hp->aux; + io = (Epio*)ep->aux + OREAD; + qlock(io); + if(waserror()){ + dmaflush(0, io->ring->ctx, 8*4 << ctlr->csz); + qunlock(io); + nexterror(); + } + + if((err = unstall(ep, io->ring)) != nil) + error(err); + + dmaflush(1, p, n); + queuetd(io->ring, TR_NORMAL | TR_IOC, n, PCIWADDR(p), w); + err = waittd(ctlr, w, ep->tmout); + dmaflush(0, p, n); + if(err != nil) + error(err); + + qunlock(io); + poperror(); + + n -= (w->er[2] & 0xFFFFFF); + if(n < 0) + n = 0; + + return n; +} + +static long +epwrite(Ep *ep, void *va, long n) +{ + Wait w[3]; + Ctlr *ctlr; + Epio *io; + uchar *p; + char *err; + + if(ep->dev->isroot) + error(Egreg); + + p = va; + if(ep->ttype == Tctl){ + int dir, len; + Ring *ring; + Slot *slot; + + if(n < 8) + error(Eshort); + + if(p[0] == 0x00 && p[1] == 0x05) + return n; + + ctlr = (Ctlr*)ep->hp->aux; + io = (Epio*)ep->aux + OREAD; + ring = io[OWRITE-OREAD].ring; + slot = ring->slot; + qlock(io); + if(waserror()){ + ilock(ring); + ring->pending = nil; + iunlock(ring); + dmaflush(0, ring->ctx, 8*4 << ctlr->csz); + qunlock(io); + nexterror(); + } + if(io->b != nil){ + freeb(io->b); + io->b = nil; + } + len = GET2(&p[6]); + dir = (p[0] & Rd2h) != 0; + if(len > 0){ + io->b = allocb(len); + if(dir == 0){ /* out */ + assert(len >= n-8); + memmove(io->b->wp, p+8, n-8); + } else { + memset(io->b->wp, 0, len); + io->b->wp += len; + } + } + if((err = unstall(ep, ring)) != nil) + error(err); + + if((ring->ctx[1]>>16) != ep->maxpkt){ + u32int *w = slot->ibase; + w[0] = 0; + w[1] = 1<id; + w += (ring->id+1)*8<csz; + initepctx(w, ring, ep); + dmaflush(1, slot->ibase, 32*33 << ctlr->csz); + err = ctlrcmd(ctlr, CR_EVALCTX | (slot->id<<24), 0, PCIWADDR(slot->ibase), nil); + dmaflush(0, slot->obase, 32*32 << ctlr->csz); + if(err != nil) + error(err); + } + + queuetd(ring, TR_SETUPSTAGE | (len > 0 ? 2+dir : 0)<<16 | TR_IDT | TR_IOC, 8, + p[0] | p[1]<<8 | GET2(&p[2])<<16 | + (u64int)(GET2(&p[4]) | len<<16)<<32, &w[0]); + if(len > 0){ + dmaflush(1, io->b->rp, len); + queuetd(ring, TR_DATASTAGE | dir<<16 | TR_IOC, len, + PCIWADDR(io->b->rp), &w[1]); + } + queuetd(ring, TR_STATUSSTAGE | (len == 0 || !dir)<<16 | TR_IOC, 0, 0, &w[2]); + + if((err = waittd(ctlr, &w[0], ep->tmout)) != nil) + error(err); + if(len > 0){ + if((err = waittd(ctlr, &w[1], ep->tmout)) != nil) + error(err); + if(dir != 0){ + dmaflush(0, io->b->rp, len); + io->b->wp -= (w[1].er[2] & 0xFFFFFF); + if(io->b->wp < io->b->rp) + io->b->wp = io->b->rp; + } + } + if((err = waittd(ctlr, &w[2], ep->tmout)) != nil) + error(err); + + if(p[0] == 0x00 && p[1] == 0x09){ + slot->confval = GET2(&p[2]); + } else if(p[0] == 0x01 && p[1] == 0x0d){ + slot->altc = GET2(&p[2]); + slot->iface = GET2(&p[4]); + } + + qunlock(io); + poperror(); + + return n; + } else if(ep->ttype == Tiso) + return isowrite(ep, p, n); + + if((uintptr)p <= KZERO){ + Block *b; + + b = allocb(n); + if(waserror()){ + freeb(b); + nexterror(); + } + memmove(b->wp, p, n); + n = epwrite(ep, b->wp, n); + freeb(b); + poperror(); + return n; + } + + ctlr = (Ctlr*)ep->hp->aux; + io = (Epio*)ep->aux + OWRITE; + qlock(io); + if(waserror()){ + dmaflush(0, io->ring->ctx, 8*4 << ctlr->csz); + qunlock(io); + nexterror(); + } + + if((err = unstall(ep, io->ring)) != nil) + error(err); + + dmaflush(1, p, n); + queuetd(io->ring, TR_NORMAL | TR_IOC, n, PCIWADDR(p), w); + if((err = waittd(ctlr, w, ep->tmout)) != nil) + error(err); + + qunlock(io); + poperror(); + + return n; +} + +static char* +seprintep(char *s, char*, Ep*) +{ + return s; +} + +static int +portstatus(Hci *hp, int port) +{ + Ctlr *ctlr = hp->aux; + u32int psc, ps; + + if(ctlr->port == nil || needrecover(ctlr)) + return 0; + + ps = 0; + psc = ctlr->port[port-1].reg[PORTSC]; + if(psc & CCS) ps |= HPpresent; + if(psc & PED) ps |= HPenable; + if(psc & OCA) ps |= HPovercurrent; + if(psc & PR) ps |= HPreset; + + if((hp->superspeed & (1<<(port-1))) != 0){ + ps |= psc & (PLS|PP); + if(psc & CSC) ps |= 1<<0+16; + if(psc & OCC) ps |= 1<<3+16; + if(psc & PRC) ps |= 1<<4+16; + if(psc & WRC) ps |= 1<<5+16; + if(psc & PLC) ps |= 1<<6+16; + if(psc & CEC) ps |= 1<<7+16; + } else { + if((ps & HPreset) == 0){ + switch((psc>>10)&15){ + case 1: + /* full speed */ + break; + case 2: + ps |= HPslow; + break; + case 3: + ps |= HPhigh; + break; + } + } + if(psc & PP) ps |= HPpower; + if(psc & CSC) ps |= HPstatuschg; + if(psc & PRC) ps |= HPchange; + } + + return ps; +} + +static int +portenable(Hci*, int, int) +{ + return 0; +} + +static int +portreset(Hci *hp, int port, int on) +{ + Ctlr *ctlr = hp->aux; + + if(ctlr->port == nil || needrecover(ctlr)) + return 0; + + if(on){ + ctlr->port[port-1].reg[PORTSC] |= PR; + tsleep(&up->sleep, return0, nil, 200); + } + return 0; +} + + +static Ctlr *ctlrs[Nhcis]; + +static void +scanpci(void) +{ + static int already = 0; + int i; + uintpci io; + Ctlr *ctlr; + Pcidev *p; + u32int *mmio; + + if(already) + return; + already = 1; + p = nil; + while ((p = pcimatch(p, 0, 0)) != nil) { + /* + * Find XHCI controllers (Programming Interface = 0x30). + */ + if(p->ccrb != Pcibcserial || p->ccru != Pciscusb || p->ccrp != 0x30) + continue; + io = p->mem[0].bar & ~0x0f; + if(io == 0) + continue; + print("usbxhci: %#x %#x: port %llux size %#x irq %d\n", + p->vid, p->did, io, p->mem[0].size, p->intl); + mmio = (u32int*)mmukmapx(VIRTPCI, io, p->mem[0].size); + if(mmio == nil){ + print("usbxhci: cannot map registers\n"); + continue; + } + ctlr = malloc(sizeof(Ctlr)); + if(ctlr == nil){ + print("usbxhci: no memory\n"); + continue; + } + ctlr->base = io; + ctlr->active = nil; + ctlr->pcidev = p; + ctlr->mmio = mmio; + for(i = 0; i < nelem(ctlrs); i++) + if(ctlrs[i] == nil){ + ctlrs[i] = ctlr; + break; + } + if(i >= nelem(ctlrs)) + print("xhci: bug: more than %d controllers\n", nelem(ctlrs)); + } +} + +static int +reset(Hci *hp) +{ + Ctlr *ctlr; + int i; + + if(getconf("*nousbxhci")) + return -1; + + scanpci(); + + /* + * Any adapter matches if no hp->port is supplied, + * otherwise the ports must match. + */ + for(i = 0; i < nelem(ctlrs) && ctlrs[i] != nil; i++){ + ctlr = ctlrs[i]; + if(ctlr->active == nil) + if(hp->port == 0 || hp->port == ctlr->base){ + ctlr->active = hp; + goto Found; + } + } + return -1; + +Found: + hp->aux = ctlr; + hp->port = ctlr->base; + hp->irq = ctlr->pcidev->intl; + hp->tbdf = ctlr->pcidev->tbdf; + + hp->init = init; + hp->dump = dump; + hp->interrupt = interrupt; + hp->epopen = epopen; + hp->epclose = epclose; + hp->epread = epread; + hp->epwrite = epwrite; + hp->seprintep = seprintep; + hp->portenable = portenable; + hp->portreset = portreset; + hp->portstatus = portstatus; + hp->shutdown = shutdown; + hp->debug = setdebug; + hp->type = "xhci"; + + return 0; +} + +void +usbxhcilink(void) +{ + addhcitype("xhci", reset); +} + +void +dmaflush(int clean, void *p, ulong len) +{ + uintptr s = (uintptr)p; + uintptr e = (uintptr)p + len; + + if(clean){ + s &= ~(BLOCKALIGN-1); + e += BLOCKALIGN-1; + e &= ~(BLOCKALIGN-1); + cachedwbse((void*)s, e - s); + return; + } + if(s & BLOCKALIGN-1){ + s &= ~(BLOCKALIGN-1); + cachedwbinvse((void*)s, BLOCKALIGN); + s += BLOCKALIGN; + } + if(e & BLOCKALIGN-1){ + e &= ~(BLOCKALIGN-1); + if(e < s) + return; + cachedwbinvse((void*)e, BLOCKALIGN); + } + if(s < e) + cachedinvse((void*)s, e - s); +} diff --git a/sys/src/9/bcm/vcore.c b/sys/src/9/bcm/vcore.c index 9df2b40fbc..6d3cdb941e 100644 --- a/sys/src/9/bcm/vcore.c +++ b/sys/src/9/bcm/vcore.c @@ -12,6 +12,7 @@ typedef struct Prophdr Prophdr; typedef struct Fbinfo Fbinfo; +typedef struct Vgpio Vgpio; enum { Read = 0x00>>2, @@ -33,12 +34,18 @@ enum { TagResp = 1<<31, TagGetfwrev = 0x00000001, + TagGetrev = 0x00010002, TagGetmac = 0x00010003, + TagGetser = 0x00010004, TagGetram = 0x00010005, TagGetpower = 0x00020001, TagSetpower = 0x00028001, Powerwait = 1<<1, TagGetclkspd= 0x00030002, + TagGetclkmax= 0x00030004, + TagSetclkspd= 0x00038002, + TagGettemp = 0x00030006, + TagXhciReset= 0x00030058, TagFballoc = 0x00040001, TagFbfree = 0x00048001, TagFbblank = 0x00040002, @@ -48,8 +55,11 @@ enum { TagSetvres = 0x00048004, TagGetdepth = 0x00040005, TagSetdepth = 0x00048005, - TagGetrgb = 0x00044006, + TagGetrgb = 0x00040006, TagSetrgb = 0x00048006, + TagGetGpio = 0x00040010, + + Nvgpio = 2, }; struct Fbinfo { @@ -75,6 +85,15 @@ struct Prophdr { u32int data[1]; }; +struct Vgpio { + u32int *counts; + u16int incs; + u16int decs; + int ison; +}; + +static Vgpio vgpio; + static void vcwrite(uint chan, int val) { @@ -114,7 +133,8 @@ vcreq(int tag, void *buf, int vallen, int rsplen) uintptr r; int n; Prophdr *prop; - static uintptr base = BUSDRAM; + uintptr aprop; + static int busaddr = 1; if(rsplen < vallen) rsplen = vallen; @@ -131,13 +151,14 @@ vcreq(int tag, void *buf, int vallen, int rsplen) memmove(prop->data, buf, vallen); cachedwbinvse(prop, prop->len); for(;;){ - vcwrite(ChanProps, PADDR(prop) + base); + aprop = busaddr? dmaaddr(prop) : PTR2UINT(prop); + vcwrite(ChanProps, aprop); r = vcread(ChanProps); - if(r == PADDR(prop) + base) + if(r == aprop) break; - if(base == 0) + if(!busaddr) return -1; - base = 0; + busaddr = 0; } if(prop->req == RspOk && prop->tag == tag && @@ -159,13 +180,17 @@ static int fbdefault(int *width, int *height, int *depth) { u32int buf[3]; + char *p; if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 || vcreq(TagGetdepth, &buf[2], 0, 4) != 4) return -1; *width = buf[0]; *height = buf[1]; - *depth = buf[2]; + if((p = getconf("bcm2708_fb.fbdepth")) != nil) + *depth = atoi(p); + else + *depth = buf[2]; return 0; } @@ -185,10 +210,10 @@ fbinit(int set, int *width, int *height, int *depth) fi->yres = fi->yresvirtual = *height; fi->bpp = *depth; cachedwbinvse(fi, sizeof(*fi)); - vcwrite(ChanFb, DMAADDR(fi)); + vcwrite(ChanFb, dmaaddr(fi)); if(vcread(ChanFb) != 0) return 0; - va = mmukmap(FRAMEBUFFER, PADDR(fi->base), fi->screensize); + va = mmukmap(FRAMEBUFFER, fi->base & ~0xC0000000, fi->screensize); if(va) memset((char*)va, 0x7F, fi->screensize); return (void*)va; @@ -250,6 +275,19 @@ getethermac(void) return buf; } +/* + * Get board revision + */ +uint +getboardrev(void) +{ + u32int buf[1]; + + if(vcreq(TagGetrev, buf, 0, sizeof buf) != sizeof buf) + return 0; + return buf[0]; +} + /* * Get firmware revision */ @@ -263,6 +301,19 @@ getfirmware(void) return buf[0]; } +/* + * Get serial number + */ +uvlong +getserial(void) +{ + uvlong buf; + + if(vcreq(TagGetser, &buf, 0, sizeof buf) != sizeof buf) + return 0; + return buf; +} + /* * Get ARM ram */ @@ -290,3 +341,80 @@ getclkrate(int clkid) return 0; return buf[1]; } + +/* + * Set clock rate to hz (or max speed if hz == 0) + */ +void +setclkrate(int clkid, ulong hz) +{ + u32int buf[2]; + + buf[0] = clkid; + if(hz != 0) + buf[1] = hz; + else if(vcreq(TagGetclkmax, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf) + return; + vcreq(TagSetclkspd, buf, sizeof(buf), sizeof(buf)); +} + +/* + * Get cpu temperature + */ +uint +getcputemp(void) +{ + u32int buf[2]; + + buf[0] = 0; + if(vcreq(TagGettemp, buf, sizeof(buf[0]), sizeof buf) != sizeof buf) + return 0; + return buf[1]; +} + +/* + * Notify gpu that xhci firmware might need loading. This is for some + * pi4 board versions which are missing the eeprom chip for the vl805, + * requiring its firmware to come from the boot eeprom instead. + */ +int +xhcireset(int devaddr) +{ + u32int buf[1]; + + buf[0] = devaddr; + if(vcreq(TagXhciReset, buf, sizeof(buf), sizeof(buf[0])) == sizeof(buf[0])) + return buf[0]; + return -1; +} + +/* + * Virtual GPIO - used for ACT LED on pi3 + */ +void +vgpinit(void) +{ + u32int buf[1]; + uintptr va; + + buf[0] = 0; + if(vcreq(TagGetGpio, buf, 0, sizeof(buf)) != sizeof buf || buf[0] == 0) + return; + va = mmukmap(VGPIO, buf[0] & ~0xC0000000, BY2PG); + if(va == 0) + return; + vgpio.counts = (u32int*)va; +} + +void +vgpset(uint port, int on) +{ + if(vgpio.counts == nil || port >= Nvgpio || on == vgpio.ison) + return; + if(on) + vgpio.incs++; + else + vgpio.decs++; + vgpio.counts[port] = (vgpio.incs << 16) | vgpio.decs; + vgpio.ison = on; +} diff --git a/sys/src/9/bcm/vfp3.c b/sys/src/9/bcm/vfp3.c index 8203b769ba..0cb935cb94 100644 --- a/sys/src/9/bcm/vfp3.c +++ b/sys/src/9/bcm/vfp3.c @@ -1 +1,512 @@ -#include "../teg2/vfp3.c" +/* + * VFPv2 or VFPv3 floating point unit + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "ureg.h" +#include "arm.h" + +/* subarchitecture code in m->havefp */ +enum { + VFPv2 = 2, + VFPv3 = 3, +}; + +/* fp control regs. most are read-only */ +enum { + Fpsid = 0, + Fpscr = 1, /* rw */ + Mvfr1 = 6, + Mvfr0 = 7, + Fpexc = 8, /* rw */ + Fpinst= 9, /* optional, for exceptions */ + Fpinst2=10, +}; +enum { + /* Fpexc bits */ + Fpex = 1u << 31, + Fpenabled = 1 << 30, + Fpdex = 1 << 29, /* defined synch exception */ +// Fp2v = 1 << 28, /* Fpinst2 reg is valid */ +// Fpvv = 1 << 27, /* if Fpdex, vecitr is valid */ +// Fptfv = 1 << 26, /* trapped fault is valid */ +// Fpvecitr = MASK(3) << 8, + /* FSR bits appear here */ + Fpmbc = Fpdex, /* bits exception handler must clear */ + + /* Fpscr bits; see u.h for more */ + Stride = MASK(2) << 20, + Len = MASK(3) << 16, + Dn= 1 << 25, + Fz= 1 << 24, + /* trap exception enables (not allowed in vfp3) */ + FPIDNRM = 1 << 15, /* input denormal */ + Alltraps = FPIDNRM | FPINEX | FPUNFL | FPOVFL | FPZDIV | FPINVAL, + /* pending exceptions */ + FPAIDNRM = 1 << 7, /* input denormal */ + Allexc = FPAIDNRM | FPAINEX | FPAUNFL | FPAOVFL | FPAZDIV | FPAINVAL, + /* condition codes */ + Allcc = MASK(4) << 28, +}; +enum { + /* CpCPaccess bits */ + Cpaccnosimd = 1u << 31, + Cpaccd16 = 1 << 30, +}; + +static char * +subarch(int impl, uint sa) +{ + static char *armarchs[] = { + "VFPv1 (unsupported)", + "VFPv2", + "VFPv3+ with common VFP subarch v2", + "VFPv3+ with null subarch", + "VFPv3+ with common VFP subarch v3", + }; + + if (impl != 'A' || sa >= nelem(armarchs)) + return "GOK"; + else + return armarchs[sa]; +} + +static char * +implement(uchar impl) +{ + if (impl == 'A') + return "arm"; + else + return "unknown"; +} + +static int +havefp(void) +{ + int gotfp; + ulong acc, sid; + + if (m->havefpvalid) + return m->havefp; + + m->havefp = 0; + gotfp = 1 << CpFP | 1 << CpDFP; + cpwrcpaccess(MASK(28)); + acc = cprdcpaccess(); + if ((acc & (MASK(2) << (2*CpFP))) == 0) { + gotfp &= ~(1 << CpFP); + print("fpon: no single FP coprocessor\n"); + } + if ((acc & (MASK(2) << (2*CpDFP))) == 0) { + gotfp &= ~(1 << CpDFP); + print("fpon: no double FP coprocessor\n"); + } + if (!gotfp) { + print("fpon: no FP coprocessors\n"); + m->havefpvalid = 1; + return 0; + } + m->fpon = 1; /* don't panic */ + sid = fprdsid(); + m->fpon = 0; + switch((sid >> 16) & MASK(7)){ + case 0: /* VFPv1 */ + break; + case 1: /* VFPv2 */ + m->havefp = VFPv2; + m->fpnregs = 16; + break; + default: /* VFPv3 or later */ + m->havefp = VFPv3; + m->fpnregs = (acc & Cpaccd16) ? 16 : 32; + break; + } + if (m->machno == 0) + print("fp: %d registers, %s simd\n", m->fpnregs, + (acc & Cpaccnosimd? " no": "")); + m->havefpvalid = 1; + return 1; +} + +/* + * these can be called to turn the fpu on or off for user procs, + * not just at system start up or shutdown. + */ + +void +fpoff(void) +{ + if (m->fpon) { + fpwrexc(0); + m->fpon = 0; + } +} + +void +fpononly(void) +{ + if (!m->fpon && havefp()) { + /* enable fp. must be first operation on the FPUs. */ + fpwrexc(Fpenabled); + m->fpon = 1; + } +} + +static void +fpcfg(void) +{ + int impl; + ulong sid; + static int printed; + + /* clear pending exceptions; no traps in vfp3; all v7 ops are scalar */ + m->fpscr = Dn | FPRNR | (FPINVAL | FPZDIV | FPOVFL) & ~Alltraps; + /* VFPv2 needs software support for underflows, so force them to zero */ + if(m->havefp == VFPv2) + m->fpscr |= Fz; + fpwrscr(m->fpscr); + m->fpconfiged = 1; + + if (printed) + return; + sid = fprdsid(); + impl = sid >> 24; + print("fp: %s arch %s; rev %ld\n", implement(impl), + subarch(impl, (sid >> 16) & MASK(7)), sid & MASK(4)); + printed = 1; +} + +void +fpinit(void) +{ + if (havefp()) { + fpononly(); + fpcfg(); + } +} + +void +fpon(void) +{ + if (havefp()) { + fpononly(); + if (m->fpconfiged) + fpwrscr((fprdscr() & Allcc) | m->fpscr); + else + fpcfg(); /* 1st time on this fpu; configure it */ + } +} + +void +fpclear(void) +{ +// ulong scr; + + fpon(); +// scr = fprdscr(); +// m->fpscr = scr & ~Allexc; +// fpwrscr(m->fpscr); + + fpwrexc(fprdexc() & ~Fpmbc); +} + + +/* + * Called when a note is about to be delivered to a + * user process, usually at the end of a system call. + * Note handlers are not allowed to use the FPU so + * the state is marked (after saving if necessary) and + * checked in the Device Not Available handler. + */ +void +fpunotify(Ureg*) +{ + if(up->fpstate == FPactive){ + fpsave(&up->fpsave); + up->fpstate = FPinactive; + } + up->fpstate |= FPillegal; +} + +/* + * Called from sysnoted() via the machine-dependent + * noted() routine. + * Clear the flag set above in fpunotify(). + */ +void +fpunoted(void) +{ + up->fpstate &= ~FPillegal; +} + +/* + * Called early in the non-interruptible path of + * sysrfork() via the machine-dependent syscall() routine. + * Save the state so that it can be easily copied + * to the child process later. + */ +void +fpusysrfork(Ureg*) +{ + if(up->fpstate == FPactive){ + fpsave(&up->fpsave); + up->fpstate = FPinactive; + } +} + +/* + * Called later in sysrfork() via the machine-dependent + * sysrforkchild() routine. + * Copy the parent FPU state to the child. + */ +void +fpusysrforkchild(Proc *p, Ureg *, Proc *up) +{ + /* don't penalize the child, it hasn't done FP in a note handler. */ + p->fpstate = up->fpstate & ~FPillegal; +} + +/* should only be called if p->fpstate == FPactive */ +void +fpsave(FPsave *fps) +{ + fpon(); + fps->control = fps->status = fprdscr(); + assert(m->fpnregs); + fpsaveregs((uvlong*)fps->regs, m->fpnregs); + fpoff(); +} + +static void +fprestore(Proc *p) +{ + fpon(); + fpwrscr(p->fpsave.control); + m->fpscr = fprdscr() & ~Allcc; + assert(m->fpnregs); + fprestregs((uvlong*)p->fpsave.regs, m->fpnregs); +} + +/* + * Called from sched() and sleep() via the machine-dependent + * procsave() routine. + * About to go in to the scheduler. + * If the process wasn't using the FPU + * there's nothing to do. + */ +void +fpuprocsave(Proc *p) +{ + if(p->fpstate == FPactive){ + if(p->state == Moribund) + fpoff(); + else{ + /* + * Fpsave() stores without handling pending + * unmasked exeptions. Postnote() can't be called + * here as sleep() already has up->rlock, so + * the handling of pending exceptions is delayed + * until the process runs again and generates an + * emulation fault to activate the FPU. + */ + fpsave(&p->fpsave); + } + p->fpstate = FPinactive; + } +} + +/* + * The process has been rescheduled and is about to run. + * Nothing to do here right now. If the process tries to use + * the FPU again it will cause a Device Not Available + * exception and the state will then be restored. + */ +void +fpuprocrestore(Proc *) +{ +} + +/* + * Disable the FPU. + * Called from sysexec() via sysprocsetup() to + * set the FPU for the new process. + */ +void +fpusysprocsetup(Proc *p) +{ + p->fpstate = FPinit; + fpoff(); +} + +static void +mathnote(void) +{ + ulong status; + char *msg, note[ERRMAX]; + + status = up->fpsave.status; + + /* + * Some attention should probably be paid here to the + * exception masks and error summary. + */ + if (status & FPAINEX) + msg = "inexact"; + else if (status & FPAOVFL) + msg = "overflow"; + else if (status & FPAUNFL) + msg = "underflow"; + else if (status & FPAZDIV) + msg = "divide by zero"; + else if (status & FPAINVAL) + msg = "bad operation"; + else + msg = "spurious"; + snprint(note, sizeof note, "sys: fp: %s fppc=%#p status=%#lux", + msg, up->fpsave.pc, status); + postnote(up, 1, note, NDebug); +} + +static void +mathemu(Ureg *) +{ + switch(up->fpstate){ + case FPemu: + error("illegal instruction: VFP opcode in emulated mode"); + case FPinit: + fpinit(); + up->fpstate = FPactive; + break; + case FPinactive: + /* + * Before restoring the state, check for any pending + * exceptions. There's no way to restore the state without + * generating an unmasked exception. + * More attention should probably be paid here to the + * exception masks and error summary. + */ + if(up->fpsave.status & (FPAINEX|FPAUNFL|FPAOVFL|FPAZDIV|FPAINVAL)){ + mathnote(); + break; + } + fprestore(up); + up->fpstate = FPactive; + break; + case FPactive: + error("sys: illegal instruction: bad vfp fpu opcode"); + break; + } + fpclear(); +} + +void +fpstuck(uintptr pc) +{ + if (m->fppc == pc && m->fppid == up->pid) { + m->fpcnt++; + if (m->fpcnt > 4) + panic("fpuemu: cpu%d stuck at pid %ld %s pc %#p " + "instr %#8.8lux", m->machno, up->pid, up->text, + pc, *(ulong *)pc); + } else { + m->fppid = up->pid; + m->fppc = pc; + m->fpcnt = 0; + } +} + +enum { + N = 1<<31, + Z = 1<<30, + C = 1<<29, + V = 1<<28, + REGPC = 15, +}; + +static int +condok(int cc, int c) +{ + switch(c){ + case 0: /* Z set */ + return cc&Z; + case 1: /* Z clear */ + return (cc&Z) == 0; + case 2: /* C set */ + return cc&C; + case 3: /* C clear */ + return (cc&C) == 0; + case 4: /* N set */ + return cc&N; + case 5: /* N clear */ + return (cc&N) == 0; + case 6: /* V set */ + return cc&V; + case 7: /* V clear */ + return (cc&V) == 0; + case 8: /* C set and Z clear */ + return cc&C && (cc&Z) == 0; + case 9: /* C clear or Z set */ + return (cc&C) == 0 || cc&Z; + case 10: /* N set and V set, or N clear and V clear */ + return (~cc&(N|V))==0 || (cc&(N|V)) == 0; + case 11: /* N set and V clear, or N clear and V set */ + return (cc&(N|V))==N || (cc&(N|V))==V; + case 12: /* Z clear, and either N set and V set or N clear and V clear */ + return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0); + case 13: /* Z set, or N set and V clear or N clear and V set */ + return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V; + case 14: /* always */ + return 1; + case 15: /* never (reserved) */ + return 0; + } + return 0; /* not reached */ +} + +/* only called to deal with user-mode instruction faults */ +int +fpuemu(Ureg* ureg) +{ + int s, nfp, cop, op; + uintptr pc; + static int already; + + if(waserror()){ + postnote(up, 1, up->errstr, NDebug); + return 1; + } + + if(up->fpstate & FPillegal) + error("floating point in note handler"); + + nfp = 0; + pc = ureg->pc; + validaddr(pc, 4, 0); + op = (*(ulong *)pc >> 24) & MASK(4); + cop = (*(ulong *)pc >> 8) & MASK(4); + if(m->fpon) + fpstuck(pc); /* debugging; could move down 1 line */ + if (ISFPAOP(cop, op)) { /* old arm 7500 fpa opcode? */ + s = spllo(); + if(!already++) + pprint("warning: emulated arm7500 fpa instr %#8.8lux at %#p\n", *(ulong *)pc, pc); + if(waserror()){ + splx(s); + nexterror(); + } + nfp = fpiarm(ureg); /* advances pc past emulated instr(s) */ + if (nfp > 1) /* could adjust this threshold */ + m->fppc = m->fpcnt = 0; + splx(s); + poperror(); + } else if (ISVFPOP(cop, op)) { /* if vfp, fpu off or unsupported instruction */ + mathemu(ureg); /* enable fpu & retry */ + nfp = 1; + } + + poperror(); + return nfp; +} diff --git a/sys/src/9/bcm/words.pi2 b/sys/src/9/bcm/words.pi2 new file mode 100644 index 0000000000..146d1d5873 --- /dev/null +++ b/sys/src/9/bcm/words.pi2 @@ -0,0 +1,11 @@ +raspberry pi 2 -- differences from raspberry pi + +broadcom 2836 SoC (based on 2709) +4 x cortex-a7 (v7 arch) 900Mhz cpu, dual-issue, vfpv3+ + +integral l2 cache + +1GB of dram at physical address 0 + +peripherals at 0x3F000000 +gpu/dma space at 0xC0000000 diff --git a/sys/src/9/bcm/words.pi4 b/sys/src/9/bcm/words.pi4 new file mode 100644 index 0000000000..3d8344486e --- /dev/null +++ b/sys/src/9/bcm/words.pi4 @@ -0,0 +1,14 @@ +raspberry pi 4 -- work in progress! + +broadcom 2838 SoC (based on 2711) +4 x cortex-a72 (1500Mhz, out-of-order pipeline) + +Needs firmware from 5 July 2019 or later. + +config.txt for pi4 should include 'core_freq=250' for +the mini-uart console, and 'device_tree=' to ensure that +the loader passes an ATAG list to the kernel instead of +a device tree. + +On a 4GB (or 2GB) pi4, a little less than 2GB will be +used. (0x7D000000 bytes to be precise.) From 6ab841b58f3ff6c916cc33500ed6f27e2225bbf0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 22 Dec 2022 16:39:26 +0000 Subject: [PATCH 077/402] sys/src/9/bcm: import bcm fixes (2022-12-22) (thanks Richard Miller) --- sys/src/9/bcm/devspi.c | 4 ++-- sys/src/9/bcm/etherusb.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/src/9/bcm/devspi.c b/sys/src/9/bcm/devspi.c index 8c39712224..327c6e17d3 100644 --- a/sys/src/9/bcm/devspi.c +++ b/sys/src/9/bcm/devspi.c @@ -171,7 +171,7 @@ spiopen(Chan* c, int omode) Spi *spi; c = devopen(c, omode, spidir, nelem(spidir), devgen); - if(c->qid.type & QTDIR) + if(c->qid.path < Qspi) return c; spi = &spidev[DEVID(c->qid.path)]; @@ -197,7 +197,7 @@ spiclose(Chan *c) { Spi *spi; - if(c->qid.type & QTDIR) + if(c->qid.path < Qspi) return; if((c->flag & COPEN) == 0) return; diff --git a/sys/src/9/bcm/etherusb.c b/sys/src/9/bcm/etherusb.c index 88d9816650..b549d19636 100644 --- a/sys/src/9/bcm/etherusb.c +++ b/sys/src/9/bcm/etherusb.c @@ -325,7 +325,7 @@ bind(Ctlr *ctlr, Udev *udev, Cmdbuf *cb) if(ctlr->buf != nil) cmderror(cb, "already bound to a device"); maxpkt = strtol(cb->f[6], 0, 0); - if(maxpkt < 8 || maxpkt > 512) + if(maxpkt < 8) cmderror(cb, "bad maxpkt"); bufsize = strtol(cb->f[5], 0, 0); if(bufsize < maxpkt || bufsize > 32*1024) From ebcbf61a332e616bd4a91f600b6271c3b7734551 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 22 Dec 2022 16:18:03 +0000 Subject: [PATCH 078/402] sys/src/9/bcm: use long descriptor format for mmu page tables to support more than 4GB physical memory (thanks Richard Miller) --- sys/src/9/bcm/arm.h | 9 + sys/src/9/bcm/armv7.s | 56 +++- sys/src/9/bcm/dat.h | 27 +- sys/src/9/bcm/fns.h | 1 + sys/src/9/bcm/gisb.c | 2 +- sys/src/9/bcm/main.c | 41 ++- sys/src/9/bcm/mem.h | 11 +- sys/src/9/bcm/mkfile | 2 +- sys/src/9/bcm/mmu.c | 16 +- sys/src/9/bcm/mmu64.c | 560 +++++++++++++++++++++++++++++++++++++ sys/src/9/bcm/pi | 1 + sys/src/9/bcm/pi2 | 3 + sys/src/9/bcm/pi2cpu | 3 + sys/src/9/bcm/pi2wifi | 1 + sys/src/9/bcm/pi4 | 2 + sys/src/9/bcm/pi4cpu | 2 + sys/src/9/bcm/pi4wifi | 1 + sys/src/9/bcm/picpu | 1 + sys/src/9/bcm/pifat | 1 + sys/src/9/bcm/piwifi | 1 + sys/src/9/bcm/rebootcode.s | 8 +- sys/src/9/bcm/trap.c | 2 +- sys/src/9/bcm/trap4.c | 4 +- 23 files changed, 718 insertions(+), 37 deletions(-) create mode 100644 sys/src/9/bcm/mmu64.c diff --git a/sys/src/9/bcm/arm.h b/sys/src/9/bcm/arm.h index 662c2d911a..8c2e312ec4 100644 --- a/sys/src/9/bcm/arm.h +++ b/sys/src/9/bcm/arm.h @@ -227,6 +227,7 @@ */ #define CpTLDlock 0 /* TLB lockdown registers */ #define CpTLDpreload 1 /* TLB preload */ +#define CpTLDmair 2 #define CpTLDi 0 /* TLB instr. lockdown reg. */ #define CpTLDd 1 /* " data " " */ @@ -270,6 +271,14 @@ #define CpTTBs (1<<1) /* page table in shareable memory */ #define CpTTBbase ~0x7F /* mask off control bits */ +/* + * CpTTBctl bits + */ +#define EAElpae (1<<31) /* large phyiscal address extension */ +#define SH0inner (3<<12) /* TTB0 inner shareable */ +#define ORGN0wb (1<<10) /* TTB0 outer region writeback cacheable */ +#define IRGN0wb (1<<8) /* TTB0 inner region writeback cacheable */ + /* * MMU page table entries. * Mbz (0x10) bit is implementation-defined and must be 0 on the cortex. diff --git a/sys/src/9/bcm/armv7.s b/sys/src/9/bcm/armv7.s index d149183b4c..450e8b39bf 100644 --- a/sys/src/9/bcm/armv7.s +++ b/sys/src/9/bcm/armv7.s @@ -76,14 +76,38 @@ _ramZ: BL mmuinit(SB) /* - * set up domain access control and page table base + * set up domain access control, translation mode and page table base */ MOVW $Client, R1 MCR CpSC, 0, R1, C(CpDAC), C(0) + + MOVW $PADDR(L1), R1 + + MOVW ttbcr(SB), R2 + MCR CpSC, 0, R2, C(CpTTB), C(0), CpTTBctl + BARRIERS + AND.S $EAElpae, R2 + BNE lpae0 + MOVW $PADDR(L1), R1 ORR $(CpTTBs|CpTTBowba|CpTTBiwba), R1 MCR CpSC, 0, R1, C(CpTTB), C(0) MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + B lpaex0 + +lpae0: + ADD $(L1SIZE-64), R1 + + BARRIERS + MOVW $0, R2 + MCRR(CpSC, 0, 1, 2, CpTTB) /* TTBR0 */ + + MOVW mair0(SB), R2 + MCR CpSC, 0, R2, C(CpTLD), C(CpTLDmair) + ISB + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS +lpaex0: /* * invalidate my caches before enabling @@ -187,15 +211,39 @@ reset: ADD $(MACHSIZE-4), R(MACH), R13 /* - * set up domain access control and page table base + * set up domain access control, translation mode and page table base */ MOVW $Client, R1 MCR CpSC, 0, R1, C(CpDAC), C(0) + MOVW 12(R(MACH)), R1 /* m->mmul1 */ SUB $KZERO, R1 /* phys addr */ + + MOVW ttbcr(SB), R2 + MCR CpSC, 0, R2, C(CpTTB), C(0), CpTTBctl + AND.S $EAElpae, R2 + BNE lpae + ORR $(CpTTBs|CpTTBowba|CpTTBiwba), R1 MCR CpSC, 0, R1, C(CpTTB), C(0) MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + B lpaex + +lpae: + /* + * L0 page table (4 entries) + */ + ADD $(L1SIZE-64), R1 + + BARRIERS + MOVW $0, R2 + MCRR(CpSC, 0, 1, 2, CpTTB) + MOVW mair0(SB), R2 + MCR CpSC, 0, R2, C(CpTLD), C(CpTLDmair) + ISB + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + BARRIERS +lpaex: /* * invalidate my caches before enabling @@ -276,6 +324,10 @@ TEXT cpctget(SB), 1, $-4 /* cache type */ MRC CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct RET +TEXT ttbrget(SB), 1, $-4 + MRC CpSC, 0, R0, C(CpTTB), C(0) + RET + TEXT lcycles(SB), 1, $-4 MRC CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0 RET diff --git a/sys/src/9/bcm/dat.h b/sys/src/9/bcm/dat.h index 39fc81ce10..347631eefe 100644 --- a/sys/src/9/bcm/dat.h +++ b/sys/src/9/bcm/dat.h @@ -28,6 +28,7 @@ typedef struct PhysUart PhysUart; typedef struct PMMU PMMU; typedef struct Proc Proc; typedef u32int PTE; +typedef u64int LPTE; typedef struct Soc Soc; typedef struct Uart Uart; typedef struct Ureg Ureg; @@ -96,11 +97,11 @@ enum struct Confmem { - uintptr base; + uvlong base; usize npage; - uintptr limit; - uintptr kbase; - uintptr klimit; + uvlong limit; + uvlong kbase; + uvlong klimit; }; struct Conf @@ -108,6 +109,7 @@ struct Conf ulong nmach; /* processors */ ulong nproc; /* processes */ Confmem mem[2]; /* physical memory */ + Confmem himem; /* physical memory above 4GiB */ ulong npage; /* total physical pages of memory */ usize upages; /* user page pool */ ulong copymode; /* 0 is copy on write, 1 is copy on reference */ @@ -155,11 +157,17 @@ struct Notsave { */ struct MMMU { - PTE* mmul1; /* l1 for this processor */ + union { + PTE* mmul1; /* l1 for this processor */ + LPTE* mmull1; /* l1 for this processor (long descriptors) */ + }; int mmul1lo; int mmul1hi; int mmupid; - PTE* kmapl2; /* l2 for section containing kmap area and vectors */ + union { + PTE* kmapl2; /* l2 for section containing kmap area and vectors */ + LPTE* kmapll2;/* as above (long descriptors) */ + }; }; /* @@ -172,7 +180,10 @@ struct PMMU Page* mmul2; Page* mmul2cache; /* free mmu pages */ int nkmap; - PTE kmaptab[NKMAPS]; + union { + PTE kmaptab[NKMAPS]; + LPTE kmapltab[NKMAPS]; + }; }; #include "../port/portdat.h" @@ -260,7 +271,7 @@ extern register Mach* m; /* R10 */ extern register Proc* up; /* R9 */ extern uintptr kseg0; extern Mach* machaddr[MAXMACH]; -extern ulong memsize; +extern uvlong memsize; extern int normalprint; /* diff --git a/sys/src/9/bcm/fns.h b/sys/src/9/bcm/fns.h index 1117dfec8f..f5506f1960 100644 --- a/sys/src/9/bcm/fns.h +++ b/sys/src/9/bcm/fns.h @@ -77,6 +77,7 @@ extern int isaconfig(char*, int, ISAConf*); extern int l2ap(int); extern void l2cacheuwbinv(void); extern void links(void); +extern void lpapageinit(void); extern void mmuinit(void*); extern void mmuinit1(void); extern void mmuinvalidate(void); diff --git a/sys/src/9/bcm/gisb.c b/sys/src/9/bcm/gisb.c index 55c1375c2a..72e57f8adc 100644 --- a/sys/src/9/bcm/gisb.c +++ b/sys/src/9/bcm/gisb.c @@ -13,7 +13,7 @@ /* * GISB arbiter registers */ -static u32int *regs = (u32int*)(VIRTIO + 0x400000); +static u32int *regs = (u32int*)(VIRTIO + 0x600000); enum { ArbMasterMask = 0x004/4, diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c index 28e4d74ed5..8ad5f3ced2 100644 --- a/sys/src/9/bcm/main.c +++ b/sys/src/9/bcm/main.c @@ -31,7 +31,7 @@ enum { uintptr kseg0 = KZERO; Mach* machaddr[MAXMACH]; Conf conf; -ulong memsize = 128*1024*1024; +uvlong memsize = 128*1024*1024; /* * Option arguments from the command line. @@ -269,7 +269,7 @@ launchinit(int ncpus) memset(mm, 0, MACHSIZE); mm->machno = mach; - memmove(l1, m->mmul1, L1SIZE); /* clone cpu0's l1 table */ + mmuinit(l1); /* clone cpu0's l1 table */ cachedwbse(l1, L1SIZE); mm->mmul1 = l1; cachedwbse(mm, MACHSIZE); @@ -308,6 +308,8 @@ main(void) ataginit((Atag*)BOOTARGS); confinit(); /* figures out amount of memory */ xinit(); + /* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */ + setclkrate(ClkArm, 0); uartconsinit(); screeninit(); @@ -321,8 +323,7 @@ main(void) for(;;) ; } - /* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */ - setclkrate(ClkArm, 0); + print("vcore reports memory = 0x%llux\n", conf.mem[0].limit); trapinit(); clockinit(); printinit(); @@ -340,6 +341,7 @@ main(void) links(); chandevreset(); /* most devices are discovered here */ pageinit(); + lpapageinit(); swapinit(); userinit(); launchinit(getncpus()); @@ -506,6 +508,7 @@ userinit(void) void confinit(void) { + extern ulong ttbcr; int i, userpcnt; ulong kpages; uintptr pa; @@ -518,7 +521,7 @@ confinit(void) cpuserver = 0; } if((p = getconf("*maxmem")) != nil){ - memsize = strtoul(p, 0, 0) - PHYSDRAM; + memsize = strtoull(p, 0, 0) - PHYSDRAM; if (memsize < 16*MB) /* sanity */ memsize = 16*MB; } @@ -540,21 +543,31 @@ confinit(void) break; case 0xC00000: conf.mem[1].base = 1*GiB; - conf.mem[1].limit = 0xFFF00000; + conf.mem[1].limit = 0xFF000000; break; case 0xD00000: conf.mem[1].base = 1*GiB; - conf.mem[1].limit = 0xFFF00000; + conf.mem[1].limit = 0xFF000000; + if(ttbcr){ + /* lpae supported */ + conf.himem.base = 4LL*GiB; + conf.himem.limit = 8LL*GiB; + } break; } if(conf.mem[1].limit > soc.dramsize) conf.mem[1].limit = soc.dramsize; if(p != nil){ - if(memsize < conf.mem[0].limit){ - conf.mem[0].limit = memsize; - conf.mem[1].limit = 0; - }else if(memsize >= conf.mem[1].base && memsize < conf.mem[1].limit) - conf.mem[1].limit = memsize; + for(i = 0; i < nelem(conf.mem); i++){ + if(memsize < conf.mem[i].base) + conf.mem[i].limit = conf.mem[i].base; + else if(memsize < conf.mem[i].limit) + conf.mem[i].limit = memsize; + } + if(memsize < conf.himem.base) + conf.himem.limit = conf.himem.base; + else if(memsize < conf.himem.limit) + conf.himem.limit = memsize; } if(p = getconf("*kernelpercent")) @@ -564,6 +577,7 @@ confinit(void) conf.npage = 0; pa = PADDR(PGROUND(PTR2UINT(end))); + pa += BY2PG; /* * we assume that the kernel is at the beginning of one of the @@ -577,6 +591,7 @@ confinit(void) conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG; conf.npage += conf.mem[i].npage; } + conf.himem.npage = (conf.himem.limit - conf.himem.base)/BY2PG; if(userpcnt < 10 || userpcnt > 99) userpcnt = 90; @@ -586,7 +601,7 @@ confinit(void) conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; /* set up other configuration parameters */ - conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; + conf.nproc = 100 + (conf.npage/(MB/BY2PG))*5; if(cpuserver) conf.nproc *= 3; if(conf.nproc > 2000) diff --git a/sys/src/9/bcm/mem.h b/sys/src/9/bcm/mem.h index 96391c071d..96f2818dbd 100644 --- a/sys/src/9/bcm/mem.h +++ b/sys/src/9/bcm/mem.h @@ -41,17 +41,17 @@ #define KZERO KSEG0 /* kernel address space */ #define CONFADDR (KZERO+0x100) /* unparsed plan9.ini */ #define MACHADDR (KZERO+0x2000) /* Mach structure */ -#define L2 (KZERO+0x3000) /* L2 ptes for vectors etc */ +#define L2 (KZERO+0x3000) /* L2 ptes for vectors etc (non-lpae) */ #define VCBUFFER (KZERO+0x3400) /* videocore mailbox buffer */ #define FIQSTKTOP (KZERO+0x4000) /* FIQ stack */ #define L1 (KZERO+0x4000) /* tt ptes: 16KiB aligned */ #define KTZERO (KZERO+0x8000) /* kernel text start */ -#define VIRTPCI 0xFD000000 /* pcie address space (pi4 only) */ +#define VIRTPCI 0xFC000000 /* pcie address space (pi4 only) */ +#define FRAMEBUFFER 0xFD000000 /* video framebuffer */ #define VIRTIO 0xFE000000 /* i/o registers */ #define IOSIZE (10*MiB) #define ARMLOCAL (VIRTIO+IOSIZE) /* armv7 only */ -#define VGPIO (ARMLOCAL+MiB) /* virtual gpio for pi3 ACT LED */ -#define FRAMEBUFFER (VGPIO+MiB) /* video framebuffer */ +#define VGPIO (ARMLOCAL+2*MiB) /* virtual gpio for pi3 ACT LED */ #define UZERO 0 /* user segment */ #define UTZERO (UZERO+BY2PG) /* user text start */ @@ -82,7 +82,7 @@ #define PTEPERTAB (PTEMAPMEM/BY2PG) #define SEGMAPSIZE 1984 #define SSEGMAPSIZE 16 -#define PPN(x) ((x)&~(BY2PG-1)) +#define PPN(x) ((x) & (~(BY2PG-1) | PTEHIMEM)) /* * With a little work these move to port. @@ -92,6 +92,7 @@ #define PTEWRITE (1<<1) #define PTEUNCACHED (1<<2) #define PTEKERNEL (1<<3) +#define PTEHIMEM (0xF<<8) /* * Physical machine information from here on. diff --git a/sys/src/9/bcm/mkfile b/sys/src/9/bcm/mkfile index f155a051fc..1b19ae9727 100644 --- a/sys/src/9/bcm/mkfile +++ b/sys/src/9/bcm/mkfile @@ -51,7 +51,7 @@ OBJ=\ fpiarm.$O\ fpimem.$O\ main.$O\ - mmu.$O\ +# mmu.$O\ syscall.$O\ # trap.$O\ $DEVS\ diff --git a/sys/src/9/bcm/mmu.c b/sys/src/9/bcm/mmu.c index 44bf7e1506..c26ff75789 100644 --- a/sys/src/9/bcm/mmu.c +++ b/sys/src/9/bcm/mmu.c @@ -21,8 +21,14 @@ enum { KMAPADDR = 0xFFF00000, }; +ulong ttbcr = 0; +ulong mair0; +void lpapageinit(void) {} + /* - * Set up initial PTEs for cpu0 (called with mmu off) + * Set up initial PTEs + * Called before main, with mmu off, to initialise cpu0's tables + * Called from launchinit to clone cpu0's tables for other cpus */ void mmuinit(void *a) @@ -31,6 +37,10 @@ mmuinit(void *a) uintptr pa, pe, va; l1 = (PTE*)a; + if((uintptr)l1 != PADDR(L1)){ + memmove(l1, m->mmul1, L1SIZE); + return; + } l2 = (PTE*)PADDR(L2); /* @@ -63,12 +73,12 @@ mmuinit(void *a) l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; /* * pi4 hack: ether and pcie are in segment 0xFD5xxxxx not 0xFE5xxxxx - * gisb is in segment 0xFC4xxxxx not FE4xxxxx + * gisb is in segment 0xFC4xxxxx not FE4xxxxx (and we map it at va FE6xxxxx) */ va = VIRTIO + 0x500000; pa = soc.physio - 0x1000000 + 0x500000; l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; - va = VIRTIO + 0x400000; + va = VIRTIO + 0x600000; pa = soc.physio - 0x2000000 + 0x400000; l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|L1noexec; diff --git a/sys/src/9/bcm/mmu64.c b/sys/src/9/bcm/mmu64.c new file mode 100644 index 0000000000..d9bb656102 --- /dev/null +++ b/sys/src/9/bcm/mmu64.c @@ -0,0 +1,560 @@ +/* + * armv7/armv8-a long-descriptor memory management + * + * Three levels of page tables: + * L0 table: 4 entries, each mapping 1GiB virtual space, as either + * a contiguous block, or + * an L1 page: 512 entries, each mapping 2MiB, as either + * a contiguous block, or + * an L2 page: 512 entries, each mapping 4KiB + * + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#include "arm.h" + +typedef uvlong LPTE; + +#define L0X(va) FEXT((va), 30, 2) +#define L1X(va) FEXT((va), 21, 11) +#define L2X(va) FEXT((va), 12, 9) + +enum { + L1lo = L1X(UZERO), + L1hi = L1X(USTKTOP+2*MiB-1), + L2size = BY2PG, + KMAPADDR = 0xFFE00000, + + LXN = 1LL<<54, + LPXN = 1LL<<53, + LAF = 1<<10, + LShareOuter = 2<<8, + LShareInner = 3<<8, + LKrw = 0<<6, + LUrw = 1<<6, + LUro = 3<<6, + LMem = 0<<2, + LUncached = 1<<2, + LDevice = 2<<2, + LBlock = 1<<0, + LTable = 3<<0, + LPage = 3<<0, + + MMem = 0xFF, /* MEM_WB */ + MUncached = 0x44, /* MEM_UC */ + MDevice = 0x04, /* DEV_nGnRE*/ + + EAE_LPAE = 1<<31, + SH0_INNER = 3<<12, + ORGN0_WB = 1<<10, + IRGN0_WB = 1<<8, + + LAttrDRAM = LKrw | LAF | LShareInner | LMem, + LAttrPhys = LPXN | LAF | LShareOuter | LUncached, + LAttrIO = LKrw | LAF | LXN | LPXN | LShareOuter | LDevice, + LAttrUser = LPXN | LAF | LShareInner | LMem, +}; + +#define XPPN(pa) ((pa)&~(BY2PG-1) | (uvlong)((pa)&PTEHIMEM) << (32-8)) +#define LPPN(pte) ((pte)&0xFFFFFF000ULL) + +/* + * TTBCR and MAIR0 register settings for LPAE (used in armv7.s) + */ +ulong mair0 = MMem<<0 | MUncached<<8 | MDevice<<16; +ulong ttbcr = EAElpae | SH0inner | ORGN0wb | IRGN0wb; + +/* + * Set up initial PTEs + * Called before main, with mmu off, to initialise cpu0's tables + * Called from launchinit to clone cpu0's tables for other cpus + */ +void +mmuinit(void *a) +{ + LPTE *l0, *l1, *l2; + uintptr pa, pe, va; + int i; + + l1 = (LPTE*)a; + if((uintptr)l1 != PADDR(L1)) + memmove(l1, m->mmul1, L1SIZE); + + /* + * embed L0 table near end of L1 table + */ + l0 = (LPTE*)((uintptr)a + L1SIZE - 64); + pa = PADDR(l1); + for(i = 0; i < 4; i++){ + l0[i] = pa|LAttrDRAM|LTable; + pa += BY2PG; + } + + if((uintptr)l1 != PADDR(L1)) + return; + + /* + * map ram at KZERO, bounded above by VIRTPCI + */ + //l0[KZERO/GiB] = PHYSDRAM|LAttrDRAM|LBlock; + //va = KZERO + GiB; + va = KZERO; + pe = VIRTPCI - KZERO; + if(pe > soc.dramsize) + pe = soc.dramsize; + for(pa = PHYSDRAM; pa < PHYSDRAM+pe; pa += 2*MiB){ + l1[L1X(va)] = pa|LAttrDRAM|LBlock; + va += 2*MiB; + } + + /* + * identity map first 2MB of ram so mmu can be enabled + */ + l1[L1X(PHYSDRAM)] = PHYSDRAM|LAttrDRAM|LBlock; + /* + * map i/o registers + */ + va = VIRTIO; + for(pa = soc.physio; pa < soc.physio+IOSIZE; pa += 2*MiB){ + l1[L1X(va)] = pa|LAttrIO|LBlock; + va += 2*MiB; + } + pa = soc.armlocal; + if(pa) + l1[L1X(va)] = pa|LAttrIO|LBlock; + /* + * pi4 hack: ether and pcie are in segment 0xFD5xxxxx not 0xFE5xxxxx + * gisb is in segment 0xFC4xxxxx not FE4xxxxx (and we map it at va FE6xxxxx) + */ + va = VIRTIO + 0x400000; + pa = soc.physio - 0x1000000 + 0x400000; + l1[L1X(va)] = pa|LAttrIO|LBlock; + va = VIRTIO + 0x600000; + pa = soc.physio - 0x2000000 + 0x400000; + l1[L1X(va)] = pa|LAttrIO|LBlock; + + /* + * double map exception vectors near top of virtual memory + * not ready for malloc, so alias first L1 page (which has only one entry) + * as temporary L2 page + */ + l2 = (LPTE*)PADDR(L1); + //memset(l2, 0, BY2PG); + va = HVECTORS; + l2[L2X(va)] = PHYSDRAM|LAttrDRAM|LPage; + l1[L1X(va)] = (uintptr)l2|LAttrDRAM|LTable; +} + +void +mmuinit1() +{ + LPTE *l1, *l2; + uintptr va; + + l1 = m->mmull1; + + /* + * first L1 page: undo identity map and L2 alias + */ + memset(l1, 0, BY2PG); + cachedwbtlb(l1, BY2PG); + + /* + * make a local mapping for highest 2MB of virtual space + * containing kmap area and exception vectors + */ + va = HVECTORS; + m->kmapll2 = l2 = mallocalign(L2size, L2size, 0, 0); + l2[L2X(va)] = PHYSDRAM|LAttrDRAM|LPage; + l1[L1X(va)] = PADDR(l2)|LAttrDRAM|LTable; + cachedwbtlb(&l1[L1X(va)], sizeof(LPTE)); + + mmuinvalidate(); +} + +static int +nonzero(uint *p) +{ + int i; + for(i = 0; i < BY2PG/sizeof(uint); i++) + if(*p++ != 0) + return 1; + return 0; +} + +static void +mmul2empty(Proc* proc, int clear) +{ + LPTE *l1; + Page **l2, *page; + + l1 = m->mmull1; + l2 = &proc->mmul2; + for(page = *l2; page != nil; page = page->next){ + if(clear){ + if(l1[page->daddr] == Fault){ + l1[page->daddr] = XPPN(page->pa)|LAttrDRAM|LTable; + coherence(); + } + memset((void*)(0xFF000000 + L2size*page->daddr), 0, L2size); + } + l1[page->daddr] = Fault; + l2 = &page->next; + } + coherence(); + *l2 = proc->mmul2cache; + proc->mmul2cache = proc->mmul2; + proc->mmul2 = nil; +} + +static void +mmul1empty(void) +{ + LPTE *l1; + + /* clean out any user mappings still in l1 */ + if(m->mmul1lo > 0){ + if(m->mmul1lo == 1) + m->mmull1[L1lo] = Fault; + else + memset(&m->mmull1[L1lo], 0, m->mmul1lo*sizeof(LPTE)); + m->mmul1lo = 0; + } + if(m->mmul1hi > 0){ + l1 = &m->mmull1[L1hi - m->mmul1hi]; + if(m->mmul1hi == 1) + *l1 = Fault; + else + memset(l1, 0, m->mmul1hi*sizeof(LPTE)); + m->mmul1hi = 0; + } + if(m->kmapll2 != nil) + memset(m->kmapll2, 0, NKMAPS*sizeof(LPTE)); +} + +void +mmuswitch(Proc* proc) +{ + int x; + LPTE *l1; + Page *page; + + if(proc != nil && proc->newtlb){ + mmul2empty(proc, 1); + proc->newtlb = 0; + } + + mmul1empty(); + + /* move in new map */ + l1 = m->mmull1; + if(proc != nil){ + for(page = proc->mmul2; page != nil; page = page->next){ + x = page->daddr; + l1[x] = XPPN(page->pa)|LAttrDRAM|LTable; + if(x >= L1lo + m->mmul1lo && x < L1hi - m->mmul1hi){ + if(x+1 - L1lo < L1hi - x) + m->mmul1lo = x+1 - L1lo; + else + m->mmul1hi = L1hi - x; + } + } + if(proc->nkmap) + memmove(m->kmapll2, proc->kmapltab, sizeof(proc->kmapltab)); + } + + /* make sure map is in memory */ + /* could be smarter about how much? */ + cachedwbtlb(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(LPTE)); + if(proc != nil && proc->nkmap) + cachedwbtlb(m->kmapll2, sizeof(proc->kmapltab)); + + /* lose any possible stale tlb entries */ + mmuinvalidate(); +} + +void +flushmmu(void) +{ + int s; + + s = splhi(); + up->newtlb = 1; + mmuswitch(up); + splx(s); +} + +void +mmurelease(Proc* proc) +{ + Page *page, *next; + + mmul2empty(proc, 0); + for(page = proc->mmul2cache; page != nil; page = next){ + next = page->next; + if(--page->ref) + panic("mmurelease: page->ref %d", page->ref); + pagechainhead(page); + } + if(proc->mmul2cache && palloc.r.p) + wakeup(&palloc.r); + proc->mmul2cache = nil; + + mmul1empty(); + + /* make sure map is in memory */ + /* could be smarter about how much? */ + cachedwbtlb(&m->mmull1[L1X(UZERO)], (L1hi - L1lo)*sizeof(LPTE)); + + /* lose any possible stale tlb entries */ + mmuinvalidate(); +} + +void +putmmu(uintptr va, uintptr pa, Page* page) +{ + int x, s; + Page *pg; + LPTE *l1, *pte; + LPTE nx; + static int chat = 0; + + /* + * disable interrupts to prevent flushmmu (called from hzclock) + * from clearing page tables while we are setting them + */ + s = splhi(); + x = L1X(va); + l1 = &m->mmull1[x]; + pte = (LPTE*)(0xFF000000 + L2size*x); + if(*l1 == Fault){ + /* l2 pages have 512 entries */ + if(up->mmul2cache == nil){ + spllo(); + pg = newpage(1, 0, 0); + splhi(); + /* if newpage slept, we might be on a different cpu */ + l1 = &m->mmull1[x]; + }else{ + pg = up->mmul2cache; + up->mmul2cache = pg->next; + } + pg->daddr = x; + pg->next = up->mmul2; + up->mmul2 = pg; + + *l1 = XPPN(pg->pa)|LAttrDRAM|LTable; + cachedwbtlb(l1, sizeof *l1); + + /* force l2 page to memory */ + if(nonzero((uint*)pte)) + if(chat++ < 32){ + iprint("nonzero L2 page from cache pa %lux va %lux daddr %lux\n", + pg->pa, pg->va, pg->daddr); + memset(pte, 0, L2size); + } + cachedwbtlb(pte, L2size); + + if(x >= L1lo + m->mmul1lo && x < L1hi - m->mmul1hi){ + if(x+1 - L1lo < L1hi - x) + m->mmul1lo = x+1 - L1lo; + else + m->mmul1hi = L1hi - x; + } + } + + /* protection bits are + * PTERONLY|PTEVALID; + * PTEWRITE|PTEVALID; + * PTEWRITE|PTEUNCACHED|PTEVALID; + */ + nx = LAttrUser|LPage; + if(pa & PTEUNCACHED) + nx = LAttrPhys|LPage; + if(pa & PTEWRITE) + nx |= LUrw; + else + nx |= LUro; + pte[L2X(va)] = XPPN(pa)|nx; + if(0)if(chat++ < 32) + iprint("putmmu %#p %lux => %llux\n", va, pa, pte[L2X(va)]); + cachedwbtlb(&pte[L2X(va)], sizeof(LPTE)); + + /* clear out the current entry */ + mmuinvalidateaddr(va); + + if(page->cachectl[m->machno] == PG_TXTFLUSH){ + /* pio() sets PG_TXTFLUSH whenever a text pg has been written */ + if(cankaddr(page->pa)) + cachedwbse((void*)(page->pa|KZERO), BY2PG); + cacheiinvse((void*)page->va, BY2PG); + page->cachectl[m->machno] = PG_NOFLUSH; + } + checkmmu(va, pa); + splx(s); +} + +/* + * Return the number of bytes that can be accessed via KADDR(pa). + * If pa is not a valid argument to KADDR, return 0. + */ +uintptr +cankaddr(uintptr pa) +{ + if(pa == 0) + return 0; + if((pa - PHYSDRAM) < VIRTPCI-KZERO) + return PHYSDRAM + VIRTPCI-KZERO - pa; + return 0; +} + +uintptr +mmukmapx(uintptr va, uvlong pa, usize size) +{ + int o; + usize n; + LPTE *pte, *pte0; + + print("mmukmapx %#p => %llux (%lux)\n", va, pa, size); + assert((va & (2*MiB-1)) == 0); + o = pa & (2*MiB-1); + pa -= o; + size += o; + pte = pte0 = &m->mmull1[L1X(va)]; + for(n = 0; n < size; n += 2*MiB) + if(*pte++ != Fault) + return 0; + pte = pte0; + for(n = 0; n < size; n += 2*MiB){ + *pte++ = (pa+n)|LAttrIO|LBlock; + mmuinvalidateaddr(va+n); + } + cachedwbtlb(pte0, (uintptr)pte - (uintptr)pte0); + return va + o; +} + +uintptr +mmukmap(uintptr va, uintptr pa, usize size) +{ + return mmukmapx(va, pa, size); +} + +void +checkmmu(uintptr va, uintptr pa) +{ + int x; + LPTE *l1, *pte; + + x = L1X(va); + l1 = &m->mmull1[x]; + if((*l1<able) != LTable){ + iprint("checkmmu cpu%d va=%lux l1 %p=%llux\n", m->machno, va, l1, *l1); + return; + } + pte = (LPTE*)(0xFF000000 + L2size*x); + pte += L2X(va); + if(pa == ~0 || (pa != 0 && LPPN(*pte) != XPPN(pa))){ + iprint("checkmmu va=%lux pa=%lux l1 %p=%llux pte %p", va, pa, l1, *l1, pte); + iprint("=%llux\n", *pte); + } +} + +KMap* +kmap(Page *p) +{ + int s, i; + uintptr va; + uvlong pa; + + pa = XPPN(p->pa); + if(pa < VIRTPCI-KZERO) + return KADDR(pa); + if(up == nil) + panic("kmap without up %#p", getcallerpc(&pa)); + s = splhi(); + if(up->nkmap == NKMAPS) + panic("kmap overflow %#p", getcallerpc(&pa)); + for(i = 0; i < NKMAPS; i++) + if(up->kmapltab[i] == 0) + break; + if(i == NKMAPS) + panic("can't happen"); + up->nkmap++; + va = KMAPADDR + i*BY2PG; + up->kmapltab[i] = pa|LAttrDRAM|LPage; + m->kmapll2[i] = up->kmapltab[i]; + cachedwbtlb(&m->kmapll2[i], sizeof(LPTE)); + mmuinvalidateaddr(va); + splx(s); + return (KMap*)va; +} + +void +kunmap(KMap *k) +{ + int i; + uintptr va; + + coherence(); + va = (uintptr)k; + if(L1X(va) != L1X(KMAPADDR)) + return; + /* wasteful: only needed for text pages aliased within data cache */ + cachedwbse((void*)va, BY2PG); + i = L2X(va); + up->kmapltab[i] = 0; + m->kmapll2[i] = 0; + up->nkmap--; + cachedwbtlb(&m->kmapll2[i], sizeof(LPTE)); + mmuinvalidateaddr(va); +} + +/* + * Append pages with physical addresses above 4GiB to the freelist + */ +void +lpapageinit(void) +{ + int j; + ulong npage; + Page *pages, *p; + uvlong pa; + + npage = conf.himem.npage; + if(npage == 0) + return; + + pages = xalloc(npage*sizeof(Page)); + if(pages == 0) + panic("lpapageinit"); + + p = pages; + pa = conf.himem.base; + for(j=0; jprev = p-1; + p->next = p+1; + p->pa = pa; + p->pa |= (pa >> (32-8)) & PTEHIMEM; + p++; + pa += BY2PG; + } + palloc.tail->next = pages; + pages[0].prev = palloc.tail; + palloc.tail = p - 1; + palloc.tail->next = 0; + + palloc.freecount += npage; + palloc.user += npage; + + /* Paging numbers */ + swapalloc.highwater = (palloc.user*5)/100; + swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4); + + print("%ldM extended memory: ", npage*(BY2PG/1024)/1024); + print("%ldM user total\n", palloc.user*(BY2PG/1024)/1024); +} diff --git a/sys/src/9/bcm/pi b/sys/src/9/bcm/pi index ad20a256fe..f4f032296a 100644 --- a/sys/src/9/bcm/pi +++ b/sys/src/9/bcm/pi @@ -49,6 +49,7 @@ ip misc armv6 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/pi2 b/sys/src/9/bcm/pi2 index 63545da1b8..6a8499be4d 100644 --- a/sys/src/9/bcm/pi2 +++ b/sys/src/9/bcm/pi2 @@ -10,6 +10,7 @@ dev arch ssl tls + bridge log cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno @@ -33,6 +34,7 @@ link archbcm2 loopbackmedium ethermedium + netdevmedium sdhost usbdwc etherusb @@ -49,6 +51,7 @@ ip misc armv7 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/pi2cpu b/sys/src/9/bcm/pi2cpu index a950880351..9862a416db 100644 --- a/sys/src/9/bcm/pi2cpu +++ b/sys/src/9/bcm/pi2cpu @@ -10,6 +10,7 @@ dev arch ssl tls + bridge log cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno @@ -33,6 +34,7 @@ link archbcm2 loopbackmedium ethermedium + netdevmedium sdhost usbdwc etherusb @@ -49,6 +51,7 @@ ip misc armv7 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/pi2wifi b/sys/src/9/bcm/pi2wifi index ad1e629f5c..06d84cff91 100644 --- a/sys/src/9/bcm/pi2wifi +++ b/sys/src/9/bcm/pi2wifi @@ -48,6 +48,7 @@ ip misc armv7 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/pi4 b/sys/src/9/bcm/pi4 index 88c2e888a5..80e88ee647 100644 --- a/sys/src/9/bcm/pi4 +++ b/sys/src/9/bcm/pi4 @@ -10,6 +10,7 @@ dev arch ssl tls + bridge log cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno @@ -53,6 +54,7 @@ ip misc armv7 + mmu64 trap4 uartmini gpio sdmmc diff --git a/sys/src/9/bcm/pi4cpu b/sys/src/9/bcm/pi4cpu index 3104e07b91..c03618b249 100644 --- a/sys/src/9/bcm/pi4cpu +++ b/sys/src/9/bcm/pi4cpu @@ -10,6 +10,7 @@ dev arch ssl tls + bridge log cap fs ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno @@ -53,6 +54,7 @@ ip misc armv7 + mmu64 trap4 uartmini gpio sdmmc diff --git a/sys/src/9/bcm/pi4wifi b/sys/src/9/bcm/pi4wifi index a188cba17c..8bde079b1f 100644 --- a/sys/src/9/bcm/pi4wifi +++ b/sys/src/9/bcm/pi4wifi @@ -53,6 +53,7 @@ ip misc armv7 + mmu64 trap4 uartmini gpio sdmmc diff --git a/sys/src/9/bcm/picpu b/sys/src/9/bcm/picpu index b265639c08..64cedbf835 100644 --- a/sys/src/9/bcm/picpu +++ b/sys/src/9/bcm/picpu @@ -49,6 +49,7 @@ ip misc armv6 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/pifat b/sys/src/9/bcm/pifat index 90f7440175..d8b04712c4 100644 --- a/sys/src/9/bcm/pifat +++ b/sys/src/9/bcm/pifat @@ -34,6 +34,7 @@ ip misc armv6 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/piwifi b/sys/src/9/bcm/piwifi index 3176f43d39..3a63a0642e 100644 --- a/sys/src/9/bcm/piwifi +++ b/sys/src/9/bcm/piwifi @@ -48,6 +48,7 @@ ip misc armv6 + mmu trap uartmini gpio sdmmc emmc diff --git a/sys/src/9/bcm/rebootcode.s b/sys/src/9/bcm/rebootcode.s index 8fa8fdfd14..70524cbf3a 100644 --- a/sys/src/9/bcm/rebootcode.s +++ b/sys/src/9/bcm/rebootcode.s @@ -4,6 +4,7 @@ #include "arm.s" #define PTEDRAM (Dom0|L1AP(Krw)|Section) +#define PTELPAE (1<<10|3<<8|1<<0) /* AF | ShareInner | Block */ #define WFI WORD $0xe320f003 /* wait for interrupt */ #define WFE WORD $0xe320f002 /* wait for event */ @@ -30,8 +31,13 @@ TEXT main(SB), 1, $-4 /* redo double map of first MiB PHYSDRAM = KZERO */ MOVW 12(R(MACH)), R2 /* m->mmul1 (virtual addr) */ - MOVW $PTEDRAM, R1 /* PTE bits */ + MRC CpSC, 0, R3, C(CpTTB), C(0), CpTTBctl + AND.S $EAElpae, R3 + MOVW.EQ $PTEDRAM, R1 /* PTE bits (non-lpae) */ + MOVW.NE $PTELPAE, R1 /* PTE bits (lpae) */ MOVW R1, (R2) + MOVW $0, R1 + MOVW R1, 4(R2) DSB MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwb), CpCACHEse diff --git a/sys/src/9/bcm/trap.c b/sys/src/9/bcm/trap.c index 310971b751..71e4c40f0d 100644 --- a/sys/src/9/bcm/trap.c +++ b/sys/src/9/bcm/trap.c @@ -441,7 +441,6 @@ trap(Ureg *ureg) panic("terminal exception at %#lux", ureg->pc); break; case 0x4: /* icache maint fault */ - case 0x6: /* access flag fault (page) */ case 0x8: /* precise external abort, non-xlat'n */ case 0x28: case 0xc: /* l1 translation, precise ext. abort */ @@ -474,6 +473,7 @@ trap(Ureg *ureg) panic("kernel access violation: pc %#lux va %#p", ureg->pc, va); break; + case 0x6: /* access flag fault (page) */ case 0xd: case 0xf: /* permission error, copy on write or real permission error */ diff --git a/sys/src/9/bcm/trap4.c b/sys/src/9/bcm/trap4.c index ca53cb2b92..d599dfe46a 100644 --- a/sys/src/9/bcm/trap4.c +++ b/sys/src/9/bcm/trap4.c @@ -711,7 +711,6 @@ datafault(Ureg *ureg, int user) panic("terminal exception at %#lux", ureg->pc); break; case 0x4: /* icache maint fault */ - case 0x6: /* access flag fault (page) */ case 0x8: /* precise external abort, non-xlat'n */ case 0x28: case 0x16: /* imprecise ext. abort, non-xlt'n */ @@ -721,7 +720,6 @@ datafault(Ureg *ureg, int user) break; case 0xc: /* l1 translation, precise ext. abort */ case 0x2c: - case 0xe: /* l2 translation, precise ext. abort */ case 0x2e: panic("external translation abort %#lux pc %#lux addr %#p", fsr, ureg->pc, va); @@ -734,6 +732,7 @@ datafault(Ureg *ureg, int user) break; case 0x5: /* translation fault, no section entry */ case 0x7: /* translation fault, no page entry */ + case 0xe: /* l2 translation, precise ext. abort */ faultarm(ureg, va, user, !writetomem(inst)); break; case 0x9: @@ -750,6 +749,7 @@ datafault(Ureg *ureg, int user) panic("kernel access violation: pc %#lux va %#p", ureg->pc, va); break; + case 0x6: /* access flag fault (page) */ case 0xd: case 0xf: /* permission error, copy on write or real permission error */ From 8d6187bf85fb52eeddad02ad80642328e8777f50 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 31 May 2024 09:16:28 +0000 Subject: [PATCH 079/402] sys/src/9/bcm: add PL011 UART driver (thanks Richard Miller) --- sys/src/9/bcm/fns.h | 1 + sys/src/9/bcm/io.h | 1 + sys/src/9/bcm/main.c | 5 +- sys/src/9/bcm/pi2 | 1 + sys/src/9/bcm/pi2cpu | 1 + sys/src/9/bcm/pi4 | 1 + sys/src/9/bcm/pi4cpu | 1 + sys/src/9/bcm/uartpl011.c | 674 ++++++++++++++++++++++++++++++++++++++ sys/src/9/bcm/words.pi4 | 15 +- 9 files changed, 695 insertions(+), 5 deletions(-) create mode 100644 sys/src/9/bcm/uartpl011.c diff --git a/sys/src/9/bcm/fns.h b/sys/src/9/bcm/fns.h index f5506f1960..3298b273f9 100644 --- a/sys/src/9/bcm/fns.h +++ b/sys/src/9/bcm/fns.h @@ -83,6 +83,7 @@ extern void mmuinit1(void); extern void mmuinvalidate(void); extern void mmuinvalidateaddr(u32int); extern void okay(int); +extern void pl011consinit(void); extern void procrestore(Proc *); extern void procsave(Proc*); extern void procsetup(Proc*); diff --git a/sys/src/9/bcm/io.h b/sys/src/9/bcm/io.h index 3287f98046..b0d4c82a72 100644 --- a/sys/src/9/bcm/io.h +++ b/sys/src/9/bcm/io.h @@ -11,6 +11,7 @@ enum { IRQi2c = 53, IRQspi = 54, IRQsdhost = 56, + IRQpl011 = 57, IRQmmc = 62, IRQbasic = 64, diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c index 8ad5f3ced2..2db6bd29d7 100644 --- a/sys/src/9/bcm/main.c +++ b/sys/src/9/bcm/main.c @@ -32,6 +32,7 @@ uintptr kseg0 = KZERO; Mach* machaddr[MAXMACH]; Conf conf; uvlong memsize = 128*1024*1024; +void (*pl011init)(void); /* * Option arguments from the command line. @@ -310,8 +311,10 @@ main(void) xinit(); /* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */ setclkrate(ClkArm, 0); - uartconsinit(); screeninit(); + uartconsinit(); + if(pl011init != nil) + (*pl011init)(); print("\nPlan 9 from Bell Labs\n"); board = getboardrev(); diff --git a/sys/src/9/bcm/pi2 b/sys/src/9/bcm/pi2 index 6a8499be4d..127825af20 100644 --- a/sys/src/9/bcm/pi2 +++ b/sys/src/9/bcm/pi2 @@ -54,6 +54,7 @@ misc mmu trap uartmini gpio + uartpl011 gpio sdmmc emmc sdaoe sdscsi dma diff --git a/sys/src/9/bcm/pi2cpu b/sys/src/9/bcm/pi2cpu index 9862a416db..6cae1c9fb6 100644 --- a/sys/src/9/bcm/pi2cpu +++ b/sys/src/9/bcm/pi2cpu @@ -54,6 +54,7 @@ misc mmu trap uartmini gpio + uartpl011 gpio sdmmc emmc sdaoe sdscsi dma diff --git a/sys/src/9/bcm/pi4 b/sys/src/9/bcm/pi4 index 80e88ee647..eba6f48c53 100644 --- a/sys/src/9/bcm/pi4 +++ b/sys/src/9/bcm/pi4 @@ -57,6 +57,7 @@ misc mmu64 trap4 uartmini gpio + uartpl011 gpio sdmmc sdaoe sdscsi dma diff --git a/sys/src/9/bcm/pi4cpu b/sys/src/9/bcm/pi4cpu index c03618b249..7ae421870f 100644 --- a/sys/src/9/bcm/pi4cpu +++ b/sys/src/9/bcm/pi4cpu @@ -57,6 +57,7 @@ misc mmu64 trap4 uartmini gpio + uartpl011 gpio sdmmc sdaoe sdscsi dma diff --git a/sys/src/9/bcm/uartpl011.c b/sys/src/9/bcm/uartpl011.c new file mode 100644 index 0000000000..141b8b8d54 --- /dev/null +++ b/sys/src/9/bcm/uartpl011.c @@ -0,0 +1,674 @@ +/* + * PL011 UART (somewhat like 8250) + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +typedef struct Pinctl Pinctl; + +struct Pinctl { + uchar txpin; + uchar rxpin; + uchar alt; +}; + +static Pinctl pinctl[] = { + { 14, 15, Alt0, }, /* rpi pins 8, 10 - shared with uartmini.c */ + { 0, 1, Alt4, }, /* rpi pins 27, 28 */ + { 4, 5, Alt4, }, /* rpi pins 7, 29 */ + { 8, 9, Alt4, }, /* rpi pins 24, 21 */ + { 12, 13, Alt4, }, /* rpi pins 32, 33 */ +}; + +enum { /* registers */ + Dr = 0x00>>2, /* Data (RW) */ + Fr = 0x18>>2, /* Flag */ + Ibrd = 0x24>>2, /* Integer Baud Rate Divisor */ + Fbrd = 0x28>>2, /* Fractional Baud Rate Divisor */ + Lcrh = 0x2C>>2, /* Line Control */ + Cr = 0x30>>2, /* Control */ + Ifls = 0x34>>2, /* Interrupt FIFO Level Select */ + Imsc = 0x38>>2, /* Interrupt Mask Set Clear */ + Mis = 0x40>>2, /* Masked Interrupt Status */ + Icr = 0x44>>2, /* Interrupt Clear */ + Dmacr = 0x48>>2, /* DMA Control */ +}; + +enum { /* Dr error bits */ + Oe = 0x800, /* Overrun */ + Be = 0x400, /* Break */ + Pe = 0x200, /* Parity */ + Fe = 0x100, /* Framing */ +}; + +enum { /* Fr */ + Txfe = 0x80, /* Transmit FIFO Empty */ + Rxff = 0x40, /* Receive FIFO Full */ + Txff = 0x20, /* Transmit FIFO Full */ + Rxfe = 0x10, /* Receive FIFO Empty */ + Busy = 0x08, /* Transmitting Data */ + Cts = 0x01, /* Clear to Send */ +}; + +enum { /* Lcrh */ + Stp = 0x80, /* Stick Parity */ + WlsMASK = 0x60, /* Word Length Select */ + Wls8 = 0x60, /* 8 bits/byte */ + Wls7 = 0x40, /* 7 bits/byte */ + Wls6 = 0x20, /* 6 bits/byte */ + Wls5 = 0x00, /* 5 bits/byte */ + Fen = 0x10, /* FIFO enable */ + Stb = 0x08, /* 2 stop bits */ + Eps = 0x04, /* Even Parity Select */ + Pen = 0x02, /* Parity Enable */ + Brk = 0x01, /* Break */ +}; + +enum { /* Cr */ + Ctsen = 0x8000, /* Auto CTS */ + Rtsen = 0x4000, /* Auto RTS */ + Rts = 0x0800, /* Ready To Send */ + Dtr = 0x0400, /* Data Terminal Ready (unsupported) */ + Rxe = 0x0200, /* Receive Enable */ + Txe = 0x0100, /* Transmit Enable */ + Lbe = 0x0080, /* Loopback Enable */ + Uarten = 0x0001, /* UART Enable */ +}; + +enum { /* Ifls */ + RFIFO1 = 0<<3, /* Rx FIFO trigger level 1/8 full */ + RFIFO2 = 1<<3, /* 2/8 full */ + RFIFO4 = 2<<3, /* 4/8 full */ + RFIFO6 = 3<<3, /* 6/8 full */ + RFIFO7 = 4<<3, /* 7/8 full */ + TFIFO1 = 0<<0, /* Tx FIFO trigger level 1/8 full */ + TFIFO2 = 1<<0, /* 2/8 full */ + TFIFO4 = 2<<0, /* 4/8 full */ + TFIFO6 = 3<<0, /* 6/8 full */ + TFIFO7 = 4<<0, /* 7/8 full */ +}; + +enum { /* Imsc, Mis, Icr */ + Oeint = 0x400, + Beint = 0x200, + Peint = 0x100, + Feint = 0x080, + Rtint = 0x040, + Txint = 0x020, + Rxint = 0x010, + Ctsmint = 0x002, +}; + + +typedef struct Ctlr { + u32int* io; + int irq; + int iena; + int poll; + + ushort sticky[Imsc+1]; + + Lock; + int fena; +} Ctlr; + +extern PhysUart pl011physuart; + +/* +* pi4 has five pl011 uarts, other pi models have only one +*/ +static Ctlr pl011ctlr[] = { +{ .io = (u32int*)(VIRTIO+0x201000), + .irq = IRQpl011, + .poll = 0, }, +{ .io = (u32int*)(VIRTIO+0x201400), + .irq = IRQpl011, + .poll = 0, }, +{ .io = (u32int*)(VIRTIO+0x201600), + .irq = IRQpl011, + .poll = 0, }, +{ .io = (u32int*)(VIRTIO+0x201800), + .irq = IRQpl011, + .poll = 0, }, +{ .io = (u32int*)(VIRTIO+0x201A00), + .irq = IRQpl011, + .poll = 0, }, +}; + +static Uart pl011uart[] = { +{ .regs = &pl011ctlr[0], + .name = "uart1", + .freq = 0, /* Not used */ + .baud = 115200, + .phys = &pl011physuart, + .next = &pl011uart[1], }, +{ .regs = &pl011ctlr[1], + .name = "uart2", + .freq = 0, + .baud = 115200, + .phys = &pl011physuart, + .next = &pl011uart[2], }, +{ .regs = &pl011ctlr[2], + .name = "uart3", + .freq = 0, + .baud = 115200, + .phys = &pl011physuart, + .next = &pl011uart[3], }, +{ .regs = &pl011ctlr[3], + .name = "uart4", + .freq = 0, + .baud = 115200, + .phys = &pl011physuart, + .next = &pl011uart[4], }, +{ .regs = &pl011ctlr[4], + .name = "uart5", + .freq = 0, + .baud = 115200, + .phys = &pl011physuart, + .next = nil, }, +}; + +static ulong pl011freq = 48000000; + +#define csr8r(c, r) ((c)->io[r]) +#define csr8w(c, r, v) ((c)->io[r] = (c)->sticky[r] | (v), coherence()) +#define csr8o(c, r, v) ((c)->io[r] = (v), coherence()) + +static long +pl011status(Uart* uart, void* buf, long n, long offset) +{ + char *p; + Ctlr *ctlr; + ushort ier, lcr, mcr, msr; + + ctlr = uart->regs; + p = malloc(READSTR); + mcr = ctlr->sticky[Cr]; + msr = csr8r(ctlr, Fr); + ier = ctlr->sticky[Imsc]; + lcr = ctlr->sticky[Lcrh]; + snprint(p, READSTR, + "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n" + "dev(%d) type(%d) framing(%d) overruns(%d) " + "berr(%d) serr(%d)%s\n", + + uart->baud, + uart->hup_dcd, + 1, + uart->hup_dsr, + ((lcr & WlsMASK) >> 5) + 5, + (ier & Ctsmint) != 0, + (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n', + (mcr & Rts) != 0, + (lcr & Stb) ? 2: 1, + ctlr->fena, + + uart->dev, + uart->type, + uart->ferr, + uart->oerr, + uart->berr, + uart->serr, + (msr & Cts) ? " cts": "" + ); + n = readstr(offset, buf, n, p); + free(p); + + return n; +} + +static void +pl011fifo(Uart* uart, int level) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + + /* + * Changing the FIFOena bit in Fcr flushes data + * from both receive and transmit FIFOs; there's + * no easy way to guarantee not losing data on + * the receive side, but it's possible to wait until + * the transmitter is really empty. + */ + ilock(ctlr); + while(!(csr8r(ctlr, Fr) & Txfe)) + ; + + /* + * Set the trigger level, default is the max. + * value. + */ + ctlr->fena = level; + switch(level){ + case 0: + break; + case 4: + level = RFIFO1|TFIFO7; + break; + case 8: + level = RFIFO2|TFIFO6; + break; + case 16: + level = RFIFO4|TFIFO4; + break; + case 24: + level = RFIFO6|TFIFO2; + break; + case 28: + default: + level = RFIFO7|TFIFO1; + break; + } + csr8w(ctlr, Ifls, level); + if(ctlr->fena) + ctlr->sticky[Lcrh] |= Fen; + else + ctlr->sticky[Lcrh] &= ~Fen; + csr8w(ctlr, Lcrh, 0); + iunlock(ctlr); +} + +static void +pl011dtr(Uart* uart, int on) +{ + USED(uart); + USED(on); +} + +static void +pl011rts(Uart* uart, int on) +{ + Ctlr *ctlr; + + /* + * Toggle RTS. + */ + ctlr = uart->regs; + if(on) + ctlr->sticky[Cr] |= Rts; + else + ctlr->sticky[Cr] &= ~Rts; + csr8w(ctlr, Cr, 0); +} + +static void +pl011modemctl(Uart* uart, int on) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + ilock(&uart->tlock); + if(on){ + ctlr->sticky[Imsc] |= Ctsmint; + csr8w(ctlr, Imsc, 0); + uart->modem = 1; + uart->cts = csr8r(ctlr, Fr) & Cts; + } + else{ + ctlr->sticky[Imsc] &= ~Ctsmint; + csr8w(ctlr, Imsc, 0); + uart->modem = 0; + uart->cts = 1; + } + iunlock(&uart->tlock); +} + +static int +pl011parity(Uart* uart, int parity) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcrh] & ~(Eps|Pen); + + switch(parity){ + case 'e': + lcr |= Eps|Pen; + break; + case 'o': + lcr |= Pen; + break; + case 'n': + break; + default: + return -1; + } + ctlr->sticky[Lcrh] = lcr; + csr8w(ctlr, Lcrh, 0); + + uart->parity = parity; + + return 0; +} + +static int +pl011stop(Uart* uart, int stop) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcrh] & ~Stb; + + switch(stop){ + case 1: + break; + case 2: + lcr |= Stb; + break; + default: + return -1; + } + ctlr->sticky[Lcrh] = lcr; + csr8w(ctlr, Lcrh, 0); + + uart->stop = stop; + + return 0; +} + +static int +pl011bits(Uart* uart, int bits) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcrh] & ~WlsMASK; + + switch(bits){ + case 5: + lcr |= Wls5; + break; + case 6: + lcr |= Wls6; + break; + case 7: + lcr |= Wls7; + break; + case 8: + lcr |= Wls8; + break; + default: + return -1; + } + ctlr->sticky[Lcrh] = lcr; + csr8w(ctlr, Lcrh, 0); + + uart->bits = bits; + + return 0; +} + +static int +pl011baud(Uart* uart, int baud) +{ + ulong bgc; + Ctlr *ctlr; + + /* + * Set the Baud rate by calculating and setting the Baud rate + * Generator Constant. This will work with fairly non-standard + * Baud rates. + */ + if(pl011freq == 0 || baud <= 0) + return -1; + bgc = 16*baud; + + ctlr = uart->regs; + csr8o(ctlr, Ibrd, pl011freq / bgc); + csr8o(ctlr, Fbrd, pl011freq % bgc); + /* + * Internally Ibrd Fbrd and Lcrh share a single register, + * updated only when Lcrh is written + */ + csr8w(ctlr, Lcrh, 0); + uart->baud = baud; + return 0; +} + +static void +pl011break(Uart* uart, int ms) +{ + Ctlr *ctlr; + + if (up == nil) + panic("pl011break: nil up"); + /* + * Send a break. + */ + if(ms <= 0) + ms = 200; + + ctlr = uart->regs; + csr8w(ctlr, Lcrh, Brk); + tsleep(&up->sleep, return0, 0, ms); + csr8w(ctlr, Lcrh, 0); +} + +static void +pl011kick(Uart* uart) +{ + int i; + Ctlr *ctlr; + + if(/* uart->cts == 0 || */ uart->blocked) + return; + + ctlr = uart->regs; + + /* + * 128 here is an arbitrary limit to make sure + * we don't stay in this loop too long. If the + * chip's output queue is longer than 128, too + * bad -- presotto + */ + for(i = 0; i < 128; i++){ + if(csr8r(ctlr, Fr) & Txff) + break; + if(uart->op >= uart->oe && uartstageoutput(uart) == 0) + break; + csr8o(ctlr, Dr, *uart->op++); /* start tx */ + } + if(csr8r(ctlr, Fr) & Txfe) + ctlr->sticky[Imsc] &= ~Txint; + else + ctlr->sticky[Imsc] |= Txint; + csr8w(ctlr, Imsc, 0); /* intr when done */ +} + +static void +pl011interrupt(Ureg*, void* arg) +{ + Ctlr *ctlr; + Uart *uart; + int iir, old, r; + + uart = arg; + ctlr = uart->regs; + for(iir = csr8r(ctlr, Mis); iir; iir = csr8r(ctlr, Mis)){ + if(iir & Ctsmint){ + r = csr8r(ctlr, Fr); + if(1){ + ilock(&uart->tlock); + old = uart->cts; + uart->cts = r & Cts; + if(old == 0 && uart->cts) + uart->ctsbackoff = 2; + iunlock(&uart->tlock); + } + } + if(iir & Txint){ + uartkick(uart); + } + if(iir & (Oeint|Beint|Peint|Feint|Rtint|Rxint)){ + /* + * Consume any received data. + * If the received byte came in with a break, + * parity or framing error, throw it away; + * overrun is an indication that something has + * already been tossed. + */ + while(!(csr8r(ctlr, Fr) & Rxfe)){ + r = csr8r(ctlr, Dr); + if(r & Oe) + uart->oerr++; + if(r & Pe) + uart->perr++; + if(r & Fe) + uart->ferr++; + if(!(r & (Be|Fe|Pe))) + uartrecv(uart, r & 0xFF); + } + } + csr8o(ctlr, Icr, iir); + } +} + +static void +pl011disable(Uart* uart) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + ctlr->sticky[Imsc] = 0; + csr8w(ctlr, Imsc, 0); + ctlr->sticky[Cr] = 0; + csr8w(ctlr, Cr, 0); +} + +static void +pl011enable(Uart* uart, int ie) +{ + Ctlr *ctlr; + Pinctl *p; + + ctlr = uart->regs; + p = &pinctl[uart->dev - pl011uart[0].dev]; + gpiosel(p->txpin, p->alt); + gpiosel(p->rxpin, p->alt); + gpiopulloff(p->txpin); + gpiopullup(p->rxpin); + + csr8o(ctlr, Cr, 0); + ctlr->sticky[Lcrh] = Wls8; /* no parity */ + csr8w(ctlr, Lcrh, 0); + pl011baud(uart, uart->baud); + + /* + * Enable interrupts and turn on DTR and RTS. + * Be careful if this is called to set up a polled serial line + * early on not to try to enable interrupts as interrupt- + * -enabling mechanisms might not be set up yet. + */ + if(ie){ + if(ctlr->iena == 0 && !ctlr->poll){ + intrenable(ctlr->irq, pl011interrupt, uart, 0, uart->name); + ctlr->iena = 1; + } + ctlr->sticky[Imsc] = Rxint|Rtint; + } + else{ + ctlr->sticky[Imsc] = 0; + } + csr8w(ctlr, Imsc, 0); + + ctlr->sticky[Cr] = Uarten|Rxe|Txe|Rts; + csr8w(ctlr, Cr, 0); +} + +static Uart* +pl011pnp(void) +{ + Uart *uart; + Ctlr *ctlr; + + uart = pl011uart; + ctlr = &pl011ctlr[1]; + csr8o(ctlr, Cr, Ctsen|Rtsen); + if(csr8r(ctlr, Cr) != (Ctsen|Rtsen)) + /* uarts 2-5 don't exist */ + uart->next = nil; + csr8o(ctlr, Cr, 0); + return uart; +} + +static int +pl011getc(Uart* uart) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + while((csr8r(ctlr, Fr) & Rxfe)) + delay(1); + return csr8r(ctlr, Dr) & 0xFF; +} + +static void +pl011putc(Uart* uart, int c) +{ + int i; + Ctlr *ctlr; + + ctlr = uart->regs; + for(i = 0; !(csr8r(ctlr, Fr) & Txfe) && i < 128; i++) + delay(1); + csr8o(ctlr, Dr, (uchar)c); + for(i = 0; !(csr8r(ctlr, Fr) & Txfe) && i < 128; i++) + delay(1); +} + +void +pl011consinit(void) +{ + Uart *uart; + int n; + char *p, *cmd; + + if((p = getconf("console")) == nil) + return; + n = strtoul(p, &cmd, 0); + if(p == cmd) + return; + if(n < 1 || n > 5) + return; + uart = &pl011uart[n-1]; + + if(!uart->enabled) + (*uart->phys->enable)(uart, 0); + uartctl(uart, "l8 pn s1"); + if(*cmd != '\0') + uartctl(uart, cmd); + + consuart = uart; + uart->console = 1; +} + +void (*pl011init)(void) = pl011consinit; + +PhysUart pl011physuart = { + .name = "pl011", + .pnp = pl011pnp, + .enable = pl011enable, + .disable = pl011disable, + .kick = pl011kick, + .dobreak = pl011break, + .baud = pl011baud, + .bits = pl011bits, + .stop = pl011stop, + .parity = pl011parity, + .modemctl = pl011modemctl, + .rts = pl011rts, + .dtr = pl011dtr, + .status = pl011status, + .fifo = pl011fifo, + .getc = pl011getc, + .putc = pl011putc, +}; diff --git a/sys/src/9/bcm/words.pi4 b/sys/src/9/bcm/words.pi4 index 3d8344486e..2edb15d848 100644 --- a/sys/src/9/bcm/words.pi4 +++ b/sys/src/9/bcm/words.pi4 @@ -5,10 +5,17 @@ broadcom 2838 SoC (based on 2711) Needs firmware from 5 July 2019 or later. -config.txt for pi4 should include 'core_freq=250' for -the mini-uart console, and 'device_tree=' to ensure that -the loader passes an ATAG list to the kernel instead of -a device tree. +config.txt for pi4 should include 'core_freq=250' if +the mini-uart is to be used, 'enable_gic=1' to ensure +that interrupts are correctly routed, and 'device_tree=' +to ensure that the loader passes an ATAG list to the +kernel instead of a device tree. +If the config file includes 'mmu' in the misc section, +the mmu will use 32-bit page table entries, limiting +the amount of accessible physical memory. On a 4GB (or 2GB) pi4, a little less than 2GB will be used. (0x7D000000 bytes to be precise.) +If the config file includes 'mmu64' instead, the mmu +will use 64-bit page table entries and LPAE to allow +all of physical memory to be used, even on an 8GB pi4. From e9a549106dc30706684b3bf10a0e487d3a5d7739 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 3 May 2021 19:05:05 +0000 Subject: [PATCH 080/402] sys/src/9/rb: import rb changes (2020-12-21) (thanks Geoff Collyer) --- sys/src/9/rb/clock.c | 33 +++-- sys/src/9/rb/dat.h | 18 ++- sys/src/9/rb/devether.c | 55 ++++---- sys/src/9/rb/faultmips.c | 4 +- sys/src/9/rb/fns.h | 6 +- sys/src/9/rb/fpimips.c | 49 +++---- sys/src/9/rb/init9.s | 2 +- sys/src/9/rb/initreboot.s | 21 ++- sys/src/9/rb/io.h | 2 - sys/src/9/rb/l.s | 262 +++++++++++++++++++------------------- sys/src/9/rb/main.c | 112 ++++++++++++---- sys/src/9/rb/mem.h | 24 +--- sys/src/9/rb/mips.s | 20 +-- sys/src/9/rb/mkfile | 3 +- sys/src/9/rb/mmu.c | 23 +++- sys/src/9/rb/notes/9rb.ms | 20 +-- sys/src/9/rb/rb | 13 +- sys/src/9/rb/rebootcode.c | 26 ++-- sys/src/9/rb/trap.c | 2 +- sys/src/9/rb/uarti8250.c | 6 +- sys/src/9/rb/words | 6 +- 21 files changed, 390 insertions(+), 317 deletions(-) diff --git a/sys/src/9/rb/clock.c b/sys/src/9/rb/clock.c index 3871049286..cc3db39498 100644 --- a/sys/src/9/rb/clock.c +++ b/sys/src/9/rb/clock.c @@ -12,31 +12,32 @@ enum { Cyccntres = 2, /* counter advances at ½ clock rate (mips 24k) */ - Basetickfreq = 680*Mhz / Cyccntres, /* rb450g */ }; +ulong basetickfreq = 680*Mhz / Cyccntres; /* rb450g */ + void (*kproftimer)(ulong); void silencewdog(void) { - *Rstwdogtimer = Basetickfreq * 2 * 5; /* pet the dog */ + *Rstwdogtimer = basetickfreq * 2 * 5; /* pet the dog */ } void sicwdog(void) { - *Rstwdogtimer = Basetickfreq * 2; + *Rstwdogtimer = basetickfreq * 2; *Rstwdogctl = Wdogreset; /* wake the dog */ } void wdogreset(void) { - *Rstwdogtimer = Basetickfreq / 100; + *Rstwdogtimer = basetickfreq / 100; *Rstwdogctl = Wdogreset; /* wake the dog */ coherence(); - *Rstwdogtimer = Basetickfreq / 10000; + *Rstwdogtimer = basetickfreq / 10000; coherence(); } @@ -74,12 +75,12 @@ microdelay(int l) speed = m->speed; if (speed == 0) - speed = Basetickfreq / Mhz * Cyccntres; + speed = basetickfreq / Mhz * Cyccntres; cyc = (ulong)l * (speed / Cyccntres); s = splhi(); cnt = rdcount(); x = cnt + cyc; - if (x < cnt || x >= ~0ul - Basetickfreq) { + if (x < cnt || x >= ~0ul - basetickfreq) { /* counter will wrap between now and x, or x is too near ~0 */ wrcount(0); /* somewhat drastic */ wrcompare(rdcompare() - cnt); /* match new count */ @@ -143,10 +144,10 @@ guessmips(long (*loop)(void), char *) iprint("again..."); } while (cyc < 0); /* - * Instrs instructions took cyc cycles @ Basetickfreq Hz. + * Instrs instructions took cyc cycles @ basetickfreq Hz. * round the result. */ - return (((vlong)Basetickfreq * Instrs) / cyc + Mhz/2) / Mhz; + return (((vlong)basetickfreq * Instrs) / cyc + Mhz/2) / Mhz; } void @@ -154,6 +155,7 @@ clockinit(void) { int mips; + basetickfreq = m->hz / Cyccntres; silencewdog(); /* @@ -169,11 +171,8 @@ clockinit(void) if(m->delayloop == 0) m->delayloop = 1; - m->speed = mips; - m->hz = m->speed*Mhz; - - m->maxperiod = Basetickfreq / HZ; - m->minperiod = Basetickfreq / (100*HZ); + m->maxperiod = basetickfreq / HZ; + m->minperiod = basetickfreq / (100*HZ); wrcompare(rdcount()+m->maxperiod); /* @@ -188,7 +187,7 @@ clockinit(void) /* * Tval is supposed to be in fastticks units. - * One fasttick unit is 1/Basetickfreq seconds. + * One fasttick unit is 1/basetickfreq seconds. */ void timerset(Tval next) @@ -221,7 +220,7 @@ fastticks(uvlong *hz) ulong delta, count; if(hz) - *hz = Basetickfreq; + *hz = basetickfreq; /* avoid reentry on interrupt or trap, to prevent recursion */ x = splhi(); @@ -269,7 +268,7 @@ cycles(uvlong *cycp) *cycp = fastticks(nil); } -Lock mpsynclock; +static Lock mpsynclock; /* * synchronize all clocks with processor 0 diff --git a/sys/src/9/rb/dat.h b/sys/src/9/rb/dat.h index f288eacc64..465c32e6fb 100644 --- a/sys/src/9/rb/dat.h +++ b/sys/src/9/rb/dat.h @@ -11,6 +11,7 @@ typedef struct MMU MMU; typedef struct Notsave Notsave; typedef struct Pcidev Pcidev; typedef struct PMMU PMMU; +typedef struct Rbconf Rbconf; typedef struct Softtlb Softtlb; typedef struct Ureg Ureg; typedef struct Proc Proc; @@ -60,6 +61,7 @@ struct Conf ulong nmach; /* processors */ ulong nproc; /* processes */ Confmem mem[1]; + /* npage may exclude kernel pages */ ulong npage; /* total physical pages of memory */ ulong upages; /* user page pool */ ulong nimage; /* number of page cache image headers */ @@ -71,6 +73,14 @@ struct Conf int nuart; /* number of uart devices */ }; +struct Rbconf { + char *ether0mac; + char *memsize; + char *hz; + char *console; + char *null; /* act as end of argv when rebooting */ +}; + /* * floating point registers */ @@ -211,7 +221,11 @@ struct Softtlb struct { Lock; - long machs; /* bitmap of processors */ + union { + uvlong machs; /* bitmap of active CPUs */ + ulong machsmap[(MAXMACH+BI2WD-1)/BI2WD]; + }; + int nmachs; /* number of bits set in machs(map) */ short exiting; int ispanic; }active; @@ -223,3 +237,5 @@ extern register Proc *up; extern FPsave initfp; extern int normalprint; +extern ulong memsize; +extern Rbconf rbconf; diff --git a/sys/src/9/rb/devether.c b/sys/src/9/rb/devether.c index 84a9c308e2..5b3f115985 100644 --- a/sys/src/9/rb/devether.c +++ b/sys/src/9/rb/devether.c @@ -1,15 +1,11 @@ /* - * Atheros 71xx ethernets for rb450g. + * Atheros 7161 & 8316 ethernets for rb450g. + * second 7161 has the 8316 switch with 4 ports on it. * - * all 5 PHYs are accessible only through first ether's register space. + * all 5 PHYs are accessible only through first 7161's register space. * - * TODO: - * promiscuous mode. - * make ether1 work: probably needs mii/phy initialisation, + * TODO: make second 7161 work: probably needs mii/phy initialisation, * maybe needs 8316 switch code too (which requires mdio, phy, etc. glop). - * to maybe do some day: - * dig mac addresses out & config phy/mii via spi or other grot and swill - * (instead of editing rb config file). */ #include "u.h" #include "../port/lib.h" @@ -32,9 +28,6 @@ enum { Rbsz = ETHERMAXTU + 4, /* 4 for CRC */ }; -extern uchar arge0mac[Eaddrlen]; /* see rb config file */ -extern uchar arge1mac[Eaddrlen]; - typedef struct Arge Arge; typedef struct Ctlr Ctlr; typedef struct Desc Desc; @@ -282,9 +275,7 @@ struct Ctlr { /* receiver */ Rendez rrendez; - uint rintr; /* count */ int pktstoread; /* flag */ - int discard; /* rx descriptors */ Desc* rdba; /* base address */ Block** rd; @@ -294,7 +285,6 @@ struct Ctlr { /* transmitter */ Rendez trendez; - uint tintr; /* count */ int pktstosend; /* flag */ int ntq; /* tx descriptors */ @@ -302,18 +292,22 @@ struct Ctlr { Block** td; uint tdh; /* head */ uint tdt; /* tail */ + + /* stats */ + uint rintr; /* count */ + int discard; + uint tintr; /* count */ }; struct Etherif { uintptr regs; int irq; - uchar *mac; int phymask; }; static Etherif etherifs[] = { - { 0x1a000000, ILenet0, arge0mac, 1<<4 }, - { 0x19000000, ILenet1, arge1mac, MASK(4) }, + { 0x1a000000, ILenet0, 1<<4 }, + { 0x19000000, ILenet1, MASK(4) }, }; static Ether *etherxx[MaxEther]; @@ -381,7 +375,7 @@ enum { Swglobalmtumask = 0x7fff, }; -#ifdef NOTYET +#ifdef INIT_SWITCH void * devicegetparent(int) { @@ -1051,17 +1045,14 @@ athcfg(Ether *ether, int phymask) delay(100); } - /* - * Set all Ethernet address registers to the same initial values - * set all four addresses to 66-88-aa-cc-dd-ee - */ eaddr = ether->ea; arge->staaddr1 = eaddr[2]<<24 | eaddr[3]<<16 | eaddr[4]<<8 | eaddr[5]; arge->staaddr2 = eaddr[0]<< 8 | eaddr[1]; - arge->fifocfg[0] = Fifocfg0all << Fifocfg0enshift; /* undocumented magic */ - arge->fifocfg[1] = 0x0fff0000; /* undocumented magic */ - arge->fifocfg[2] = 0x00001fff; /* undocumented magic */ + /* undocumented magic */ + arge->fifocfg[0] = Fifocfg0all << Fifocfg0enshift; + arge->fifocfg[1] = 0x0fff0000; + arge->fifocfg[2] = 0x00001fff; arge->fiforxfiltmatch = Ffmatchdflt; arge->fiforxfiltmask = Ffmaskdflt; @@ -1121,11 +1112,14 @@ athattach(Ether *ether) /* * strategy: RouterBOOT has initialised arge0, try to leave it alone. + * sadly, staaddr[12] seem to have been tampered with. * copy arge0 registers to arge1, with a few exceptions. */ static int athreset(Ether *ether) { + char *p; + uchar zeromac[Eaddrlen]; Arge *arge; Ctlr *ctlr; Etherif *ep; @@ -1146,7 +1140,13 @@ athreset(Ether *ether) ether->port = (uint)arge; ether->irq = ep->irq; - memmove(ether->ea, ep->mac, Eaddrlen); + if (rbconf.ether0mac && (p = strchr(rbconf.ether0mac, '='))) + parseether(ether->ea, p+1); + if(memcmp(ether->ea, zeromac, sizeof zeromac) == 0) + panic("ether%d: no mac", ether->ctlrno); + ether->ea[5] += ether->ctlrno; + if (ether->ea[5] == 0) + ether->ea[4]++; ether->ifstat = ifstat; ether->promiscuous = promiscuous; ether->multicast = multicast; @@ -1156,6 +1156,9 @@ athreset(Ether *ether) return 0; } +extern int sprint(char*, char*, ...); +#pragma varargck argpos sprint 2 + static Ether* etherprobe(int ctlrno) { diff --git a/sys/src/9/rb/faultmips.c b/sys/src/9/rb/faultmips.c index b4e4124117..88461ad9f1 100644 --- a/sys/src/9/rb/faultmips.c +++ b/sys/src/9/rb/faultmips.c @@ -226,10 +226,10 @@ faultmips(Ureg *ur, int user, int code) } /* - * called in syscallfmt.c, sysfile.c, sysproc.c + * called in sysfile.c */ void -validalign(uintptr addr, unsigned align) +validalign(ulong addr, ulong align) { /* * Plan 9 is a 32-bit O/S, and the hardware it runs on diff --git a/sys/src/9/rb/fns.h b/sys/src/9/rb/fns.h index 2f72315347..1228151b2c 100644 --- a/sys/src/9/rb/fns.h +++ b/sys/src/9/rb/fns.h @@ -12,11 +12,11 @@ int cmpswap(long*, long, long); void coherence(void); void cycles(uvlong *); void dcflush(void*, ulong); +void validalign(ulong, ulong); void faultmips(Ureg*, int, int); ulong fcr31(void); void firmware(int); void fpclear(void); -void fpsave(FPsave *); void fptrap(Ureg*); int fpuemu(Ureg *); void fpwatch(Ureg *); @@ -122,11 +122,13 @@ ulong tlbvirt(void); void touser(uintptr); void unleash(void); #define userureg(ur) ((ur)->status & KUSER) -void validalign(uintptr, unsigned); void vecinit(void); void vector0(void); void vector100(void); void vector180(void); +void* vmap(uintptr, usize); +int vmapsync(ulong); +void vunmap(void*, usize); void wdogreset(void); void wrcompare(ulong); void wrcount(ulong); diff --git a/sys/src/9/rb/fpimips.c b/sys/src/9/rb/fpimips.c index 30961000d5..8b7378f2df 100644 --- a/sys/src/9/rb/fpimips.c +++ b/sys/src/9/rb/fpimips.c @@ -37,9 +37,9 @@ #define dbgstuck _dbgstuck #else #define DBG(bits) (0) -#define internsane(i, ur) do { USED(ur); } while(0) -#define intpr(i, reg, fmt, ufp) do {} while(0) -#define dbgstuck(pc, ur, ufp) do {} while(0) +#define internsane(i, ur) do { USED(i, ur); } while(0) +#define intpr(i, reg, fmt, ufp) do { USED(i, reg, fmt, ufp); } while(0) +#define dbgstuck(pc, ur, ufp) do { USED(pc, ur, ufp); } while(0) #endif #define OFR(memb) (uintptr)&((Ureg*)0)->memb /* offset into Ureg of memb */ @@ -306,19 +306,15 @@ frnd(Internal *m, Internal *d) /* debugging: print internal representation of an fp reg */ static void -_intpr(Internal *i, int reg, int fmt, FPsave *ufp) +_intpr(Internal *i, uint reg, int fmt, FPsave *) { - USED(i); + USED(i, reg, fmt); if (!(DBG(Dbgregs))) return; - if (fmt == Fdouble && reg < 31) - iprint("\tD%02d: l %08lux h %08lux =\ts %d e %04d h %08lux l %08lux\n", - reg, FREG(ufp, reg), FREG(ufp, reg+1), - i->s, i->e, i->h, i->l); - else - iprint("\tF%02d: %08lux =\ts %d e %04d h %08lux l %08lux\n", - reg, FREG(ufp, reg), - i->s, i->e, i->h, i->l); + if (reg < Nfpregs) + iprint("\t%c%02d: %c e %04d %08lux%08lux\n", + (fmt == Fdouble || fmt == Fvlong? 'D': 'F'), reg, + (i->s? '-': '+'), i->e, i->h, i->l); delay(75); } @@ -364,27 +360,25 @@ fcvtd(int fmt, int rm, int rd, Ureg *ur, FPsave *ufp) switch (fmt) { case Ffloat: fpis2i(&intrn, &FREG(ufp, rm)); - internsane(&intrn, ur); - fpii2d(&d, &intrn); break; case Fdouble: dreg2dbl(&d, rm, ufp); break; case Flong: fpiw2i(&intrn, &FREG(ufp, rm)); - internsane(&intrn, ur); - fpii2d(&d, &intrn); break; case Fvlong: vreg2dbl(&d, rm, ufp); fpiv2i(&intrn, &d); + break; + } + if (fmt != Fdouble) { + if (DBG(Dbgregs)) + intpr(&intrn, rd, Fdouble, ufp); internsane(&intrn, ur); fpii2d(&d, &intrn); - break; } dbl2dreg(rd, &d, ufp); - if (fmt != Fdouble && DBG(Dbgregs)) - intpr(&intrn, rm, Fdouble, ufp); } /* convert fmt (rm) to single (rd) */ @@ -412,7 +406,7 @@ fcvts(int fmt, int rm, int rd, Ureg *ur, FPsave *ufp) } if (fmt != Ffloat) { if(DBG(Dbgregs)) - intpr(&intrn, rm, Ffloat, ufp); + intpr(&intrn, rd, Ffloat, ufp); internsane(&intrn, ur); fpii2s(&FREG(ufp, rd), &intrn); } @@ -443,7 +437,7 @@ fcvtw(int fmt, int rm, int rd, Ureg *ur, FPsave *ufp) } if (fmt != Flong) { if(DBG(Dbgregs)) - intpr(&intrn, rm, Flong, ufp); + intpr(&intrn, rd, Flong, ufp); internsane(&intrn, ur); fpii2w((long *)&FREG(ufp, rd), &intrn); } @@ -474,7 +468,7 @@ fcvtv(int fmt, int rm, int rd, Ureg *ur, FPsave *ufp) } if (fmt != Fvlong) { if(DBG(Dbgregs)) - intpr(&intrn, rm, Fvlong, ufp); + intpr(&intrn, rd, Fvlong, ufp); internsane(&intrn, ur); fpii2v((vlong *)&FREG(ufp, rd), &intrn); } @@ -525,7 +519,7 @@ static void fld(int d, ulong ea, int n, FPsave *ufp) { if(DBG(Dbgmoves)) - iprint("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d); + iprint("MOV%c\t%#lux, F%d\n", n==8? 'D': 'F', ea, d); if (n == 4) memmove(&FREG(ufp, d), (void *)ea, 4); else if (n == 8){ @@ -541,7 +535,7 @@ static void fst(ulong ea, int s, int n, FPsave *ufp) { if(DBG(Dbgmoves)) - iprint("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea); + iprint("MOV%c\tF%d,%#lux\n", n==8? 'D': 'F', s, ea); if (n == 4) memmove((void *)ea, &FREG(ufp, s), 4); else if (n == 8){ @@ -837,7 +831,7 @@ fpwatch(Ureg *ur) /* called on watch-point trap */ qunlock(&watchlock); ur->pc = ufp->fpdelaypc; /* pc of fp branch */ - ur->cause &= BD; /* take no chances */ + ur->cause &= ~BD; /* take no chances */ ufp->fpstatus = ufp->fpdelaysts; followbr(ur); /* sets ur->pc to fp branch target */ if (DBG(Dbgdelay)) @@ -1213,7 +1207,7 @@ fpimips(ulong pc, ulong op, Ureg *ur, FPsave *ufp) } static FPsave * -fpinit(Ureg *ur) +fpinit(Ureg *) { int i, n; Double d; @@ -1241,7 +1235,6 @@ fpinit(Ureg *ur) else i = n; tmp = fpconst[i]; - internsane(&tmp, ur); fpii2d(&d, &tmp); dbl2dreg(n, &d, ufp); } diff --git a/sys/src/9/rb/init9.s b/sys/src/9/rb/init9.s index 6698f397c2..3a28f53d73 100644 --- a/sys/src/9/rb/init9.s +++ b/sys/src/9/rb/init9.s @@ -5,4 +5,4 @@ TEXT _main(SB), $8 MOVW R1, 4(R29) MOVW R2, 8(R29) JAL startboot(SB) - + NOP diff --git a/sys/src/9/rb/initreboot.s b/sys/src/9/rb/initreboot.s index 2e3b1c590e..6f750bd376 100644 --- a/sys/src/9/rb/initreboot.s +++ b/sys/src/9/rb/initreboot.s @@ -9,11 +9,12 @@ TEXT _main(SB), $0 MOVW $setR30(SB), R30 JMP main(SB) + NOP /* target for JALRHB in BARRIERS */ TEXT ret(SB), $-4 JMP (R22) - NOP + NOP TEXT setsp(SB), $-4 MOVW R1, SP @@ -25,6 +26,18 @@ TEXT coherence(SB), $-4 EHB RETURN +/* + * next_kernel(entry, r4, r5, r6, r7) + * set R4-R7 for next kernel, then jump to it. + */ +TEXT next_kernel(SB), $-4 + MOVW r4+4(FP), R4 + MOVW r5+8(FP), R5 + MOVW r6+12(FP), R6 + MOVW r7+16(FP), R7 + JMP (R1) + NOP + /* * cache manipulation */ @@ -42,7 +55,7 @@ iccache: SUBU $CACHELINESZ, R9 ADDU $CACHELINESZ, R1 BGTZ R9, iccache - NOP + NOP MOVW R0, R1 /* index, not address */ MOVW $DCACHESIZE, R9 @@ -51,10 +64,10 @@ dccache: SUBU $CACHELINESZ, R9 ADDU $CACHELINESZ, R1 BGTZ R9, dccache - NOP + NOP SYNC - MOVW R10, M(STATUS) + MOVW R10, M(STATUS) /* restore processor level */ JRHB(31) /* return and clear all hazards */ SCHED diff --git a/sys/src/9/rb/io.h b/sys/src/9/rb/io.h index 8061f9b44f..30b76a2e32 100644 --- a/sys/src/9/rb/io.h +++ b/sys/src/9/rb/io.h @@ -300,8 +300,6 @@ enum { #define PCIWINDOW 0 #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) -#define ISAWINDOW 0 -#define ISAWADDR(va) (PADDR(va)+ISAWINDOW) /* SMBus transactions */ enum diff --git a/sys/src/9/rb/l.s b/sys/src/9/rb/l.s index 3a40d9ba24..8ec023b211 100644 --- a/sys/src/9/rb/l.s +++ b/sys/src/9/rb/l.s @@ -12,6 +12,12 @@ * Boot only processor */ TEXT start(SB), $-4 + /* save parameters passed from routerboot */ + MOVW R4, R19 /* argc */ + MOVW R5, R20 /* argv */ + MOVW R6, R21 /* envp */ + MOVW R7, R23 /* memory size */ + MOVW $setR30(SB), R30 PUTC('9', R1, R2) @@ -21,7 +27,7 @@ PUTC('9', R1, R2) CONST(SANITY, R2) SUBU R1, R2, R2 BNE R2, insane - NOP + NOP MOVW R0, M(COMPARE) EHB @@ -42,7 +48,7 @@ PUTC('9', R1, R2) MOVW R1, M(CACHEECC) /* aka ErrCtl */ EHB JAL cleancache(SB) - NOP + NOP MOVW $TLBROFF, R1 MOVW R1, M(WIRED) @@ -68,18 +74,34 @@ clrmach: MOVW R0, (R1) ADDU $BY2WD, R1 BNE R1, SP, clrmach - NOP + NOP MOVW R0, 0(R(MACH)) /* m->machno = 0 */ MOVW R0, R(USER) /* up = nil */ - /* zero bss, byte-by-byte */ + /* zero bss */ MOVW $edata(SB), R1 MOVW $end(SB), R2 clrbss: - MOVB R0, (R1) - ADDU $1, R1 + MOVW R0, (R1) + ADDU $BY2WD, R1 BNE R1, R2, clrbss - NOP + NOP + + MOVW R0, HI + MOVW R0, LO + +PUTC('\r', R1, R2) +PUTC('\n', R1, R2) + + /* + * restore parameters passed from routerboot and + * pass them as arguments to main(). + */ + SUB $(5*4), SP /* reserve space for args to main() + link */ + MOVW R19, R1 /* argc */ + MOVW R20, 8(SP) /* argv */ + MOVW R21, 12(SP) /* envp */ + MOVW R23, 16(SP) /* memory size */ MOVW $0x16, R16 MOVW $0x17, R17 @@ -90,22 +112,20 @@ clrbss: MOVW $0x22, R22 MOVW $0x23, R23 - MOVW R0, HI - MOVW R0, LO - -PUTC('\r', R1, R2) -PUTC('\n', R1, R2) JAL main(SB) - NOP + NOP + + /* shouldn't get here */ CONST(ROM, R1) JMP (R1) /* back to the rom */ + NOP #define PUT(c) PUTC(c, R1, R2) #define DELAY(lab) \ CONST(34000000, R3); \ lab: SUBU $1, R3; \ BNE R3, lab; \ - NOP + NOP insane: /* @@ -119,12 +139,12 @@ insane: PUT('\r'); PUT('\n'); DELAY(dl5) CONST(ROM, R1) JMP (R1) /* back to the rom */ - NOP + NOP /* target for JALRHB in BARRIERS */ TEXT ret(SB), $-4 JMP (R22) - NOP + NOP /* print R1 in hex; clobbers R3—8 */ TEXT printhex(SB), $-4 @@ -137,16 +157,16 @@ prtop: AND $0xf, R6 SGTU R6, R7, R8 BEQ R8, prdec /* branch if R6 <= 9 */ - NOP + NOP ADD $('a'-10), R6 JMP prchar - NOP + NOP prdec: ADD $'0', R6 prchar: PUTC(R6, R3, R4) BNE R5, prtop - NOP + NOP RETURN /* @@ -154,6 +174,7 @@ prchar: * - argument is stack pointer to user */ TEXT touser(SB), $-4 + DI(0) /* ensure intrs see consistent M(STATUS) */ MOVW R1, SP MOVW $(UTZERO+32), R2 /* header appears in text */ MOVW R2, M(EPC) @@ -193,7 +214,7 @@ TEXT idle(SB), $-4 TEXT wait(SB), $-4 WAIT - NOP + NOP MOVW R1, M(STATUS) /* interrupts restored */ EHB @@ -237,6 +258,14 @@ TEXT coherence(SB), $-4 EHB RETURN +/* + * bit twiddling + */ + +TEXT clz(SB), $-4 /* dest = clz(src): count leading zeroes */ + CLZ(1, 1) + RETURN + /* * process switching */ @@ -276,9 +305,9 @@ TEXT puttlb(SB), $0 /* puttlb(virt, phys0, phys1) */ EHB MOVW M(INDEX), R1 BGEZ R1, index /* if tlb entry found, use it */ - NOP + NOP BEQ R4, dont /* not valid? cf. kunmap */ - NOP + NOP MOVW M(RANDOM), R1 /* write random tlb entry */ MOVW R1, M(INDEX) index: @@ -365,7 +394,7 @@ TEXT gettlbp(SB), $0 /* gettlbp(tlbvirt, &entry) */ EHB MOVW M(INDEX), R1 BLTZ R1, gettlbp1 /* if no tlb entry found, return */ - NOP + NOP EHB TLBR /* read indexed tlb entry */ EHB @@ -399,14 +428,16 @@ TEXT gettlbvirt(SB), $0 /* gettlbvirt(index) */ /* * exceptions. + * * mips promises that there will be no current hazards upon entry * to exception handlers. */ + /* will be copied into low memory vectors; must fit in 32 words */ TEXT vector0(SB), $-4 MOVW $utlbmiss(SB), R26 JMP (R26) - NOP + NOP /* * compute stlb hash index. @@ -416,9 +447,8 @@ TEXT vector0(SB), $-4 * stir in swizzled asid; we get best results with asid in both high & low bits. * * page = tlbvirt >> (PGSHIFT+1); // ignoring even/odd bit - * R27 = ((tlbvirt<<(STLBLOG-8) ^ (uchar)tlbvirt ^ page ^ - * ((page & (MASK(HIPFNBITS) << STLBLOG)) >> HIPFNBITS)) & - * (STLBSIZE-1)) * 12; + * arg = (tlbvirt<<(STLBLOG-8) ^ (uchar)tlbvirt ^ page ^ + * ((page & (MASK(HIPFNBITS) << STLBLOG)) >> HIPFNBITS)) & (STLBSIZE-1); */ #define STLBHASH(arg, tmp, tmp2) \ MOVW arg, tmp2; \ @@ -430,10 +460,24 @@ TEXT vector0(SB), $-4 MOVW tmp2, tmp; /* asid in low byte */ \ SLL $(STLBLOG-8), tmp; /* move asid to high bits */ \ XOR tmp, arg; /* include asid in high bits too */ \ - AND $0xff, tmp2, tmp; /* asid in low byte */ \ + MOVBU tmp2, tmp; /* asid in low byte of tlbvirt */ \ XOR tmp, arg; /* include asid in low bits */ \ CONST (STLBSIZE-1, tmp); \ AND tmp, arg /* chop to fit */ +/* + * vc -S generated essentially this, which uses 4 registers and + * R28 for big constants: + MOVW R1, R4 + SRL $(PGSHIFT+1), R1, R3 // page = tlbvirt>>(PGSHIFT+1) + SLL $(STLBLOG-8), R1, R1 // tlbvirt<<(STLBLOG-8) + MOVBU R4, R5 // (uchar)tlbvirt + XOR R5, R1 + XOR R3, R1 + AND $(MASK(HIPFNBITS) << STLBLOG), R3 + SRL $HIPFNBITS, R3 + XOR R3, R1 + AND $(STLBSIZE-1), R1 // chop to fit + */ TEXT utlbmiss(SB), $-4 /* @@ -441,27 +485,25 @@ TEXT utlbmiss(SB), $-4 * it's unsaved so far. avoid R24 (up in kernel) and R25 (m in kernel). */ /* update statistics */ - CONST (MACHADDR, R26) /* R26 = m-> */ - MOVW 16(R26), R27 + CONST (MACHADDR+16, R26) /* R26 = &m->tlbfault */ + MOVW (R26), R27 ADDU $1, R27 - MOVW R27, 16(R26) /* m->tlbfault++ */ + MOVW R27, (R26) /* m->tlbfault++ */ MOVW R23, M(DESAVE) /* save R23 */ -#ifdef KUTLBSTATS +#ifdef KUTLBSTATS + ADDU $4, R26 /* &m->ktlbfault */ + MOVW M(STATUS), R23 AND $KUSER, R23 BEQ R23, kmiss - - MOVW 24(R26), R27 - ADDU $1, R27 - MOVW R27, 24(R26) /* m->utlbfault++ */ - JMP either + NOP + ADDU $4, R26 /* m->utlbfault */ kmiss: - MOVW 20(R26), R27 + MOVW (R26), R27 ADDU $1, R27 - MOVW R27, 20(R26) /* m->ktlbfault++ */ -either: + MOVW R27, (R26) /* m->[ku]tlbfault++ */ #endif /* compute stlb index */ @@ -470,7 +512,7 @@ either: STLBHASH(R27, R26, R23) MOVW M(DESAVE), R23 /* restore R23 */ - /* scale to a byte index (multiply by 12) */ + /* scale to a byte index (multiply by 12 [3 ulongs]) */ SLL $1, R27, R26 /* × 2 */ ADDU R26, R27 /* × 3 */ SLL $2, R27 /* × 12 */ @@ -482,22 +524,22 @@ either: MOVW M(BADVADDR), R26 AND $BY2PG, R26 BNE R26, utlbodd /* odd page? */ - NOP + NOP utlbeven: MOVW 4(R27), R26 /* R26 = m->stb[hash].phys0 */ BEQ R26, stlbm /* nothing cached? do it the hard way */ - NOP + NOP MOVW R26, M(TLBPHYS0) EHB MOVW 8(R27), R26 /* R26 = m->stb[hash].phys1 */ JMP utlbcom - MOVW R26, M(TLBPHYS1) /* branch delay slot */ + MOVW R26, M(TLBPHYS1) /* branch delay slot */ utlbodd: MOVW 8(R27), R26 /* R26 = m->stb[hash].phys1 */ BEQ R26, stlbm /* nothing cached? do it the hard way */ - NOP + NOP MOVW R26, M(TLBPHYS1) EHB MOVW 4(R27), R26 /* R26 = m->stb[hash].phys0 */ @@ -508,10 +550,10 @@ utlbcom: MOVW M(TLBVIRT), R26 MOVW (R27), R27 /* R27 = m->stb[hash].virt */ BEQ R27, stlbm /* nothing cached? do it the hard way */ - NOP + NOP /* is the stlb entry for the right virtual address? */ BNE R26, R27, stlbm /* M(TLBVIRT) != m->stb[hash].virt? */ - NOP + NOP /* if an entry exists, overwrite it, else write a random one */ CONST (PGSZ, R27) @@ -521,38 +563,36 @@ utlbcom: EHB MOVW M(INDEX), R26 BGEZ R26, utlindex /* if tlb entry found, rewrite it */ - EHB /* delay slot */ + EHB /* delay slot */ TLBWR /* else write random tlb entry */ ERET utlindex: TLBWI /* write indexed tlb entry */ ERET -/* not in the stlb either; make trap.c figure it out */ -stlbm: +/* + * will be copied into low memory vectors; must fit in 32 words + * and avoid relative branches. + */ +TEXT vector100(SB), $-4 /* cache trap */ +TEXT vector180(SB), $-4 /* most exceptions */ +stlbm: /* not in the stlb either; make trap.c figure it out */ MOVW $exception(SB), R26 JMP (R26) - NOP + NOP TEXT stlbhash(SB), $-4 STLBHASH(R1, R2, R3) RETURN -TEXT vector100(SB), $-4 - MOVW $exception(SB), R26 - JMP (R26) - NOP - -TEXT vector180(SB), $-4 - MOVW $exception(SB), R26 - JMP (R26) - NOP - +/* + * exceptions other than tlb miss come here directly. + */ TEXT exception(SB), $-4 MOVW M(STATUS), R26 AND $KUSER, R26, R27 BEQ R27, waskernel - MOVW SP, R27 /* delay slot */ + MOVW SP, R27 /* delay slot */ wasuser: CONST (MACHADDR, SP) /* m-> */ @@ -563,7 +603,7 @@ wasuser: MOVW R31, Ureg_r31(SP) JAL savereg1(SB) - NOP + NOP MOVW R30, Ureg_r30(SP) MOVW R(MACH), Ureg_r25(SP) @@ -577,17 +617,17 @@ wasuser: AND $(EXCMASK<<2), R26, R1 SUBU $(CSYS<<2), R1 BNE R1, notsys - NOP + NOP /* the carrera does this: */ // ADDU $8, SP, R1 /* first arg for syscall */ MOVW SP, R1 /* first arg for syscall */ - JAL syscall(SB) - SUBU $Notuoffset, SP /* delay slot */ + JAL syscall(SB) /* to C */ + SUBU $Notuoffset, SP /* delay slot */ sysrestore: JAL restreg1(SB) - ADDU $Notuoffset, SP /* delay slot */ + ADDU $Notuoffset, SP /* delay slot */ MOVW Ureg_r31(SP), R31 MOVW Ureg_status(SP), R26 @@ -595,36 +635,36 @@ sysrestore: MOVW R26, M(STATUS) EHB MOVW Ureg_pc(SP), R26 /* old pc */ +erettor26: MOVW Ureg_sp(SP), SP MOVW R26, M(EPC) ERET notsys: JAL savereg2(SB) - NOP + NOP /* the carrera does this: */ // ADDU $8, SP, R1 /* first arg for trap */ MOVW SP, R1 /* first arg for trap */ - JAL trap(SB) - SUBU $Notuoffset, SP /* delay slot */ + JAL trap(SB) /* to C for user trap */ + SUBU $Notuoffset, SP /* delay slot */ ADDU $Notuoffset, SP restore: JAL restreg1(SB) - NOP + NOP JAL restreg2(SB) /* restores R28, among others */ - NOP + NOP MOVW Ureg_r30(SP), R30 MOVW Ureg_r31(SP), R31 MOVW Ureg_r25(SP), R(MACH) MOVW Ureg_r24(SP), R(USER) - MOVW Ureg_sp(SP), SP - MOVW R26, M(EPC) - ERET + JMP erettor26 + NOP waskernel: SUBU $UREGSIZE, SP @@ -633,21 +673,21 @@ waskernel: MOVW R31, Ureg_r31(SP) JAL savereg1(SB) - NOP + NOP JAL savereg2(SB) - NOP + NOP /* the carrera does this: */ // ADDU $8, SP, R1 /* first arg for trap */ - MOVW SP, R1 /* first arg for trap */ - JAL trap(SB) - SUBU $Notuoffset, SP /* delay slot */ + MOVW SP, R1 /* first arg for trap */ + JAL trap(SB) /* to C for kernel trap */ + SUBU $Notuoffset, SP /* delay slot */ ADDU $Notuoffset, SP JAL restreg1(SB) - NOP + NOP /* * if about to return to `wait', interrupt arrived just before @@ -658,21 +698,20 @@ waskernel: MOVW $wait(SB), R1 SUBU R1, R31 BNE R31, notwait - NOP + NOP ADD $BY2WD, R26 /* advance saved pc */ MOVW R26, Ureg_pc(SP) notwait: JAL restreg2(SB) /* restores R28, among others */ - NOP + NOP MOVW Ureg_r31(SP), R31 - MOVW Ureg_sp(SP), SP - MOVW R26, M(EPC) - ERET + JMP erettor26 + NOP TEXT forkret(SB), $0 JMP sysrestore - MOVW R0, R1 /* delay slot; child returns 0 */ + MOVW R0, R1 /* delay slot; child returns 0 */ /* * save mandatory registers. @@ -795,14 +834,6 @@ TEXT restreg2(SB), $-4 MOVW Ureg_pc(SP), R26 RETURN -#ifdef OLD_MIPS_EXAMPLE -/* this appears to be a dreg from the distant past */ -TEXT rfnote(SB), $0 - MOVW R1, R26 /* 1st arg is &uregpointer */ - JMP restore - SUBU $(BY2WD), R26, SP /* delay slot: pc hole */ -#endif - /* * degenerate floating-point stuff */ @@ -833,36 +864,7 @@ tas1: SC(2, 3) NOP BEQ R3, tas1 - NOP - RETURN - -TEXT ainc(SB), $0 - MOVW R1, R2 /* address of counter */ -loop: - MOVW $1, R3 - LL(2, 1) - NOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ - SC(2, 3) - NOP - BEQ R3, loop - NOP - RETURN - -TEXT adec(SB), $0 - SYNC - MOVW R1, R2 /* address of counter */ -loop1: - MOVW $-1, R3 - LL(2, 1) - NOP - ADDU R1, R3 - MOVW R3, R1 /* return new value */ - SC(2, 3) - NOP - BEQ R3, loop1 - NOP + NOP RETURN /* used by the semaphore implementation */ @@ -873,7 +875,7 @@ TEXT cmpswap(SB), $0 LL(2, 1) /* R1 = (R2) */ NOP BNE R1, R3, fail - NOP + NOP MOVW R4, R1 SC(2, 1) /* (R2) = R1 if (R2) hasn't changed; R1 = success */ NOP @@ -905,7 +907,7 @@ icflush1: CACHE PI+HINV, (R8) /* invalidate in I */ SUBU $CACHELINESZ, R9 BGTZ R9, icflush1 - ADDU $CACHELINESZ, R8 /* delay slot */ + ADDU $CACHELINESZ, R8 /* delay slot */ BARRIERS(7, R7, ic2hb); /* return to kseg0 (cached) */ MOVW R10, M(STATUS) @@ -927,7 +929,7 @@ dcflush1: CACHE PD+HWBI, (R8) /* flush & invalidate in D */ SUBU $CACHELINESZ, R9 BGTZ R9, dcflush1 - ADDU $CACHELINESZ, R8 /* delay slot */ + ADDU $CACHELINESZ, R8 /* delay slot */ SYNC EHB MOVW R10, M(STATUS) @@ -944,7 +946,7 @@ iccache: CACHE PI+IWBI, (R1) /* flush & invalidate I by index */ SUBU $CACHELINESZ, R9 BGTZ R9, iccache - ADDU $CACHELINESZ, R1 /* delay slot */ + ADDU $CACHELINESZ, R1 /* delay slot */ BARRIERS(7, R7, cc2hb); /* return to kseg0 (cached) */ @@ -954,7 +956,7 @@ dccache: CACHE PD+IWBI, (R1) /* flush & invalidate D by index */ SUBU $CACHELINESZ, R9 BGTZ R9, dccache - ADDU $CACHELINESZ, R1 /* delay slot */ + ADDU $CACHELINESZ, R1 /* delay slot */ SYNC MOVW R10, M(STATUS) diff --git a/sys/src/9/rb/main.c b/sys/src/9/rb/main.c index 60f7f826bc..84654d3035 100644 --- a/sys/src/9/rb/main.c +++ b/sys/src/9/rb/main.c @@ -36,8 +36,10 @@ static Softtlb stlb[MAXMACH][STLBSIZE]; Conf conf; FPsave initfp; +Rbconf rbconf; int normalprint; +ulong memsize; char * getconf(char *) @@ -156,17 +158,59 @@ parsemipsboothdr(Chan *c, ulong magic, Execvals *evp) return -1; } +/* + * parse args kmac=AA:BB:CC:DD:EE:FF for ether0 mac, mem=256M, + * HZ=340000000, console=ttyS0,115200. + * args seem to live above 8MB, where they are likely to be clobbered + * by kernel allocations, so make copies for rebooting. + * + * at this early stage, we can't use the usual kernel memory allocators, + * thus we can't use kstrdup. + */ +static void +saverbconfig(int argc, char **argv) +{ + int i; + char *p; + static char ether0mac[32], mem[16], hz[16], console[32]; + + if (argv == nil) + return; + rbconf.ether0mac = ether0mac; + rbconf.memsize = mem; + rbconf.hz = hz; + rbconf.console = console; + for (i = 0; i < argc; i++) { + p = argv[i]; + if (strncmp(p, "kmac=", 5) == 0) + strncpy(rbconf.ether0mac, p, sizeof ether0mac); + else if (strncmp(p, "mem=", 4) == 0) + strncpy(rbconf.memsize, p, sizeof mem); + else if (strncmp(p, "HZ=", 3) == 0) + strncpy(rbconf.hz, p, sizeof hz); + else if (strncmp(p, "console=", 8) == 0) + strncpy(rbconf.console, p, sizeof console); + } + memsize = 256*MB; /* routerboard default */ + p = strchr(rbconf.memsize, '='); + if (p) + memsize = atoi(p+1) * MB; +} + +/* arguments come from routerboot; only argc and argv are non-zero. */ void -main(void) +main(int argc, char **argv, char **envp, ulong memsz) { stopwdog(); /* tranquilise the dog */ optionsinit("/boot/boot boot"); + saverbconfig(argc, argv); + USED(envp, memsz); + confinit(); savefpregs(&initfp); - machinit(); /* calls clockinit */ active.exiting = 0; - active.machs = 1; + cpuactive(0); kmapinit(); xinit(); @@ -176,7 +220,7 @@ main(void) vecinit(); normalprint = 1; - print("\nPlan 9\n"); + print("\nPlan 9 from Bell Labs (mips)\n"); prcpuid(); if (PTECACHABILITY == PTENONCOHERWT) print("caches configured as write-through\n"); @@ -253,7 +297,7 @@ init0(void) if(!waserror()){ ksetenv("cputype", "mips", 0); - snprint(buf, sizeof buf, "mips %s rb450g", conffile); + snprint(buf, sizeof buf, "mips %s", conffile); ksetenv("terminal", buf, 0); if(cpuserver) ksetenv("service", "cpu", 0); @@ -288,7 +332,7 @@ bootargs(uintptr base) * of the argument list checked in syscall. */ i = oargblen+1; - p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i)); + p = (char *)STACKALIGN(base + BY2PG - Stkheadroom - i); memmove(p, oargb, i); /* @@ -300,7 +344,7 @@ bootargs(uintptr base) * not the usual (int argc, char* argv[]) */ av = (char**)(p - (oargc+1)*sizeof(char*)); - ssize = base + BY2PG - PTR2UINT(av); + ssize = base + BY2PG - (uintptr)av; for(i = 0; i < oargc; i++) *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG); *av = nil; @@ -434,16 +478,16 @@ shutdown(int ispanic) ilock(&active); if(ispanic) active.ispanic = ispanic; - else if(m->machno == 0 && (active.machs & (1<machno)) == 0) + else if(m->machno == 0 && !iscpuactive(m->machno)) active.ispanic = 0; - once = active.machs & (1<machno); + once = iscpuactive(m->machno); /* * setting exiting will make hzclock() on each processor call exit(0), * which calls shutdown(0) and idles non-bootstrap cpus and returns * on bootstrap processors (to permit a reboot). clearing our bit * in machs avoids calling exit(0) from hzclock() on this processor. */ - active.machs &= ~(1<machno); + cpuinactive(m->machno); active.exiting = 1; iunlock(&active); @@ -455,7 +499,7 @@ shutdown(int ispanic) ms = MAXMACH * 1000; for(; ms > 0; ms -= TK2MS(2)){ delay(TK2MS(2)); - if(active.machs == 0 && consactive() == 0) + if(active.nmachs == 0 && consactive() == 0) break; } delay(100); @@ -463,14 +507,25 @@ shutdown(int ispanic) /* * the new kernel is already loaded at address `code' - * of size `size' and entry point `entry'. + * of size `size' and physical entry point `entry'. */ void reboot(void *entry, void *code, ulong size) { - void (*f)(ulong, ulong, ulong); + Rbconf *rbc; + void (*f)(void *, ulong, ulong, ulong); writeconf(); + /* + * copy rbconf and contents into allocated memory, thus safe from + * being overwritten by the new kernel in the reboot trampoline + * code below. + */ + rbc = smalloc(sizeof *rbc); + kstrdup(&rbc->ether0mac, rbconf.ether0mac); + kstrdup(&rbc->memsize, rbconf.memsize); + kstrdup(&rbc->hz, rbconf.hz); + kstrdup(&rbc->console, rbconf.console); /* * the boot processor is cpu0. execute this function on it @@ -513,13 +568,16 @@ reboot(void *entry, void *code, ulong size) /* setup reboot trampoline function */ f = (void*)REBOOTADDR; memmove(f, rebootcode, sizeof(rebootcode)); + dcflush(f, sizeof(rebootcode)); icflush(f, sizeof(rebootcode)); setstatus(BEV); /* also, kernel mode, no interrupts */ coherence(); /* off we go - never to return */ - (*f)((ulong)entry, (ulong)code, size); + if (((ulong)entry & KSEGM) == 0) /* physical address? */ + entry = KADDR(entry); /* make it kernel virtual */ + (*f)(rbc, (ulong)entry, (ulong)code, size); panic("loaded kernel returned!"); } @@ -534,14 +592,14 @@ exit(int type) delay(1000); lock(&active); - active.machs &= ~(1<machno); + cpuinactive(m->machno); active.exiting = 1; unlock(&active); spllo(); print("cpu %d exiting\n", m->machno); timer = 0; - while(active.machs || consactive()) { + while(active.nmachs || consactive()) { if(timer++ > 400) break; delay(10); @@ -581,14 +639,15 @@ idlehands(void) void confinit(void) { + char *p; ulong kpages, ktop; /* * divide memory twixt user pages and kernel. */ conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end)); - /* fixed memory on routerboard */ - conf.mem[0].npage = MEMSIZE/BY2PG - ktop/BY2PG; + assert(memsize > 16*MB); + conf.mem[0].npage = memsize/BY2PG - ktop/BY2PG; conf.npage = conf.mem[0].npage; conf.nuart = 1; @@ -601,11 +660,11 @@ confinit(void) conf.ialloc = (kpages/2)*BY2PG; kpages *= BY2PG; - kpages -= conf.upages*sizeof(Page) - + conf.nproc*sizeof(Proc) - + conf.nimage*sizeof(Image) - + conf.nswap - + conf.nswppo*sizeof(Page*); + kpages -= conf.upages*sizeof(Page) /* palloc.pages in pageinit */ + + conf.nproc*sizeof(Proc) /* procalloc.free in procinit0 */ + + conf.nimage*sizeof(Image) /* imagealloc.free in initseg */ + + conf.nswap /* swapalloc.swmap in swapinit */ + + conf.nswppo*sizeof(Page*); /* iolist in swapinit */ mainmem->maxsize = kpages; /* @@ -614,7 +673,12 @@ confinit(void) */ m->machno = 0; m->speed = 680; /* initial guess at MHz, for rb450g */ - m->hz = m->speed * Mhz; + m->hz = 680 * Mhz; + p = strchr(rbconf.hz, '='); + if (p) { + m->hz = 2 * strtol(p+1, 0, 10); + m->speed = m->hz / Mhz; + } conf.nmach = 1; /* set up other configuration parameters */ diff --git a/sys/src/9/rb/mem.h b/sys/src/9/rb/mem.h index 1b560fb8f1..9b523e679f 100644 --- a/sys/src/9/rb/mem.h +++ b/sys/src/9/rb/mem.h @@ -14,23 +14,15 @@ #define MAXBY2PG (16*1024) /* rounding for UTZERO in executables; see mkfile */ #define UTROUND(t) ROUNDUP((t), MAXBY2PG) -#ifndef BIGPAGES #define BY2PG 4096 /* bytes per page */ #define PGSHIFT 12 /* log2(BY2PG) */ #define PGSZ PGSZ4K #define MACHSIZE (2*BY2PG) -#else -/* 16K pages work very poorly */ -#define BY2PG (16*1024) /* bytes per page */ -#define PGSHIFT 14 /* log2(BY2PG) */ -#define PGSZ PGSZ16K -#define MACHSIZE BY2PG -#endif #define KSTACK 8192 /* Size of kernel stack */ #define WD2PG (BY2PG/BY2WD) /* words per page */ -#define MAXMACH 1 /* max # cpus system can run; see active.machs */ +#define MAXMACH 1 /* max # cpus system can run */ #define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ #define BLOCKALIGN 16 #define CACHELINESZ 32 /* mips24k */ @@ -261,16 +253,10 @@ #define PHYSCONS (KSEG1|0x18020000) /* i8250 uart */ #define PIDXSHFT 12 -#ifndef BIGPAGES +/* future ref.: no cache aliases are possible with pages of 16K or larger */ #define NCOLOR 8 #define PIDX ((NCOLOR-1)<>PIDXSHFT) % NCOLOR) -#else -/* no cache aliases are possible with pages of 16K or larger */ -#define NCOLOR 1 -#define PIDX 0 -#define getpgcolor(a) 0 -#endif #define KMAPSHIFT 15 #define PTEGLOBL (1<<0) @@ -294,10 +280,10 @@ #define PTEPID(n) (n) #define PTEMAPMEM (1024*1024) #define PTEPERTAB (PTEMAPMEM/BY2PG) -#define SEGMAPSIZE 512 +#define SEGMAPSIZE (ROUND(USTKTOP, PTEMAPMEM) / PTEMAPMEM) #define SSEGMAPSIZE 16 -#define STLBLOG 15 +#define STLBLOG 16 /* was 15 */ #define STLBSIZE (1<= KZERO || pa >= MEMSIZE) + if(pa >= KZERO || pa >= memsize) return 0; - return MEMSIZE - pa; + return memsize - pa; +} + +/* + * although needed by the pc port, this mapping can be trivial on our mips systems, + * which have less memory. + */ +void* +vmap(uintptr pa, usize) +{ + return UINT2PTR(KSEG0|pa); +} + +void +vunmap(void* v, usize size) +{ + /* + upafree(PADDR(v), size); + */ + USED(v, size); } diff --git a/sys/src/9/rb/notes/9rb.ms b/sys/src/9/rb/notes/9rb.ms index 5c48b00d83..4efd0884f8 100644 --- a/sys/src/9/rb/notes/9rb.ms +++ b/sys/src/9/rb/notes/9rb.ms @@ -1,11 +1,16 @@ +.nr PS 11 +.nr VS 13 .FP palatino +. .TM +.DA 23 July 2013 .TL Plan 9 on the Mikrotik RB450G Routerboard .AU Geoff Collyer .AI .MH +. .NH 1 Motivation .LP @@ -57,7 +62,7 @@ to generate a NOP before every third consecutive store. The fix could be better, in particular the technique for keeping stores out of branch delay slots. .NH 2 -Driver for Undocumented Ethernet Controller +Driver for Undocumented Atheros 7161 Ethernet Controller .LP The FreeBSD Atheros .I arge @@ -151,11 +156,6 @@ we'll just live with the absurdly-high number of TLB faults (around 20k–30k per second). It probably doesn't help that one 16K page is half of the L1 data cache and one quarter of the L1 instruction cache. -.LP -Page size is controlled by -.CW BIGPAGES -in -.CW mem.h . .NH 3 Combined TLB Pool .LP @@ -179,11 +179,3 @@ There's some kludgey stuff in .CW uarti8250.c that makes output work most of the time (characters do sometimes get dropped). -.LP -The Ethernet driver currently does not -dig out the MAC addresses from the hardware, -so you'll need to edit the -.CW rb -configuration file for each Routerboard; the format should be obvious. -I don't have the stomach to dig the MAC address out of the hardware -via SPI or whatever vile interface it requires. diff --git a/sys/src/9/rb/rb b/sys/src/9/rb/rb index aac7b332d3..2dfa1bae4f 100644 --- a/sys/src/9/rb/rb +++ b/sys/src/9/rb/rb @@ -9,14 +9,14 @@ dev mnt srv dup -# rtc +# rtc # no hardware tod clock ssl tls cap kprof - fs +# fs - ether netif + ether ethermii netif ip arp chandial inferno ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum uart @@ -30,7 +30,6 @@ misc fpi fpimips fpimem - ethermii ip tcp @@ -38,15 +37,13 @@ ip ipifc icmp icmp6 - gre +# only used by mobile ip code +# gre ipmux esp port int cpuserver = 1; - uchar arge0mac[] = { 0xd4, 0xca, 0x6d, 0x7d, 0xf1, 0xce, }; - uchar arge1mac[] = { 0xd4, 0xca, 0x6d, 0x7d, 0xf1, 0xcf, }; -}; boot cpu tcp diff --git a/sys/src/9/rb/rebootcode.c b/sys/src/9/rb/rebootcode.c index bff0dc722d..27572f151b 100644 --- a/sys/src/9/rb/rebootcode.c +++ b/sys/src/9/rb/rebootcode.c @@ -20,36 +20,40 @@ enum { /* Lsr */ }; void putc(int); +void next_kernel(void *, ulong, char **, char **, ulong); /* - * Copy the new kernel to its correct location in physical memory, + * Copy the new kernel to its correct location in memory, * flush caches, ignore TLBs (we're in KSEG0 space), and jump to - * the start of the kernel. + * the start of the kernel. Argument addresses are virtual (KSEG0). */ void -main(ulong aentry, ulong acode, ulong asize) +main(Rbconf *rbconf, ulong aentry, ulong acode, ulong asize) { - void (*kernel)(void); - static ulong entry, code, size; + static ulong entry, code, size, argc; + static char **argv; - putc('B'); putc('o'); putc('o'); putc('t'); + putc('B'); putc('o'); /* copy args to heap before moving stack to before a.out header */ + argv = (char **)rbconf; entry = aentry; code = acode; size = asize; setsp(entry-0x20-4); + putc('o'); memmove((void *)entry, (void *)code, size); - + putc('t'); cleancache(); coherence(); + putc(' '); /* - * jump to kernel entry point. + * jump to new kernel's entry point. + * pass routerboot arg vector in R4-R5. + * off we go - never to return. */ - putc(' '); - kernel = (void*)entry; - (*kernel)(); /* off we go - never to return */ + next_kernel((void*)entry, 4, argv, 0, 0); putc('?'); putc('!'); diff --git a/sys/src/9/rb/trap.c b/sys/src/9/rb/trap.c index d6bd2bcf31..cf972769a6 100644 --- a/sys/src/9/rb/trap.c +++ b/sys/src/9/rb/trap.c @@ -548,7 +548,7 @@ fpexcname(Ureg *ur, ulong fcr31, char *buf, uint size) return buf; } -#define KERNPC(x) (KTZERO <= (ulong)(x) && (ulong)(x) < (ulong)&etext) +// #define KERNPC(x) (KTZERO <= (ulong)(x) && (ulong)(x) < (ulong)&etext) void kernfault(Ureg *ur, int code) diff --git a/sys/src/9/rb/uarti8250.c b/sys/src/9/rb/uarti8250.c index 9ae3924d5a..8570d3dbbd 100644 --- a/sys/src/9/rb/uarti8250.c +++ b/sys/src/9/rb/uarti8250.c @@ -118,7 +118,7 @@ enum { /* Mdr */ typedef struct Ctlr { - u32int* io; + ulong* io; int irq; int tbdf; int iena; @@ -135,7 +135,7 @@ typedef struct Ctlr { extern PhysUart i8250physuart; static Ctlr i8250ctlr[] = { -{ .io = (u32int*)PHYSCONS, +{ .io = (ulong*)PHYSCONS, .irq = ILduart0, .tbdf = -1, .poll = 0, }, @@ -396,7 +396,7 @@ i8250bits(Uart* uart, int bits) static int i8250baud(Uart* uart, int baud) { -#ifdef notdef /* don't change the speed */ +#ifdef CHANGE_SPEED ulong bgc; Ctlr *ctlr; extern int i8250freq; /* In the config file */ diff --git a/sys/src/9/rb/words b/sys/src/9/rb/words index bc5a88aeb2..bd14fe5fac 100644 --- a/sys/src/9/rb/words +++ b/sys/src/9/rb/words @@ -22,7 +22,7 @@ perf ctl 1: 0x0 ll/sc target memory must be cached. 1 uart 8250 (actually 16550ish) -2 ethers arge[01] ar71xx, 2nd has 4 ports & a bridge +2 ethers arge[01] ar7161, 2nd has 4 ports & a bridge pci bus(es) no video no disk but has flash, alas @@ -44,8 +44,8 @@ devices; access by KSEG1|addr irqs 2 pci 3 ehci -4 arge1 ar71xx @ 0x19:: + ar8316 switch -5 arge0 ar71xx @ 0x1a:: +4 arge1 ar7161 @ 0x19:: + ar8316 switch +5 arge0 ar7161 @ 0x1a:: 6 uart 7 clock From f283cdb2013b4f6bc223a4fa220bc2ea7750d05c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 8 Oct 2017 16:46:17 +0000 Subject: [PATCH 081/402] sys/src/9/rb: use AS, CC and LD variables to build initcode --- sys/src/9/rb/mkfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/src/9/rb/mkfile b/sys/src/9/rb/mkfile index 1a2e219d37..6d48dda259 100644 --- a/sys/src/9/rb/mkfile +++ b/sys/src/9/rb/mkfile @@ -95,9 +95,9 @@ install:V: $p$CONF <|../port/mkbootrules $CONF init.h: init9.s ../port/initcode.c /sys/src/libc/9syscall/sys.h - va init9.s - vc ../port/initcode.c - vl -T$UTZERO -R4 -o init.out init9.$O initcode.$O + $AS init9.s + $CC ../port/initcode.c + $LD -T$UTZERO -R4 -o init.out init9.$O initcode.$O {echo 'uchar initcode[]={' xd -r -1x init.out | sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g' From 525db0476015e93c02b83b7de893c6b6ec1b1d86 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 18 Apr 2016 15:00:41 +0000 Subject: [PATCH 082/402] sys/src/9/teg2: don't force flush-to-zero mode in vfp3 (thanks Richard Miller) --- sys/src/9/teg2/vfp3.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sys/src/9/teg2/vfp3.c b/sys/src/9/teg2/vfp3.c index 08a912b7b4..5f72137b6c 100644 --- a/sys/src/9/teg2/vfp3.c +++ b/sys/src/9/teg2/vfp3.c @@ -163,7 +163,10 @@ fpcfg(void) static int printed; /* clear pending exceptions; no traps in vfp3; all v7 ops are scalar */ - m->fpscr = Dn | Fz | FPRNR | (FPINVAL | FPZDIV | FPOVFL) & ~Alltraps; + m->fpscr = Dn | FPRNR | (FPINVAL | FPZDIV | FPOVFL) & ~Alltraps; + /* VFPv2 needs software support for underflows, so force them to zero */ + if(m->havefp == VFPv2) + m->fpscr |= Fz; fpwr(Fpscr, m->fpscr); m->fpconfiged = 1; @@ -305,7 +308,7 @@ fpuprocsave(Proc *p) { if(p->fpstate == FPactive){ if(p->state == Moribund) - fpclear(); + fpoff(); else{ /* * Fpsave() stores without handling pending @@ -399,7 +402,7 @@ mathemu(Ureg *) up->fpstate = FPactive; break; case FPactive: - error("illegal instruction: bad vfp fpu opcode"); + error("sys: illegal instruction: bad vfp fpu opcode"); break; } fpclear(); @@ -475,6 +478,7 @@ fpuemu(Ureg* ureg) { int s, nfp, cop, op; uintptr pc; + static int already; if(waserror()){ postnote(up, 1, up->errstr, NDebug); @@ -487,16 +491,14 @@ fpuemu(Ureg* ureg) nfp = 0; pc = ureg->pc; validaddr(pc, 4, 0); - if(!condok(ureg->psr, *(ulong*)pc >> 28)) - iprint("fpuemu: conditional instr shouldn't have got here\n"); op = (*(ulong *)pc >> 24) & MASK(4); cop = (*(ulong *)pc >> 8) & MASK(4); if(m->fpon) fpstuck(pc); /* debugging; could move down 1 line */ if (ISFPAOP(cop, op)) { /* old arm 7500 fpa opcode? */ -// iprint("fpuemu: fpa instr %#8.8lux at %#p\n", *(ulong *)pc, pc); -// error("illegal instruction: old arm 7500 fpa opcode"); s = spllo(); + if(!already++) + pprint("warning: emulated arm7500 fpa instr %#8.8lux at %#p\n", *(ulong *)pc, pc); if(waserror()){ splx(s); nexterror(); @@ -506,7 +508,7 @@ fpuemu(Ureg* ureg) m->fppc = m->fpcnt = 0; splx(s); poperror(); - } else if (ISVFPOP(cop, op)) { /* if vfp, fpu must be off */ + } else if (ISVFPOP(cop, op)) { /* if vfp, fpu off or unsupported instruction */ mathemu(ureg); /* enable fpu & retry */ nfp = 1; } From aa45941b506985fed4999d54df308be52981f943 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 18 Jan 2022 04:46:14 +0000 Subject: [PATCH 083/402] sys/src/cmd/aux/vmware: import aux/vmware sources from github.com/rsc/plan9vmware (thanks Russ Cox ) --- sys/src/cmd/aux/mkfile | 3 +- sys/src/cmd/aux/vmware/all.h | 84 ++++ sys/src/cmd/aux/vmware/asmbackdoor.s | 28 ++ sys/src/cmd/aux/vmware/backdoor.c | 34 ++ sys/src/cmd/aux/vmware/inout.c | 175 +++++++ sys/src/cmd/aux/vmware/isvmware.c | 33 ++ sys/src/cmd/aux/vmware/mkfile | 12 + sys/src/cmd/aux/vmware/msgchan.c | 224 +++++++++ sys/src/cmd/aux/vmware/vmmousepoll.c | 44 ++ sys/src/cmd/aux/vmware/vmwarefs.c | 657 +++++++++++++++++++++++++++ 10 files changed, 1293 insertions(+), 1 deletion(-) create mode 100644 sys/src/cmd/aux/vmware/all.h create mode 100644 sys/src/cmd/aux/vmware/asmbackdoor.s create mode 100644 sys/src/cmd/aux/vmware/backdoor.c create mode 100644 sys/src/cmd/aux/vmware/inout.c create mode 100644 sys/src/cmd/aux/vmware/isvmware.c create mode 100644 sys/src/cmd/aux/vmware/mkfile create mode 100644 sys/src/cmd/aux/vmware/msgchan.c create mode 100644 sys/src/cmd/aux/vmware/vmmousepoll.c create mode 100644 sys/src/cmd/aux/vmware/vmwarefs.c diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index 579666f104..654f1b92c8 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -52,7 +52,8 @@ DIRS=mnihongo\ flashfs\ gps\ na\ - vga + vga\ + vmware all:V: $DIRS diff --git a/sys/src/cmd/aux/vmware/all.h b/sys/src/cmd/aux/vmware/all.h new file mode 100644 index 0000000000..ea77b6e47c --- /dev/null +++ b/sys/src/cmd/aux/vmware/all.h @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +typedef struct Msgchan Msgchan; +typedef struct Ureg Ureg; + +typedef ulong uint32; +typedef int int32; +typedef short int16; +typedef char int8; +typedef uvlong uint64; +typedef vlong int64; +typedef char Bool; + +struct Msgchan +{ + ushort id; + uchar *a; + int na; +}; + +enum +{ + /* low bits of u.cx */ + BackGetmhz = 1, + BackApm = 2, + BackGetdiskgeo = 3, + BackGetptrloc = 4, + BackSetptrloc = 5, + BackGetsellength = 6, + BackGetnextpiece = 7, + BackSetsellength = 8, + BackSetnextpiece = 9, + BackGetversion = 10, + BackGetdevlistel = 11, + BackToggledev = 12, + BackGetguiopt = 13, + BackSetguiopt = 14, + BackGetscreensize = 15, + BackGetpcisvgaen = 16, + BackSetpcisvgaen = 17, + /* 18-20 not used */ + BackHostcopy = 21, + BackGetos2intcurs = 22, + BackGettime = 23, + BackStopcatchup = 24, + BackPutchr = 25, + BackEnablemsg = 26, + BackGototcl = 27, + BackInitscsiprom = 28, + BackInt13 = 29, + BackMessage = 30, + + BackMagic = 0x564D5868, + VersionMagic = 6, + BackPort = 0x5658, + +}; + +void asmbackdoor(Ureg*); +void backdoor(Ureg*, int); +int backdoorbell(void*, char*); +int closemsg(Msgchan*); +int getdeviceinfo(uint, uint, uint*); +Point getmousepoint(void); +int getsnarflength(void); +uint getsnarfpiece(void); +Msgchan* openmsg(ulong); +int recvmsg(Msgchan*, void**); +int sendmsg(Msgchan*, void*, int); +int setdevicestate(uint, int); +void setmousepoint(Point); +void setsnarflength(uint); +void setsnarfpiece(uint); +int getversion(void); +void setguistate(uint); +uint getguistate(void); +uint copystep(uint); +void gettime(uint*, uint*, uint*); +void stopcatchup(void); + +extern jmp_buf backdoorjmp; diff --git a/sys/src/cmd/aux/vmware/asmbackdoor.s b/sys/src/cmd/aux/vmware/asmbackdoor.s new file mode 100644 index 0000000000..9c5e688add --- /dev/null +++ b/sys/src/cmd/aux/vmware/asmbackdoor.s @@ -0,0 +1,28 @@ +TEXT asmbackdoor(SB), $0 + MOVL ureg+0(FP), BP + MOVL 16(BP), BX + MOVL 20(BP), DX + MOVL 24(BP), CX + MOVL 0(BP), AX + ANDL $1, AX + MOVL 28(BP), AX + JNZ out + +in: + INL + JMP done + +out: + OUTL + +done: + MOVL ureg+0(FP), BP + MOVL BX, 16(BP) + MOVL DX, 20(BP) + MOVL CX, 24(BP) + MOVL AX, 28(BP) + + RET + + + diff --git a/sys/src/cmd/aux/vmware/backdoor.c b/sys/src/cmd/aux/vmware/backdoor.c new file mode 100644 index 0000000000..4a904013f4 --- /dev/null +++ b/sys/src/cmd/aux/vmware/backdoor.c @@ -0,0 +1,34 @@ +#include "all.h" + +jmp_buf backdoorjmp; +static int doorerror; + +int +backdoorbell(void *v, char *msg) +{ + uchar *p; + Ureg *u; + + u = v; + p = (uchar*)u->pc; + /* ED is INL and EF is OUTL */ + if((*p==0xED || *p==0xEF) && strstr(msg, "sys: trap: general protection violation")){ + u->pc++; /* hop over INL/OUTL */ + doorerror = 1; + return 1; + } + return 0; +} + +void +backdoor(Ureg *u, int isout) +{ + u->ax = BackMagic; + u->dx &= ~0xFFFF; + u->dx |= BackPort; + u->di = isout; + doorerror = 0; + asmbackdoor(u); + if(doorerror) + longjmp(backdoorjmp, 1); +} diff --git a/sys/src/cmd/aux/vmware/inout.c b/sys/src/cmd/aux/vmware/inout.c new file mode 100644 index 0000000000..663ddf440c --- /dev/null +++ b/sys/src/cmd/aux/vmware/inout.c @@ -0,0 +1,175 @@ +#include "all.h" + +void +setmousepoint(Point p) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackSetptrloc; + u.bx = (p.x<<16) | p.y; + backdoor(&u, 1); +} + +Point +getmousepoint(void) +{ + Point p; + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackGetptrloc; + backdoor(&u, 0); + p.x = (signed)((u.ax>>16)&0xFFFF); + p.y = (signed)(u.ax & 0xFFFF); + return p; +} + +int +getsnarflength(void) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackGetsellength; + backdoor(&u, 0); + return u.ax; +} + +uint +getsnarfpiece(void) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackGetnextpiece; + backdoor(&u, 0); + return u.ax; +} + +void +setsnarflength(uint len) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackSetsellength; + u.bx = len; + backdoor(&u, 1); +} + +void +setsnarfpiece(uint p) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackSetnextpiece; + u.bx = p; + backdoor(&u, 1); +} + +int +getversion(void) +{ + Ureg u; + jmp_buf jb; + + memset(&u, 0, sizeof u); + u.cx = BackGetversion; + memmove(jb, backdoorjmp, sizeof jb); + if(setjmp(backdoorjmp)){ + memmove(backdoorjmp, jb, sizeof jb); + return -1; + } + backdoor(&u, 0); + memmove(backdoorjmp, jb, sizeof jb); + if(u.ax != VersionMagic || u.bx != BackMagic) + return -1; + return 0; +} + +int +setdevicestate(uint id, int enable) +{ + Ureg u; + + if(enable) + id |= 0x80000000; + memset(&u, 0, sizeof u); + u.cx = BackToggledev; + u.bx = id; + backdoor(&u, 0); + return u.ax; +} + +int +getdeviceinfo(uint id, uint offset, uint *p) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.bx = (id<<16) | offset; + u.cx = BackGetdevlistel; + backdoor(&u, 0); + *p = u.bx; + return u.ax; +} + +void +setguistate(uint state) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.bx = state; + u.cx = BackSetguiopt; + backdoor(&u, 1); +} + +uint +getguistate(void) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackGetguiopt; + backdoor(&u, 0); + return u.ax; +} + +uint +copystep(uint x) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackHostcopy; + u.bx = x; + backdoor(&u, 0); + return u.ax; +} + +void +gettime(uint *sec, uint *micro, uint *lag) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackGettime; + backdoor(&u, 0); + + *sec = u.ax; + *micro = u.bx; + *lag = u.cx; +} + +void +stopcatchup(void) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = BackStopcatchup; + backdoor(&u, 0); +} diff --git a/sys/src/cmd/aux/vmware/isvmware.c b/sys/src/cmd/aux/vmware/isvmware.c new file mode 100644 index 0000000000..e6c0fafa43 --- /dev/null +++ b/sys/src/cmd/aux/vmware/isvmware.c @@ -0,0 +1,33 @@ +#include "all.h" + +int statusonly; + +void +usage(void) +{ + fprint(2, "usage: aux/isvmware [-s]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + ARGBEGIN{ + case 's': + statusonly = 1; + break; + default: + usage(); + }ARGEND + + if(argc != 0) + usage(); + + atnotify(backdoorbell, 1); + if(getversion() < 0){ + if(!statusonly) + print("no vmware\n"); + exits("no vmware"); + } + exits(nil); +} diff --git a/sys/src/cmd/aux/vmware/mkfile b/sys/src/cmd/aux/vmware/mkfile new file mode 100644 index 0000000000..0d68fbd05c --- /dev/null +++ b/sys/src/cmd/aux/vmware/mkfile @@ -0,0 +1,12 @@ +objtype=386 + +#include +#include <9p.h> /* for emalloc9p */ + +enum +{ + /* high bits of u.cx */ + CmdOpen = 0x00, + CmdSendsize = 0x01, + CmdSenddata = 0x02, + CmdRecvsize = 0x03, + CmdRecvdata = 0x04, + CmdRecvstatus = 0x05, + CmdClose = 0x06, + + StatSuccess = 0x0001, /* request succeeded */ + StatHavedata = 0x0002, /* vmware has message available */ + StatClosed = 0x0004, /* channel got closed */ + StatUnsent = 0x0008, /* vmware removed message before it got delivered */ + StatChkpt = 0x0010, /* checkpoint occurred */ + StatPoweroff = 0x0020, /* underlying device is powering off */ +}; + + +Msgchan* +openmsg(ulong proto) +{ + Msgchan *c; + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = (CmdOpen<<16) | BackMessage; + u.bx = proto; + + backdoor(&u, 0); + +fprint(2, "msgopen %.8lux\n", u.cx); + if(!(u.cx & (StatSuccess<<16))){ + fprint(2, "message %.8lux\n", u.cx); + werrstr("unable to open message channel (%.8lux)", u.cx); + return nil; + } + + c = emalloc9p(sizeof(*c)); + c->id = u.dx>>16; + return c; +} + +enum +{ + Ok = 0, + ErrBad = -1, + ErrChkpt = -2, +}; + +static int +sendpiece(Msgchan *c, int ty, ulong a) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = (ty<<16) | BackMessage; + u.dx = c->id<<16; + u.bx = a; + + backdoor(&u, 0); + + if(!(u.cx & (StatSuccess<<16))){ +fprint(2, "cmd %x failed\n", ty); + if(u.cx & (StatChkpt<<16)) + return ErrChkpt; + return ErrBad; + } + return 0; +} + +int +sendmsg(Msgchan *c, void *a, int n) +{ + int i, m, e, left; + uchar *p; + ulong v; + +Again: + v = n; + if(sendpiece(c, CmdSendsize, v) < 0) + return -1; + + p = a; + left = n; + while(left > 0){ + m = left; + if(m > 4) + m = 4; + v = 0; + for(i=0; iid, ty); + memset(&u, 0, sizeof u); + u.cx = (ty<<16) | BackMessage; + u.bx = StatSuccess; + u.dx = c->id<<16; + + backdoor(&u, 0); + + if(!(u.cx & (StatSuccess<<16))){ +fprint(2, "no success %lux\n", u.cx); + if(u.cx & (StatChkpt<<16)) + return ErrChkpt; + return ErrBad; + } + *stat = u.cx; + if(ty == CmdRecvsize && !(u.cx&(StatHavedata<<16))){ +fprint(2, "poll got no data\n"); + return 0; + } + + if(ty != CmdRecvstatus && (u.dx>>16) != ty-2){ +fprint(2, "got wrong answer! %lux\n", u.dx); + werrstr("protocol error"); + return ErrBad; + } + *a = u.bx; +fprint(2, "got %lux\n", *a); + return 0; +} + +static void +signalerror(Msgchan *c, int ty) +{ + Ureg u; + + memset(&u, 0, sizeof u); + u.cx = (ty<<16) | BackMessage; + u.dx = c->id<<16; + u.bx = 0; + backdoor(&u, 0); +} + +int +recvmsg(Msgchan *c, void **pp) +{ + int left; + ulong v, stat, tot; + uchar *p; + +Top: + if(recvpiece(c, CmdRecvsize, &stat, &tot) < 0) + return -1; + + if(!(stat & (StatHavedata<<16))) + return 0; + + free(c->a); + c->a = emalloc9p(tot+5); + c->na = tot; + p = c->a; /* NUL terminate for callers */ + + left = tot; + while(left > 0){ + switch(recvpiece(c, CmdRecvdata, &stat, &v)){ + case ErrChkpt: + goto Top; + case ErrBad: + signalerror(c, CmdRecvdata); + return -1; + } + *(uint*)p = v; + p += 4; + left -= 4; + } + ((char*)c->a)[tot] = '\0'; + + switch(recvpiece(c, CmdRecvstatus, &stat, &v)){ + case ErrChkpt: + goto Top; + case ErrBad: + /* BUG: signal receipt of error */ + signalerror(c, CmdRecvstatus); + return -1; + } + + *pp = c->a; + return tot; +} + +int +closemsg(Msgchan *c) +{ + Ureg u; + + memset(&u, 0, sizeof u); + + u.cx = (CmdClose<<16) | BackMessage; + u.dx = c->id; + + backdoor(&u, 0); + + if(!(u.cx & (StatSuccess<<16))){ + werrstr("unable to close message channel"); + return -1; + } + + free(c->a); + c->a = nil; + free(c); + return 0; +} diff --git a/sys/src/cmd/aux/vmware/vmmousepoll.c b/sys/src/cmd/aux/vmware/vmmousepoll.c new file mode 100644 index 0000000000..53dad93a65 --- /dev/null +++ b/sys/src/cmd/aux/vmware/vmmousepoll.c @@ -0,0 +1,44 @@ +#include +#include + +void +usage(void) +{ + fprint(2, "usage: aux/vmmousepoll [/mnt/vmware/mouse]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int fd; + char *file; + char buf[50]; + + quotefmtinstall(); + ARGBEGIN{ + default: + usage(); + }ARGEND + + switch(argc){ + default: + usage(); + case 0: + file = "/mnt/vmware/mouse"; + break; + case 1: + file = argv[0]; + break; + } + + if((fd = open(file, OREAD)) < 0) + sysfatal("open %q: %r", file); + + for(;;){ + sleep(250); + if(pread(fd, buf, sizeof buf, 0) < 0) + break; + } + exits(nil); +} diff --git a/sys/src/cmd/aux/vmware/vmwarefs.c b/sys/src/cmd/aux/vmware/vmwarefs.c new file mode 100644 index 0000000000..e870fb6cfc --- /dev/null +++ b/sys/src/cmd/aux/vmware/vmwarefs.c @@ -0,0 +1,657 @@ +#include "all.h" +#include +#include +#include <9p.h> + +char *mtpt = "/mnt/vmware"; +char *srvname; +uint time0; + +enum +{ + Qroot = 0, + Qmousepoint, + Qsnarf, + Qgui, + Qdev, + Qtime, + Qbintime, + Qmsg, +}; + +typedef struct Tab Tab; +struct Tab +{ + int qid; + char *name; + uint perm; + uint vers; + void (*open)(Req*); + void (*read)(Req*); + void (*write)(Req*); + void (*close)(Fid*); +}; + +static void +mousepointread(Req *r) +{ + char buf[32]; + Point p; + + p = getmousepoint(); + snprint(buf, sizeof buf, "%11d %11d ", p.x, p.y); + readstr(r, buf); + respond(r, nil); +} + +static void +mousepointwrite(Req *r) +{ + char buf[32], *f[3]; + int nf, n; + Point p; + + n = r->ifcall.count; + if(n >= sizeof buf){ + respond(r, "write too large"); + return; + } + memmove(buf, r->ifcall.data, n); + buf[n] = '\0'; + nf = tokenize(buf, f, nelem(f)); + if(nf != 2){ + respond(r, "bad point format"); + return; + } + p.x = atoi(f[0]); + p.y = atoi(f[1]); + setmousepoint(p); + respond(r, nil); +} + +static void +timeread(Req *r) +{ + char buf[32]; + uint sec, microsec, lag; + + gettime(&sec, µsec, &lag); + snprint(buf, sizeof buf, "%11d ", sec); + readstr(r, buf); + respond(r, nil); +} + +static uvlong uvorder = 0x0001020304050607ULL; +static uchar* +vlong2le(uchar *t, vlong from) +{ + uchar *f, *o; + int i; + + f = (uchar*)&from; + o = (uchar*)&uvorder; + for(i = 0; i < sizeof(vlong); i++) + t[i] = f[o[i]]; + return t+sizeof(vlong); +} + +static void +bintimeread(Req *r) +{ + uchar *b; + int i, n; + uint sec, microsec, lag; + vlong nsec; + + b = (uchar*)r->ofcall.data; + n = r->ifcall.count; + + i = 0; + if(n >= 8){ + gettime(&sec, µsec, &lag); + nsec = sec*1000000000LL+microsec*1000LL; + vlong2le(b, nsec); + i = 8; + } + if(n >= 16){ + vlong2le(b+8, nsec); + i = 16; + } + if(n >= 24){ + vlong2le(b+16, 1000000000LL); + i = 24; + } + r->ofcall.count = i; + respond(r, nil); +} + +char *snarf; +int nsnarf; +char *tsnarf; +int ntsnarf; + +static void +snarfread(Req *r) +{ + int i; + + if(r->ifcall.offset == 0){ + if(snarf) + free(snarf); + nsnarf = getsnarflength(); + snarf = emalloc9p(nsnarf+4+1); + for(i=0; iifcall.offset == 0){ + free(tsnarf); + tsnarf = nil; + ntsnarf = 0; + } + if(r->ifcall.offset > 100*1024){ + respond(r, "snarf buffer too long"); + return; + } + tsnarf = erealloc9p(tsnarf, ntsnarf+r->ifcall.count); + memmove(tsnarf+ntsnarf, r->ifcall.data, r->ifcall.count); + ntsnarf += r->ifcall.count; + r->ofcall.count = r->ifcall.count; + respond(r, nil); +} + +static void +snarfclose(Fid *fid) +{ + int i, n; + + if((fid->omode&3) == OREAD) + return; + + // read old snarf - dunno why but it helps + n = getsnarflength(); + for(i=0; iifcall.data, r->ifcall.count); + if(cb->nf != 2){ + respondcmderror(r, cb, "bad gui ctl"); + free(cb); + return; + } + + if(strcmp(cb->f[1], "off")==0) + on = 0; + else if(strcmp(cb->f[1], "on") == 0) + on = 1; + else{ + respondcmderror(r, cb, "bad gui ctl"); + free(cb); + return; + } + + for(i=0; if[0]) == 0) + goto Have; + respondcmderror(r, cb, "bad gui ctl"); + free(cb); + return; + +Have: + v = getguistate(); + if(on) + v |= guibit[i].bit; + else + v &= ~guibit[i].bit; + setguistate(v); + r->ofcall.count = r->ifcall.count; + free(cb); + respond(r, nil); +} + +typedef struct Info Info; +struct Info +{ + char name[32]; + uint uid; + uint enabled; +}; +static int +getinfo(uint id, Info *p) +{ + uint i; + + for(i=0; ifid->aux; + if(c == nil){ + respond(r, "message channel not open"); + return; + } + + if(r->ifcall.offset == 0){ + if(recvmsg(c, &s) < 0){ + respond(r, "no messages waiting"); + return; + } + } + if(c->a == nil){ + respond(r, "no messages waiting"); + return; + } + readbuf(r, c->a, c->na); + respond(r, nil); +} + +static void +fsmsgwrite(Req *r) +{ + char buf[32], *p; + int n; + Msgchan *c; + + if(r->ifcall.offset != 0){ + respond(r, "must write at offset zero"); + return; + } + + r->ofcall.count = r->ifcall.count; + c = r->fid->aux; + if(c == nil){ + if(r->ifcall.count >= sizeof buf){ + respond(r, "bad message channel number"); + return; + } + memmove(buf, r->ifcall.data, r->ifcall.count); + buf[r->ifcall.count] = 0; + p = buf; + n = strtol(buf, &p, 0); + if(p == buf){ + respond(r, "bad message channel number"); + return; + } + c = openmsg(n); + if(c == nil){ + respond(r, "could not open message channel"); + return; + } + r->fid->aux = c; + respond(r, nil); + return; + } + + if(sendmsg(c, r->ifcall.data, r->ifcall.count) < 0){ + respond(r, "could not send message"); + return; + } + respond(r, nil); +} + +static void +fsmsgclose(Fid *fid) +{ + Msgchan *c; + + c = fid->aux; + if(c) + closemsg(c); +} + +Tab tab[] = { + Qmousepoint, "mouse", 0666, 0, nil, mousepointread, mousepointwrite, nil, + Qsnarf, "snarf", 0666, 0, nil, snarfread, snarfwrite, snarfclose, + Qgui, "gui", 0666, 0, nil, guiread, guiwrite, nil, + Qdev, "dev", 0444, 0, nil, devread, nil, nil, + Qtime, "time", 0444, 0, nil, timeread, nil, nil, + Qbintime, "bintime", 0444, 0, nil, bintimeread, nil, nil, + Qmsg, "msg", 0666, 0, nil, fsmsgread, fsmsgwrite, fsmsgclose, +}; + +void +fsattach(Req *r) +{ + char *spec; + + spec = r->ifcall.aname; + if(spec && spec[0]){ + respond(r, "invalid attach specifier"); + return; + } + r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; + r->fid->qid = r->ofcall.qid; + respond(r, nil); +} + +char* +fswalk1(Fid *fid, char *name, Qid *qid) +{ + int i; + + switch((int)fid->qid.path){ + case Qroot: + for(i=0; iqid.path = tab[i].qid; + fid->qid.type = tab[i].perm>>24;; + fid->qid.vers = tab[i].vers; + *qid = fid->qid; + return nil; + } + } + break; + } + + return "file not found"; +} + +void +fsstat(Req *r) +{ + int i, q; + Dir *d; + + d = &r->d; + memset(d, 0, sizeof *d); + q = r->fid->qid.path; + d->qid = r->fid->qid; + switch(q){ + case Qroot: + d->name = estrdup9p("/"); + d->mode = DMDIR|0777; + break; + + default: + for(i=0; iqid.vers = tab[i].vers; + d->qid.type = tab[i].perm>>24; + d->mode = tab[i].perm; + goto Out; + } + } + respond(r, "file not found"); + } + +Out: + d->atime = d->mtime = time0; + d->uid = estrdup9p("vmware"); + d->gid = estrdup9p("vmware"); + d->muid = estrdup9p(""); + respond(r, nil); +} + +int +dirgen(int off, Dir *d, void*) +{ + if(off >= nelem(tab)) + return -1; + + memset(d, 0, sizeof *d); + d->atime = d->mtime = time0; + d->name = estrdup9p(tab[off].name); + d->mode = tab[off].perm; + d->qid.path = tab[off].qid; + d->qid.vers = tab[off].vers; + d->qid.type = d->mode>>24; + d->uid = estrdup9p("vmware"); + d->gid = estrdup9p("vmware"); + d->muid = estrdup9p(""); + return 0; +} + +void +fsread(Req *r) +{ + int i, q; + + q = r->fid->qid.path; + switch(q){ + case Qroot: + dirread9p(r, dirgen, nil); + respond(r, nil); + return; + + default: + for(i=0; ifid->qid.path; + for(i=0; ifid->qid.path; + for(i=0; iifcall.mode&3){ + case OREAD: + if(!(tab[i].perm&0400)) + goto Eperm; + break; + case OWRITE: + if(!(tab[i].perm&0200)) + goto Eperm; + break; + case ORDWR: + if((tab[i].perm&0600) != 0600) + goto Eperm; + break; + case OEXEC: + Eperm: + respond(r, "permission denied"); + return; + } + if(tab[i].open) + tab[i].open(r); + else + respond(r, nil); + return; + } + + /* directory */ + if(r->ifcall.mode != OREAD) + respond(r, "permission denied"); + else + respond(r, nil); +} + +void +fsdestroyfid(Fid *fid) +{ + int i, q; + + q = fid->qid.path; + for(i=0; i Date: Fri, 19 Feb 2016 18:50:33 +0000 Subject: [PATCH 084/402] sys/src/9/pc: implement PCI capabilities (thanks Erik Quanstrom) --- sys/src/9/pc/etherm10g.c | 40 ---------------------------- sys/src/9/pc/fns.h | 1 + sys/src/9/pc/io.h | 17 ++++++++++++ sys/src/9/pc/pci.c | 56 +++++++++++++++------------------------- 4 files changed, 39 insertions(+), 75 deletions(-) diff --git a/sys/src/9/pc/etherm10g.c b/sys/src/9/pc/etherm10g.c index ab60e696ea..178b3dd3c2 100644 --- a/sys/src/9/pc/etherm10g.c +++ b/sys/src/9/pc/etherm10g.c @@ -238,21 +238,6 @@ typedef struct Ctlr { static Ctlr *ctlrs; -enum { - PciCapPMG = 0x01, /* power management */ - PciCapAGP = 0x02, - PciCapVPD = 0x03, /* vital product data */ - PciCapSID = 0x04, /* slot id */ - PciCapMSI = 0x05, - PciCapCHS = 0x06, /* compact pci hot swap */ - PciCapPCIX = 0x07, - PciCapHTC = 0x08, /* hypertransport irq conf */ - PciCapVND = 0x09, /* vendor specific information */ - PciCapHSW = 0x0C, /* hot swap */ - PciCapPCIe = 0x10, - PciCapMSIX = 0x11, -}; - enum { PcieAERC = 1, PcieVC, @@ -270,31 +255,6 @@ enum { PcieMRD = 0x7000, /* maximum read size */ }; -static int -pcicap(Pcidev *p, int cap) -{ - int i, c, off; - - pcicapdbg("pcicap: %x:%d\n", p->vid, p->did); - off = 0x34; /* 0x14 for cardbus */ - for(i = 48; i--; ){ - pcicapdbg("\t" "loop %x\n", off); - off = pcicfgr8(p, off); - pcicapdbg("\t" "pcicfgr8 %x\n", off); - if(off < 0x40) - break; - off &= ~3; - c = pcicfgr8(p, off); - pcicapdbg("\t" "pcicfgr8 %x\n", c); - if(c == 0xff) - break; - if(c == cap) - return off; - off++; - } - return 0; -} - /* * this function doesn't work because pcicgr32 doesn't have access * to the pcie extended configuration space. diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index a79d4d894a..8d873f2ac4 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -121,6 +121,7 @@ void outsl(int, void*, int); ulong paddr(void*); ulong pcibarsize(Pcidev*, int); void pcibussize(Pcidev*, ulong*, ulong*); +int pcicap(Pcidev*, int); int pcicfgr8(Pcidev*, int); int pcicfgr16(Pcidev*, int); int pcicfgr32(Pcidev*, int); diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h index 13a55e1746..0b85d09f96 100644 --- a/sys/src/9/pc/io.h +++ b/sys/src/9/pc/io.h @@ -214,6 +214,23 @@ enum { /* type 2 pre-defined header */ PciCBLMBAR = 0x44, /* legacy mode base address */ }; +/* capabilities */ +enum { + PciCapPMG = 0x01, /* power management */ + PciCapAGP = 0x02, + PciCapVPD = 0x03, /* vital product data */ + PciCapSID = 0x04, /* slot id */ + PciCapMSI = 0x05, + PciCapCHS = 0x06, /* compact pci hot swap */ + PciCapPCIX = 0x07, + PciCapHTC = 0x08, /* hypertransport irq conf */ + PciCapVND = 0x09, /* vendor specific information */ + PciCapPCIe = 0x10, + PciCapMSIX = 0x11, + PciCapSATA = 0x12, + PciCapHSW = 0x0c, /* hot swap */ +}; + typedef struct Pcisiz Pcisiz; struct Pcisiz { diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index afee0f12ef..bb35c357c4 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -1404,50 +1404,36 @@ pciclrmwi(Pcidev* p) pcicfgw16(p, PciPCR, p->pcr); } -static int -pcigetpmrb(Pcidev* p) +int +pcicap(Pcidev* p, int cap) { - int ptr; + int i, c, off; - if(p->pmrb != 0) - return p->pmrb; - p->pmrb = -1; - - /* - * If there are no extended capabilities implemented, - * (bit 4 in the status register) assume there's no standard - * power management method. - * Find the capabilities pointer based on PCI header type. - */ - if(!(pcicfgr16(p, PciPSR) & 0x0010)) + /* status register bit 4 has capabilities */ + if((pcicfgr16(p, PciPSR) & 1<<4) == 0) return -1; - switch(pcicfgr8(p, PciHDT)){ + switch(pcicfgr8(p, PciHDT) & 0x7f){ default: return -1; case 0: /* all other */ case 1: /* PCI to PCI bridge */ - ptr = 0x34; + off = 0x34; break; case 2: /* CardBus bridge */ - ptr = 0x14; + off = 0x14; break; } - ptr = pcicfgr32(p, ptr); - - while(ptr != 0){ - /* - * Check for validity. - * Can't be in standard header and must be double - * word aligned. - */ - if(ptr < 0x40 || (ptr & ~0xFC)) - return -1; - if(pcicfgr8(p, ptr) == 0x01){ - p->pmrb = ptr; - return ptr; - } - - ptr = pcicfgr8(p, ptr+1); + for(i = 48; i--;){ + off = pcicfgr8(p, off); + if(off < 0x40 || (off & 3)) + break; + off &= ~3; + c = pcicfgr8(p, off); + if(c == 0xff) + break; + if(c == cap) + return off; + off++; } return -1; @@ -1458,7 +1444,7 @@ pcigetpms(Pcidev* p) { int pmcsr, ptr; - if((ptr = pcigetpmrb(p)) == -1) + if((ptr = pcicap(p, PciCapPMG)) == -1) return -1; /* @@ -1480,7 +1466,7 @@ pcisetpms(Pcidev* p, int state) { int ostate, pmc, pmcsr, ptr; - if((ptr = pcigetpmrb(p)) == -1) + if((ptr = pcicap(p, PciCapPMG)) == -1) return -1; pmc = pcicfgr16(p, ptr+2); From 326aace726dad10a0a9c5b752fcc8209160520c3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 16:17:04 +0000 Subject: [PATCH 085/402] sys/src/9/pc: implement custom PCI capabilities enumeration (thanks Cinap Lenrek) --- sys/src/9/pc/fns.h | 2 ++ sys/src/9/pc/pci.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 8d873f2ac4..d0c550d8ea 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -122,6 +122,8 @@ ulong paddr(void*); ulong pcibarsize(Pcidev*, int); void pcibussize(Pcidev*, ulong*, ulong*); int pcicap(Pcidev*, int); +int pcihtcap(Pcidev*, int); +int pcienumcaps(Pcidev*, int (*fmatch)(Pcidev*, int, int, int), int); int pcicfgr8(Pcidev*, int); int pcicfgr16(Pcidev*, int); int pcicfgr32(Pcidev*, int); diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index bb35c357c4..9b5d70a876 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -1405,9 +1405,9 @@ pciclrmwi(Pcidev* p) } int -pcicap(Pcidev* p, int cap) +pcienumcaps(Pcidev* p, int (*fmatch)(Pcidev*, int, int, int), int arg) { - int i, c, off; + int i, r, cap, off; /* status register bit 4 has capabilities */ if((pcicfgr16(p, PciPSR) & 1<<4) == 0) @@ -1428,10 +1428,13 @@ pcicap(Pcidev* p, int cap) if(off < 0x40 || (off & 3)) break; off &= ~3; - c = pcicfgr8(p, off); - if(c == 0xff) + cap = pcicfgr8(p, off); + if(cap == 0xff) + break; + r = (*fmatch)(p, cap, off, arg); + if(r < 0) break; - if(c == cap) + if(r == 0) return off; off++; } @@ -1439,6 +1442,39 @@ pcicap(Pcidev* p, int cap) return -1; } +static int +matchcap(Pcidev*, int cap, int, int arg) +{ + return cap != arg; +} + +static int +matchhtcap(Pcidev* p, int cap, int off, int arg) +{ + int mask; + + if(cap != PciCapHTC) + return 1; + if(arg == 0x00 || arg == 0x20) + mask = 0xE0; + else + mask = 0xF8; + cap = pcicfgr8(p, off+3); + return (cap & mask) != arg; +} + +int +pcicap(Pcidev* p, int cap) +{ + return pcienumcaps(p, matchcap, cap); +} + +int +pcihtcap(Pcidev* p, int cap) +{ + return pcienumcaps(p, matchhtcap, cap); +} + int pcigetpms(Pcidev* p) { From e72facd16a04537b19671bab2d99e0d23cec33fe Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 17 Apr 2017 16:36:02 +0000 Subject: [PATCH 086/402] sys/src/9/pc: add etheriwl, etherrt2860 and etherwpi Wi-Fi drivers (thanks Cinap Lenrek) --- sys/src/9/pc/etheriwl.c | 2549 ++++++++++++++++++++++++++ sys/src/9/pc/etherrt2860.c | 3566 ++++++++++++++++++++++++++++++++++++ sys/src/9/pc/etherwpi.c | 1861 +++++++++++++++++++ sys/src/9/pc/wifi.c | 1690 +++++++++++++++++ sys/src/9/pc/wifi.h | 99 + 5 files changed, 9765 insertions(+) create mode 100644 sys/src/9/pc/etheriwl.c create mode 100644 sys/src/9/pc/etherrt2860.c create mode 100644 sys/src/9/pc/etherwpi.c create mode 100644 sys/src/9/pc/wifi.c create mode 100644 sys/src/9/pc/wifi.h diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c new file mode 100644 index 0000000000..f73318402b --- /dev/null +++ b/sys/src/9/pc/etheriwl.c @@ -0,0 +1,2549 @@ +/* + * Intel WiFi Link driver. + * + * Written without any documentation but Damien Bergaminis + * OpenBSD iwn(4) driver sources. Requires intel firmware + * to be present in /lib/firmware/iwn-* on attach. + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "wifi.h" + +enum { + Ntxlog = 8, + Ntx = 1<nic+((r)/4))) +#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) + +static uint +get16(uchar *p){ + return *((u16int*)p); +} +static uint +get32(uchar *p){ + return *((u32int*)p); +} +static void +put32(uchar *p, uint v){ + *((u32int*)p) = v; +} +static void +put16(uchar *p, uint v){ + *((u16int*)p) = v; +}; + +static char* +niclock(Ctlr *ctlr) +{ + int i; + + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq); + for(i=0; i<1000; i++){ + if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna) + return 0; + delay(10); + } + return "niclock: timeout"; +} + +static void +nicunlock(Ctlr *ctlr) +{ + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq); +} + +static u32int +prphread(Ctlr *ctlr, uint off) +{ + csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off); + coherence(); + return csr32r(ctlr, PrphRdata); +} +static void +prphwrite(Ctlr *ctlr, uint off, u32int data) +{ + csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off); + coherence(); + csr32w(ctlr, PrphWdata, data); +} + +static u32int +memread(Ctlr *ctlr, uint off) +{ + csr32w(ctlr, MemRaddr, off); + coherence(); + return csr32r(ctlr, MemRdata); +} +static void +memwrite(Ctlr *ctlr, uint off, u32int data) +{ + csr32w(ctlr, MemWaddr, off); + coherence(); + csr32w(ctlr, MemWdata, data); +} + +static void +setfwinfo(Ctlr *ctlr, uchar *d, int len) +{ + FWInfo *i; + + if(len < 32) + return; + i = &ctlr->fwinfo; + i->minjor = *d++; + i->major = *d++; + d += 2+8; + i->type = *d++; + i->subtype = *d++; + d += 2; + i->logptr = get32(d); d += 4; + i->errptr = get32(d); d += 4; + i->tstamp = get32(d); d += 4; + i->valid = get32(d); +}; + +static void +dumpctlr(Ctlr *ctlr) +{ + u32int dump[13]; + int i; + + print("lastcmd: %ud (0x%ux)\n", ctlr->tx[4].lastcmd, ctlr->tx[4].lastcmd); + if(ctlr->fwinfo.errptr == 0){ + print("no error pointer\n"); + return; + } + for(i=0; ifwinfo.errptr + i*4); + print( "error:\tid %ux, pc %ux,\n" + "\tbranchlink %.8ux %.8ux, interruptlink %.8ux %.8ux,\n" + "\terrordata %.8ux %.8ux, srcline %ud, tsf %ux, time %ux\n", + dump[1], dump[2], + dump[4], dump[3], dump[6], dump[5], + dump[7], dump[8], dump[9], dump[10], dump[11]); +} + +static char* +eepromlock(Ctlr *ctlr) +{ + int i, j; + + for(i=0; i<100; i++){ + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | EepromLocked); + for(j=0; j<100; j++){ + if(csr32r(ctlr, Cfg) & EepromLocked) + return 0; + delay(10); + } + } + return "eepromlock: timeout"; +} +static void +eepromunlock(Ctlr *ctlr) +{ + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~EepromLocked); +} +static char* +eepromread(Ctlr *ctlr, void *data, int count, uint off) +{ + uchar *out = data; + u32int w, s; + int i; + + w = 0; + off += ctlr->eeprom.off; + for(; count > 0; count -= 2, off++){ + csr32w(ctlr, EepromIo, off << 2); + for(i=0; i<10; i++){ + w = csr32r(ctlr, EepromIo); + if(w & 1) + break; + delay(5); + } + if(i == 10) + return "eepromread: timeout"; + if(ctlr->eeprom.otp){ + s = csr32r(ctlr, OtpromGp); + if(s & EccUncorrStts) + return "eepromread: otprom ecc error"; + if(s & EccCorrStts) + csr32w(ctlr, OtpromGp, s); + } + *out++ = w >> 16; + if(count > 1) + *out++ = w >> 24; + } + return 0; +} + +static char* +handover(Ctlr *ctlr) +{ + int i; + + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady); + for(i=0; i<5; i++){ + if(csr32r(ctlr, Cfg) & NicReady) + return 0; + delay(10); + } + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare); + for(i=0; i<15000; i++){ + if((csr32r(ctlr, Cfg) & PrepareDone) == 0) + break; + delay(10); + } + if(i >= 15000) + return "handover: timeout"; + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady); + for(i=0; i<5; i++){ + if(csr32r(ctlr, Cfg) & NicReady) + return 0; + delay(10); + } + return "handover: timeout"; +} + +static char* +clockwait(Ctlr *ctlr) +{ + int i; + + /* Set "initialization complete" bit. */ + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone); + for(i=0; i<2500; i++){ + if(csr32r(ctlr, Gpc) & MacClockReady) + return 0; + delay(10); + } + return "clockwait: timeout"; +} + +static char* +poweron(Ctlr *ctlr) +{ + int capoff; + char *err; + + /* Disable L0s exit timer (NMI bug workaround). */ + csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | DisL0Stimer); + + /* Don't wait for ICH L0s (ICH bug workaround). */ + csr32w(ctlr, Giochicken, csr32r(ctlr, Giochicken) | L1AnoL0Srx); + + /* Set FH wait threshold to max (HW bug under stress workaround). */ + csr32w(ctlr, Dbghpetmem, csr32r(ctlr, Dbghpetmem) | 0xffff0000); + + /* Enable HAP INTA to move adapter from L1a to L0s. */ + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | HapwakeL1A); + + capoff = pcicap(ctlr->pdev, PciCapPCIe); + if(capoff != -1){ + /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */ + if(pcicfgr16(ctlr->pdev, capoff + 0x10) & 0x2) /* LCSR -> L1 Entry enabled. */ + csr32w(ctlr, Gio, csr32r(ctlr, Gio) | EnaL0S); + else + csr32w(ctlr, Gio, csr32r(ctlr, Gio) & ~EnaL0S); + } + + if(ctlr->type != Type4965 && ctlr->type <= Type1000) + csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | 0x00880300); + + /* Wait for clock stabilization before accessing prph. */ + if((err = clockwait(ctlr)) != nil) + return err; + + if((err = niclock(ctlr)) != nil) + return err; + + /* Enable DMA and BSM (Bootstrap State Machine). */ + if(ctlr->type == Type4965) + prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt); + else + prphwrite(ctlr, ApmgClkEna, DmaClkRqt); + delay(20); + + /* Disable L1-Active. */ + prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11)); + + nicunlock(ctlr); + + ctlr->power = 1; + + return 0; +} + +static void +poweroff(Ctlr *ctlr) +{ + int i, j; + + csr32w(ctlr, Reset, 1); + + /* Disable interrupts */ + ctlr->ie = 0; + csr32w(ctlr, Imr, 0); + csr32w(ctlr, Isr, ~0); + csr32w(ctlr, FhIsr, ~0); + + /* Stop scheduler */ + if(ctlr->type != Type4965) + prphwrite(ctlr, SchedTxFact5000, 0); + else + prphwrite(ctlr, SchedTxFact4965, 0); + + /* Stop TX ring */ + if(niclock(ctlr) == nil){ + for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--){ + csr32w(ctlr, FhTxConfig + i*32, 0); + for(j = 0; j < 200; j++){ + if(csr32r(ctlr, FhTxStatus) & (0x10000<power = 0; +} + +static char* +rominit(Ctlr *ctlr) +{ + uint prev, last; + uchar buf[2]; + char *err; + int i; + + ctlr->eeprom.otp = 0; + ctlr->eeprom.off = 0; + if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0) + return nil; + + /* Wait for clock stabilization before accessing prph. */ + if((err = clockwait(ctlr)) != nil) + return err; + + if((err = niclock(ctlr)) != nil) + return err; + prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq); + delay(5); + prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq); + nicunlock(ctlr); + + /* Set auto clock gate disable bit for HW with OTP shadow RAM. */ + if(ctlr->type != Type1000) + csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31)); + + csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180); + + /* Clear ECC status. */ + csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts)); + + ctlr->eeprom.otp = 1; + if(ctlr->type != Type1000) + return nil; + + /* Switch to absolute addressing mode. */ + csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess); + + /* + * Find the block before last block (contains the EEPROM image) + * for HW without OTP shadow RAM. + */ + prev = last = 0; + for(i=0; i<3; i++){ + if((err = eepromread(ctlr, buf, 2, last)) != nil) + return err; + if(get16(buf) == 0) + break; + prev = last; + last = get16(buf); + } + if(i == 0 || i >= 3) + return "rominit: missing eeprom image"; + + ctlr->eeprom.off = prev+1; + return nil; +} + +static int +iwlinit(Ether *edev) +{ + Ctlr *ctlr; + char *err; + uchar b[4]; + uint u, caloff, regoff; + + ctlr = edev->ctlr; + if((err = handover(ctlr)) != nil) + goto Err; + if((err = poweron(ctlr)) != nil) + goto Err; + if((csr32r(ctlr, EepromGp) & 0x7) == 0){ + err = "bad rom signature"; + goto Err; + } + if((err = eepromlock(ctlr)) != nil) + goto Err; + if((err = rominit(ctlr)) != nil) + goto Err2; + if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){ + eepromunlock(ctlr); + goto Err; + } + if((err = eepromread(ctlr, b, 2, 0x048)) != nil){ + Err2: + eepromunlock(ctlr); + goto Err; + } + u = get16(b); + ctlr->rfcfg.type = u & 3; u >>= 2; + ctlr->rfcfg.step = u & 3; u >>= 2; + ctlr->rfcfg.dash = u & 3; u >>= 4; + ctlr->rfcfg.txantmask = u & 15; u >>= 4; + ctlr->rfcfg.rxantmask = u & 15; + if((err = eepromread(ctlr, b, 2, 0x66)) != nil) + goto Err2; + regoff = get16(b); + if((err = eepromread(ctlr, b, 4, regoff+1)) != nil) + goto Err2; + strncpy(ctlr->eeprom.regdom, (char*)b, 4); + ctlr->eeprom.regdom[4] = 0; + if((err = eepromread(ctlr, b, 2, 0x67)) != nil) + goto Err2; + caloff = get16(b); + if((err = eepromread(ctlr, b, 4, caloff)) != nil) + goto Err2; + ctlr->eeprom.version = b[0]; + ctlr->eeprom.type = b[1]; + ctlr->eeprom.volt = get16(b+2); + + ctlr->eeprom.temp = 0; + ctlr->eeprom.rawtemp = 0; + if(ctlr->type == Type2030){ + if((err = eepromread(ctlr, b, 2, caloff + 0x12a)) != nil) + goto Err2; + ctlr->eeprom.temp = get16(b); + if((err = eepromread(ctlr, b, 2, caloff + 0x12b)) != nil) + goto Err2; + ctlr->eeprom.rawtemp = get16(b); + } + + if(ctlr->type != Type4965 && ctlr->type != Type5150){ + if((err = eepromread(ctlr, b, 4, caloff + 0x128)) != nil) + goto Err2; + ctlr->eeprom.crystal = get32(b); + } + eepromunlock(ctlr); + + switch(ctlr->type){ + case Type4965: + ctlr->rfcfg.txantmask = 3; + ctlr->rfcfg.rxantmask = 7; + break; + case Type5100: + ctlr->rfcfg.txantmask = 2; + ctlr->rfcfg.rxantmask = 3; + break; + case Type6000: + if(ctlr->pdev->did == 0x422c || ctlr->pdev->did == 0x4230){ + ctlr->rfcfg.txantmask = 6; + ctlr->rfcfg.rxantmask = 6; + } + break; + } + poweroff(ctlr); + return 0; +Err: + print("iwlinit: %s\n", err); + poweroff(ctlr); + return -1; +} + +static char* +crackfw(FWImage *i, uchar *data, uint size, int alt) +{ + uchar *p, *e; + FWSect *s; + + memset(i, 0, sizeof(*i)); + if(size < 4){ +Tooshort: + return "firmware image too short"; + } + p = data; + e = p + size; + i->rev = get32(p); p += 4; + if(i->rev == 0){ + uvlong altmask; + + if(size < (4+64+4+4+8)) + goto Tooshort; + if(memcmp(p, "IWL\n", 4) != 0) + return "bad firmware signature"; + p += 4; + strncpy(i->descr, (char*)p, 64); + i->descr[64] = 0; + p += 64; + i->rev = get32(p); p += 4; + i->build = get32(p); p += 4; + altmask = get32(p); p += 4; + altmask |= (uvlong)get32(p) << 32; p += 4; + while(alt > 0 && (altmask & (1ULL< e) + goto Tooshort; + switch(get16(p)){ + case 1: s = &i->main.text; break; + case 2: s = &i->main.data; break; + case 3: s = &i->init.text; break; + case 4: s = &i->init.data; break; + case 5: s = &i->boot.text; break; + default:s = &dummy; + } + p += 2; + if(get16(p) != 0 && get16(p) != alt) + s = &dummy; + p += 2; + s->size = get32(p); p += 4; + s->data = p; + if((p + s->size) > e) + goto Tooshort; + p += (s->size + 3) & ~3; + } + } else { + if(((i->rev>>8) & 0xFF) < 2) + return "need firmware api >= 2"; + if(((i->rev>>8) & 0xFF) >= 3){ + i->build = get32(p); p += 4; + } + if((p + 5*4) > e) + goto Tooshort; + i->main.text.size = get32(p); p += 4; + i->main.data.size = get32(p); p += 4; + i->init.text.size = get32(p); p += 4; + i->init.data.size = get32(p); p += 4; + i->boot.text.size = get32(p); p += 4; + i->main.text.data = p; p += i->main.text.size; + i->main.data.data = p; p += i->main.data.size; + i->init.text.data = p; p += i->init.text.size; + i->init.data.data = p; p += i->init.data.size; + i->boot.text.data = p; p += i->boot.text.size; + if(p > e) + goto Tooshort; + } + return 0; +} + +static FWImage* +readfirmware(char *name) +{ + uchar dirbuf[sizeof(Dir)+100], *data; + char buf[128], *err; + FWImage *fw; + int n, r; + Chan *c; + Dir d; + + if(!iseve()) + error(Eperm); + if(!waserror()){ + snprint(buf, sizeof buf, "/boot/%s", name); + c = namec(buf, Aopen, OREAD, 0); + poperror(); + } else { + snprint(buf, sizeof buf, "/lib/firmware/%s", name); + c = namec(buf, Aopen, OREAD, 0); + } + if(waserror()){ + cclose(c); + nexterror(); + } + n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf); + if(n <= 0) + error("can't stat firmware"); + convM2D(dirbuf, n, &d, nil); + fw = smalloc(sizeof(*fw) + 16 + d.length); + data = (uchar*)(fw+1); + if(waserror()){ + free(fw); + nexterror(); + } + r = 0; + while(r < d.length){ + n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r); + if(n <= 0) + break; + r += n; + } + if((err = crackfw(fw, data, r, 1)) != nil) + error(err); + poperror(); + poperror(); + cclose(c); + return fw; +} + + +static int +gotirq(void *arg) +{ + Ctlr *ctlr = arg; + return (ctlr->wait.m & ctlr->wait.w) != 0; +} + +static u32int +irqwait(Ctlr *ctlr, u32int mask, int timeout) +{ + u32int r; + + ilock(ctlr); + r = ctlr->wait.m & mask; + if(r == 0){ + ctlr->wait.w = mask; + iunlock(ctlr); + if(!waserror()){ + tsleep(&ctlr->wait, gotirq, ctlr, timeout); + poperror(); + } + ilock(ctlr); + ctlr->wait.w = 0; + r = ctlr->wait.m & mask; + } + ctlr->wait.m &= ~r; + iunlock(ctlr); + return r; +} + +static int +rbplant(Ctlr *ctlr, int i) +{ + Block *b; + + b = iallocb(Rbufsize + 256); + if(b == nil) + return -1; + b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256); + memset(b->rp, 0, Rdscsize); + ctlr->rx.b[i] = b; + ctlr->rx.p[i] = PCIWADDR(b->rp) >> 8; + return 0; +} + +static char* +initring(Ctlr *ctlr) +{ + RXQ *rx; + TXQ *tx; + int i, q; + + rx = &ctlr->rx; + if(rx->b == nil) + rx->b = malloc(sizeof(Block*) * Nrx); + if(rx->p == nil) + rx->p = mallocalign(sizeof(u32int) * Nrx, 256, 0, 0); + if(rx->s == nil) + rx->s = mallocalign(Rstatsize, 16, 0, 0); + if(rx->b == nil || rx->p == nil || rx->s == nil) + return "no memory for rx ring"; + memset(ctlr->rx.s, 0, Rstatsize); + for(i=0; ip[i] = 0; + if(rx->b[i] != nil){ + freeb(rx->b[i]); + rx->b[i] = nil; + } + if(rbplant(ctlr, i) < 0) + return "no memory for rx descriptors"; + } + rx->i = 0; + + if(ctlr->sched.s == nil) + ctlr->sched.s = mallocalign(512 * nelem(ctlr->tx) * 2, 1024, 0, 0); + if(ctlr->sched.s == nil) + return "no memory for sched buffer"; + memset(ctlr->sched.s, 0, 512 * nelem(ctlr->tx)); + + for(q=0; qtx); q++){ + tx = &ctlr->tx[q]; + if(tx->b == nil) + tx->b = malloc(sizeof(Block*) * Ntx); + if(tx->d == nil) + tx->d = mallocalign(Tdscsize * Ntx, 256, 0, 0); + if(tx->c == nil) + tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0); + if(tx->b == nil || tx->d == nil || tx->c == nil) + return "no memory for tx ring"; + memset(tx->d, 0, Tdscsize * Ntx); + memset(tx->c, 0, Tcmdsize * Ntx); + for(i=0; ib[i] != nil){ + freeb(tx->b[i]); + tx->b[i] = nil; + } + } + tx->i = 0; + tx->n = 0; + tx->lastcmd = 0; + } + + if(ctlr->kwpage == nil) + ctlr->kwpage = mallocalign(4096, 4096, 0, 0); + if(ctlr->kwpage == nil) + return "no memory for kwpage"; + memset(ctlr->kwpage, 0, 4096); + + return nil; +} + +static char* +reset(Ctlr *ctlr) +{ + char *err; + int i, q; + + if(ctlr->power) + poweroff(ctlr); + if((err = initring(ctlr)) != nil) + return err; + if((err = poweron(ctlr)) != nil) + return err; + + if((err = niclock(ctlr)) != nil) + return err; + prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain); + nicunlock(ctlr); + + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RadioSi | MacSi); + + if((err = niclock(ctlr)) != nil) + return err; + if(ctlr->type != Type4965) + prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | EarlyPwroffDis); + if(ctlr->type == Type1000){ + /* + * Select first Switching Voltage Regulator (1.32V) to + * solve a stability issue related to noisy DC2DC line + * in the silicon of 1000 Series. + */ + prphwrite(ctlr, ApmgDigitalSvr, + (prphread(ctlr, ApmgDigitalSvr) & ~(0xf<<5)) | (3<<5)); + } + nicunlock(ctlr); + + if((err = niclock(ctlr)) != nil) + return err; + if((ctlr->type == Type6005 || ctlr->type == Type6050) && ctlr->eeprom.version == 6) + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvCalV6); + if(ctlr->type == Type6005) + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrv1X2); + if(ctlr->type == Type2030) + csr32w(ctlr, GpDrv, csr32r(ctlr, GpDrv) | GpDrvRadioIqInvert); + nicunlock(ctlr); + + if((err = niclock(ctlr)) != nil) + return err; + csr32w(ctlr, FhRxConfig, 0); + csr32w(ctlr, FhRxWptr, 0); + csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p) >> 8); + csr32w(ctlr, FhStatusWptr, PCIWADDR(ctlr->rx.s) >> 4); + csr32w(ctlr, FhRxConfig, + FhRxConfigEna | + FhRxConfigIgnRxfEmpty | + FhRxConfigIrqDstHost | + FhRxConfigSingleFrame | + (Nrxlog << FhRxConfigNrbdShift)); + csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7); + nicunlock(ctlr); + + if((err = niclock(ctlr)) != nil) + return err; + if(ctlr->type != Type4965) + prphwrite(ctlr, SchedTxFact5000, 0); + else + prphwrite(ctlr, SchedTxFact4965, 0); + csr32w(ctlr, FhKwAddr, PCIWADDR(ctlr->kwpage) >> 4); + for(q = (ctlr->type != Type4965) ? 19 : 15; q >= 0; q--) + csr32w(ctlr, FhCbbcQueue + q*4, PCIWADDR(ctlr->tx[q].d) >> 8); + nicunlock(ctlr); + + for(i = (ctlr->type != Type4965) ? 7 : 6; i >= 0; i--) + csr32w(ctlr, FhTxConfig + i*32, FhTxConfigDmaEna | FhTxConfigDmaCreditEna); + + csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill); + csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked); + + ctlr->broken = 0; + ctlr->wait.m = 0; + ctlr->wait.w = 0; + + ctlr->ie = Idefmask; + csr32w(ctlr, Imr, ctlr->ie); + csr32w(ctlr, Isr, ~0); + + if(ctlr->type >= Type6000) + csr32w(ctlr, ShadowRegCtrl, csr32r(ctlr, ShadowRegCtrl) | 0x800fffff); + + return nil; +} + +static char* +sendbtcoexadv(Ctlr *ctlr) +{ + static u32int btcoex3wire[12] = { + 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, + 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa, + 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000, + }; + + uchar c[Tcmdsize], *p; + char *err; + int i; + + /* set BT config */ + memset(c, 0, sizeof(c)); + p = c; + + if(ctlr->type == Type2030){ + *p++ = 145; /* flags */ + p++; /* lead time */ + *p++ = 5; /* max kill */ + *p++ = 1; /* bt3 t7 timer */ + put32(p, 0xffff0000); /* kill ack */ + p += 4; + put32(p, 0xffff0000); /* kill cts */ + p += 4; + *p++ = 2; /* sample time */ + *p++ = 0xc; /* bt3 t2 timer */ + p += 2; /* bt4 reaction */ + for (i = 0; i < nelem(btcoex3wire); i++){ + put32(p, btcoex3wire[i]); + p += 4; + } + p += 2; /* bt4 decision */ + put16(p, 0xff); /* valid */ + p += 2; + put32(p, 0xf0); /* prio boost */ + p += 4; + p++; /* reserved */ + p++; /* tx prio boost */ + p += 2; /* rx prio boost */ + } + if((err = cmd(ctlr, 155, c, p-c)) != nil) + return err; + + /* set BT priority */ + memset(c, 0, sizeof(c)); + p = c; + + *p++ = 0x6; /* init1 */ + *p++ = 0x7; /* init2 */ + *p++ = 0x2; /* periodic low1 */ + *p++ = 0x3; /* periodic low2 */ + *p++ = 0x4; /* periodic high1 */ + *p++ = 0x5; /* periodic high2 */ + *p++ = 0x6; /* dtim */ + *p++ = 0x8; /* scan52 */ + *p++ = 0xa; /* scan24 */ + p += 7; /* reserved */ + if((err = cmd(ctlr, 204, c, p-c)) != nil) + return err; + + /* force BT state machine change */ + memset(c, 0, sizeof(c)); + p = c; + + *p++ = 1; /* open */ + *p++ = 1; /* type */ + p += 2; /* reserved */ + if((err = cmd(ctlr, 205, c, p-c)) != nil) + return err; + + c[0] = 0; /* open */ + return cmd(ctlr, 205, c, p-c); +} + +static char* +postboot(Ctlr *ctlr) +{ + uint ctxoff, ctxlen, dramaddr; + char *err; + int i, q; + + if((err = niclock(ctlr)) != nil) + return err; + + if(ctlr->type != Type4965){ + dramaddr = SchedDramAddr5000; + ctxoff = SchedCtxOff5000; + ctxlen = SchedCtxLen5000; + } else { + dramaddr = SchedDramAddr4965; + ctxoff = SchedCtxOff4965; + ctxlen = SchedCtxLen4965; + } + + ctlr->sched.base = prphread(ctlr, SchedSramAddr); + for(i=0; i < ctxlen; i += 4) + memwrite(ctlr, ctlr->sched.base + ctxoff + i, 0); + + prphwrite(ctlr, dramaddr, PCIWADDR(ctlr->sched.s)>>10); + + csr32w(ctlr, FhTxChicken, csr32r(ctlr, FhTxChicken) | 2); + + if(ctlr->type != Type4965){ + /* Enable chain mode for all queues, except command queue 4. */ + prphwrite(ctlr, SchedQChainSel5000, 0xfffef); + prphwrite(ctlr, SchedAggrSel5000, 0); + + for(q=0; q<20; q++){ + prphwrite(ctlr, SchedQueueRdptr5000 + q*4, 0); + csr32w(ctlr, HbusTargWptr, q << 8); + + memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 0); + /* Set scheduler window size and frame limit. */ + memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16 | 64); + } + /* Enable interrupts for all our 20 queues. */ + prphwrite(ctlr, SchedIntrMask5000, 0xfffff); + + /* Identify TX FIFO rings (0-7). */ + prphwrite(ctlr, SchedTxFact5000, 0xff); + } else { + /* Disable chain mode for all our 16 queues. */ + prphwrite(ctlr, SchedQChainSel4965, 0); + + for(q=0; q<16; q++) { + prphwrite(ctlr, SchedQueueRdptr4965 + q*4, 0); + csr32w(ctlr, HbusTargWptr, q << 8); + + /* Set scheduler window size. */ + memwrite(ctlr, ctlr->sched.base + ctxoff + q*8, 64); + /* Set scheduler window size and frame limit. */ + memwrite(ctlr, ctlr->sched.base + ctxoff + q*8 + 4, 64<<16); + } + /* Enable interrupts for all our 16 queues. */ + prphwrite(ctlr, SchedIntrMask4965, 0xffff); + + /* Identify TX FIFO rings (0-7). */ + prphwrite(ctlr, SchedTxFact4965, 0xff); + } + + /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */ + for(q=0; q<7; q++){ + if(ctlr->type != Type4965){ + static uchar qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 }; + prphwrite(ctlr, SchedQueueStatus5000 + q*4, 0x00ff0018 | qid2fifo[q]); + } else { + static uchar qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 }; + prphwrite(ctlr, SchedQueueStatus4965 + q*4, 0x0007fc01 | qid2fifo[q]<<1); + } + } + nicunlock(ctlr); + + if(ctlr->type != Type4965){ + uchar c[Tcmdsize]; + + /* disable wimax coexistance */ + memset(c, 0, sizeof(c)); + if((err = cmd(ctlr, 90, c, 4+4*16)) != nil) + return err; + + if(ctlr->type != Type5150){ + /* calibrate crystal */ + memset(c, 0, sizeof(c)); + c[0] = 15; /* code */ + c[1] = 0; /* group */ + c[2] = 1; /* ngroup */ + c[3] = 1; /* isvalid */ + c[4] = ctlr->eeprom.crystal; + c[5] = ctlr->eeprom.crystal>>16; + /* for some reason 8086:4238 needs a second try */ + if(cmd(ctlr, 176, c, 8) != nil && (err = cmd(ctlr, 176, c, 8)) != nil) + return err; + } + + if(ctlr->calib.done == 0){ + /* query calibration (init firmware) */ + memset(c, 0, sizeof(c)); + put32(c + 0*(5*4) + 0, 0xffffffff); + put32(c + 0*(5*4) + 4, 0xffffffff); + put32(c + 0*(5*4) + 8, 0xffffffff); + put32(c + 2*(5*4) + 0, 0xffffffff); + if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil) + return err; + + /* wait to collect calibration records */ + if(irqwait(ctlr, Ierr, 2000)) + return "calibration failed"; + + if(ctlr->calib.done == 0){ + print("iwl: no calibration results\n"); + ctlr->calib.done = 1; + } + } else { + static uchar cmds[] = {8, 9, 11, 17, 16}; + + /* send calibration records (runtime firmware) */ + for(q=0; qtype != Type5150 && ctlr->type != Type2030) + continue; + if(i == 17 && (ctlr->type >= Type6000 || ctlr->type == Type5150) && + ctlr->type != Type2030) + continue; + + if((b = ctlr->calib.cmd[i]) == nil) + continue; + b = copyblock(b, BLEN(b)); + if((err = qcmd(ctlr, 4, 176, nil, 0, b)) != nil){ + freeb(b); + return err; + } + if((err = flushq(ctlr, 4)) != nil) + return err; + } + + /* temperature sensor offset */ + switch (ctlr->type){ + case Type6005: + memset(c, 0, sizeof(c)); + c[0] = 18; + c[1] = 0; + c[2] = 1; + c[3] = 1; + put16(c + 4, 2700); + if((err = cmd(ctlr, 176, c, 4+2+2)) != nil) + return err; + break; + + case Type2030: + memset(c, 0, sizeof(c)); + c[0] = 18; + c[1] = 0; + c[2] = 1; + c[3] = 1; + if(ctlr->eeprom.rawtemp != 0){ + put16(c + 4, ctlr->eeprom.temp); + put16(c + 6, ctlr->eeprom.rawtemp); + } else{ + put16(c + 4, 2700); + put16(c + 6, 2700); + } + put16(c + 8, ctlr->eeprom.volt); + if((err = cmd(ctlr, 176, c, 4+2+2+2+2)) != nil) + return err; + break; + } + + if(ctlr->type == Type6005 || ctlr->type == Type6050){ + /* runtime DC calibration */ + memset(c, 0, sizeof(c)); + put32(c + 0*(5*4) + 0, 0xffffffff); + put32(c + 0*(5*4) + 4, 1<<1); + if((err = cmd(ctlr, 101, c, (((2*(5*4))+4)*2)+4)) != nil) + return err; + } + + /* set tx antenna config */ + put32(c, ctlr->rfcfg.txantmask & 7); + if((err = cmd(ctlr, 152, c, 4)) != nil) + return err; + + if(ctlr->type == Type2030){ + if((err = sendbtcoexadv(ctlr)) != nil) + return err; + } + } + } + + return nil; +} + +static char* +loadfirmware1(Ctlr *ctlr, u32int dst, uchar *data, int size) +{ + uchar *dma; + char *err; + + dma = mallocalign(size, 16, 0, 0); + if(dma == nil) + return "no memory for dma"; + memmove(dma, data, size); + coherence(); + if((err = niclock(ctlr)) != 0){ + free(dma); + return err; + } + csr32w(ctlr, FhTxConfig + 9*32, 0); + csr32w(ctlr, FhSramAddr + 9*4, dst); + csr32w(ctlr, FhTfbdCtrl0 + 9*8, PCIWADDR(dma)); + csr32w(ctlr, FhTfbdCtrl1 + 9*8, size); + csr32w(ctlr, FhTxBufStatus + 9*32, + (1<fw; + + if(fw->boot.text.size == 0){ + if(ctlr->calib.done == 0){ + if((err = loadfirmware1(ctlr, 0x00000000, fw->init.text.data, fw->init.text.size)) != nil) + return err; + if((err = loadfirmware1(ctlr, 0x00800000, fw->init.data.data, fw->init.data.size)) != nil) + return err; + csr32w(ctlr, Reset, 0); + if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive) + return "init firmware boot failed"; + if((err = postboot(ctlr)) != nil) + return err; + if((err = reset(ctlr)) != nil) + return err; + } + if((err = loadfirmware1(ctlr, 0x00000000, fw->main.text.data, fw->main.text.size)) != nil) + return err; + if((err = loadfirmware1(ctlr, 0x00800000, fw->main.data.data, fw->main.data.size)) != nil) + return err; + csr32w(ctlr, Reset, 0); + if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive) + return "main firmware boot failed"; + return postboot(ctlr); + } + + size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16); + dma = mallocalign(size, 16, 0, 0); + if(dma == nil) + return "no memory for dma"; + + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + + p = dma; + memmove(p, fw->init.data.data, fw->init.data.size); + coherence(); + prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4); + prphwrite(ctlr, BsmDramDataSize, fw->init.data.size); + p += ROUND(fw->init.data.size, 16); + memmove(p, fw->init.text.data, fw->init.text.size); + coherence(); + prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4); + prphwrite(ctlr, BsmDramTextSize, fw->init.text.size); + + nicunlock(ctlr); + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + + p = fw->boot.text.data; + n = fw->boot.text.size/4; + for(i=0; imain.data.size, 16) + ROUND(fw->main.text.size, 16); + dma = mallocalign(size, 16, 0, 0); + if(dma == nil) + return "no memory for dma"; + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + p = dma; + memmove(p, fw->main.data.data, fw->main.data.size); + coherence(); + prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p) >> 4); + prphwrite(ctlr, BsmDramDataSize, fw->main.data.size); + p += ROUND(fw->main.data.size, 16); + memmove(p, fw->main.text.data, fw->main.text.size); + coherence(); + prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p) >> 4); + prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31)); + nicunlock(ctlr); + + if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){ + free(dma); + return "main firmware boot failed"; + } + free(dma); + return postboot(ctlr); +} + +static int +txqready(void *arg) +{ + TXQ *q = arg; + return q->n < Ntx; +} + +static char* +qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block) +{ + uchar *d, *c; + TXQ *q; + + assert(qid < nelem(ctlr->tx)); + assert(size <= Tcmdsize-4); + + ilock(ctlr); + q = &ctlr->tx[qid]; + while(q->n >= Ntx && !ctlr->broken){ + iunlock(ctlr); + qlock(q); + if(!waserror()){ + tsleep(q, txqready, q, 10); + poperror(); + } + qunlock(q); + ilock(ctlr); + } + if(ctlr->broken){ + iunlock(ctlr); + return "qcmd: broken"; + } + q->n++; + + q->lastcmd = code; + q->b[q->i] = block; + c = q->c + q->i * Tcmdsize; + d = q->d + q->i * Tdscsize; + + /* build command */ + c[0] = code; + c[1] = 0; /* flags */ + c[2] = q->i; + c[3] = qid; + + if(size > 0) + memmove(c+4, data, size); + + size += 4; + + /* build descriptor */ + *d++ = 0; + *d++ = 0; + *d++ = 0; + *d++ = 1 + (block != nil); /* nsegs */ + put32(d, PCIWADDR(c)); d += 4; + put16(d, size << 4); d += 2; + if(block != nil){ + size = BLEN(block); + put32(d, PCIWADDR(block->rp)); d += 4; + put16(d, size << 4); + } + + coherence(); + + q->i = (q->i+1) % Ntx; + csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i); + + iunlock(ctlr); + + return nil; +} + +static int +txqempty(void *arg) +{ + TXQ *q = arg; + return q->n == 0; +} + +static char* +flushq(Ctlr *ctlr, uint qid) +{ + TXQ *q; + int i; + + q = &ctlr->tx[qid]; + qlock(q); + for(i = 0; i < 200 && !ctlr->broken; i++){ + if(txqempty(q)){ + qunlock(q); + return nil; + } + if(!waserror()){ + tsleep(q, txqempty, q, 10); + poperror(); + } + } + qunlock(q); + if(ctlr->broken) + return "flushq: broken"; + return "flushq: timeout"; +} + +static char* +cmd(Ctlr *ctlr, uint code, uchar *data, int size) +{ + char *err; + + if(0) print("cmd %ud\n", code); + if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil) + return err; + return flushq(ctlr, 4); +} + +static void +setled(Ctlr *ctlr, int which, int on, int off) +{ + uchar c[8]; + + csr32w(ctlr, Led, csr32r(ctlr, Led) & ~LedBsmCtrl); + + memset(c, 0, sizeof(c)); + put32(c, 10000); + c[4] = which; + c[5] = on; + c[6] = off; + cmd(ctlr, 72, c, sizeof(c)); +} + +static void +addnode(Ctlr *ctlr, uchar id, uchar *addr) +{ + uchar c[Tcmdsize], *p; + + memset(p = c, 0, sizeof(c)); + *p++ = 0; /* control (1 = update) */ + p += 3; /* reserved */ + memmove(p, addr, 6); + p += 6; + p += 2; /* reserved */ + *p++ = id; /* node id */ + p++; /* flags */ + p += 2; /* reserved */ + p += 2; /* kflags */ + p++; /* tcs2 */ + p++; /* reserved */ + p += 5*2; /* ttak */ + p++; /* kid */ + p++; /* reserved */ + p += 16; /* key */ + if(ctlr->type != Type4965){ + p += 8; /* tcs */ + p += 8; /* rxmic */ + p += 8; /* txmic */ + } + p += 4; /* htflags */ + p += 4; /* mask */ + p += 2; /* disable tid */ + p += 2; /* reserved */ + p++; /* add ba tid */ + p++; /* del ba tid */ + p += 2; /* add ba ssn */ + p += 4; /* reserved */ + cmd(ctlr, 24, c, p - c); +} + +static void +rxon(Ether *edev, Wnode *bss) +{ + uchar c[Tcmdsize], *p; + int filter, flags; + Ctlr *ctlr; + char *err; + + ctlr = edev->ctlr; + filter = FilterNoDecrypt | FilterMulticast | FilterBeacon; + if(ctlr->prom){ + filter |= FilterPromisc; + if(bss != nil) + ctlr->channel = bss->channel; + bss = nil; + } + flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto; + if(bss != nil){ + if(bss->cap & (1<<5)) + flags |= RFlagShPreamble; + if(bss->cap & (1<<10)) + flags |= RFlagShSlot; + ctlr->channel = bss->channel; + memmove(ctlr->bssid, bss->bssid, Eaddrlen); + ctlr->aid = bss->aid; + if(ctlr->aid != 0){ + filter |= FilterBSS; + filter &= ~FilterBeacon; + ctlr->bssnodeid = -1; + } else + ctlr->bcastnodeid = -1; + } else { + memmove(ctlr->bssid, edev->bcast, Eaddrlen); + ctlr->aid = 0; + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + } + + if(ctlr->aid != 0) + setled(ctlr, 2, 0, 1); /* on when associated */ + else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0) + setled(ctlr, 2, 10, 10); /* slow blink when connecting */ + else + setled(ctlr, 2, 5, 5); /* fast blink when scanning */ + + if(ctlr->wifi->debug) + print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n", + edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags); + + memset(p = c, 0, sizeof(c)); + memmove(p, edev->ea, 6); p += 8; /* myaddr */ + memmove(p, ctlr->bssid, 6); p += 8; /* bssid */ + memmove(p, edev->ea, 6); p += 8; /* wlap */ + *p++ = 3; /* mode (STA) */ + *p++ = 0; /* air (?) */ + /* rxchain */ + put16(p, ((ctlr->rfcfg.rxantmask & 7)<<1) | (2<<10) | (2<<12)); + p += 2; + *p++ = 0xff; /* ofdm mask (not yet negotiated) */ + *p++ = 0x0f; /* cck mask (not yet negotiated) */ + put16(p, ctlr->aid & 0x3fff); + p += 2; /* aid */ + put32(p, flags); + p += 4; + put32(p, filter); + p += 4; + *p++ = ctlr->channel; + p++; /* reserved */ + *p++ = 0xff; /* ht single mask */ + *p++ = 0xff; /* ht dual mask */ + if(ctlr->type != Type4965){ + *p++ = 0xff; /* ht triple mask */ + p++; /* reserved */ + put16(p, 0); p += 2; /* acquisition */ + p += 2; /* reserved */ + } + if((err = cmd(ctlr, 16, c, p - c)) != nil){ + print("rxon: %s\n", err); + return; + } + + if(ctlr->bcastnodeid == -1){ + ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31; + addnode(ctlr, ctlr->bcastnodeid, edev->bcast); + } + if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){ + ctlr->bssnodeid = 0; + addnode(ctlr, ctlr->bssnodeid, bss->bssid); + } +} + +static struct ratetab { + uchar rate; + uchar plcp; + uchar flags; +} ratetab[] = { + { 2, 10, RFlagCCK }, + { 4, 20, RFlagCCK }, + { 11, 55, RFlagCCK }, + { 22, 110, RFlagCCK }, + { 12, 0xd, 0 }, + { 18, 0xf, 0 }, + { 24, 0x5, 0 }, + { 36, 0x7, 0 }, + { 48, 0x9, 0 }, + { 72, 0xb, 0 }, + { 96, 0x1, 0 }, + { 108, 0x3, 0 }, + { 120, 0x3, 0 } +}; + +static uchar iwlrates[] = { + 0x80 | 2, + 0x80 | 4, + 0x80 | 11, + 0x80 | 22, + 0x80 | 12, + 0x80 | 18, + 0x80 | 24, + 0x80 | 36, + 0x80 | 48, + 0x80 | 72, + 0x80 | 96, + 0x80 | 108, + 0x80 | 120, + + 0 +}; + +enum { + TFlagNeedProtection = 1<<0, + TFlagNeedRTS = 1<<1, + TFlagNeedCTS = 1<<2, + TFlagNeedACK = 1<<3, + TFlagLinkq = 1<<4, + TFlagImmBa = 1<<6, + TFlagFullTxOp = 1<<7, + TFlagBtDis = 1<<12, + TFlagAutoSeq = 1<<13, + TFlagMoreFrag = 1<<14, + TFlagInsertTs = 1<<16, + TFlagNeedPadding = 1<<20, +}; + +static void +transmit(Wifi *wifi, Wnode *wn, Block *b) +{ + int flags, nodeid, rate, ant; + uchar c[Tcmdsize], *p; + Ether *edev; + Ctlr *ctlr; + Wifipkt *w; + char *err; + + edev = wifi->ether; + ctlr = edev->ctlr; + + qlock(ctlr); + if(ctlr->attached == 0 || ctlr->broken){ + qunlock(ctlr); + freeb(b); + return; + } + + if((wn->channel != ctlr->channel) + || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))) + rxon(edev, wn); + + if(b == nil){ + /* association note has no data to transmit */ + qunlock(ctlr); + return; + } + + flags = 0; + nodeid = ctlr->bcastnodeid; + p = wn->minrate; + w = (Wifipkt*)b->rp; + if((w->a1[0] & 1) == 0){ + flags |= TFlagNeedACK; + + if(BLEN(b) > 512-4) + flags |= TFlagNeedRTS; + + if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ + nodeid = ctlr->bssnodeid; + p = wn->actrate; + } + + if(flags & (TFlagNeedRTS|TFlagNeedCTS)){ + if(ctlr->type != Type4965){ + flags &= ~(TFlagNeedRTS|TFlagNeedCTS); + flags |= TFlagNeedProtection; + } else + flags |= TFlagFullTxOp; + } + } + qunlock(ctlr); + + rate = 0; + if(p >= iwlrates && p < &iwlrates[nelem(ratetab)]) + rate = p - iwlrates; + + /* select first available antenna */ + ant = ctlr->rfcfg.txantmask & 7; + ant |= (ant == 0); + ant = ((ant - 1) & ant) ^ ant; + + memset(p = c, 0, sizeof(c)); + put16(p, BLEN(b)); + p += 2; + p += 2; /* lnext */ + put32(p, flags); + p += 4; + put32(p, 0); + p += 4; /* scratch */ + + *p++ = ratetab[rate].plcp; + *p++ = ratetab[rate].flags | (ant<<6); + + p += 2; /* xflags */ + *p++ = nodeid; + *p++ = 0; /* security */ + *p++ = 0; /* linkq */ + p++; /* reserved */ + p += 16; /* key */ + p += 2; /* fnext */ + p += 2; /* reserved */ + put32(p, ~0); /* lifetime */ + p += 4; + + /* BUG: scratch ptr? not clear what this is for */ + put32(p, PCIWADDR(ctlr->kwpage)); + p += 5; + + *p++ = 60; /* rts ntries */ + *p++ = 15; /* data ntries */ + *p++ = 0; /* tid */ + put16(p, 0); /* timeout */ + p += 2; + p += 2; /* txop */ + if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){ + print("transmit: %s\n", err); + freeb(b); + } +} + +static long +iwlctl(Ether *edev, void *buf, long n) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(n >= 5 && memcmp(buf, "reset", 5) == 0){ + ctlr->broken = 1; + return n; + } + if(ctlr->wifi) + return wifictl(ctlr->wifi, buf, n); + return 0; +} + +static long +iwlifstat(Ether *edev, void *buf, long n, ulong off) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->wifi) + return wifistat(ctlr->wifi, buf, n, off); + return 0; +} + +static void +setoptions(Ether *edev) +{ + Ctlr *ctlr; + int i; + + ctlr = edev->ctlr; + for(i = 0; i < edev->nopt; i++) + wificfg(ctlr->wifi, edev->opt[i]); +} + +static void +iwlpromiscuous(void *arg, int on) +{ + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + qlock(ctlr); + ctlr->prom = on; + rxon(edev, ctlr->wifi->bss); + qunlock(ctlr); +} + +static void +iwlmulticast(void *, uchar*, int) +{ +} + +static void +iwlrecover(void *arg) +{ + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + while(waserror()) + ; + for(;;){ + tsleep(&up->sleep, return0, 0, 4000); + + qlock(ctlr); + for(;;){ + if(ctlr->broken == 0) + break; + + if(ctlr->power) + poweroff(ctlr); + + if((csr32r(ctlr, Gpc) & RfKill) == 0) + break; + + if(reset(ctlr) != nil) + break; + if(boot(ctlr) != nil) + break; + + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + ctlr->aid = 0; + rxon(edev, ctlr->wifi->bss); + break; + } + qunlock(ctlr); + } +} + +static void +iwlattach(Ether *edev) +{ + FWImage *fw; + Ctlr *ctlr; + char *err; + + ctlr = edev->ctlr; + qlock(ctlr); + if(waserror()){ + print("#l%d: %s\n", edev->ctlrno, up->errstr); + if(ctlr->power) + poweroff(ctlr); + qunlock(ctlr); + nexterror(); + } + if(ctlr->attached == 0){ + if((csr32r(ctlr, Gpc) & RfKill) == 0) + error("wifi disabled by switch"); + + if(ctlr->wifi == nil){ + ctlr->wifi = wifiattach(edev, transmit); + /* tested with 2230, it has transmit issues using higher bit rates */ + if(ctlr->type != Type2030) + ctlr->wifi->rates = iwlrates; + } + + if(ctlr->fw == nil){ + char *fn = fwname[ctlr->type]; + if(ctlr->type == Type6005){ + switch(ctlr->pdev->did){ + case 0x0082: /* Centrino Advanced-N 6205 */ + case 0x0085: /* Centrino Advanced-N 6205 */ + break; + default: /* Centrino Advanced-N 6030, 6235 */ + fn = "iwn-6030"; + } + } + fw = readfirmware(fn); + print("#l%d: firmware: %s, rev %ux, build %ud, size %ux+%ux+%ux+%ux+%ux\n", + edev->ctlrno, fn, + fw->rev, fw->build, + fw->main.text.size, fw->main.data.size, + fw->init.text.size, fw->init.data.size, + fw->boot.text.size); + ctlr->fw = fw; + } + + if((err = reset(ctlr)) != nil) + error(err); + if((err = boot(ctlr)) != nil) + error(err); + + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + ctlr->channel = 1; + ctlr->aid = 0; + + setoptions(edev); + + ctlr->attached = 1; + + kproc("iwlrecover", iwlrecover, edev); + } + qunlock(ctlr); + poperror(); +} + +static void +receive(Ctlr *ctlr) +{ + Block *b, *bb; + uchar *d; + RXQ *rx; + TXQ *tx; + uint hw; + + rx = &ctlr->rx; + if(ctlr->broken || rx->s == nil || rx->b == nil) + return; + + bb = nil; + for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){ + uchar type, flags, idx, qid; + u32int len; + + b = rx->b[rx->i]; + if(b == nil) + continue; + + d = b->rp; + len = get32(d); d += 4; + type = *d++; + flags = *d++; + USED(flags); + idx = *d++; + qid = *d++; + + if(bb != nil){ + freeb(bb); + bb = nil; + } + if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){ + tx = &ctlr->tx[qid]; + if(tx->n > 0){ + bb = tx->b[idx]; + tx->b[idx] = nil; + tx->n--; + + wakeup(tx); + } + } + + len &= 0x3fff; + if(len < 4 || type == 0) + continue; + + len -= 4; + switch(type){ + case 1: /* microcontroller ready */ + setfwinfo(ctlr, d, len); + break; + case 24: /* add node done */ + break; + case 28: /* tx done */ + if(ctlr->type == Type4965){ + if(len <= 20 || d[20] == 1 || d[20] == 2) + break; + } else { + if(len <= 32 || d[32] == 1 || d[32] == 2) + break; + } + wifitxfail(ctlr->wifi, bb); + break; + case 102: /* calibration result (Type5000 only) */ + if(len < 4) + break; + idx = d[0]; + if(idx >= nelem(ctlr->calib.cmd)) + break; + if(rbplant(ctlr, rx->i) < 0) + break; + if(ctlr->calib.cmd[idx] != nil) + freeb(ctlr->calib.cmd[idx]); + b->rp = d; + b->wp = d + len; + ctlr->calib.cmd[idx] = b; + continue; + case 103: /* calibration done (Type5000 only) */ + ctlr->calib.done = 1; + break; + case 130: /* start scan */ + break; + case 132: /* stop scan */ + break; + case 156: /* rx statistics */ + break; + case 157: /* beacon statistics */ + break; + case 161: /* state changed */ + break; + case 162: /* beacon missed */ + break; + case 192: /* rx phy */ + break; + case 195: /* rx done */ + if(d + 2 > b->lim) + break; + d += d[1]; + d += 56; + case 193: /* mpdu rx done */ + if(d + 4 > b->lim) + break; + len = get16(d); d += 4; + if(d + len + 4 > b->lim) + break; + if((get32(d + len) & 3) != 3) + break; + if(ctlr->wifi == nil) + break; + if(rbplant(ctlr, rx->i) < 0) + break; + b->rp = d; + b->wp = d + len; + wifiiq(ctlr->wifi, b); + continue; + case 197: /* rx compressed ba */ + break; + } + } + csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7); + if(bb != nil) + freeb(bb); +} + +static void +iwlinterrupt(Ureg*, void *arg) +{ + u32int isr, fhisr; + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + ilock(ctlr); + csr32w(ctlr, Imr, 0); + isr = csr32r(ctlr, Isr); + fhisr = csr32r(ctlr, FhIsr); + if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){ + iunlock(ctlr); + return; + } + if(isr == 0 && fhisr == 0) + goto done; + csr32w(ctlr, Isr, isr); + csr32w(ctlr, FhIsr, fhisr); + if((isr & (Iswrx | Ifhrx | Irxperiodic)) || (fhisr & Ifhrx)) + receive(ctlr); + if(isr & Ierr){ + ctlr->broken = 1; + print("#l%d: fatal firmware error\n", edev->ctlrno); + dumpctlr(ctlr); + } + ctlr->wait.m |= isr; + if(ctlr->wait.m & ctlr->wait.w) + wakeup(&ctlr->wait); +done: + csr32w(ctlr, Imr, ctlr->ie); + iunlock(ctlr); +} + +static void +iwlshutdown(Ether *edev) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->power) + poweroff(ctlr); + ctlr->broken = 0; +} + +static Ctlr *iwlhead, *iwltail; + +static void +iwlpci(void) +{ + Pcidev *pdev; + + pdev = nil; + while(pdev = pcimatch(pdev, 0, 0)) { + Ctlr *ctlr; + void *mem; + + if(pdev->ccrb != 2 || pdev->ccru != 0x80) + continue; + if(pdev->vid != 0x8086) + continue; + + switch(pdev->did){ + default: + continue; + case 0x0084: /* WiFi Link 1000 */ + case 0x4229: /* WiFi Link 4965 */ + case 0x4230: /* WiFi Link 4965 */ + case 0x4232: /* Wifi Link 5100 */ + case 0x4236: /* WiFi Link 5300 AGN */ + case 0x4237: /* Wifi Link 5100 AGN */ + case 0x423d: /* Wifi Link 5150 */ + case 0x423b: /* PRO/Wireless 5350 AGN */ + case 0x0082: /* Centrino Advanced-N 6205 */ + case 0x0085: /* Centrino Advanced-N 6205 */ + case 0x422b: /* Centrino Ultimate-N 6300 variant 1 */ + case 0x4238: /* Centrino Ultimate-N 6300 variant 2 */ + case 0x08ae: /* Centrino Wireless-N 100 */ + case 0x0083: /* Centrino Wireless-N 1000 */ + case 0x0887: /* Centrino Wireless-N 2230 */ + case 0x0888: /* Centrino Wireless-N 2230 */ + case 0x0090: /* Centrino Advanced-N 6030 */ + case 0x0091: /* Centrino Advanced-N 6030 */ + case 0x088e: /* Centrino Advanced-N 6235 */ + case 0x088f: /* Centrino Advanced-N 6235 */ + break; + } + + /* Clear device-specific "PCI retry timeout" register (41h). */ + if(pcicfgr8(pdev, 0x41) != 0) + pcicfgw8(pdev, 0x41, 0); + + /* Clear interrupt disable bit. Hardware bug workaround. */ + if(pdev->pcr & 0x400){ + pdev->pcr &= ~0x400; + pcicfgw16(pdev, PciPCR, pdev->pcr); + } + + pcisetbme(pdev); + pcisetpms(pdev, 0); + + ctlr = malloc(sizeof(Ctlr)); + if(ctlr == nil) { + print("iwl: unable to alloc Ctlr\n"); + continue; + } + ctlr->port = pdev->mem[0].bar & ~0x0F; + mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size); + if(mem == nil) { + print("iwl: can't map %8.8luX\n", pdev->mem[0].bar); + free(ctlr); + continue; + } + ctlr->nic = mem; + ctlr->pdev = pdev; + ctlr->type = (csr32r(ctlr, Rev) >> 4) & 0x1F; + + if(fwname[ctlr->type] == nil){ + print("iwl: unsupported controller type %d\n", ctlr->type); + vunmap(mem, pdev->mem[0].size); + free(ctlr); + continue; + } + + if(iwlhead != nil) + iwltail->link = ctlr; + else + iwlhead = ctlr; + iwltail = ctlr; + } +} + +static int +iwlpnp(Ether* edev) +{ + Ctlr *ctlr; + + if(iwlhead == nil) + iwlpci(); +again: + for(ctlr = iwlhead; ctlr != nil; ctlr = ctlr->link){ + if(ctlr->active) + continue; + if(edev->port == 0 || edev->port == ctlr->port){ + ctlr->active = 1; + break; + } + } + + if(ctlr == nil) + return -1; + + edev->ctlr = ctlr; + edev->port = ctlr->port; + edev->irq = ctlr->pdev->intl; + edev->tbdf = ctlr->pdev->tbdf; + edev->arg = edev; + edev->interrupt = iwlinterrupt; + edev->attach = iwlattach; + edev->ifstat = iwlifstat; + edev->ctl = iwlctl; + edev->shutdown = iwlshutdown; + edev->promiscuous = iwlpromiscuous; + edev->multicast = iwlmulticast; + edev->mbps = 54; + + if(iwlinit(edev) < 0){ + edev->ctlr = nil; + goto again; + } + + return 0; +} + +void +etheriwllink(void) +{ + addethercard("iwl", iwlpnp); +} diff --git a/sys/src/9/pc/etherrt2860.c b/sys/src/9/pc/etherrt2860.c new file mode 100644 index 0000000000..ad939fc1d3 --- /dev/null +++ b/sys/src/9/pc/etherrt2860.c @@ -0,0 +1,3566 @@ +/* + * Ralink RT2860 driver + * + * Written without any documentation but Damien Bergaminis + * OpenBSD ral(4) driver sources. Requires ralink firmware + * to be present in /lib/firmware/ral-rt2860 on attach. + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "wifi.h" + +/* for consistency */ +typedef signed char s8int; + +enum { + /* PCI registers */ + PciCfg = 0x0000, + PciCfgUsb = (1 << 17), + PciCfgPci = (1 << 16), + PciEectrl = 0x0004, + EectrlC = (1 << 0), + EectrlS = (1 << 1), + EectrlD = (1 << 2), + EectrlShiftD = 2, + EectrlQ = (1 << 3), + EectrlShiftQ = 3, + PciMcuctrl = 0x0008, + PciSysctrl = 0x000c, + PcieJtag = 0x0010, + + Rt3090AuxCtrl = 0x010c, + + Rt3070Opt14 = 0x0114, +}; + +enum { + /* SCH/DMA registers */ + IntStatus = 0x0200, + /* flags for registers IntStatus/IntMask */ + TxCoherent = (1 << 17), + RxCoherent = (1 << 16), + MacInt4 = (1 << 15), + MacInt3 = (1 << 14), + MacInt2 = (1 << 13), + MacInt1 = (1 << 12), + MacInt0 = (1 << 11), + TxRxCoherent = (1 << 10), + McuCmdInt = (1 << 9), + TxDoneInt5 = (1 << 8), + TxDoneInt4 = (1 << 7), + TxDoneInt3 = (1 << 6), + TxDoneInt2 = (1 << 5), + TxDoneInt1 = (1 << 4), + TxDoneInt0 = (1 << 3), + RxDoneInt = (1 << 2), + TxDlyInt = (1 << 1), + RxDlyInt = (1 << 0), + IntMask = 0x0204, + WpdmaGloCfg = 0x0208, + HdrSegLenShift = 8, + BigEndian = (1 << 7), + TxWbDdone = (1 << 6), + WpdmaBtSizeShift = 4, + WpdmaBtSize16 = 0, + WpdmaBtSize32 = 1, + WpdmaBtSize64 = 2, + WpdmaBtSize128 = 3, + RxDmaBusy = (1 << 3), + RxDmaEn = (1 << 2), + TxDmaBusy = (1 << 1), + TxDmaEn = (1 << 0), + WpdmaRstIdx = 0x020c, + DelayIntCfg = 0x0210, + TxdlyIntEn = (1 << 31), + TxmaxPintShift = 24, + TxmaxPtimeShift = 16, + RxdlyIntEn = (1 << 15), + RxmaxPintShift = 8, + RxmaxPtimeShift = 0, + WmmAifsnCfg = 0x0214, + WmmCwminCfg = 0x0218, + WmmCwmaxCfg = 0x021c, + WmmTxop0Cfg = 0x0220, + WmmTxop1Cfg = 0x0224, + GpioCtrl = 0x0228, + GpioDShift = 8, + GpioOShift = 0, + McuCmdReg = 0x022c, +#define TxBasePtr(qid) (0x0230 + (qid) * 16) +#define TxMaxCnt(qid) (0x0234 + (qid) * 16) +#define TxCtxIdx(qid) (0x0238 + (qid) * 16) +#define TxDtxIdx(qid) (0x023c + (qid) * 16) + RxBasePtr = 0x0290, + RxMaxCnt = 0x0294, + RxCalcIdx = 0x0298, + FsDrxIdx = 0x029c, + UsbDmaCfg = 0x02a0 /* RT2870 only */, + UsbTxBusy = (1 << 31), + UsbRxBusy = (1 << 30), + UsbEpoutVldShift = 24, + UsbTxEn = (1 << 23), + UsbRxEn = (1 << 22), + UsbRxAggEn = (1 << 21), + UsbTxopHalt = (1 << 20), + UsbTxClear = (1 << 19), + UsbPhyWdEn = (1 << 16), + UsbPhyManRst = (1 << 15), +#define UsbRxAggLmt(x) ((x) << 8) /* in unit of 1KB */ +#define UsbRxAggTo(x) ((x) & 0xff) /* in unit of 33ns */ + UsCycCnt = 0x02a4, + TestEn = (1 << 24), + TestSelShift = 16, + BtModeEn = (1 << 8), + UsCycCntShift = 0, +}; + +enum { + /* PBF registers */ + SysCtrl = 0x0400, + HstPmSel = (1 << 16), + CapMode = (1 << 14), + PmeOen = (1 << 13), + Clkselect = (1 << 12), + PbfClkEn = (1 << 11), + MacClkEn = (1 << 10), + DmaClkEn = (1 << 9), + McuReady = (1 << 7), + AsyReset = (1 << 4), + PbfReset = (1 << 3), + MacReset = (1 << 2), + DmaReset = (1 << 1), + McuReset = (1 << 0), + HostCmd = 0x0404, + McuCmdSleep = 0x30, + McuCmdWakeup = 0x31, + McuCmdLeds = 0x50, + LedRadio = (1 << 13), + LedLink2ghz = (1 << 14), + LedLink5ghz = (1 << 15), + McuCmdLedRssi = 0x51, + McuCmdLed1 = 0x52, + McuCmdLed2 = 0x53, + McuCmdLed3 = 0x54, + McuCmdRfreset = 0x72, + McuCmdAntsel = 0x73, + McuCmdBbp = 0x80, + McuCmdPslevel = 0x83, + PbfCfg = 0x0408, + Tx1qNumShift = 21, + Tx2qNumShift = 16, + Null0Mode = (1 << 15), + Null1Mode = (1 << 14), + RxDropMode = (1 << 13), + Tx0qManual = (1 << 12), + Tx1qManual = (1 << 11), + Tx2qManual = (1 << 10), + Rx0qManual = (1 << 9), + HccaEn = (1 << 8), + Tx0qEn = (1 << 4), + Tx1qEn = (1 << 3), + Tx2qEn = (1 << 2), + Rx0qEn = (1 << 1), + MaxPcnt = 0x040c, + BufCtrl = 0x0410, +#define WriteTxq(qid) (1 << (11 - (qid))) + Null0Kick = (1 << 7), + Null1Kick = (1 << 6), + BufReset = (1 << 5), +#define ReadTxq(qid) = (1 << (3 - (qid)) + ReadRx0q = (1 << 0), + McuIntSta = 0x0414, + /* flags for registers McuIntSta/McuIntEna */ + McuMacInt8 = (1 << 24), + McuMacInt7 = (1 << 23), + McuMacInt6 = (1 << 22), + McuMacInt4 = (1 << 20), + McuMacInt3 = (1 << 19), + McuMacInt2 = (1 << 18), + McuMacInt1 = (1 << 17), + McuMacInt0 = (1 << 16), + Dtx0Int = (1 << 11), + Dtx1Int = (1 << 10), + Dtx2Int = (1 << 9), + Drx0Int = (1 << 8), + HcmdInt = (1 << 7), + N0txInt = (1 << 6), + N1txInt = (1 << 5), + BcntxInt = (1 << 4), + Mtx0Int = (1 << 3), + Mtx1Int = (1 << 2), + Mtx2Int = (1 << 1), + Mrx0Int = (1 << 0), + McuIntEna = 0x0418, +#define TxqIo(qid) (0x041c + (qid) * 4) + Rx0qIo = 0x0424, + BcnOffset0 = 0x042c, + BcnOffset1 = 0x0430, + TxrxqSta = 0x0434, + TxrxqPcnt = 0x0438, + Rx0qPcntMask = 0xff000000, + Tx2qPcntMask = 0x00ff0000, + Tx1qPcntMask = 0x0000ff00, + Tx0qPcntMask = 0x000000ff, + PbfDbg = 0x043c, + CapCtrl = 0x0440, + CapAdcFeq = (1 << 31), + CapStart = (1 << 30), + ManTrig = (1 << 29), + TrigOffsetShift = 16, + StartAddrShift = 0, +}; + +enum { + /* RT3070 registers */ + Rt3070RfCsrCfg = 0x0500, + Rt3070RfKick = (1 << 17), + Rt3070RfWrite = (1 << 16), + Rt3070EfuseCtrl = 0x0580, + Rt3070SelEfuse = (1 << 31), + Rt3070EfsromKick = (1 << 30), + Rt3070EfsromAinMask = 0x03ff0000, + Rt3070EfsromAinShift = 16, + Rt3070EfsromModeMask = 0x000000c0, + Rt3070EfuseAoutMask = 0x0000003f, + Rt3070EfuseData0 = 0x0590, + Rt3070EfuseData1 = 0x0594, + Rt3070EfuseData2 = 0x0598, + Rt3070EfuseData3 = 0x059c, + Rt3090OscCtrl = 0x05a4, + Rt3070LdoCfg0 = 0x05d4, + Rt3070GpioSwitch = 0x05dc, +}; + +enum { + /* MAC registers */ + AsicVerId = 0x1000, + MacSysCtrl = 0x1004, + RxTsEn = (1 << 7), + WlanHaltEn = (1 << 6), + PbfLoopEn = (1 << 5), + ContTxTest = (1 << 4), + MacRxEn = (1 << 3), + MacTxEn = (1 << 2), + BbpHrst = (1 << 1), + MacSrst = (1 << 0), + MacAddrDw0 = 0x1008, + MacAddrDw1 = 0x100c, + MacBssidDw0 = 0x1010, + MacBssidDw1 = 0x1014, + MultiBcnNumShift = 18, + MultiBssidModeShift = 16, + MaxLenCfg = 0x1018, + MinMpduLenShift = 16, + MaxPsduLenShift = 12, + MaxPsduLen8k = 0, + MaxPsduLen16k = 1, + MaxPsduLen32k = 2, + MaxPsduLen64k = 3, + MaxMpduLenShift = 0, + BbpCsrCfg = 0x101c, + BbpRwParallel = (1 << 19), + BbpParDur1125 = (1 << 18), + BbpCsrKick = (1 << 17), + BbpCsrRead = (1 << 16), + BbpAddrShift = 8, + BbpDataShift = 0, + RfCsrCfg0 = 0x1020, + RfRegCtrl = (1 << 31), + RfLeSel1 = (1 << 30), + RfLeStby = (1 << 29), + RfRegWidthShift = 24, + RfReg0Shift = 0, + RfCsrCfg1 = 0x1024, + RfDur5 = (1 << 24), + RfReg1Shift = 0, + RfCsrCfg2 = 0x1028, + LedCfg = 0x102c, + LedPol = (1 << 30), + YLedModeShift = 28, + GLedModeShift = 26, + RLedModeShift = 24, + LedModeOff = 0, + LedModeBlinkTx = 1, + LedModeSlowBlink = 2, + LedModeOn = 3, + SlowBlkTimeShift = 16, + LedOffTimeShift = 8, + LedOnTimeShift = 0, +}; + +enum { + /* undocumented registers */ + Debug = 0x10f4, +}; + +enum { + /* MAC Timing control registers */ + XifsTimeCfg = 0x1100, + BbRxendEn = (1 << 29), + EifsTimeShift = 20, + OfdmXifsTimeShift = 16, + OfdmSifsTimeShift = 8, + CckSifsTimeShift = 0, + BkoffSlotCfg = 0x1104, + CcDelayTimeShift = 8, + SlotTime = 0, + NavTimeCfg = 0x1108, + NavUpd = (1 << 31), + NavUpdValShift = 16, + NavClrEn = (1 << 15), + NavTimerShift = 0, + ChTimeCfg = 0x110c, + EifsAsChBusy = (1 << 4), + NavAsChBusy = (1 << 3), + RxAsChBusy = (1 << 2), + TxAsChBusy = (1 << 1), + ChStaTimerEn = (1 << 0), + PbfLifeTimer = 0x1110, + BcnTimeCfg = 0x1114, + TsfInsCompShift = 24, + BcnTxEn = (1 << 20), + TbttTimerEn = (1 << 19), + TsfSyncModeShift = 17, + TsfSyncModeDis = 0, + TsfSyncModeSta = 1, + TsfSyncModeIbss = 2, + TsfSyncModeHostap = 3, + TsfTimerEn = (1 << 16), + BcnIntvalShift = 0, + TbttSyncCfg = 0x1118, + BcnCwminShift = 20, + BcnAifsnShift = 16, + BcnExpWinShift = 8, + TbttAdjustShift = 0, + TsfTimerDw0 = 0x111c, + TsfTimerDw1 = 0x1120, + TbttTimer = 0x1124, + IntTimerCfg = 0x1128, + GpTimerShift = 16, + PreTbttTimerShift = 0, + IntTimerEn = 0x112c, + GpTimerEn = (1 << 1), + PreTbttIntEn = (1 << 0), + ChIdleTime = 0x1130, +}; + +enum { + /* MAC Power Save configuration registers */ + MacStatusReg = 0x1200, + RxStatusBusy = (1 << 1), + TxStatusBusy = (1 << 0), + PwrPinCfg = 0x1204, + IoAddaPd = (1 << 3), + IoPllPd = (1 << 2), + IoRaPe = (1 << 1), + IoRfPe = (1 << 0), + AutoWakeupCfg = 0x1208, + AutoWakeupEn = (1 << 15), + SleepTbttNumShift = 8, + WakeupLeadTimeShift = 0, +}; + +enum { + /* MAC TX configuration registers */ +#define EdcaAcCfg(aci) (0x1300 + (aci) * 4) + EdcaTidAcMap = 0x1310, +#define TxPwrCfg(ridx) (0x1314 + (ridx) * 4) + TxPinCfg = 0x1328, + Rt3593LnaPeG2Pol = (1 << 31), + Rt3593LnaPeA2Pol = (1 << 30), + Rt3593LnaPeG2En = (1 << 29), + Rt3593LnaPeA2En = (1 << 28), + Rt3593LnaPe2En = (Rt3593LnaPeA2En | Rt3593LnaPeG2En), + Rt3593PaPeG2Pol = (1 << 27), + Rt3593PaPeA2Pol = (1 << 26), + Rt3593PaPeG2En = (1 << 25), + Rt3593PaPeA2En = (1 << 24), + TrswPol = (1 << 19), + TrswEn = (1 << 18), + RftrPol = (1 << 17), + RftrEn = (1 << 16), + LnaPeG1Pol = (1 << 15), + LnaPeA1Pol = (1 << 14), + LnaPeG0Pol = (1 << 13), + LnaPeA0Pol = (1 << 12), + LnaPeG1En = (1 << 11), + LnaPeA1En = (1 << 10), + LnaPe1En = (LnaPeA1En | LnaPeG1En), + LnaPeG0En = (1 << 9), + LnaPeA0En = (1 << 8), + LnaPe0En = (LnaPeA0En | LnaPeG0En), + PaPeG1Pol = (1 << 7), + PaPeA1Pol = (1 << 6), + PaPeG0Pol = (1 << 5), + PaPeA0Pol = (1 << 4), + PaPeG1En = (1 << 3), + PaPeA1En = (1 << 2), + PaPeG0En = (1 << 1), + PaPeA0En = (1 << 0), + TxBandCfg = 0x132c, + Tx5gBandSelN = (1 << 2), + Tx5gBandSelP = (1 << 1), + TxBandSel = (1 << 0), + TxSwCfg0 = 0x1330, + DlyRftrEnShift = 24, + DlyTrswEnShift = 16, + DlyPapeEnShift = 8, + DlyTxpeEnShift = 0, + TxSwCfg1 = 0x1334, + DlyRftrDisShift = 16, + DlyTrswDisShift = 8, + DlyPapeDisShift = 0, + TxSwCfg2 = 0x1338, + DlyLnaEnShift = 24, + DlyLnaDisShift = 16, + DlyDacEnShift = 8, + DlyDacDisShift = 0, + TxopThresCfg = 0x133c, + TxopRemThresShift = 24, + CfEndThresShift = 16, + RdgInThres = 8, + RdgOutThres = 0, + TxopCtrlCfg = 0x1340, + ExtCwMinShift = 16, + ExtCcaDlyShift = 8, + ExtCcaEn = (1 << 7), + LsigTxopEn = (1 << 6), + TxopTrunEnMimops = (1 << 4), + TxopTrunEnTxop = (1 << 3), + TxopTrunEnRate = (1 << 2), + TxopTrunEnAc = (1 << 1), + TxopTrunEnTimeout = (1 << 0), + TxRtsCfg = 0x1344, + RtsFbkEn = (1 << 24), + RtsThresShift = 8, + RtsRtyLimitShift = 0, + TxTimeoutCfg = 0x1348, + TxopTimeoutShift = 16, + RxAckTimeoutShift = 8, + MpduLifeTimeShift = 4, + TxRtyCfg = 0x134c, + TxAutofbEn = (1 << 30), + AggRtyModeTimer = (1 << 29), + NagRtyModeTimer = (1 << 28), + LongRtyThresShift = 16, + LongRtyLimitShift = 8, + ShortRtyLimitShift = 0, + TxLinkCfg = 0x1350, + RemoteMfsShift = 24, + RemoteMfbShift = 16, + TxCfackEn = (1 << 12), + TxRdgEn = (1 << 11), + TxMrqEn = (1 << 10), + RemoteUmfsEn = (1 << 9), + TxMfbEn = (1 << 8), + RemoteMfbLtShift = 0, + HtFbkCfg0 = 0x1354, + HtFbkCfg1 = 0x1358, + LgFbkCfg0 = 0x135c, + LgFbkCfg1 = 0x1360, + CckProtCfg = 0x1364, + /* possible flags for registers *ProtCfg */ + RtsthEn = (1 << 26), + TxopAllowGf40 = (1 << 25), + TxopAllowGf20 = (1 << 24), + TxopAllowMm40 = (1 << 23), + TxopAllowMm20 = (1 << 22), + TxopAllowOfdm = (1 << 21), + TxopAllowCck = (1 << 20), + TxopAllowAll = (0x3f << 20), + ProtNavShort = (1 << 18), + ProtNavLong = (2 << 18), + ProtCtrlRtsCts = (1 << 16), + ProtCtrlCts = (2 << 16), + OfdmProtCfg = 0x1368, + Mm20ProtCfg = 0x136c, + Mm40ProtCfg = 0x1370, + Gf20ProtCfg = 0x1374, + Gf40ProtCfg = 0x1378, + ExpCtsTime = 0x137c, + /* possible flags for registers EXP_{CTS,ACK}_TIME */ + ExpOfdmTimeShift = 16, + ExpCckTimeShift = 0, + ExpAckTime = 0x1380, +}; + +enum { + /* MAC RX configuration registers */ + RxFiltrCfg = 0x1400, + DropCtrlRsv = (1 << 16), + DropBar = (1 << 15), + DropBa = (1 << 14), + DropPspoll = (1 << 13), + DropRts = (1 << 12), + DropCts = (1 << 11), + DropAck = (1 << 10), + DropCfend = (1 << 9), + DropCfack = (1 << 8), + DropDupl = (1 << 7), + DropBc = (1 << 6), + DropMc = (1 << 5), + DropVerErr = (1 << 4), + DropNotMybss = (1 << 3), + DropUcNome = (1 << 2), + DropPhyErr = (1 << 1), + DropCrcErr = (1 << 0), + AutoRspCfg = 0x1404, + CtrlPwrBit = (1 << 7), + BacAckPolicy = (1 << 6), + CckShortEn = (1 << 4), + Cts40mRefEn = (1 << 3), + Cts40mModeEn = (1 << 2), + BacAckpolicyEn = (1 << 1), + AutoRspEn = (1 << 0), + LegacyBasicRate = 0x1408, + HtBasicRate = 0x140c, + HtCtrlCfg = 0x1410, + SifsCostCfg = 0x1414, + OfdmSifsCostShift = 8, + CckSifsCostShift = 0, + RxParserCfg = 0x1418, +}; + +enum { + /* MAC Security configuration registers */ + TxSecCnt0 = 0x1500, + RxSecCnt0 = 0x1504, + CcmpFcMute = 0x1508, +}; + +enum { + /* MAC HCCA/PSMP configuration registers */ + TxopHldrAddr0 = 0x1600, + TxopHldrAddr1 = 0x1604, + TxopHldrEt = 0x1608, + TxopEtm1En = (1 << 25), + TxopEtm0En = (1 << 24), + TxopEtmThresShift = 16, + TxopEtoEn = (1 << 8), + TxopEtoThresShift = 1, + PerRxRstEn = (1 << 0), + QosCfpollRaDw0 = 0x160c, + QosCfpollA1Dw1 = 0x1610, + QosCfpollQc = 0x1614, +}; + +enum { + /* MAC Statistics Counters */ + RxStaCnt0 = 0x1700, + RxStaCnt1 = 0x1704, + RxStaCnt2 = 0x1708, + TxStaCnt0 = 0x170c, + TxStaCnt1 = 0x1710, + TxStaCnt2 = 0x1714, + TxStatFifo = 0x1718, + TxqMcsShift = 16, + TxqWcidShift = 8, + TxqAckreq = (1 << 7), + TxqAgg = (1 << 6), + TxqOk = (1 << 5), + TxqPidShift = 1, + TxqVld = (1 << 0), +}; + +/* RX WCID search table */ +#define WcidEntry(wcid) (0x1800 + (wcid) * 8) + +enum { + FwBase = 0x2000, + Rt2870FwBase = 0x3000, +}; + +/* Pair-wise key table */ +#define Pkey(wcid) (0x4000 + (wcid) * 32) + +/* IV/EIV table */ +#define Iveiv(wcid) (0x6000 + (wcid) * 8) + +/* WCID attribute table */ +#define WcidAttr(wcid) (0x6800 + (wcid) * 4) + +/* possible flags for register WCID_ATTR */ +enum { + ModeNosec = 0, + ModeWep40 = 1, + ModeWep104 = 2, + ModeTkip = 3, + ModeAesCcmp = 4, + ModeCkip40 = 5, + ModeCkip104 = 6, + ModeCkip128 = 7, + RxPkeyEn = (1 << 0), +}; + +/* Shared Key Table */ +#define Skey(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32) + +/* Shared Key Mode */ +enum { + SkeyMode07 = 0x7000, + SkeyMode815 = 0x7004, + SkeyMode1623 = 0x7008, + SkeyMode2431 = 0x700c, +}; + +enum { + /* Shared Memory between MCU and host */ + H2mMailbox = 0x7010, + H2mBusy = (1 << 24), + TokenNoIntr = 0xff, + H2mMailboxCid = 0x7014, + H2mMailboxStatus = 0x701c, + H2mBbpagent = 0x7028, +#define BcnBase(vap) (0x7800 + (vap) * 512) +}; + +/* + * RT2860 TX descriptor + * -------------------- + * u32int sdp0 Segment Data Pointer 0 + * u16int sdl1 Segment Data Length 1 + * u16int sdl0 Segment Data Length 0 + * u32int sdp1 Segment Data Pointer 1 + * u8int reserved[3] + * u8int flags + */ + +enum { + /* sdl1 flags */ + TxBurst = (1 << 15), + TxLs1 = (1 << 14) /* SDP1 is the last segment */, + /* sdl0 flags */ + TxDdone = (1 << 15), + TxLs0 = (1 << 14) /* SDP0 is the last segment */, + /* flags */ + TxQselShift = 1, + TxQselMgmt = (0 << 1), + TxQselHcca = (1 << 1), + TxQselEdca = (2 << 1), + TxWiv = (1 << 0), +}; + +/* + * TX Wireless Information + * ----------------------- + * u8int flags + * u8int txop + * u16int phy + * u8int xflags + * u8int wcid Wireless Client ID + * u16int len + * u32int iv + * u32int eiv + */ + +enum { + /* flags */ + TxMpduDsityShift = 5, + TxAmpdu = (1 << 4), + TxTs = (1 << 3), + TxCfack = (1 << 2), + TxMmps = (1 << 1), + TxFrag = (1 << 0), + /* txop */ + TxTxopHt = 0, + TxTxopPifs = 1, + TxTxopSifs = 2, + TxTxopBackoff = 3, + /* phy */ + PhyMode = 0xc000, + PhyCck = (0 << 14), + PhyOfdm = (1 << 14), + PhyHt = (2 << 14), + PhyHtGf = (3 << 14), + PhySgi = (1 << 8), + PhyBw40 = (1 << 7), + PhyMcs = 0x7f, + PhyShpre = (1 << 3), + /* xflags */ + TxBawinsizeShift = 2, + TxNseq = (1 << 1), + TxAck = (1 << 0), + /* len */ + TxPidShift = 12, +}; + +/* + * RT2860 RX descriptor + * -------------------- + * u32int sdp0 + * u16int sdl1 unused + * u16int sdl0 + * u32int sdp1 unused + * u32int flags + */ + +enum { + /* sdl flags */ + RxDdone = (1 << 15), + RxLs0 = (1 << 14), + /* flags */ + RxDec = (1 << 16), + RxAmpdu = (1 << 15), + RxL2pad = (1 << 14), + RxRssi = (1 << 13), + RxHtc = (1 << 12), + RxAmsdu = (1 << 11), + RxMicerr = (1 << 10), + RxIcverr = (1 << 9), + RxCrcerr = (1 << 8), + RxMybss = (1 << 7), + RxBc = (1 << 6), + RxMc = (1 << 5), + RxUc2me = (1 << 4), + RxFrag = (1 << 3), + RxNull = (1 << 2), + RxData = (1 << 1), + RxBa = (1 << 0), +}; + +/* + * RX Wireless Information + * ----------------------- + * u8int wcid + * u8int keyidx + * u16int len + * u16int seq + * u16int phy + * u8int rssi[3] + * u8int reserved1 + * u8int snr[2] + * u16int reserved2 + */ + +enum { + /* keyidx flags */ + RxUdfShift = 5, + RxBssIdxShift = 2, + /* len flags */ + RxTidShift = 12, +}; + +enum { + WIFIHDRSIZE = 2+2+3*6+2, + Rdscsize = 16, + Tdscsize = 16, + Rbufsize = 4096, + Tbufsize = 4096, + Rxwisize = 16, + Txwisize = 16, + /* first DMA segment contains TXWI + 802.11 header + 32-bit padding */ + TxwiDmaSz = Txwisize + WIFIHDRSIZE + 2 +}; + +/* RF registers */ +enum { + Rf1 = 0, + Rf2 = 2, + Rf3 = 1, + Rf4 = 3, +}; + +enum { + Rf2820 = 1 /* 2T3R */, + Rf2850 = 2 /* dual-band 2T3R */, + Rf2720 = 3 /* 1T2R */, + Rf2750 = 4 /* dual-band 1T2R */, + Rf3020 = 5 /* 1T1R */, + Rf2020 = 6 /* b/g */, + Rf3021 = 7 /* 1T2R */, + Rf3022 = 8 /* 2T2R */, + Rf3052 = 9 /* dual-band 2T2R */, + Rf3320 = 11 /* 1T1R */, + Rf3053 = 13 /* dual-band 3T3R */, +}; + +enum { + Rt3070RfBlock = (1 << 0), + Rt3070Rx0Pd = (1 << 2), + Rt3070Tx0Pd = (1 << 3), + Rt3070Rx1Pd = (1 << 4), + Rt3070Tx1Pd = (1 << 5), + Rt3070Rx2Pd = (1 << 6), + Rt3070Tx2Pd = (1 << 7), + Rt3070Tune = (1 << 0), + Rt3070TxLo2 = (1 << 3), + Rt3070TxLo1 = (1 << 3), + Rt3070RxLo1 = (1 << 3), + Rt3070RxLo2 = (1 << 3), + Rt3070RxCtb = (1 << 7), + Rt3070BbLoopback = (1 << 0), + + Rt3593Vco = (1 << 0), + Rt3593Rescal = (1 << 7), + Rt3593Vcocal = (1 << 7), + Rt3593VcoIc = (1 << 6), + Rt3593LdoPllVcMask = 0x0e, + Rt3593LdoRfVcMask = 0xe0, + Rt3593CpIcMask = 0xe0, + Rt3593CpIcShift = 5, + Rt3593RxCtb = (1 << 5) +}; + +static const char* rfnames[] = { + [Rf2820] "RT2820", + [Rf2850] "RT2850", + [Rf2720] "RT2720", + [Rf2750] "RT2750", + [Rf3020] "RT3020", + [Rf2020] "RT2020", + [Rf3021] "RT3021", + [Rf3022] "RT3022", + [Rf3052] "RT3052", + [Rf3320] "RT3320", + [Rf3053] "RT3053", +}; + +enum { + /* USB commands, RT2870 only */ + Rt2870Reset = 1, + Rt2870Write2 = 2, + Rt2870WriteRegion1 = 6, + Rt2870ReadRegion1 = 7, + Rt2870EepromRead = 9, +}; + +enum { + EepromDelay = 1 /* minimum hold time (microsecond) */, + + EepromVersion = 0x01, + EepromMac01 = 0x02, + EepromMac23 = 0x03, + EepromMac45 = 0x04, + EepromPciePslevel = 0x11, + EepromRev = 0x12, + EepromAntenna = 0x1a, + EepromConfig = 0x1b, + EepromCountry = 0x1c, + EepromFreqLeds = 0x1d, + EepromLed1 = 0x1e, + EepromLed2 = 0x1f, + EepromLed3 = 0x20, + EepromLna = 0x22, + EepromRssi12ghz = 0x23, + EepromRssi22ghz = 0x24, + EepromRssi15ghz = 0x25, + EepromRssi25ghz = 0x26, + EepromDeltapwr = 0x28, + EepromPwr2ghzBase1 = 0x29, + EepromPwr2ghzBase2 = 0x30, + EepromTssi12ghz = 0x37, + EepromTssi22ghz = 0x38, + EepromTssi32ghz = 0x39, + EepromTssi42ghz = 0x3a, + EepromTssi52ghz = 0x3b, + EepromPwr5ghzBase1 = 0x3c, + EepromPwr5ghzBase2 = 0x53, + EepromTssi15ghz = 0x6a, + EepromTssi25ghz = 0x6b, + EepromTssi35ghz = 0x6c, + EepromTssi45ghz = 0x6d, + EepromTssi55ghz = 0x6e, + EepromRpwr = 0x6f, + EepromBbpBase = 0x78, + Rt3071EepromRfBase = 0x82, +}; + +enum { + RidxCck1 = 0, + RidxCck11 = 3, + RidxOfdm6 = 4, + RidxMax = 11, +}; + +/* ring and pool count */ +enum { + Nrx = 128, + Ntx = 64, + Ntxpool = Ntx * 2 +}; + +typedef struct FWImage FWImage; +typedef struct TXQ TXQ; +typedef struct RXQ RXQ; +typedef struct Pool Pool; + +typedef struct Ctlr Ctlr; + +struct FWImage { + uint size; + uchar *data; +}; + +struct TXQ +{ + uint n; /* next */ + uint i; /* current */ + Block **b; + u32int *d; /* descriptors */ + + Rendez; + QLock; +}; + +struct RXQ +{ + uint i; + Block **b; + u32int *p; +}; + +struct Pool +{ + uint i; /* current */ + uchar *p; /* txwi */ +}; + +struct Ctlr { + Lock; + QLock; + + Ctlr *link; + Pcidev *pdev; + Wifi *wifi; + + u16int mac_ver; + u16int mac_rev; + u8int rf_rev; + u8int freq; + u8int ntxchains; + u8int nrxchains; + u8int pslevel; + s8int txpow1[54]; + s8int txpow2[54]; + s8int rssi_2ghz[3]; + s8int rssi_5ghz[3]; + u8int lna[4]; + u8int rf24_20mhz; + u8int rf24_40mhz; + u8int patch_dac; + u8int rfswitch; + u8int ext_2ghz_lna; + u8int ext_5ghz_lna; + u8int calib_2ghz; + u8int calib_5ghz; + u8int txmixgain_2ghz; + u8int txmixgain_5ghz; + u8int tssi_2ghz[9]; + u8int tssi_5ghz[9]; + u8int step_2ghz; + u8int step_5ghz; + uint mgtqid; + + struct { + u8int reg; + u8int val; + } bbp[8], rf[10]; + u8int leds; + u16int led[3]; + u32int txpow20mhz[5]; + u32int txpow40mhz_2ghz[5]; + u32int txpow40mhz_5ghz[5]; + + int flags; + + int port; + int power; + int active; + int broken; + int attached; + + u32int *nic; + + /* assigned node ids in hardware node table or -1 if unassigned */ + int bcastnodeid; + int bssnodeid; + u8int wcid; + /* current receiver settings */ + uchar bssid[Eaddrlen]; + int channel; + int prom; + int aid; + + RXQ rx; + TXQ tx[6]; + Pool pool; + + FWImage *fw; +}; + +/* controller flags */ +enum { + AdvancedPs = 1 << 0, + ConnPciE = 1 << 1, +}; + +static const struct rt2860_rate { + u8int rate; + u8int mcs; + /*enum ieee80211_phytype phy;*/ + u8int ctl_ridx; + u16int sp_ack_dur; + u16int lp_ack_dur; +} rt2860_rates[] = { + { 2, 0,/* IEEE80211_T_DS,*/ 0, 314, 314 }, + { 4, 1,/* IEEE80211_T_DS,*/ 1, 258, 162 }, + { 11, 2,/* IEEE80211_T_DS,*/ 2, 223, 127 }, + { 22, 3,/* IEEE80211_T_DS,*/ 3, 213, 117 }, + { 12, 0,/* IEEE80211_T_OFDM,*/ 4, 60, 60 }, + { 18, 1,/* IEEE80211_T_OFDM,*/ 4, 52, 52 }, + { 24, 2,/* IEEE80211_T_OFDM,*/ 6, 48, 48 }, + { 36, 3,/* IEEE80211_T_OFDM,*/ 6, 44, 44 }, + { 48, 4,/* IEEE80211_T_OFDM,*/ 8, 44, 44 }, + { 72, 5,/* IEEE80211_T_OFDM,*/ 8, 40, 40 }, + { 96, 6,/* IEEE80211_T_OFDM,*/ 8, 40, 40 }, + { 108, 7,/* IEEE80211_T_OFDM,*/ 8, 40, 40 } +}; + +/* + * Default values for MAC registers; values taken from the reference driver. + */ +static const struct { + u32int reg; + u32int val; +} rt2860_def_mac[] = { + { BcnOffset0, 0xf8f0e8e0 }, + { LegacyBasicRate, 0x0000013f }, + { HtBasicRate, 0x00008003 }, + { MacSysCtrl, 0x00000000 }, + { BkoffSlotCfg, 0x00000209 }, + { TxSwCfg0, 0x00000000 }, + { TxSwCfg1, 0x00080606 }, + { TxLinkCfg, 0x00001020 }, + { TxTimeoutCfg, 0x000a2090 }, + { LedCfg, 0x7f031e46 }, + { WmmAifsnCfg, 0x00002273 }, + { WmmCwminCfg, 0x00002344 }, + { WmmCwmaxCfg, 0x000034aa }, + { MaxPcnt, 0x1f3fbf9f }, + { TxRtyCfg, 0x47d01f0f }, + { AutoRspCfg, 0x00000013 }, + { CckProtCfg, 0x05740003 }, + { OfdmProtCfg, 0x05740003 }, + { Gf20ProtCfg, 0x01744004 }, + { Gf40ProtCfg, 0x03f44084 }, + { Mm20ProtCfg, 0x01744004 }, + { Mm40ProtCfg, 0x03f54084 }, + { TxopCtrlCfg, 0x0000583f }, + { TxopHldrEt, 0x00000002 }, + { TxRtsCfg, 0x00092b20 }, + { ExpAckTime, 0x002400ca }, + { XifsTimeCfg, 0x33a41010 }, + { PwrPinCfg, 0x00000003 }, +}; + +/* + * Default values for BBP registers; values taken from the reference driver. + */ +static const struct { + u8int reg; + u8int val; +} rt2860_def_bbp[] = { + { 65, 0x2c }, + { 66, 0x38 }, + { 69, 0x12 }, + { 70, 0x0a }, + { 73, 0x10 }, + { 81, 0x37 }, + { 82, 0x62 }, + { 83, 0x6a }, + { 84, 0x99 }, + { 86, 0x00 }, + { 91, 0x04 }, + { 92, 0x00 }, + { 103, 0x00 }, + { 105, 0x05 }, + { 106, 0x35 }, +}; + +/* + * Default settings for RF registers; values derived from the reference driver. + */ +static const struct rfprog { + u8int chan; + u32int r1, r2, r3, r4; +} rt2860_rf2850[] = { + { 1, 0x100bb3, 0x1301e1, 0x05a014, 0x001402 }, + { 2, 0x100bb3, 0x1301e1, 0x05a014, 0x001407 }, + { 3, 0x100bb3, 0x1301e2, 0x05a014, 0x001402 }, + { 4, 0x100bb3, 0x1301e2, 0x05a014, 0x001407 }, + { 5, 0x100bb3, 0x1301e3, 0x05a014, 0x001402 }, + { 6, 0x100bb3, 0x1301e3, 0x05a014, 0x001407 }, + { 7, 0x100bb3, 0x1301e4, 0x05a014, 0x001402 }, + { 8, 0x100bb3, 0x1301e4, 0x05a014, 0x001407 }, + { 9, 0x100bb3, 0x1301e5, 0x05a014, 0x001402 }, + { 10, 0x100bb3, 0x1301e5, 0x05a014, 0x001407 }, + { 11, 0x100bb3, 0x1301e6, 0x05a014, 0x001402 }, + { 12, 0x100bb3, 0x1301e6, 0x05a014, 0x001407 }, + { 13, 0x100bb3, 0x1301e7, 0x05a014, 0x001402 }, + { 14, 0x100bb3, 0x1301e8, 0x05a014, 0x001404 }, + { 36, 0x100bb3, 0x130266, 0x056014, 0x001408 }, + { 38, 0x100bb3, 0x130267, 0x056014, 0x001404 }, + { 40, 0x100bb2, 0x1301a0, 0x056014, 0x001400 }, + { 44, 0x100bb2, 0x1301a0, 0x056014, 0x001408 }, + { 46, 0x100bb2, 0x1301a1, 0x056014, 0x001402 }, + { 48, 0x100bb2, 0x1301a1, 0x056014, 0x001406 }, + { 52, 0x100bb2, 0x1301a2, 0x056014, 0x001404 }, + { 54, 0x100bb2, 0x1301a2, 0x056014, 0x001408 }, + { 56, 0x100bb2, 0x1301a3, 0x056014, 0x001402 }, + { 60, 0x100bb2, 0x1301a4, 0x056014, 0x001400 }, + { 62, 0x100bb2, 0x1301a4, 0x056014, 0x001404 }, + { 64, 0x100bb2, 0x1301a4, 0x056014, 0x001408 }, + { 100, 0x100bb2, 0x1301ac, 0x05e014, 0x001400 }, + { 102, 0x100bb2, 0x1701ac, 0x15e014, 0x001404 }, + { 104, 0x100bb2, 0x1701ac, 0x15e014, 0x001408 }, + { 108, 0x100bb3, 0x17028c, 0x15e014, 0x001404 }, + { 110, 0x100bb3, 0x13028d, 0x05e014, 0x001400 }, + { 112, 0x100bb3, 0x13028d, 0x05e014, 0x001406 }, + { 116, 0x100bb3, 0x13028e, 0x05e014, 0x001408 }, + { 118, 0x100bb3, 0x13028f, 0x05e014, 0x001404 }, + { 120, 0x100bb1, 0x1300e0, 0x05e014, 0x001400 }, + { 124, 0x100bb1, 0x1300e0, 0x05e014, 0x001404 }, + { 126, 0x100bb1, 0x1300e0, 0x05e014, 0x001406 }, + { 128, 0x100bb1, 0x1300e0, 0x05e014, 0x001408 }, + { 132, 0x100bb1, 0x1300e1, 0x05e014, 0x001402 }, + { 134, 0x100bb1, 0x1300e1, 0x05e014, 0x001404 }, + { 136, 0x100bb1, 0x1300e1, 0x05e014, 0x001406 }, + { 140, 0x100bb1, 0x1300e2, 0x05e014, 0x001400 }, + { 149, 0x100bb1, 0x1300e2, 0x05e014, 0x001409 }, + { 151, 0x100bb1, 0x1300e3, 0x05e014, 0x001401 }, + { 153, 0x100bb1, 0x1300e3, 0x05e014, 0x001403 }, + { 157, 0x100bb1, 0x1300e3, 0x05e014, 0x001407 }, + { 159, 0x100bb1, 0x1300e3, 0x05e014, 0x001409 }, + { 161, 0x100bb1, 0x1300e4, 0x05e014, 0x001401 }, + { 165, 0x100bb1, 0x1300e4, 0x05e014, 0x001405 }, + { 167, 0x100bb1, 0x1300f4, 0x05e014, 0x001407 }, + { 169, 0x100bb1, 0x1300f4, 0x05e014, 0x001409 }, + { 171, 0x100bb1, 0x1300f5, 0x05e014, 0x001401 }, + { 173, 0x100bb1, 0x1300f5, 0x05e014, 0x001403 }, +}; + +struct { + u8int n; + u8int r; + u8int k; +} rt3090_freqs[] = { + { 0xf1, 2, 2 }, + { 0xf1, 2, 7 }, + { 0xf2, 2, 2 }, + { 0xf2, 2, 7 }, + { 0xf3, 2, 2 }, + { 0xf3, 2, 7 }, + { 0xf4, 2, 2 }, + { 0xf4, 2, 7 }, + { 0xf5, 2, 2 }, + { 0xf5, 2, 7 }, + { 0xf6, 2, 2 }, + { 0xf6, 2, 7 }, + { 0xf7, 2, 2 }, + { 0xf8, 2, 4 }, + { 0x56, 0, 4 }, + { 0x56, 0, 6 }, + { 0x56, 0, 8 }, + { 0x57, 0, 0 }, + { 0x57, 0, 2 }, + { 0x57, 0, 4 }, + { 0x57, 0, 8 }, + { 0x57, 0, 10 }, + { 0x58, 0, 0 }, + { 0x58, 0, 4 }, + { 0x58, 0, 6 }, + { 0x58, 0, 8 }, + { 0x5b, 0, 8 }, + { 0x5b, 0, 10 }, + { 0x5c, 0, 0 }, + { 0x5c, 0, 4 }, + { 0x5c, 0, 6 }, + { 0x5c, 0, 8 }, + { 0x5d, 0, 0 }, + { 0x5d, 0, 2 }, + { 0x5d, 0, 4 }, + { 0x5d, 0, 8 }, + { 0x5d, 0, 10 }, + { 0x5e, 0, 0 }, + { 0x5e, 0, 4 }, + { 0x5e, 0, 6 }, + { 0x5e, 0, 8 }, + { 0x5f, 0, 0 }, + { 0x5f, 0, 9 }, + { 0x5f, 0, 11 }, + { 0x60, 0, 1 }, + { 0x60, 0, 5 }, + { 0x60, 0, 7 }, + { 0x60, 0, 9 }, + { 0x61, 0, 1 }, + { 0x61, 0, 3 }, + { 0x61, 0, 5 }, + { 0x61, 0, 7 }, + { 0x61, 0, 9 } +}; + +static const struct { + u8int reg; + u8int val; +} rt3090_def_rf[] = { + { 4, 0x40 }, + { 5, 0x03 }, + { 6, 0x02 }, + { 7, 0x70 }, + { 9, 0x0f }, + { 10, 0x41 }, + { 11, 0x21 }, + { 12, 0x7b }, + { 14, 0x90 }, + { 15, 0x58 }, + { 16, 0xb3 }, + { 17, 0x92 }, + { 18, 0x2c }, + { 19, 0x02 }, + { 20, 0xba }, + { 21, 0xdb }, + { 24, 0x16 }, + { 25, 0x01 }, + { 29, 0x1f } +}; + +/* vendors */ +enum { + Ralink = 0x1814, + Awt = 0x1a3b, +}; +/* products */ +enum { + RalinkRT2890 = 0x0681, + RalinkRT2790 = 0x0781, + RalinkRT3090 = 0x3090, + AwtRT2890 = 0x1059, +}; + +#define csr32r(c, r) (*((c)->nic+((r)/4))) +#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) + +static int rbplant(Ctlr*, int); +static void setchan(Ctlr*, uint); +static void rt3090setchan(Ctlr*, uint); +static void selchangroup(Ctlr*, int); +static void setleds(Ctlr*, u16int); + +static uint +get16(uchar *p){ + return *((u16int*)p); +} +static uint +get32(uchar *p){ + return *((u32int*)p); +} +static void +put32(uchar *p, uint v){ + *((u32int*)p) = v; +} +static void +put16(uchar *p, uint v){ + *((u16int*)p) = v; +}; +static void +memwrite(Ctlr *ctlr, u32int off, uchar *data, uint size){ + memmove((uchar*)ctlr->nic + off, data, size); +} +static void +setregion(Ctlr *ctlr, u32int off, uint val, uint size){ + memset((uchar*)ctlr->nic + off, val, size); +} + +static long +rt2860ctl(Ether *edev, void *buf, long n) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->wifi) + return wifictl(ctlr->wifi, buf, n); + return 0; +} + +static long +rt2860ifstat(Ether *edev, void *buf, long n, ulong off) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->wifi) + return wifistat(ctlr->wifi, buf, n, off); + return 0; +} + +static void +setoptions(Ether *edev) +{ + Ctlr *ctlr; + int i; + + ctlr = edev->ctlr; + for(i = 0; i < edev->nopt; i++) + wificfg(ctlr->wifi, edev->opt[i]); +} + +static void +rxon(Ether *edev, Wnode *bss) +{ + u32int tmp; + Ctlr *ctlr; + int cap; + + ctlr = edev->ctlr; + + if(bss != nil){ + cap = bss->cap; + ctlr->channel = bss->channel; + memmove(ctlr->bssid, bss->bssid, Eaddrlen); + ctlr->aid = bss->aid; + if(ctlr->aid != 0){ + if(ctlr->wifi->debug) + print("new assoc!"); + ctlr->bssnodeid = -1; + }else + ctlr->bcastnodeid = -1; + }else{ + cap = 0; + memmove(ctlr->bssid, edev->bcast, Eaddrlen); + ctlr->aid = 0; + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + } + if(ctlr->aid != 0) + setleds(ctlr, LedRadio | LedLink2ghz); + else + setleds(ctlr, LedRadio); + + if(ctlr->wifi->debug) + print("#l%d: rxon: bssid %E, aid %x, channel %d wcid %d\n", + edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->wcid); + + /* Set channel */ + if(ctlr->mac_ver >= 0x3071) + rt3090setchan(ctlr, ctlr->channel); + else + setchan(ctlr, ctlr->channel); + selchangroup(ctlr, 0); + microdelay(1000); + + /* enable mrr(?) */ +#define CCK(mcs) (mcs) +#define OFDM(mcs) (1 << 3 | (mcs)) + csr32w(ctlr, LgFbkCfg0, + OFDM(6) << 28 | /* 54->48 */ + OFDM(5) << 24 | /* 48->36 */ + OFDM(4) << 20 | /* 36->24 */ + OFDM(3) << 16 | /* 24->18 */ + OFDM(2) << 12 | /* 18->12 */ + OFDM(1) << 8 | /* 12-> 9 */ + OFDM(0) << 4 | /* 9-> 6 */ + OFDM(0)); /* 6-> 6 */ + + csr32w(ctlr, LgFbkCfg1, + CCK(2) << 12 | /* 11->5.5 */ + CCK(1) << 8 | /* 5.5-> 2 */ + CCK(0) << 4 | /* 2-> 1 */ + CCK(0)); /* 1-> 1 */ +#undef OFDM +#undef CCK + /* update slot */ + tmp = csr32r(ctlr, BkoffSlotCfg); + tmp &= ~0xff; + tmp |= (cap & (1<<10)) ? 9 : 20; + csr32w(ctlr, BkoffSlotCfg, tmp); + + /* set TX preamble */ + tmp = csr32r(ctlr, AutoRspCfg); + tmp &= ~CckShortEn; + if(cap & (1<<5)) tmp |= CckShortEn; + csr32w(ctlr, AutoRspCfg, tmp); + + /* set basic rates */ + csr32w(ctlr, LegacyBasicRate, 0x003); /* 11B */ + + /* Set BSSID */ + csr32w(ctlr, MacBssidDw0, + ctlr->bssid[0] | ctlr->bssid[1] << 8 | ctlr->bssid[2] << 16 | ctlr->bssid[3] << 24); + csr32w(ctlr, MacBssidDw1, + ctlr->bssid[4] | ctlr->bssid[5] << 8); + + if(ctlr->bcastnodeid == -1){ + ctlr->bcastnodeid = 0xff; + memwrite(ctlr, WcidEntry(ctlr->bcastnodeid), edev->bcast, Eaddrlen); + } + if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){ + ctlr->bssnodeid = 0; + memwrite(ctlr, WcidEntry(ctlr->bssnodeid), ctlr->bssid, Eaddrlen); + } +} + +static void +rt2860promiscuous(void *arg, int on) +{ + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + if(ctlr->attached == 0) + return; + qlock(ctlr); + ctlr->prom = on; + rxon(edev, ctlr->wifi->bss); + qunlock(ctlr); +} + +static void +rt2860multicast(void *, uchar*, int) +{ +} + +static FWImage* +readfirmware(void){ + static char name[] = "ral-rt2860"; + uchar dirbuf[sizeof(Dir)+100], *data; + char buf[128]; + FWImage *fw; + int n, r; + Chan *c; + Dir d; + + if(!iseve()) + error(Eperm); + if(!waserror()){ + snprint(buf, sizeof buf, "/boot/%s", name); + c = namec(buf, Aopen, OREAD, 0); + poperror(); + }else{ + snprint(buf, sizeof buf, "/lib/firmware/%s", name); + c = namec(buf, Aopen, OREAD, 0); + } + if(waserror()){ + cclose(c); + nexterror(); + } + n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf); + if(n <= 0) + error("can't stat firmware"); + convM2D(dirbuf, n, &d, nil); + fw = malloc(sizeof(*fw)); + fw->size = d.length; + data = fw->data = smalloc(d.length); + if(waserror()){ + free(fw); + nexterror(); + } + r = 0; + while(r < d.length){ + n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r); + if(n <= 0) + break; + r += n; + } + poperror(); + poperror(); + cclose(c); + return fw; +} + +static char* +boot(Ctlr *ctlr) +{ + int ntries; + + /* set "host program ram write selection" bit */ + csr32w(ctlr, SysCtrl, HstPmSel); + /* write microcode image */ + memwrite(ctlr, FwBase, ctlr->fw->data, ctlr->fw->size); + /* kick microcontroller unit */ + csr32w(ctlr, SysCtrl, 0); + coherence(); + csr32w(ctlr, SysCtrl, McuReset); + + csr32w(ctlr, H2mBbpagent, 0); + csr32w(ctlr, H2mMailbox, 0); + + /* wait until microcontroller is ready */ + coherence(); + for(ntries = 0; ntries < 1000; ntries++){ + if(csr32r(ctlr, SysCtrl) & McuReady) + break; + microdelay(1000); + } + if(ntries == 1000) + return "timeout waiting for MCU to initialize"; + return 0; +} + +/* + * Send a command to the 8051 microcontroller unit. + */ +static int +mcucmd(Ctlr *ctlr, u8int cmd, u16int arg, int wait) +{ + int slot, ntries; + u32int tmp; + u8int cid; + + SET(slot); + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, H2mMailbox) & H2mBusy)) + break; + microdelay(2); + } + if(ntries == 100) + return -1; + + cid = wait ? cmd : TokenNoIntr; + csr32w(ctlr, H2mMailbox, H2mBusy | cid << 16 | arg); + coherence(); + csr32w(ctlr, HostCmd, cmd); + + if(!wait) + return 0; + /* wait for the command to complete */ + for(ntries = 0; ntries < 200; ntries++){ + tmp = csr32r(ctlr, H2mMailboxCid); + /* find the command slot */ + for(slot = 0; slot < 4; slot++, tmp >>= 8) + if((tmp & 0xff) == cid) + break; + if(slot < 4) + break; + microdelay(100); + } + if(ntries == 200){ + /* clear command and status */ + csr32w(ctlr, H2mMailboxStatus, 0xffffffff); + csr32w(ctlr, H2mMailboxCid, 0xffffffff); + return -1; + } + /* get command status (1 means success) */ + tmp = csr32r(ctlr, H2mMailboxStatus); + tmp = (tmp >> (slot * 8)) & 0xff; + /* clear command and status */ + csr32w(ctlr, H2mMailboxStatus, 0xffffffff); + csr32w(ctlr, H2mMailboxCid, 0xffffffff); + return (tmp == 1) ? 0 : -1; +} + + +/* + * Reading and writing from/to the BBP is different from RT2560 and RT2661. + * We access the BBP through the 8051 microcontroller unit which means that + * the microcode must be loaded first. + */ +static void +bbpwrite(Ctlr *ctlr, u8int reg, u8int val) +{ + int ntries; + + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, H2mBbpagent) & BbpCsrKick)) + break; + microdelay(1); + } + if(ntries == 100){ + print("could not write to BBP through MCU\n"); + return; + } + + csr32w(ctlr, H2mBbpagent, BbpRwParallel | + BbpCsrKick | reg << 8 | val); + coherence(); + + mcucmd(ctlr, McuCmdBbp, 0, 0); + microdelay(1000); +} + +static u8int +bbpread(Ctlr *ctlr, u8int reg) +{ + u32int val; + int ntries; + + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, H2mBbpagent) & BbpCsrKick)) + break; + microdelay(1); + } + if(ntries == 100){ + print("could not read from BBP through MCU"); + return 0; + } + + csr32w(ctlr, H2mBbpagent, BbpRwParallel | + BbpCsrKick | BbpCsrRead | reg << 8); + coherence(); + + mcucmd(ctlr, McuCmdBbp, 0, 0); + microdelay(1000); + + for(ntries = 0; ntries < 100; ntries++){ + val = csr32r(ctlr, H2mBbpagent); + if(!(val & BbpCsrKick)) + return val & 0xff; + microdelay(1); + } + print("could not read from BBP through MCU\n"); + + return 0; +} + +static char* +bbpinit(Ctlr *ctlr) +{ + int i, ntries; + char *err; + + /* wait for BBP to wake up */ + for(ntries = 0; ntries < 20; ntries++){ + u8int bbp0 = bbpread(ctlr, 0); + if(bbp0 != 0 && bbp0 != 0xff) + break; + } + if(ntries == 20){ + err = "timeout waiting for BBP to wake up"; + return err; + } + + /* initialize BBP registers to default values */ + for(i = 0; i < nelem(rt2860_def_bbp); i++){ + bbpwrite(ctlr, rt2860_def_bbp[i].reg, + rt2860_def_bbp[i].val); + } + + /* fix BBP84 for RT2860E */ + if(ctlr->mac_ver == 0x2860 && ctlr->mac_rev != 0x0101) + bbpwrite(ctlr, 84, 0x19); + + if(ctlr->mac_ver >= 0x3071){ + bbpwrite(ctlr, 79, 0x13); + bbpwrite(ctlr, 80, 0x05); + bbpwrite(ctlr, 81, 0x33); + }else if(ctlr->mac_ver == 0x2860 && ctlr->mac_rev == 0x0100){ + bbpwrite(ctlr, 69, 0x16); + bbpwrite(ctlr, 73, 0x12); + } + + return nil; + +} + +static void +setleds(Ctlr *ctlr, u16int which) +{ + mcucmd(ctlr, McuCmdLeds, + which | (ctlr->leds & 0x7f), 0); +} + +static char* +txrxon(Ctlr *ctlr) +{ + u32int tmp; + int ntries; + char *err; + + SET(tmp); + /* enable Tx/Rx DMA engine */ + csr32w(ctlr, MacSysCtrl, MacTxEn); + coherence(); + for(ntries = 0; ntries < 200; ntries++){ + tmp = csr32r(ctlr, WpdmaGloCfg); + if((tmp & (TxDmaBusy | RxDmaBusy)) == 0) + break; + microdelay(1000); + } + if(ntries == 200){ + err = "timeout waiting for DMA engine"; + return err; + } + + microdelay(50); + + tmp |= RxDmaEn | TxDmaEn | + WpdmaBtSize64 << WpdmaBtSizeShift; + csr32w(ctlr, WpdmaGloCfg, tmp); + + /* set Rx filter */ + tmp = DropCrcErr | DropPhyErr; + if(!ctlr->prom){ + tmp |= DropUcNome | DropDupl | + DropCts | DropBa | DropAck | + DropVerErr | DropCtrlRsv | + DropCfack | DropCfend; + tmp |= DropRts | DropPspoll; + } + csr32w(ctlr, RxFiltrCfg, tmp); + + csr32w(ctlr, MacSysCtrl, MacRxEn | MacTxEn); + + return 0; +} + +/* + * Write to one of the 4 programmable 24-bit RF registers. + */ +static void +rfwrite(Ctlr *ctlr, u8int reg, u32int val) +{ + u32int tmp; + int ntries; + + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, RfCsrCfg0) & RfRegCtrl)) + break; + microdelay(1); + } + if(ntries == 100){ + print("could not write to RF\n"); + return; + } + + /* RF registers are 24-bit on the RT2860 */ + tmp = RfRegCtrl | 24 << RfRegWidthShift | + (val & 0x3fffff) << 2 | (reg & 3); + csr32w(ctlr, RfCsrCfg0, tmp); +} + +u8int +rt3090rfread(Ctlr *ctlr, u8int reg) +{ + u32int tmp; + int ntries; + + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, Rt3070RfCsrCfg) & Rt3070RfKick)) + break; + microdelay(1); + } + if(ntries == 100){ + print("could not read RF register\n"); + return 0xff; + } + tmp = Rt3070RfKick | reg << 8; + csr32w(ctlr, Rt3070RfCsrCfg, tmp); + + for(ntries = 0; ntries < 100; ntries++){ + tmp = csr32r(ctlr, Rt3070RfCsrCfg); + if(!(tmp & Rt3070RfKick)) + break; + microdelay(1); + } + if(ntries == 100){ + print("could not read RF register\n"); + return 0xff; + } + return tmp & 0xff; +} + +static void +rt3090rfwrite(Ctlr *ctlr, u8int reg, u8int val) +{ + u32int tmp; + int ntries; + + for(ntries = 0; ntries < 10; ntries++){ + if(!(csr32r(ctlr, Rt3070RfCsrCfg) & Rt3070RfKick)) + break; + microdelay(10); + } + if(ntries == 10){ + print("could not write to RF\n"); + return; + } + + tmp = Rt3070RfWrite | Rt3070RfKick | reg << 8 | val; + csr32w(ctlr, Rt3070RfCsrCfg, tmp); +} + +static void +selchangroup(Ctlr *ctlr, int group) +{ + u32int tmp; + u8int agc; + + bbpwrite(ctlr, 62, 0x37 - ctlr->lna[group]); + bbpwrite(ctlr, 63, 0x37 - ctlr->lna[group]); + bbpwrite(ctlr, 64, 0x37 - ctlr->lna[group]); + bbpwrite(ctlr, 86, 0x00); + + if(group == 0){ + if(ctlr->ext_2ghz_lna){ + bbpwrite(ctlr, 82, 0x62); + bbpwrite(ctlr, 75, 0x46); + }else{ + bbpwrite(ctlr, 82, 0x84); + bbpwrite(ctlr, 75, 0x50); + } + }else{ + if(ctlr->ext_5ghz_lna){ + bbpwrite(ctlr, 82, 0xf2); + bbpwrite(ctlr, 75, 0x46); + }else{ + bbpwrite(ctlr, 82, 0xf2); + bbpwrite(ctlr, 75, 0x50); + } + } + + tmp = csr32r(ctlr, TxBandCfg); + tmp &= ~(Tx5gBandSelN | Tx5gBandSelP); + tmp |= (group == 0) ? Tx5gBandSelN : Tx5gBandSelP; + csr32w(ctlr, TxBandCfg, tmp); + + /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ + tmp = RftrEn | TrswEn | LnaPe0En; + if(ctlr->nrxchains > 1) + tmp |= LnaPe1En; + if(ctlr->mac_ver == 0x3593 && ctlr->nrxchains > 2) + tmp |= Rt3593LnaPe2En; + if(group == 0){ /* 2GHz */ + tmp |= PaPeG0En; + if(ctlr->ntxchains > 1) + tmp |= PaPeG1En; + if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains > 2) + tmp |= Rt3593PaPeG2En; + }else{ /* 5GHz */ + tmp |= PaPeA0En; + if(ctlr->ntxchains > 1) + tmp |= PaPeA1En; + if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains > 2) + tmp |= Rt3593PaPeA2En; + } + csr32w(ctlr, TxPinCfg, tmp); + + if(ctlr->mac_ver == 0x3593){ + tmp = csr32r(ctlr, GpioCtrl); + if(ctlr->flags & ConnPciE){ + tmp &= ~0x01010000; + if(group == 0) + tmp |= 0x00010000; + }else{ + tmp &= ~0x00008080; + if(group == 0) + tmp |= 0x00000080; + } + tmp = (tmp & ~0x00001000) | 0x00000010; + csr32w(ctlr, GpioCtrl, tmp); + } + + /* set initial AGC value */ + if(group == 0){ /* 2GHz band */ + if(ctlr->mac_ver >= 0x3071) + agc = 0x1c + ctlr->lna[0] * 2; + else + agc = 0x2e + ctlr->lna[0]; + }else{ /* 5GHz band */ + agc = 0x32 + (ctlr->lna[group] * 5) / 3; + } + bbpwrite(ctlr, 66, agc); + + microdelay(1000); + +} + +static void +setchan(Ctlr *ctlr, uint chan) +{ + const struct rfprog *rfprog = rt2860_rf2850; + u32int r2, r3, r4; + s8int txpow1, txpow2; + uint i; + + /* find the settings for this channel (we know it exists) */ + for(i = 0; rfprog[i].chan != chan; i++); + + r2 = rfprog[i].r2; + if(ctlr->ntxchains == 1) + r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ + if(ctlr->nrxchains == 1) + r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ + else if(ctlr->nrxchains == 2) + r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ + + /* use Tx power values from EEPROM */ + txpow1 = ctlr->txpow1[i]; + txpow2 = ctlr->txpow2[i]; + if(chan > 14){ + if(txpow1 >= 0) + txpow1 = txpow1 << 1 | 1; + else + txpow1 = (7 + txpow1) << 1; + if(txpow2 >= 0) + txpow2 = txpow2 << 1 | 1; + else + txpow2 = (7 + txpow2) << 1; + } + r3 = rfprog[i].r3 | txpow1 << 7; + r4 = rfprog[i].r4 | ctlr->freq << 13 | txpow2 << 4; + + rfwrite(ctlr, Rf1, rfprog[i].r1); + rfwrite(ctlr, Rf2, r2); + rfwrite(ctlr, Rf3, r3); + rfwrite(ctlr, Rf4, r4); + + microdelay(200); + + rfwrite(ctlr, Rf1, rfprog[i].r1); + rfwrite(ctlr, Rf2, r2); + rfwrite(ctlr, Rf3, r3 | 1); + rfwrite(ctlr, Rf4, r4); + + microdelay(200); + + rfwrite(ctlr, Rf1, rfprog[i].r1); + rfwrite(ctlr, Rf2, r2); + rfwrite(ctlr, Rf3, r3); + rfwrite(ctlr, Rf4, r4); +} + +static void +rt3090setchan(Ctlr *ctlr, uint chan) +{ + s8int txpow1, txpow2; + u8int rf; + int i; + + assert(chan >= 1 && chan <= 14); /* RT3090 is 2GHz only */ + + /* find the settings for this channel (we know it exists) */ + for(i = 0; rt2860_rf2850[i].chan != chan; i++); + + /* use Tx power values from EEPROM */ + txpow1 = ctlr->txpow1[i]; + txpow2 = ctlr->txpow2[i]; + + rt3090rfwrite(ctlr, 2, rt3090_freqs[i].n); + rf = rt3090rfread(ctlr, 3); + rf = (rf & ~0x0f) | rt3090_freqs[i].k; + rt3090rfwrite(ctlr, 3, rf); + rf = rt3090rfread(ctlr, 6); + rf = (rf & ~0x03) | rt3090_freqs[i].r; + rt3090rfwrite(ctlr, 6, rf); + + /* set Tx0 power */ + rf = rt3090rfread(ctlr, 12); + rf = (rf & ~0x1f) | txpow1; + rt3090rfwrite(ctlr, 12, rf); + + /* set Tx1 power */ + rf = rt3090rfread(ctlr, 13); + rf = (rf & ~0x1f) | txpow2; + rt3090rfwrite(ctlr, 13, rf); + + rf = rt3090rfread(ctlr, 1); + rf &= ~0xfc; + if(ctlr->ntxchains == 1) + rf |= Rt3070Tx1Pd | Rt3070Tx2Pd; + else if(ctlr->ntxchains == 2) + rf |= Rt3070Tx2Pd; + if(ctlr->nrxchains == 1) + rf |= Rt3070Rx1Pd | Rt3070Rx2Pd; + else if(ctlr->nrxchains == 2) + rf |= Rt3070Rx2Pd; + rt3090rfwrite(ctlr, 1, rf); + + /* set RF offset */ + rf = rt3090rfread(ctlr, 23); + rf = (rf & ~0x7f) | ctlr->freq; + rt3090rfwrite(ctlr, 23, rf); + + /* program RF filter */ + rf = rt3090rfread(ctlr, 24); /* Tx */ + rf = (rf & ~0x3f) | ctlr->rf24_20mhz; + rt3090rfwrite(ctlr, 24, rf); + rf = rt3090rfread(ctlr, 31); /* Rx */ + rf = (rf & ~0x3f) | ctlr->rf24_20mhz; + rt3090rfwrite(ctlr, 31, rf); + + /* enable RF tuning */ + rf = rt3090rfread(ctlr, 7); + rt3090rfwrite(ctlr, 7, rf | Rt3070Tune); +} + +static int +rt3090filtercalib(Ctlr *ctlr, u8int init, u8int target, u8int *val) +{ + u8int rf22, rf24; + u8int bbp55_pb, bbp55_sb, delta; + int ntries; + + /* program filter */ + rf24 = rt3090rfread(ctlr, 24); + rf24 = (rf24 & 0xc0) | init; /* initial filter value */ + rt3090rfwrite(ctlr, 24, rf24); + + /* enable baseband loopback mode */ + rf22 = rt3090rfread(ctlr, 22); + rt3090rfwrite(ctlr, 22, rf22 | Rt3070BbLoopback); + + /* set power and frequency of passband test tone */ + bbpwrite(ctlr, 24, 0x00); + for(ntries = 0, bbp55_pb = 0; ntries < 100; ntries++){ + /* transmit test tone */ + bbpwrite(ctlr, 25, 0x90); + microdelay(1000); + /* read received power */ + bbp55_pb = bbpread(ctlr, 55); + if(bbp55_pb != 0) + break; + } + if(ntries == 100) + return -1; + + /* set power and frequency of stopband test tone */ + bbpwrite(ctlr, 24, 0x06); + for(ntries = 0; ntries < 100; ntries++){ + /* transmit test tone */ + bbpwrite(ctlr, 25, 0x90); + microdelay(1000); + /* read received power */ + bbp55_sb = bbpread(ctlr, 55); + + delta = bbp55_pb - bbp55_sb; + if(delta > target) + break; + + /* reprogram filter */ + rf24++; + rt3090rfwrite(ctlr, 24, rf24); + } + if(ntries < 100){ + if(rf24 != init) + rf24--; /* backtrack */ + *val = rf24; + rt3090rfwrite(ctlr, 24, rf24); + } + + /* restore initial state */ + bbpwrite(ctlr, 24, 0x00); + + /* disable baseband loopback mode */ + rf22 = rt3090rfread(ctlr, 22); + rt3090rfwrite(ctlr, 22, rf22 & ~Rt3070BbLoopback); + + return 0; +} + +static void +rt3090setrxantenna(Ctlr *ctlr, int aux) +{ + u32int tmp; + + if(aux){ + tmp = csr32r(ctlr, PciEectrl); + csr32w(ctlr, PciEectrl, tmp & ~EectrlC); + tmp = csr32r(ctlr, GpioCtrl); + csr32w(ctlr, GpioCtrl, (tmp & ~0x0808) | 0x08); + }else{ + tmp = csr32r(ctlr, PciEectrl); + csr32w(ctlr, PciEectrl, tmp | EectrlC); + tmp = csr32r(ctlr, GpioCtrl); + csr32w(ctlr, GpioCtrl, tmp & ~0x0808); + } +} + +static int +rt3090rfinit(Ctlr *ctlr) +{ + u32int tmp; + u8int rf, bbp; + int i; + + rf = rt3090rfread(ctlr, 30); + /* toggle RF R30 bit 7 */ + rt3090rfwrite(ctlr, 30, rf | 0x80); + microdelay(1000); + rt3090rfwrite(ctlr, 30, rf & ~0x80); + + tmp = csr32r(ctlr, Rt3070LdoCfg0); + tmp &= ~0x1f000000; + if(ctlr->patch_dac && ctlr->mac_rev < 0x0211) + tmp |= 0x0d000000; /* 1.35V */ + else + tmp |= 0x01000000; /* 1.2V */ + csr32w(ctlr, Rt3070LdoCfg0, tmp); + + /* patch LNA_PE_G1 */ + tmp = csr32r(ctlr, Rt3070GpioSwitch); + csr32w(ctlr, Rt3070GpioSwitch, tmp & ~0x20); + + /* initialize RF registers to default value */ + for(i = 0; i < nelem(rt3090_def_rf); i++){ + rt3090rfwrite(ctlr, rt3090_def_rf[i].reg, + rt3090_def_rf[i].val); + } + + /* select 20MHz bandwidth */ + rt3090rfwrite(ctlr, 31, 0x14); + + rf = rt3090rfread(ctlr, 6); + rt3090rfwrite(ctlr, 6, rf | 0x40); + + if(ctlr->mac_ver != 0x3593){ + /* calibrate filter for 20MHz bandwidth */ + ctlr->rf24_20mhz = 0x1f; /* default value */ + rt3090filtercalib(ctlr, 0x07, 0x16, &ctlr->rf24_20mhz); + + /* select 40MHz bandwidth */ + bbp = bbpread(ctlr, 4); + bbpwrite(ctlr, 4, (bbp & ~0x08) | 0x10); + rf = rt3090rfread(ctlr, 31); + rt3090rfwrite(ctlr, 31, rf | 0x20); + + /* calibrate filter for 40MHz bandwidth */ + ctlr->rf24_40mhz = 0x2f; /* default value */ + rt3090filtercalib(ctlr, 0x27, 0x19, &ctlr->rf24_40mhz); + + /* go back to 20MHz bandwidth */ + bbp = bbpread(ctlr, 4); + bbpwrite(ctlr, 4, bbp & ~0x18); + } + if(ctlr->mac_rev < 0x0211) + rt3090rfwrite(ctlr, 27, 0x03); + + tmp = csr32r(ctlr, Rt3070Opt14); + csr32w(ctlr, Rt3070Opt14, tmp | 1); + + if(ctlr->rf_rev == Rf3020) + rt3090setrxantenna(ctlr, 0); + + bbp = bbpread(ctlr, 138); + if(ctlr->mac_ver == 0x3593){ + if(ctlr->ntxchains == 1) + bbp |= 0x60; /* turn off DAC1 and DAC2 */ + else if(ctlr->ntxchains == 2) + bbp |= 0x40; /* turn off DAC2 */ + if(ctlr->nrxchains == 1) + bbp &= ~0x06; /* turn off ADC1 and ADC2 */ + else if(ctlr->nrxchains == 2) + bbp &= ~0x04; /* turn off ADC2 */ + }else{ + if(ctlr->ntxchains == 1) + bbp |= 0x20; /* turn off DAC1 */ + if(ctlr->nrxchains == 1) + bbp &= ~0x02; /* turn off ADC1 */ + } + bbpwrite(ctlr, 138, bbp); + + rf = rt3090rfread(ctlr, 1); + rf &= ~(Rt3070Rx0Pd | Rt3070Tx0Pd); + rf |= Rt3070RfBlock | Rt3070Rx1Pd | Rt3070Tx1Pd; + rt3090rfwrite(ctlr, 1, rf); + + rf = rt3090rfread(ctlr, 15); + rt3090rfwrite(ctlr, 15, rf & ~Rt3070TxLo2); + + rf = rt3090rfread(ctlr, 17); + rf &= ~Rt3070TxLo1; + if(ctlr->mac_rev >= 0x0211 && !ctlr->ext_2ghz_lna) + rf |= 0x20; /* fix for long range Rx issue */ + if(ctlr->txmixgain_2ghz >= 2) + rf = (rf & ~0x7) | ctlr->txmixgain_2ghz; + rt3090rfwrite(ctlr, 17, rf); + + rf = rt3090rfread(ctlr, 20); + rt3090rfwrite(ctlr, 20, rf & ~Rt3070RxLo1); + + rf = rt3090rfread(ctlr, 21); + rt3090rfwrite(ctlr, 21, rf & ~Rt3070RxLo2); + + return 0; +} + +static void +rt3090rfwakeup(Ctlr *ctlr) +{ + u32int tmp; + u8int rf; + + if(ctlr->mac_ver == 0x3593){ + /* enable VCO */ + rf = rt3090rfread(ctlr, 1); + rt3090rfwrite(ctlr, 1, rf | Rt3593Vco); + + /* initiate VCO calibration */ + rf = rt3090rfread(ctlr, 3); + rt3090rfwrite(ctlr, 3, rf | Rt3593Vcocal); + + /* enable VCO bias current control */ + rf = rt3090rfread(ctlr, 6); + rt3090rfwrite(ctlr, 6, rf | Rt3593VcoIc); + + /* initiate res calibration */ + rf = rt3090rfread(ctlr, 2); + rt3090rfwrite(ctlr, 2, rf | Rt3593Rescal); + + /* set reference current control to 0.33 mA */ + rf = rt3090rfread(ctlr, 22); + rf &= ~Rt3593CpIcMask; + rf |= 1 << Rt3593CpIcShift; + rt3090rfwrite(ctlr, 22, rf); + + /* enable RX CTB */ + rf = rt3090rfread(ctlr, 46); + rt3090rfwrite(ctlr, 46, rf | Rt3593RxCtb); + + rf = rt3090rfread(ctlr, 20); + rf &= ~(Rt3593LdoRfVcMask | Rt3593LdoPllVcMask); + rt3090rfwrite(ctlr, 20, rf); + }else{ + /* enable RF block */ + rf = rt3090rfread(ctlr, 1); + rt3090rfwrite(ctlr, 1, rf | Rt3070RfBlock); + + /* enable VCO bias current control */ + rf = rt3090rfread(ctlr, 7); + rt3090rfwrite(ctlr, 7, rf | 0x30); + + rf = rt3090rfread(ctlr, 9); + rt3090rfwrite(ctlr, 9, rf | 0x0e); + + /* enable RX CTB */ + rf = rt3090rfread(ctlr, 21); + rt3090rfwrite(ctlr, 21, rf | Rt3070RxCtb); + + /* fix Tx to Rx IQ glitch by raising RF voltage */ + rf = rt3090rfread(ctlr, 27); + rf &= ~0x77; + if(ctlr->mac_rev < 0x0211) + rf |= 0x03; + rt3090rfwrite(ctlr, 27, rf); + } + if(ctlr->patch_dac && ctlr->mac_rev < 0x0211){ + tmp = csr32r(ctlr, Rt3070LdoCfg0); + tmp = (tmp & ~0x1f000000) | 0x0d000000; + csr32w(ctlr, Rt3070LdoCfg0, tmp); + } +} + +static void +rt3090rfsetup(Ctlr *ctlr) +{ + u8int bbp; + int i; + + if(ctlr->mac_rev >= 0x0211){ + /* enable DC filter */ + bbpwrite(ctlr, 103, 0xc0); + + /* improve power consumption */ + bbp = bbpread(ctlr, 31); + bbpwrite(ctlr, 31, bbp & ~0x03); + } + + csr32w(ctlr, TxSwCfg1, 0); + if(ctlr->mac_rev < 0x0211){ + csr32w(ctlr, TxSwCfg2, + ctlr->patch_dac ? 0x2c : 0x0f); + }else + csr32w(ctlr, TxSwCfg2, 0); + + /* initialize RF registers from ROM */ + for(i = 0; i < 10; i++){ + if(ctlr->rf[i].reg == 0 || ctlr->rf[i].reg == 0xff) + continue; + rt3090rfwrite(ctlr, ctlr->rf[i].reg, ctlr->rf[i].val); + } +} + +static void +updateprot(Ctlr *ctlr) +{ + u32int tmp; + + tmp = RtsthEn | ProtNavShort | TxopAllowAll; + /* setup protection frame rate (MCS code) */ + tmp |= /*(ic->ic_curmode == IEEE80211_MODE_11A) ? + rt2860_rates[RT2860_RIDX_OFDM6].mcs :*/ + rt2860_rates[RidxCck11].mcs; + + /* CCK frames don't require protection */ + csr32w(ctlr, CckProtCfg, tmp); +/* XXX + if(ic->ic_flags & IEEE80211_F_USEPROT){ + if(ic->ic_protmode == IEEE80211_PROT_RTSCTS) + tmp |= ProtCtrlRtsCts; + else if(ic->ic_protmode == IEEE80211_PROT_CTSONLY) + tmp |= ProtCtrlCts; + } + csr32w(ctlr, OfdmProtCfg, tmp); */ +} + +static char* +rt2860start(Ether *edev) +{ + u32int tmp; + u8int bbp1, bbp3; + int i, qid, ridx, ntries; + char *err; + Ctlr *ctlr; + + ctlr = edev->ctlr; + csr32w(ctlr, PwrPinCfg, IoRaPe); + + /* disable DMA */ + tmp = csr32r(ctlr, WpdmaGloCfg); + tmp &= 0xff0; + csr32w(ctlr, WpdmaGloCfg, tmp); + + /* PBF hardware reset */ + csr32w(ctlr, SysCtrl, 0xe1f); + coherence(); + csr32w(ctlr, SysCtrl, 0xe00); + + if((err = boot(ctlr)) != nil){ + /*XXX: rt2860stop(ifp, 1);*/ + return err; + } + /* set MAC address */ + csr32w(ctlr, MacAddrDw0, + edev->ea[0] | edev->ea[1] << 8 | edev->ea[2] << 16 | edev->ea[3] << 24); + csr32w(ctlr, MacAddrDw1, + edev->ea[4] | edev->ea[5] << 8 | 0xff << 16); + + /* init Tx power for all Tx rates (from EEPROM) */ + for(ridx = 0; ridx < 5; ridx++){ + if(ctlr->txpow20mhz[ridx] == 0xffffffff) + continue; + csr32w(ctlr, TxPwrCfg(ridx), ctlr->txpow20mhz[ridx]); + } + + for(ntries = 0; ntries < 100; ntries++){ + tmp = csr32r(ctlr, WpdmaGloCfg); + if((tmp & (TxDmaBusy | RxDmaBusy)) == 0) + break; + microdelay(1000); + } + if(ntries == 100){ + err = "timeout waiting for DMA engine"; + /*rt2860_stop(ifp, 1);*/ + return err; + } + tmp &= 0xff0; + csr32w(ctlr, WpdmaGloCfg, tmp); + + /* reset Rx ring and all 6 Tx rings */ + csr32w(ctlr, WpdmaRstIdx, 0x1003f); + + /* PBF hardware reset */ + csr32w(ctlr, SysCtrl, 0xe1f); + coherence(); + csr32w(ctlr, SysCtrl, 0xe00); + + csr32w(ctlr, PwrPinCfg, IoRaPe | IoRfPe); + + csr32w(ctlr, MacSysCtrl, BbpHrst | MacSrst); + coherence(); + csr32w(ctlr, MacSysCtrl, 0); + + for(i = 0; i < nelem(rt2860_def_mac); i++) + csr32w(ctlr, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); + if(ctlr->mac_ver >= 0x3071){ + /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ + csr32w(ctlr, TxSwCfg0, + 4 << DlyPapeEnShift); + } + + if(!(csr32r(ctlr, PciCfg) & PciCfgPci)){ + ctlr->flags |= ConnPciE; + /* PCIe has different clock cycle count than PCI */ + tmp = csr32r(ctlr, UsCycCnt); + tmp = (tmp & ~0xff) | 0x7d; + csr32w(ctlr, UsCycCnt, tmp); + } + + /* wait while MAC is busy */ + for(ntries = 0; ntries < 100; ntries++){ + if(!(csr32r(ctlr, MacStatusReg) & + (RxStatusBusy | TxStatusBusy))) + break; + microdelay(1000); + } + if(ntries == 100){ + err = "timeout waiting for MAC"; + /*rt2860_stop(ifp, 1);*/ + return err; + } + + /* clear Host to MCU mailbox */ + csr32w(ctlr, H2mBbpagent, 0); + csr32w(ctlr, H2mMailbox, 0); + + mcucmd(ctlr, McuCmdRfreset, 0, 0); + microdelay(1000); + + if((err = bbpinit(ctlr)) != nil){ + /*rt2860_stop(ifp, 1);*/ + return err; + } + /* clear RX WCID search table */ + setregion(ctlr, WcidEntry(0), 0, 512); + /* clear pairwise key table */ + setregion(ctlr, Pkey(0), 0, 2048); + /* clear IV/EIV table */ + setregion(ctlr, Iveiv(0), 0, 512); + /* clear WCID attribute table */ + setregion(ctlr, WcidAttr(0), 0, 256); + /* clear shared key table */ + setregion(ctlr, Skey(0, 0), 0, 8 * 32); + /* clear shared key mode */ + setregion(ctlr, SkeyMode07, 0, 4); + + /* init Tx rings (4 EDCAs + HCCA + Mgt) */ + for(qid = 0; qid < 6; qid++){ + csr32w(ctlr, TxBasePtr(qid), PCIWADDR(ctlr->tx[qid].d)); + csr32w(ctlr, TxMaxCnt(qid), Ntx); + csr32w(ctlr, TxCtxIdx(qid), 0); + } + + /* init Rx ring */ + csr32w(ctlr, RxBasePtr, PCIWADDR(ctlr->rx.p)); + csr32w(ctlr, RxMaxCnt, Nrx); + csr32w(ctlr, RxCalcIdx, Nrx - 1); + + /* setup maximum buffer sizes */ + csr32w(ctlr, MaxLenCfg, 1 << 12 | + (Rbufsize - Rxwisize - 2)); + + for(ntries = 0; ntries < 100; ntries++){ + tmp = csr32r(ctlr, WpdmaGloCfg); + if((tmp & (TxDmaBusy | RxDmaBusy)) == 0) + break; + microdelay(1000); + } + if(ntries == 100){ + err = "timeout waiting for DMA engine"; + /*rt2860_stop(ifp, 1);*/ + return err; + } + tmp &= 0xff0; + csr32w(ctlr, WpdmaGloCfg, tmp); + + /* disable interrupts mitigation */ + csr32w(ctlr, DelayIntCfg, 0); + + /* write vendor-specific BBP values (from EEPROM) */ + for(i = 0; i < 8; i++){ + if(ctlr->bbp[i].reg == 0 || ctlr->bbp[i].reg == 0xff) + continue; + bbpwrite(ctlr, ctlr->bbp[i].reg, ctlr->bbp[i].val); + } + + /* select Main antenna for 1T1R devices */ + if(ctlr->rf_rev == Rf2020 || + ctlr->rf_rev == Rf3020 || + ctlr->rf_rev == Rf3320) + rt3090setrxantenna(ctlr, 0); + + /* send LEDs operating mode to microcontroller */ + mcucmd(ctlr, McuCmdLed1, ctlr->led[0], 0); + mcucmd(ctlr, McuCmdLed2, ctlr->led[1], 0); + mcucmd(ctlr, McuCmdLed3, ctlr->led[2], 0); + + if(ctlr->mac_ver >= 0x3071) + rt3090rfinit(ctlr); + + mcucmd(ctlr, McuCmdSleep, 0x02ff, 1); + mcucmd(ctlr, McuCmdWakeup, 0, 1); + + if(ctlr->mac_ver >= 0x3071) + rt3090rfwakeup(ctlr); + + /* disable non-existing Rx chains */ + bbp3 = bbpread(ctlr, 3); + bbp3 &= ~(1 << 3 | 1 << 4); + if(ctlr->nrxchains == 2) + bbp3 |= 1 << 3; + else if(ctlr->nrxchains == 3) + bbp3 |= 1 << 4; + bbpwrite(ctlr, 3, bbp3); + + /* disable non-existing Tx chains */ + bbp1 = bbpread(ctlr, 1); + if(ctlr->ntxchains == 1) + bbp1 = (bbp1 & ~(1 << 3 | 1 << 4)); + else if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 2) + bbp1 = (bbp1 & ~(1 << 4)) | 1 << 3; + else if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 3) + bbp1 = (bbp1 & ~(1 << 3)) | 1 << 4; + bbpwrite(ctlr, 1, bbp1); + + if(ctlr->mac_ver >= 0x3071) + rt3090rfsetup(ctlr); + + /* select default channel */ + if(ctlr->mac_ver >= 0x3071) + rt3090setchan(ctlr, 3); + else + setchan(ctlr, 3); + + /* reset RF from MCU */ + mcucmd(ctlr, McuCmdRfreset, 0, 0); + + /* set RTS threshold */ + tmp = csr32r(ctlr, TxRtsCfg); + tmp &= ~0xffff00; + tmp |= 1 /* ic->ic_rtsthreshold */ << 8; + csr32w(ctlr, TxRtsCfg, tmp); + + /* setup initial protection mode */ + updateprot(ctlr); + + /* turn radio LED on */ + setleds(ctlr, LedRadio); + + /* enable Tx/Rx DMA engine */ + if((err = txrxon(ctlr)) != 0){ + /*rt2860_stop(ifp, 1);*/ + return err; + } + + /* clear pending interrupts */ + csr32w(ctlr, IntStatus, 0xffffffff); + /* enable interrupts */ + csr32w(ctlr, IntMask, 0x3fffc); + + if(ctlr->flags & AdvancedPs) + mcucmd(ctlr, McuCmdPslevel, ctlr->pslevel, 0); + return nil; +} + +/* + * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. + * Used to adjust per-rate Tx power registers. + */ +static u32int +b4inc(u32int b32, s8int delta) +{ + s8int i, b4; + + for(i = 0; i < 8; i++){ + b4 = b32 & 0xf; + b4 += delta; + if(b4 < 0) + b4 = 0; + else if(b4 > 0xf) + b4 = 0xf; + b32 = b32 >> 4 | b4 << 28; + } + return b32; +} + +static void +transmit(Wifi *wifi, Wnode *wn, Block *b) +{ + Ether *edev; + Ctlr *ctlr; + Wifipkt *w; + u8int mcs, qid; + int ridx, /*ctl_ridx,*/ hdrlen; + uchar *p; + int nodeid; + Block *outb; + TXQ *tx; + Pool *pool; + + edev = wifi->ether; + ctlr = edev->ctlr; + + qlock(ctlr); + if(ctlr->attached == 0 || ctlr->broken){ + qunlock(ctlr); + freeb(b); + return; + } + if((wn->channel != ctlr->channel) + || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))) + rxon(edev, wn); + + if(b == nil){ + /* association note has no data to transmit */ + qunlock(ctlr); + return; + } + + pool = &ctlr->pool; + qid = 0; /* for now */ + ridx = 0; + tx = &ctlr->tx[qid]; + + nodeid = ctlr->bcastnodeid; + w = (Wifipkt*)b->rp; + hdrlen = wifihdrlen(w); + + p = pool->p + pool->i * TxwiDmaSz; + if((w->a1[0] & 1) == 0){ + *(p+4) = TxAck; /* xflags */ + + if(BLEN(b) > 512-4) + *(p+1) = TxTxopBackoff; /* txop */ + + if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ + nodeid = ctlr->bssnodeid; + ridx = 2; /* BUG: hardcode 11Mbit */ + } + } + + /*ctl_ridx = rt2860_rates[ridx].ctl_ridx;*/ + mcs = rt2860_rates[ridx].mcs; + + /* setup TX Wireless Information */ + *p = 0; /* flags */ + *(p+2) = PhyCck | mcs; /* phy */ + /* let HW generate seq numbers */ + *(p+4) |= TxNseq; /* xflags */ + put16(p + 6, BLEN(b) | (((mcs+1) & 0xf) << TxPidShift) ); /* length */ + +/* put16((uchar*)&w->dur[0], rt2860_rates[ctl_ridx].lp_ack_dur); */ + + *(p+5) = nodeid; /* wcid */ + + /* copy packet header */ + memmove(p + Txwisize, b->rp, hdrlen); + + /* setup tx descriptor */ + /* first segment is TXWI + 802.11 header */ + p = (uchar*)tx->d + Tdscsize * tx->i; + put32(p, PCIWADDR(pool->p + pool->i * TxwiDmaSz)); /* sdp0 */ + put16(p + 6, Txwisize + hdrlen); /* sdl0 */ + *(p + 15) = TxQselEdca; /* flags */ + + /* allocate output buffer */ + b->rp += hdrlen; + tx->b[tx->i] = outb = iallocb(BLEN(b) + 256); + if(outb == nil){ + print("outb = nil\n"); + return; + } + outb->rp = (uchar*)ROUND((uintptr)outb->base, 256); + memset(outb->rp, 0, BLEN(b)); + memmove(outb->rp, b->rp, BLEN(b)); + outb->wp = outb->rp + BLEN(b); + freeb(b); + + /* setup payload segments */ + put32(p + 8, PCIWADDR(outb->rp)); /* sdp1 */ + put16(p + 4, BLEN(outb) | TxLs1); /* sdl1 */ + + p = pool->p + pool->i * TxwiDmaSz; + w = (Wifipkt*)(p + Txwisize); + if(ctlr->wifi->debug){ + print("transmit: %E->%E,%E nodeid=%x txq[%d]=%d size=%ld\n", w->a2, w->a1, w->a3, nodeid, qid, ctlr->tx[qid].i, BLEN(outb)); + } + + tx->i = (tx->i + 1) % Ntx; + pool->i = (pool->i + 1) % Ntxpool; + + coherence(); + + /* kick Tx */ + csr32w(ctlr, TxCtxIdx(qid), ctlr->tx[qid].i); + + qunlock(ctlr); + return; +} + +static void +rt2860attach(Ether *edev) +{ + FWImage *fw; + Ctlr *ctlr; + char *err; + + ctlr = edev->ctlr; + qlock(ctlr); + if(waserror()){ + print("#l%d: %s\n", edev->ctlrno, up->errstr); + /*if(ctlr->power) + poweroff(ctlr);*/ + qunlock(ctlr); + nexterror(); + } + if(ctlr->attached == 0){ + if(ctlr->wifi == nil) + ctlr->wifi = wifiattach(edev, transmit); + + if(ctlr->fw == nil){ + fw = readfirmware(); + ctlr->fw = fw; + } + if((err = rt2860start(edev)) != nil){ + error(err); + } + + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + ctlr->channel = 1; + ctlr->aid = 0; + + setoptions(edev); + + ctlr->attached = 1; + } + qunlock(ctlr); + poperror(); +} + +static void +receive(Ctlr *ctlr) +{ + u32int hw; + RXQ *rx; + Block *b; + uchar *d; + + rx = &ctlr->rx; + if(rx->b == nil){ + print("rx->b == nil!"); + return; + } + hw = csr32r(ctlr, FsDrxIdx) & 0xfff; + while(rx->i != hw){ + u16int sdl0, len; + u32int flags; + uchar *p; + Wifipkt *w; + int hdrlen; + + p = (uchar*)rx->p + Rdscsize * rx->i; + sdl0 = get16(p + 4 /* sdp0 */ + 2 /* sdl1 */); + if(!(sdl0 & RxDdone)){ + print("rxd ddone bit not set\n"); + break; /* should not happen */ + } + flags = get32(p + 12); + if(flags & (RxCrcerr | RxIcverr)){ + /* print("crc | icv err\n"); */ + goto skip; + } + + b = rx->b[rx->i]; + if(b == nil){ + print("no buf\n"); + goto skip; + } + d = b->rp; + if(ctlr->wifi == nil) + goto skip; + if(rbplant(ctlr, rx->i) < 0){ + print("can't plant"); + goto skip; + } + ctlr->wcid = *b->rp; + len = get16(b->rp + 2 /* wcid, keyidx */) & 0xfff; + b->rp = d + Rxwisize; + b->wp = b->rp + len; + w = (Wifipkt*)b->rp; + hdrlen = wifihdrlen(w); + /* HW may insert 2 padding bytes after 802.11 header */ + if(flags & RxL2pad){ + memmove(b->rp + 2, b->rp, hdrlen); + b->rp += 2; + } + w = (Wifipkt*)b->rp; + if(ctlr->wifi->debug) + print("receive: %E->%E,%E wcid 0x%x \n", w->a2, w->a1, w->a3, ctlr->wcid); + wifiiq(ctlr->wifi, b); +skip: + put16(p + 4 /* sdp0 */ + 2 /* sdl1 */, sdl0 & ~RxDdone); + rx->i = (rx->i + 1) % Nrx; + } + coherence(); + /* tell HW what we have processed */ + csr32w(ctlr, RxCalcIdx, (rx->i - 1) % Nrx); +} + +static void +stats(Ctlr *ctlr) +{ + u32int stat; + u8int wcid; + + while((stat = csr32r(ctlr, TxStatFifo)) & TxqVld){ + wcid = (stat >> TxqWcidShift) & 0xff; + /* if no ACK was requested, no feedback is available */ + if(!(stat & TxqAckreq) || wcid == 0xff){ + continue; + } + } +} + +static void +rt2860tx(Ctlr *ctlr, u8int q) +{ + u32int hw; + TXQ *tx; + + stats(ctlr); + tx = &ctlr->tx[q]; + hw = csr32r(ctlr, TxDtxIdx(q)); + while(tx->n != hw){ + uchar *p = (uchar*)tx->d + Rdscsize * tx->n; + u16int sdl0; + + if(tx->b[tx->n]){ + freeb(tx->b[tx->n]); + tx->b[tx->n] = nil; + } + sdl0 = get16(p + 4 /* sdp0 */ + 2 /* sdl1 */); + if(!(sdl0 & TxDdone)){ + print("txd ddone bit not set\n"); + break; /* should not happen */ + } + memset((uchar*)ctlr->pool.p + TxwiDmaSz * tx->n, 0, TxwiDmaSz); + memset((uchar*)tx->d + Tdscsize * tx->n, 0, Tdscsize); + // put16(p + 4 /* sdp0 */ + 2 /* sdl1 */, sdl0 & ~TxDdone); + tx->n = (tx->n + 1) % Ntx; + } + coherence(); +} + +static void +rt2860interrupt(Ureg*, void *arg) +{ + u32int r; + Ether *edev; + Ctlr *ctlr; + int debug; + + edev = arg; + ctlr = edev->ctlr; + ilock(ctlr); + + debug = ctlr->wifi->debug; + + r = csr32r(ctlr, IntStatus); + if(r == 0xffffffff){ + iunlock(ctlr); + return; + } + if(r == 0){ + iunlock(ctlr); + return; + } + + /* acknowledge interrupts */ + csr32w(ctlr, IntStatus, r); + + if(r & TxRxCoherent){ + u32int tmp; + /* DMA finds data coherent event when checking the DDONE bit */ + if(debug) + print("txrx coherent intr\n"); + + /* restart DMA engine */ + tmp = csr32r(ctlr, WpdmaGloCfg); + tmp &= ~(TxWbDdone | RxDmaEn | TxDmaEn); + csr32w(ctlr, WpdmaGloCfg, tmp); + + txrxon(ctlr); + } + if(r & MacInt2) + stats(ctlr); + + if(r & TxDoneInt5) + rt2860tx(ctlr, 5); + + if(r & RxDoneInt) + receive(ctlr); + + if(r & TxDoneInt4) + rt2860tx(ctlr, 4); + + if(r & TxDoneInt3) + rt2860tx(ctlr, 3); + + if(r & TxDoneInt2) + rt2860tx(ctlr, 2); + + if(r & TxDoneInt1) + rt2860tx(ctlr, 1); + + if(r & TxDoneInt0) + rt2860tx(ctlr, 0); + + iunlock(ctlr); +} + +static void +eepromctl(Ctlr *ctlr, u32int val) +{ + csr32w(ctlr, PciEectrl, val); + coherence(); + microdelay(EepromDelay); +} + +/* + * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, + * 93C66 or 93C86). + */ +static u16int +eeread2(Ctlr *ctlr, u16int addr) +{ + u32int tmp; + u16int val; + int n; + + /* clock C once before the first command */ + eepromctl(ctlr, 0); + + eepromctl(ctlr, EectrlS); + eepromctl(ctlr, EectrlS | EectrlC); + eepromctl(ctlr, EectrlS); + + /* write start bit (1) */ + eepromctl(ctlr, EectrlS | EectrlD); + eepromctl(ctlr, EectrlS | EectrlD | EectrlC); + + /* write READ opcode (10) */ + eepromctl(ctlr, EectrlS | EectrlD); + eepromctl(ctlr, EectrlS | EectrlD | EectrlC); + eepromctl(ctlr, EectrlS); + eepromctl(ctlr, EectrlS | EectrlC); + + /* write address (A5-A0 or A7-A0) */ + n = ((csr32r(ctlr, PciEectrl) & 0x30) == 0) ? 5 : 7; + for(; n >= 0; n--){ + eepromctl(ctlr, EectrlS | + (((addr >> n) & 1) << EectrlShiftD)); + eepromctl(ctlr, EectrlS | + (((addr >> n) & 1) << EectrlShiftD) | EectrlC); + } + + eepromctl(ctlr, EectrlS); + + /* read data Q15-Q0 */ + val = 0; + for(n = 15; n >= 0; n--){ + eepromctl(ctlr, EectrlS | EectrlC); + tmp = csr32r(ctlr, PciEectrl); + val |= ((tmp & EectrlQ) >> EectrlShiftQ) << n; + eepromctl(ctlr, EectrlS); + } + + eepromctl(ctlr, 0); + + /* clear Chip Select and clock C */ + eepromctl(ctlr, EectrlS); + eepromctl(ctlr, 0); + eepromctl(ctlr, EectrlC); + + return val; +} + +/* Read 16-bit from eFUSE ROM (>=RT3071 only.) */ +static u16int +efuseread2(Ctlr *ctlr, u16int addr) +{ + u32int tmp; + u16int reg; + int ntries; + + addr *= 2; + /*- + * Read one 16-byte block into registers EFUSE_DATA[0-3]: + * DATA0: F E D C + * DATA1: B A 9 8 + * DATA2: 7 6 5 4 + * DATA3: 3 2 1 0 + */ + tmp = csr32r(ctlr, Rt3070EfuseCtrl); + tmp &= ~(Rt3070EfsromModeMask | Rt3070EfsromAinMask); + tmp |= (addr & ~0xf) << Rt3070EfsromAinShift | Rt3070EfsromKick; + csr32w(ctlr, Rt3070EfuseCtrl, tmp); + for(ntries = 0; ntries < 500; ntries++){ + tmp = csr32r(ctlr, Rt3070EfuseCtrl); + if(!(tmp & Rt3070EfsromKick)) + break; + microdelay(2); + } + if(ntries == 500) + return 0xffff; + + if((tmp & Rt3070EfuseAoutMask) == Rt3070EfuseAoutMask) + return 0xffff; /* address not found */ + + /* determine to which 32-bit register our 16-bit word belongs */ + reg = Rt3070EfuseData3 - (addr & 0xc); + tmp = csr32r(ctlr, reg); + + return (addr & 2) ? tmp >> 16 : tmp & 0xffff; +} + +static char* +eepromread(Ether *edev) +{ + s8int delta_2ghz, delta_5ghz; + u32int tmp; + u16int val; + int ridx, ant, i; + u16int (*rom_read)(Ctlr*, u16int); + Ctlr *ctlr; + + enum { DefLna = 10 }; + + ctlr = edev->ctlr; + /* check whether the ROM is eFUSE ROM or EEPROM */ + rom_read = eeread2; + if(ctlr->mac_ver >= 0x3071){ + tmp = csr32r(ctlr, Rt3070EfuseCtrl); + if(tmp & Rt3070SelEfuse) + rom_read = efuseread2; + } + + /* read MAC address */ + val = rom_read(ctlr, EepromMac01); + edev->ea[0] = val & 0xff; + edev->ea[1] = val >> 8; + val = rom_read(ctlr, EepromMac23); + edev->ea[2] = val & 0xff; + edev->ea[3] = val >> 8; + val = rom_read(ctlr, EepromMac45); + edev->ea[4] = val & 0xff; + edev->ea[5] = val >> 8; + + /* read vendor BBP settings */ + for(i = 0; i < 8; i++){ + val = rom_read(ctlr, EepromBbpBase + i); + ctlr->bbp[i].val = val & 0xff; + ctlr->bbp[i].reg = val >> 8; + } + + if(ctlr->mac_ver >= 0x3071){ + /* read vendor RF settings */ + for(i = 0; i < 10; i++){ + val = rom_read(ctlr, Rt3071EepromRfBase + i); + ctlr->rf[i].val = val & 0xff; + ctlr->rf[i].reg = val >> 8; + } + } + + /* read RF frequency offset from EEPROM */ + val = rom_read(ctlr, EepromFreqLeds); + ctlr->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; + if((val >> 8) != 0xff){ + /* read LEDs operating mode */ + ctlr->leds = val >> 8; + ctlr->led[0] = rom_read(ctlr, EepromLed1); + ctlr->led[1] = rom_read(ctlr, EepromLed2); + ctlr->led[2] = rom_read(ctlr, EepromLed3); + }else{ + /* broken EEPROM, use default settings */ + ctlr->leds = 0x01; + ctlr->led[0] = 0x5555; + ctlr->led[1] = 0x2221; + ctlr->led[2] = 0xa9f8; + } + /* read RF information */ + val = rom_read(ctlr, EepromAntenna); + if(val == 0xffff){ + if(ctlr->mac_ver == 0x3593){ + /* default to RF3053 3T3R */ + ctlr->rf_rev = Rf3053; + ctlr->ntxchains = 3; + ctlr->nrxchains = 3; + }else if(ctlr->mac_ver >= 0x3071){ + /* default to RF3020 1T1R */ + ctlr->rf_rev = Rf3020; + ctlr->ntxchains = 1; + ctlr->nrxchains = 1; + }else{ + /* default to RF2820 1T2R */ + ctlr->rf_rev = Rf2820; + ctlr->ntxchains = 1; + ctlr->nrxchains = 2; + } + }else{ + ctlr->rf_rev = (val >> 8) & 0xf; + ctlr->ntxchains = (val >> 4) & 0xf; + ctlr->nrxchains = val & 0xf; + } + + /* check if RF supports automatic Tx access gain control */ + val = rom_read(ctlr, EepromConfig); + /* check if driver should patch the DAC issue */ + if((val >> 8) != 0xff) + ctlr->patch_dac = (val >> 15) & 1; + if((val & 0xff) != 0xff){ + ctlr->ext_5ghz_lna = (val >> 3) & 1; + ctlr->ext_2ghz_lna = (val >> 2) & 1; + /* check if RF supports automatic Tx access gain control */ + ctlr->calib_2ghz = ctlr->calib_5ghz = 0; /* XXX (val >> 1) & 1 */; + /* check if we have a hardware radio switch */ + ctlr->rfswitch = val & 1; + } + if(ctlr->flags & AdvancedPs){ + /* read PCIe power save level */ + val = rom_read(ctlr, EepromPciePslevel); + if((val & 0xff) != 0xff){ + ctlr->pslevel = val & 0x3; + val = rom_read(ctlr, EepromRev); + if((val & 0xff80) != 0x9280) + ctlr->pslevel = MIN(ctlr->pslevel, 1); + } + } + + /* read power settings for 2GHz channels */ + for(i = 0; i < 14; i += 2){ + val = rom_read(ctlr, + EepromPwr2ghzBase1 + i / 2); + ctlr->txpow1[i + 0] = (s8int)(val & 0xff); + ctlr->txpow1[i + 1] = (s8int)(val >> 8); + + val = rom_read(ctlr, + EepromPwr2ghzBase2 + i / 2); + ctlr->txpow2[i + 0] = (s8int)(val & 0xff); + ctlr->txpow2[i + 1] = (s8int)(val >> 8); + } + /* fix broken Tx power entries */ + + for(i = 0; i < 14; i++){ + if(ctlr->txpow1[i] < 0 || ctlr->txpow1[i] > 31) + ctlr->txpow1[i] = 5; + if(ctlr->txpow2[i] < 0 || ctlr->txpow2[i] > 31) + ctlr->txpow2[i] = 5; + } + /* read power settings for 5GHz channels */ + for(i = 0; i < 40; i += 2){ + val = rom_read(ctlr, + EepromPwr5ghzBase1 + i / 2); + ctlr->txpow1[i + 14] = (s8int)(val & 0xff); + ctlr->txpow1[i + 15] = (s8int)(val >> 8); + + val = rom_read(ctlr, + EepromPwr5ghzBase2 + i / 2); + ctlr->txpow2[i + 14] = (s8int)(val & 0xff); + ctlr->txpow2[i + 15] = (s8int)(val >> 8); + } + + /* fix broken Tx power entries */ + for(i = 0; i < 40; i++){ + if(ctlr->txpow1[14 + i] < -7 || ctlr->txpow1[14 + i] > 15) + ctlr->txpow1[14 + i] = 5; + if(ctlr->txpow2[14 + i] < -7 || ctlr->txpow2[14 + i] > 15) + ctlr->txpow2[14 + i] = 5; + } + + /* read Tx power compensation for each Tx rate */ + val = rom_read(ctlr, EepromDeltapwr); + delta_2ghz = delta_5ghz = 0; + if((val & 0xff) != 0xff && (val & 0x80)){ + delta_2ghz = val & 0xf; + if(!(val & 0x40)) /* negative number */ + delta_2ghz = -delta_2ghz; + } + val >>= 8; + if((val & 0xff) != 0xff && (val & 0x80)){ + delta_5ghz = val & 0xf; + if(!(val & 0x40)) /* negative number */ + delta_5ghz = -delta_5ghz; + } + + for(ridx = 0; ridx < 5; ridx++){ + u32int reg; + + val = rom_read(ctlr, EepromRpwr + ridx * 2); + reg = val; + val = rom_read(ctlr, EepromRpwr + ridx * 2 + 1); + reg |= (u32int)val << 16; + + ctlr->txpow20mhz[ridx] = reg; + ctlr->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); + ctlr->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); + } + + /* read factory-calibrated samples for temperature compensation */ + val = rom_read(ctlr, EepromTssi12ghz); + ctlr->tssi_2ghz[0] = val & 0xff; /* [-4] */ + ctlr->tssi_2ghz[1] = val >> 8; /* [-3] */ + val = rom_read(ctlr, EepromTssi22ghz); + ctlr->tssi_2ghz[2] = val & 0xff; /* [-2] */ + ctlr->tssi_2ghz[3] = val >> 8; /* [-1] */ + val = rom_read(ctlr, EepromTssi32ghz); + ctlr->tssi_2ghz[4] = val & 0xff; /* [+0] */ + ctlr->tssi_2ghz[5] = val >> 8; /* [+1] */ + val = rom_read(ctlr, EepromTssi42ghz); + ctlr->tssi_2ghz[6] = val & 0xff; /* [+2] */ + ctlr->tssi_2ghz[7] = val >> 8; /* [+3] */ + val = rom_read(ctlr, EepromTssi52ghz); + ctlr->tssi_2ghz[8] = val & 0xff; /* [+4] */ + ctlr->step_2ghz = val >> 8; + /* check that ref value is correct, otherwise disable calibration */ + if(ctlr->tssi_2ghz[4] == 0xff) + ctlr->calib_2ghz = 0; + + val = rom_read(ctlr, EepromTssi15ghz); + ctlr->tssi_5ghz[0] = val & 0xff; /* [-4] */ + ctlr->tssi_5ghz[1] = val >> 8; /* [-3] */ + val = rom_read(ctlr, EepromTssi25ghz); + ctlr->tssi_5ghz[2] = val & 0xff; /* [-2] */ + ctlr->tssi_5ghz[3] = val >> 8; /* [-1] */ + val = rom_read(ctlr, EepromTssi35ghz); + ctlr->tssi_5ghz[4] = val & 0xff; /* [+0] */ + ctlr->tssi_5ghz[5] = val >> 8; /* [+1] */ + val = rom_read(ctlr, EepromTssi45ghz); + ctlr->tssi_5ghz[6] = val & 0xff; /* [+2] */ + ctlr->tssi_5ghz[7] = val >> 8; /* [+3] */ + val = rom_read(ctlr, EepromTssi55ghz); + ctlr->tssi_5ghz[8] = val & 0xff; /* [+4] */ + ctlr->step_5ghz = val >> 8; + /* check that ref value is correct, otherwise disable calibration */ + if(ctlr->tssi_5ghz[4] == 0xff) + ctlr->calib_5ghz = 0; + + /* read RSSI offsets and LNA gains from EEPROM */ + val = rom_read(ctlr, EepromRssi12ghz); + ctlr->rssi_2ghz[0] = val & 0xff; /* Ant A */ + ctlr->rssi_2ghz[1] = val >> 8; /* Ant B */ + val = rom_read(ctlr, EepromRssi22ghz); + if(ctlr->mac_ver >= 0x3071){ + /* + * On RT3090 chips (limited to 2 Rx chains), this ROM + * field contains the Tx mixer gain for the 2GHz band. + */ + if((val & 0xff) != 0xff) + ctlr->txmixgain_2ghz = val & 0x7; + }else + ctlr->rssi_2ghz[2] = val & 0xff; /* Ant C */ + ctlr->lna[2] = val >> 8; /* channel group 2 */ + + val = rom_read(ctlr, EepromRssi15ghz); + ctlr->rssi_5ghz[0] = val & 0xff; /* Ant A */ + ctlr->rssi_5ghz[1] = val >> 8; /* Ant B */ + val = rom_read(ctlr, EepromRssi25ghz); + ctlr->rssi_5ghz[2] = val & 0xff; /* Ant C */ + ctlr->lna[3] = val >> 8; /* channel group 3 */ + + val = rom_read(ctlr, EepromLna); + if(ctlr->mac_ver >= 0x3071) + ctlr->lna[0] = DefLna; + else /* channel group 0 */ + ctlr->lna[0] = val & 0xff; + ctlr->lna[1] = val >> 8; /* channel group 1 */ + + /* fix broken 5GHz LNA entries */ + if(ctlr->lna[2] == 0 || ctlr->lna[2] == 0xff){ + ctlr->lna[2] = ctlr->lna[1]; + } + if(ctlr->lna[3] == 0 || ctlr->lna[3] == 0xff){ + ctlr->lna[3] = ctlr->lna[1]; + } + + /* fix broken RSSI offset entries */ + for(ant = 0; ant < 3; ant++){ + if(ctlr->rssi_2ghz[ant] < -10 || ctlr->rssi_2ghz[ant] > 10){ + ctlr->rssi_2ghz[ant] = 0; + } + if(ctlr->rssi_5ghz[ant] < -10 || ctlr->rssi_5ghz[ant] > 10){ + ctlr->rssi_5ghz[ant] = 0; + } + } + + return 0; +} + +static const char * +getrfname(u8int rev) +{ + if((rev == 0) || (rev >= nelem(rfnames))) + return "unknown"; + if(rfnames[rev][0] == '\0') + return "unknown"; + return rfnames[rev]; +} + +static int +rbplant(Ctlr *ctlr, int i) +{ + Block *b; + uchar *p; + + b = iallocb(Rbufsize + 256); + if(b == nil) + return -1; + b->rp = b->wp = (uchar*)ROUND((uintptr)b->base, 256); + memset(b->rp, 0, Rbufsize); + ctlr->rx.b[i] = b; + p = (uchar*)&ctlr->rx.p[i * 4]; /* sdp0 */ + memset(p, 0, Rdscsize); + put32(p, PCIWADDR(b->rp)); + p = (uchar*)&ctlr->rx.p[i * 4 + 1]; /* sdl0 */ + p += 2; /* sdl1 */ + put16(p, Rbufsize);; + + return 0; +} + +static char* +allocrx(Ctlr *ctlr, RXQ *rx) +{ + int i; + + if(rx->b == nil) + rx->b = malloc(sizeof(Block*) * Nrx); + if(rx->p == nil) /* Rx descriptors */ + rx->p = mallocalign(Nrx * Rdscsize, 16, 0, 0); + if(rx->b == nil || rx->p == nil) + return "no memory for rx ring"; + memset(rx->p, 0, Nrx * Rdscsize); + for(i=0; ib[i] != nil){ + freeb(rx->b[i]); + rx->b[i] = nil; + } + if(rbplant(ctlr, i) < 0) + return "no memory for rx descriptors"; + } + rx->i = 0; + return nil; +} + +static void +freerx(Ctlr *, RXQ *rx) +{ + int i; + + for(i = 0; i < Nrx; i++){ + if(rx->b[i] != nil){ + freeb(rx->b[i]); + rx->b[i] = nil; + } + } + free(rx->b); + free(rx->p); + rx->p = nil; + rx->b = nil; + rx->i = 0; +} + +static char* +alloctx(Ctlr *, TXQ *tx) +{ + if(tx->b == nil) + tx->b = malloc(sizeof(Block*) * Ntx); + if(tx->d == nil) /* Tx descriptors */ + tx->d = mallocalign(Ntx * Tdscsize, 16, 0, 0); + if(tx->b == nil || tx->d == nil) + return "no memory for tx ring"; + memset(tx->d, 0, Ntx * Tdscsize); + memset(tx->b, 0, Ntx * sizeof(Block*)); + tx->i = 0; + return nil; +} + +static void +freetx(Ctlr *, TXQ *tx) +{ + free(tx->b); + free(tx->d); + tx->d = nil; + tx->i = 0; +} + +static char* +alloctxpool(Ctlr *ctlr) +{ + Pool *pool; + + pool = &ctlr->pool; + if(pool->p == nil) + pool->p = mallocalign(Ntxpool * TxwiDmaSz, 4096, 0, 0); + if(pool->p == nil) + return "no memory for pool"; + memset(pool->p, 0, Ntxpool * TxwiDmaSz); + pool->i = 0; + return 0; +} + +static char* +initring(Ctlr *ctlr) +{ + int qid; + char *err; + + /* + * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. + */ + for(qid = 0; qid < 6; qid++){ + if((err = alloctx(ctlr, &ctlr->tx[qid])) != nil) + goto fail1; + } + if((err = allocrx(ctlr, &ctlr->rx)) != nil) + goto fail1; + + if((err = alloctxpool(ctlr)) != nil) + goto fail2; + /* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */ + + ctlr->mgtqid = (ctlr->mac_ver == 0x2860 && ctlr->mac_rev == 0x0100) ? + 3 : 5; + + return nil; +fail2: freerx(ctlr, &ctlr->rx); + return err; +fail1: while(--qid >= 0) + freetx(ctlr, &ctlr->tx[qid]); + return err; +} + +static int +rt2860init(Ether *edev) +{ + Ctlr *ctlr; + int ntries; + char *err; + u32int tmp; + + SET(tmp); + ctlr = edev->ctlr; + /* wait for NIC to initialize */ + for(ntries = 0; ntries < 100; ntries++){ + tmp = csr32r(ctlr, AsicVerId); + if(tmp != 0 && tmp != 0xffffffff) + break; + microdelay(10); + } + if(ntries == 100){ + print("timeout waiting for NIC to initialize"); + return -1; + } + ctlr->mac_ver = tmp >> 16; + ctlr->mac_rev = tmp & 0xffff; + + if(ctlr->mac_ver != 0x2860){ + switch(ctlr->pdev->did){ + default: + break; + case RalinkRT2890: + case RalinkRT2790: + case RalinkRT3090: + case AwtRT2890: + ctlr->flags = AdvancedPs; + break; + } + } + /* retrieve RF rev. no and various other things from EEPROM */ + eepromread(edev); + + print("MAC/BBP RT%X (rev 0x%04X), RF %s (MIMO %dT%dR)\n", + ctlr->mac_ver, ctlr->mac_rev, + getrfname(ctlr->rf_rev), ctlr->ntxchains, ctlr->nrxchains); + if((err = initring(ctlr)) != nil){ + print("error: %s", err); + return -1; + } + + return 0; +} + +static Ctlr *rt2860head, *rt2860tail; + +static void +rt2860pci(void) +{ + Pcidev *pdev; + + pdev = nil; + while(pdev = pcimatch(pdev, 0, 0)){ + Ctlr *ctlr; + void *mem; + + if(pdev->ccrb != 2 || pdev->ccru != 0x80) + continue; + if(pdev->vid != 0x1814) /* Ralink */ + continue; + + switch(pdev->did){ + default: + continue; + case RalinkRT2790: + case RalinkRT3090: + break; + } + + pcisetbme(pdev); + pcisetpms(pdev, 0); + + ctlr = malloc(sizeof(Ctlr)); + if(ctlr == nil){ + print("rt2860: unable to alloc Ctlr\n"); + continue; + } + ctlr->port = pdev->mem[0].bar & ~0x0F; + mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size); + if(mem == nil){ + print("rt2860: can't map %8.8luX\n", pdev->mem[0].bar); + free(ctlr); + continue; + } + ctlr->nic = mem; + ctlr->pdev = pdev; + + if(rt2860head != nil) + rt2860tail->link = ctlr; + else + rt2860head = ctlr; + rt2860tail = ctlr; + } +} + +static int +rt2860pnp(Ether* edev) +{ + Ctlr *ctlr; + + if(rt2860head == nil) + rt2860pci(); +again: + for(ctlr = rt2860head; ctlr != nil; ctlr = ctlr->link){ + if(ctlr->active) + continue; + if(edev->port == 0 || edev->port == ctlr->port){ + ctlr->active = 1; + break; + } + } + + if(ctlr == nil) + return -1; + + edev->ctlr = ctlr; + edev->port = ctlr->port; + edev->irq = ctlr->pdev->intl; + edev->tbdf = ctlr->pdev->tbdf; + edev->arg = edev; + edev->interrupt = rt2860interrupt; + edev->attach = rt2860attach; + edev->ifstat = rt2860ifstat; + edev->ctl = rt2860ctl; + edev->promiscuous = rt2860promiscuous; + edev->multicast = rt2860multicast; + edev->mbps = 10; + + if(rt2860init(edev) < 0){ + edev->ctlr = nil; + goto again; + } + return 0; +} + +void +etherrt2860link(void) +{ + addethercard("rt2860", rt2860pnp); +} diff --git a/sys/src/9/pc/etherwpi.c b/sys/src/9/pc/etherwpi.c new file mode 100644 index 0000000000..aa39b6d684 --- /dev/null +++ b/sys/src/9/pc/etherwpi.c @@ -0,0 +1,1861 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "wifi.h" + +enum { + Nrxlog = 6, + Nrx = 1<nic+((r)/4))) +#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) + +static uint +get32(uchar *p){ + return *((u32int*)p); +} +static uint +get16(uchar *p) +{ + return *((u16int*)p); +} +static void +put32(uchar *p, uint v){ + *((u32int*)p) = v; +} +static void +put16(uchar *p, uint v){ + *((u16int*)p) = v; +}; + +static char* +niclock(Ctlr *ctlr) +{ + int i; + + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq); + for(i=0; i<1000; i++){ + if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna) + return 0; + delay(10); + } + return "niclock: timeout"; +} + +static void +nicunlock(Ctlr *ctlr) +{ + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~MacAccessReq); +} + +static u32int +prphread(Ctlr *ctlr, uint off) +{ + csr32w(ctlr, PrphRaddr, ((sizeof(u32int)-1)<<24) | off); + coherence(); + return csr32r(ctlr, PrphRdata); +} +static void +prphwrite(Ctlr *ctlr, uint off, u32int data) +{ + csr32w(ctlr, PrphWaddr, ((sizeof(u32int)-1)<<24) | off); + coherence(); + csr32w(ctlr, PrphWdata, data); +} + +static char* +eepromread(Ctlr *ctlr, void *data, int count, uint off) +{ + uchar *out = data; + char *err; + u32int w = 0; + int i; + + if((err = niclock(ctlr)) != nil) + return err; + + for(; count > 0; count -= 2, off++){ + csr32w(ctlr, Eeprom, off << 2); + csr32w(ctlr, Eeprom, csr32r(ctlr, Eeprom) & ~(1<<1)); + + for(i = 0; i < 10; i++){ + w = csr32r(ctlr, Eeprom); + if(w & 1) + break; + delay(5); + } + if(i == 10) + break; + *out++ = w >> 16; + if(count > 1) + *out++ = w >> 24; + } + nicunlock(ctlr); + + if(count > 0) + return "eeprompread: timeout"; + return nil; +} + +static char* +clockwait(Ctlr *ctlr) +{ + int i; + + /* Set "initialization complete" bit. */ + csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | InitDone); + for(i=0; i<2500; i++){ + if(csr32r(ctlr, Gpc) & MacClockReady) + return nil; + delay(10); + } + return "clockwait: timeout"; +} + +static char* +poweron(Ctlr *ctlr) +{ + char *err; + + if(ctlr->power) + return nil; + + csr32w(ctlr, AnaPll, csr32r(ctlr, AnaPll) | Init); + /* Disable L0s. */ + csr32w(ctlr, GioChicken, csr32r(ctlr, GioChicken) | L1AnoL0Srx); + + if((err = clockwait(ctlr)) != nil) + return err; + + if((err = niclock(ctlr)) != nil) + return err; + + prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt); + delay(20); + + /* Disable L1. */ + prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11)); + + nicunlock(ctlr); + + ctlr->power = 1; + + return nil; +} + +static void +poweroff(Ctlr *ctlr) +{ + int i, j; + + csr32w(ctlr, Reset, Nevo); + + /* Disable interrupts. */ + csr32w(ctlr, Imr, 0); + csr32w(ctlr, Isr, ~0); + csr32w(ctlr, FhIsr, ~0); + + if(niclock(ctlr) == nil){ + /* Stop TX scheduler. */ + prphwrite(ctlr, AlmSchedMode, 0); + prphwrite(ctlr, AlmSchedTxfact, 0); + + /* Stop all DMA channels */ + for(i = 0; i < 6; i++){ + csr32w(ctlr, FhTxConfig + i*32, 0); + for(j = 0; j < 100; j++){ + if((csr32r(ctlr, FhTxStatus) & (0x1010000<power = 0; +} + +static struct { + u32int addr; /* offset in EEPROM */ + u8int nchan; + u8int chan[14]; +} bands[5] = { + { 0x63, 14, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } }, + { 0x72, 13, + { 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 } }, + { 0x80, 12, + { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 } }, + { 0x8d, 11, + { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 } }, + { 0x99, 6, + { 145, 149, 153, 157, 161, 165 } } +}; + +static int +wpiinit(Ether *edev) +{ + Ctlr *ctlr; + char *err; + uchar b[64]; + int i, j; + Powergrp *g; + + ctlr = edev->ctlr; + if((err = poweron(ctlr)) != nil) + goto Err; + if((csr32r(ctlr, EepromGp) & 0x6) == 0){ + err = "bad rom signature"; + goto Err; + } + /* Clear HW ownership of EEPROM. */ + csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x180); + + if((err = eepromread(ctlr, b, 1, 0x45)) != nil) + goto Err; + ctlr->eeprom.cap = b[0]; + if((err = eepromread(ctlr, b, 2, 0x35)) != nil) + goto Err; + ctlr->eeprom.rev = get16(b); + if((err = eepromread(ctlr, b, 1, 0x4a)) != nil) + goto Err; + ctlr->eeprom.type = b[0]; + if((err = eepromread(ctlr, b, 4, 0x60)) != nil) + goto Err; + strncpy(ctlr->eeprom.regdom, (char*)b, 4); + ctlr->eeprom.regdom[4] = '\0'; + + print("wpi: %X %X %X %s\n", ctlr->eeprom.cap, ctlr->eeprom.rev, ctlr->eeprom.type, ctlr->eeprom.regdom); + + if((err = eepromread(ctlr, b, 6, 0x15)) != nil) + goto Err; + memmove(edev->ea, b, Eaddrlen); + + memset(ctlr->maxpwr, 0, sizeof(ctlr->maxpwr)); + for(i = 0; i < nelem(bands); i++){ + if((err = eepromread(ctlr, b, 2*bands[i].nchan, bands[i].addr)) != nil) + goto Err; + for(j = 0; j < bands[i].nchan; j++){ + if(!(b[j*2] & 1)) + continue; + ctlr->maxpwr[bands[i].chan[j]] = b[j*2+1]; + } + } + + for(i = 0; i < nelem(ctlr->eeprom.pwrgrps); i++){ + if((err = eepromread(ctlr, b, 64, 0x100 + i*32)) != nil) + goto Err; + g = &ctlr->eeprom.pwrgrps[i]; + g->maxpwr = b[60]; + g->chan = b[61]; + g->temp = get16(b+62); + for(j = 0; j < 5; j++){ + g->samples[j].index = b[j*4]; + g->samples[j].power = b[j*4+1]; + } + } + + poweroff(ctlr); + return 0; +Err: + print("wpiinit: %s\n", err); + poweroff(ctlr); + return -1; +} + +static char* +crackfw(FWImage *i, uchar *data, uint size) +{ + uchar *p, *e; + + memset(i, 0, sizeof(*i)); + if(size < 4*6){ +Tooshort: + return "firmware image too short"; + } + p = data; + e = p + size; + i->version = get32(p); p += 4; + i->main.text.size = get32(p); p += 4; + i->main.data.size = get32(p); p += 4; + i->init.text.size = get32(p); p += 4; + i->init.data.size = get32(p); p += 4; + i->boot.text.size = get32(p); p += 4; + i->main.text.data = p; p += i->main.text.size; + i->main.data.data = p; p += i->main.data.size; + i->init.text.data = p; p += i->init.text.size; + i->init.data.data = p; p += i->init.data.size; + i->boot.text.data = p; p += i->boot.text.size; + if(p > e) + goto Tooshort; + return nil; +} + +static FWImage* +readfirmware(void) +{ + uchar dirbuf[sizeof(Dir)+100], *data; + char *err; + FWImage *fw; + int n, r; + Chan *c; + Dir d; + + if(!iseve()) + error(Eperm); + if(!waserror()){ + c = namec("/boot/wpi-3945abg", Aopen, OREAD, 0); + poperror(); + }else + c = namec("/lib/firmware/wpi-3945abg", Aopen, OREAD, 0); + if(waserror()){ + cclose(c); + nexterror(); + } + n = devtab[c->type]->stat(c, dirbuf, sizeof dirbuf); + if(n <= 0) + error("can't stat firmware"); + convM2D(dirbuf, n, &d, nil); + fw = smalloc(sizeof(*fw) + 16 + d.length); + data = (uchar*)(fw+1); + if(waserror()){ + free(fw); + nexterror(); + } + r = 0; + while(r < d.length){ + n = devtab[c->type]->read(c, data+r, d.length-r, (vlong)r); + if(n <= 0) + break; + r += n; + } + if((err = crackfw(fw, data, r)) != nil) + error(err); + poperror(); + poperror(); + cclose(c); + return fw; +} + +static int +gotirq(void *arg) +{ + Ctlr *ctlr = arg; + return (ctlr->wait.m & ctlr->wait.w) != 0; +} + +static u32int +irqwait(Ctlr *ctlr, u32int mask, int timeout) +{ + u32int r; + + ilock(ctlr); + r = ctlr->wait.m & mask; + if(r == 0){ + ctlr->wait.w = mask; + iunlock(ctlr); + if(!waserror()){ + tsleep(&ctlr->wait, gotirq, ctlr, timeout); + poperror(); + } + ilock(ctlr); + ctlr->wait.w = 0; + r = ctlr->wait.m & mask; + } + ctlr->wait.m &= ~r; + iunlock(ctlr); + return r; +} + +static int +rbplant(Ctlr *ctlr, int i) +{ + Block *b; + + b = iallocb(Rbufsize+127); + if(b == nil) + return -1; + b->rp = b->wp = (uchar*)((((uintptr)b->base+127)&~127)); + memset(b->rp, 0, Rdscsize); + coherence(); + ctlr->rx.b[i] = b; + ctlr->rx.p[i] = PCIWADDR(b->rp); + return 0; +} + +static char* +initring(Ctlr *ctlr) +{ + RXQ *rx; + TXQ *tx; + int i, q; + + rx = &ctlr->rx; + if(rx->b == nil) + rx->b = malloc(sizeof(Block*) * Nrx); + if(rx->p == nil) + rx->p = mallocalign(sizeof(u32int) * Nrx, 16 * 1024, 0, 0); + if(rx->b == nil || rx->p == nil) + return "no memory for rx ring"; + for(i = 0; ip[i] = 0; + if(rx->b[i] != nil){ + freeb(rx->b[i]); + rx->b[i] = nil; + } + if(rbplant(ctlr, i) < 0) + return "no memory for rx descriptors"; + } + rx->i = 0; + + if(ctlr->shared == nil) + ctlr->shared = mallocalign(4096, 4096, 0, 0); + if(ctlr->shared == nil) + return "no memory for shared buffer"; + memset(ctlr->shared, 0, 4096); + + for(q=0; qtx); q++){ + tx = &ctlr->tx[q]; + if(tx->b == nil) + tx->b = malloc(sizeof(Block*) * Ntx); + if(tx->d == nil) + tx->d = mallocalign(Tdscsize * Ntx, 16 * 1024, 0, 0); + if(tx->c == nil) + tx->c = mallocalign(Tcmdsize * Ntx, 4, 0, 0); + if(tx->b == nil || tx->d == nil || tx->c == nil) + return "no memory for tx ring"; + memset(tx->d, 0, Tdscsize * Ntx); + memset(tx->c, 0, Tcmdsize * Ntx); + for(i=0; ib[i] != nil){ + freeb(tx->b[i]); + tx->b[i] = nil; + } + } + ctlr->shared->txbase[q] = PCIWADDR(tx->d); + tx->i = 0; + tx->n = 0; + tx->lastcmd = 0; + } + return nil; +} + +static char* +reset(Ctlr *ctlr) +{ + uchar rev; + char *err; + int i; + + if(ctlr->power) + poweroff(ctlr); + if((err = initring(ctlr)) != nil) + return err; + if((err = poweron(ctlr)) != nil) + return err; + + /* Select VMAIN power source. */ + if((err = niclock(ctlr)) != nil) + return err; + prphwrite(ctlr, ApmgPs, (prphread(ctlr, ApmgPs) & ~PwrSrcMask) | PwrSrcVMain); + nicunlock(ctlr); + /* Spin until VMAIN gets selected. */ + for(i = 0; i < 5000; i++){ + if(csr32r(ctlr, GpioIn) & (1 << 9)) + break; + delay(10); + } + + /* Perform adapter initialization. */ + rev = ctlr->pdev->rid; + if((rev & 0xc0) == 0x40) + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMb); + else if(!(rev & 0x80)) + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | AlmMm); + + if(ctlr->eeprom.cap == 0x80) + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | SkuMrc); + + if((ctlr->eeprom.rev & 0xf0) == 0xd0) + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | RevD); + else + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) & ~RevD); + + if(ctlr->eeprom.type > 1) + csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | TypeB); + + /* Initialize RX ring. */ + if((err = niclock(ctlr)) != nil) + return err; + + coherence(); + csr32w(ctlr, FhRxBase, PCIWADDR(ctlr->rx.p)); + csr32w(ctlr, FhRxRptrAddr, PCIWADDR(&ctlr->shared->next)); + csr32w(ctlr, FhRxWptr, 0); + csr32w(ctlr, FhRxConfig, + FhRxConfigDmaEna | + FhRxConfigRdrbdEna | + FhRxConfigWrstatusEna | + FhRxConfigMaxfrag | + (Nrxlog << FhRxConfigNrdbShift) | + FhRxConfigIrqDstHost | + (1 << FhRxConfigIrqRbthShift)); + USED(csr32r(ctlr, FhRssrTbl)); + csr32w(ctlr, FhRxWptr, (Nrx-1) & ~7); + nicunlock(ctlr); + + /* Initialize TX rings. */ + if((err = niclock(ctlr)) != nil) + return err; + prphwrite(ctlr, AlmSchedMode, 2); + prphwrite(ctlr, AlmSchedArastat, 1); + prphwrite(ctlr, AlmSchedTxfact, 0x3f); + prphwrite(ctlr, AlmSchedBP1, 0x10000); + prphwrite(ctlr, AlmSchedBP2, 0x30002); + prphwrite(ctlr, AlmSchedTxf4mf, 4); + prphwrite(ctlr, AlmSchedTxf5mf, 5); + csr32w(ctlr, FhTxBase, PCIWADDR(ctlr->shared)); + csr32w(ctlr, FhMsgConfig, 0xffff05a5); + for(i = 0; i < 6; i++){ + csr32w(ctlr, FhCbbcCtrl+i*8, 0); + csr32w(ctlr, FhCbbcBase+i*8, 0); + csr32w(ctlr, FhTxConfig+i*32, 0x80200008); + } + nicunlock(ctlr); + USED(csr32r(ctlr, FhTxBase)); + + csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill); + csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked); + + ctlr->broken = 0; + ctlr->wait.m = 0; + ctlr->wait.w = 0; + + ctlr->ie = Idefmask; + csr32w(ctlr, Imr, ctlr->ie); + csr32w(ctlr, Isr, ~0); + + csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill); + csr32w(ctlr, UcodeGp1Clr, UcodeGp1RfKill); + + return nil; +} + +static char* +postboot(Ctlr *); + +static char* +boot(Ctlr *ctlr) +{ + int i, n, size; + uchar *dma, *p; + FWImage *fw; + char *err; + + fw = ctlr->fw; + /* 16 byte padding may not be necessary. */ + size = ROUND(fw->init.data.size, 16) + ROUND(fw->init.text.size, 16); + dma = mallocalign(size, 16, 0, 0); + if(dma == nil) + return "no memory for dma"; + + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + + p = dma; + memmove(p, fw->init.data.data, fw->init.data.size); + coherence(); + prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p)); + prphwrite(ctlr, BsmDramDataSize, fw->init.data.size); + p += ROUND(fw->init.data.size, 16); + memmove(p, fw->init.text.data, fw->init.text.size); + coherence(); + prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p)); + prphwrite(ctlr, BsmDramTextSize, fw->init.text.size); + + nicunlock(ctlr); + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + + /* Copy microcode image into NIC memory. */ + p = fw->boot.text.data; + n = fw->boot.text.size/4; + for(i=0; imain.data.size, 16) + ROUND(fw->main.text.size, 16); + dma = mallocalign(size, 16, 0, 0); + if(dma == nil) + return "no memory for dma"; + if((err = niclock(ctlr)) != nil){ + free(dma); + return err; + } + p = dma; + memmove(p, fw->main.data.data, fw->main.data.size); + coherence(); + prphwrite(ctlr, BsmDramDataAddr, PCIWADDR(p)); + prphwrite(ctlr, BsmDramDataSize, fw->main.data.size); + p += ROUND(fw->main.data.size, 16); + memmove(p, fw->main.text.data, fw->main.text.size); + coherence(); + prphwrite(ctlr, BsmDramTextAddr, PCIWADDR(p)); + prphwrite(ctlr, BsmDramTextSize, fw->main.text.size | (1<<31)); + nicunlock(ctlr); + + if(irqwait(ctlr, Ierr|Ialive, 5000) != Ialive){ + free(dma); + return "main firmware boot failed"; + } + free(dma); + return postboot(ctlr); +} + +static int +txqready(void *arg) +{ + TXQ *q = arg; + return q->n < Ntx; +} + +static char* +qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block) +{ + uchar *d, *c; + int pad; + TXQ *q; + + assert(qid < nelem(ctlr->tx)); + assert(size <= Tcmdsize-4); + + ilock(ctlr); + q = &ctlr->tx[qid]; + while(q->n >= Ntx && !ctlr->broken){ + iunlock(ctlr); + qlock(q); + if(!waserror()){ + tsleep(q, txqready, q, 10); + poperror(); + } + qunlock(q); + ilock(ctlr); + } + if(ctlr->broken){ + iunlock(ctlr); + return "qcmd: broken"; + } + q->n++; + + q->lastcmd = code; + q->b[q->i] = block; + c = q->c + q->i * Tcmdsize; + d = q->d + q->i * Tdscsize; + + /* build command */ + c[0] = code; + c[1] = 0; /* flags */ + c[2] = q->i; + c[3] = qid; + + if(size > 0) + memmove(c+4, data, size); + size += 4; + + memset(d, 0, Tdscsize); + + pad = size - 4; + if(block != nil) + pad += BLEN(block); + pad = ((pad + 3) & ~3) - pad; + + put32(d, (pad << 28) | ((1 + (block != nil)) << 24)), d += 4; + put32(d, PCIWADDR(c)), d += 4; + put32(d, size), d += 4; + + if(block != nil){ + size = BLEN(block); + put32(d, PCIWADDR(block->rp)), d += 4; + put32(d, size), d += 4; + } + + USED(d); + + coherence(); + + q->i = (q->i+1) % Ntx; + csr32w(ctlr, HbusTargWptr, (qid<<8) | q->i); + + iunlock(ctlr); + + return nil; +} + +static int +txqempty(void *arg) +{ + TXQ *q = arg; + return q->n == 0; +} + +static char* +flushq(Ctlr *ctlr, uint qid) +{ + TXQ *q; + int i; + + q = &ctlr->tx[qid]; + qlock(q); + for(i = 0; i < 200 && !ctlr->broken; i++){ + if(txqempty(q)){ + qunlock(q); + return nil; + } + if(islo() && !waserror()){ + tsleep(q, txqempty, q, 10); + poperror(); + } + } + qunlock(q); + if(ctlr->broken) + return "flushq: broken"; + return "flushq: timeout"; +} + +static char* +cmd(Ctlr *ctlr, uint code, uchar *data, int size) +{ + char *err; + + if((err = qcmd(ctlr, 4, code, data, size, nil)) != nil) + return err; + return flushq(ctlr, 4); +} + +static void +setled(Ctlr *ctlr, int which, int on, int off) +{ + uchar c[8]; + + memset(c, 0, sizeof(c)); + put32(c, 10000); + c[4] = which; + c[5] = on; + c[6] = off; + cmd(ctlr, 72, c, sizeof(c)); +} + +static char* +btcoex(Ctlr *ctlr) +{ + uchar c[Tcmdsize], *p; + + /* configure bluetooth coexistance. */ + p = c; + *p++ = 3; /* flags WPI_BT_COEX_MODE_4WIRE */ + *p++ = 30; /* lead time */ + *p++ = 5; /* max kill */ + *p++ = 0; /* reserved */ + put32(p, 0), p += 4; /* kill_ack */ + put32(p, 0), p += 4; /* kill_cts */ + return cmd(ctlr, 155, c, p-c); +} + +static char* +powermode(Ctlr *ctlr) +{ + uchar c[Tcmdsize]; + int capoff, reg; + + memset(c, 0, sizeof(c)); + capoff = pcicap(ctlr->pdev, PciCapPCIe); + if(capoff >= 0){ + reg = pcicfgr8(ctlr->pdev, capoff+1); + if((reg & 1) == 0) /* PCI_PCIE_LCR_ASPM_L0S */ + c[0] |= 1<<3; /* WPI_PS_PCI_PMGT */ + } + return cmd(ctlr, 119, c, 4*(3+5)); +} + +static char* +postboot(Ctlr *ctlr) +{ + while((ctlr->temp = (int)csr32r(ctlr, UcodeGp2)) == 0) + delay(10); + +if(0){ + char *err; + + if((err = btcoex(ctlr)) != nil) + print("btcoex: %s\n", err); + if((err = powermode(ctlr)) != nil) + print("powermode: %s\n", err); +} + + return nil; +} + +static uchar wpirates[] = { + 0x80 | 12, + 0x80 | 18, + 0x80 | 24, + 0x80 | 36, + 0x80 | 48, + 0x80 | 72, + 0x80 | 96, + 0x80 | 108, + 0x80 | 2, + 0x80 | 4, + 0x80 | 11, + 0x80 | 22, + + 0 +}; + +static struct { + uchar rate; + uchar plcp; +} ratetab[] = { + { 12, 0xd }, + { 18, 0xf }, + { 24, 0x5 }, + { 36, 0x7 }, + { 48, 0x9 }, + { 72, 0xb }, + { 96, 0x1 }, + { 108, 0x3 }, + { 2, 10 }, + { 4, 20 }, + { 11, 55 }, + { 22, 110 }, +}; + +static u8int rfgain_2ghz[] = { + 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xd3, 0xd3, 0xb3, 0xb3, 0xb3, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x73, 0xeb, 0xeb, 0xeb, + 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xab, 0xab, 0xab, 0x8b, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xc3, 0xc3, 0xc3, 0xc3, 0xa3, + 0xa3, 0xa3, 0xa3, 0x83, 0x83, 0x83, 0x83, 0x63, 0x63, 0x63, 0x63, + 0x43, 0x43, 0x43, 0x43, 0x23, 0x23, 0x23, 0x23, 0x03, 0x03, 0x03, + 0x03 +}; + +static u8int dspgain_2ghz[] = { + 0x7f, 0x7f, 0x7f, 0x7f, 0x7d, 0x6e, 0x69, 0x62, 0x7d, 0x73, 0x6c, + 0x63, 0x77, 0x6f, 0x69, 0x61, 0x5c, 0x6a, 0x64, 0x78, 0x71, 0x6b, + 0x7d, 0x77, 0x70, 0x6a, 0x65, 0x61, 0x5b, 0x6b, 0x79, 0x73, 0x6d, + 0x7f, 0x79, 0x73, 0x6c, 0x66, 0x60, 0x5c, 0x6e, 0x68, 0x62, 0x74, + 0x7d, 0x77, 0x71, 0x6b, 0x65, 0x60, 0x71, 0x6a, 0x66, 0x5f, 0x71, + 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, + 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, 0x5f, 0x71, 0x6a, 0x66, + 0x5f +}; + +static int +pwridx(Ctlr *ctlr, Powergrp *pwgr, int chan, int rate) +{ +/* Fixed-point arithmetic division using a n-bit fractional part. */ +#define fdivround(a, b, n) \ + ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n)) + +/* Linear interpolation. */ +#define interpolate(x, x1, y1, x2, y2, n) \ + ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n)) + + int pwr; + Sample *sample; + int idx; + + /* Default TX power is group maximum TX power minus 3dB. */ + pwr = pwgr->maxpwr / 2; + + /* Decrease TX power for highest OFDM rates to reduce distortion. */ + switch(rate){ + case 5: /* WPI_RIDX_OFDM36 */ + pwr -= 0; + break; + case 6: /* WPI_RIDX_OFDM48 */ + pwr -=7; + break; + case 7: /* WPI_RIDX_OFDM54 */ + pwr -= 9; + break; + } + + /* Never exceed the channel maximum allowed TX power. */ + pwr = MIN(pwr, ctlr->maxpwr[chan]); + + /* Retrieve TX power index into gain tables from samples. */ + for(sample = pwgr->samples; sample < &pwgr->samples[3]; sample++) + if(pwr > sample[1].power) + break; + /* Fixed-point linear interpolation using a 19-bit fractional part. */ + idx = interpolate(pwr, sample[0].power, sample[0].index, + sample[1].power, sample[1].index, 19); + + /*- + * Adjust power index based on current temperature: + * - if cooler than factory-calibrated: decrease output power + * - if warmer than factory-calibrated: increase output power + */ + idx -= (ctlr->temp - pwgr->temp) * 11 / 100; + + /* Decrease TX power for CCK rates (-5dB). */ + if (rate >= 8) + idx += 10; + + /* Make sure idx stays in a valid range. */ + if (idx < 0) + idx = 0; + else if (idx >= nelem(rfgain_2ghz)) + idx = nelem(rfgain_2ghz)-1; + return idx; +#undef fdivround +#undef interpolate +} + +static void +addnode(Ctlr *ctlr, uchar id, uchar *addr, int plcp, int antenna) +{ + uchar c[Tcmdsize], *p; + + memset(p = c, 0, sizeof(c)); + *p++ = 0; /* control (1 = update) */ + p += 3; /* reserved */ + memmove(p, addr, 6); + p += 6; + p += 2; /* reserved */ + *p++ = id; /* node id */ + p++; /* flags */ + p += 2; /* reserved */ + p += 2; /* kflags */ + p++; /* tcs2 */ + p++; /* reserved */ + p += 5*2; /* ttak */ + p += 2; /* reserved */ + p += 16; /* key */ + put32(p, 4); /* action (4 = set_rate) */ + p += 4; + p += 4; /* mask */ + p += 2; /* tid */ + *p++ = plcp; /* plcp */ + *p++ = antenna; /* antenna */ + p++; /* add_imm */ + p++; /* del_imm */ + p++; /* add_imm_start */ + cmd(ctlr, 24, c, p - c); +} + +static void +rxon(Ether *edev, Wnode *bss) +{ + uchar c[Tcmdsize], *p; + int filter, flags, rate; + Ctlr *ctlr; + char *err; + int idx; + + ctlr = edev->ctlr; + filter = FilterNoDecrypt | FilterMulticast; + if(ctlr->prom){ + filter |= FilterPromisc; + if(bss != nil) + ctlr->channel = bss->channel; + bss = nil; + } + flags = RFlagTSF | RFlag24Ghz | RFlagAuto; + if(bss != nil){ + if(bss->cap & (1<<5)) + flags |= RFlagShPreamble; + if(bss->cap & (1<<10)) + flags |= RFlagShSlot; + ctlr->channel = bss->channel; + memmove(ctlr->bssid, bss->bssid, Eaddrlen); + ctlr->aid = bss->aid; + if(ctlr->aid != 0){ + filter |= FilterBSS; + ctlr->bssnodeid = -1; + }else + ctlr->bcastnodeid = -1; + }else{ + memmove(ctlr->bssid, edev->bcast, Eaddrlen); + ctlr->aid = 0; + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + } + + if(ctlr->aid != 0) + setled(ctlr, 2, 0, 1); /* on when associated */ + else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0) + setled(ctlr, 2, 10, 10); /* slow blink when connecting */ + else + setled(ctlr, 2, 5, 5); /* fast blink when scanning */ + + memset(p = c, 0, sizeof(c)); + memmove(p, edev->ea, 6); p += 8; /* myaddr */ + memmove(p, ctlr->bssid, 6); p += 16; /* bssid */ + *p++ = 3; /* mode (STA) */ + p += 3; + *p++ = 0xff; /* ofdm mask (not yet negotiated) */ + *p++ = 0x0f; /* cck mask (not yet negotiated) */ + put16(p, ctlr->aid & 0x3fff); /* associd */ + p += 2; + put32(p, flags); + p += 4; + put32(p, filter); + p += 4; + *p++ = ctlr->channel; + p += 3; + + if((err = cmd(ctlr, 16, c, p - c)) != nil){ + print("rxon: %s\n", err); + return; + } + + if(ctlr->maxpwr[ctlr->channel] != 0){ + /* tx power */ + memset(p = c, 0, sizeof(c)); + *p++ = 1; /* band (0 = 5ghz) */ + p++; /* reserved */ + put16(p, ctlr->channel), p += 2; + for(rate = 0; rate < nelem(ratetab); rate++){ + idx = pwridx(ctlr, &ctlr->eeprom.pwrgrps[0], ctlr->channel, rate); + *p++ = ratetab[rate].plcp; + *p++ = rfgain_2ghz[idx]; /* rf_gain */ + *p++ = dspgain_2ghz[idx]; /* dsp_gain */ + p++; /* reservd */ + } + cmd(ctlr, 151, c, p - c); + } + + if(ctlr->bcastnodeid == -1){ + ctlr->bcastnodeid = 24; + addnode(ctlr, ctlr->bcastnodeid, edev->bcast, ratetab[0].plcp, 3<<6); + } + if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){ + ctlr->bssnodeid = 0; + addnode(ctlr, ctlr->bssnodeid, bss->bssid, ratetab[0].plcp, 3<<6); + } +} + +enum { + TFlagNeedRTS = 1<<1, + TFlagNeedCTS = 1<<2, + TFlagNeedACK = 1<<3, + TFlagFullTxOp = 1<<7, + TFlagBtDis = 1<<12, + TFlagAutoSeq = 1<<13, + TFlagInsertTs = 1<<16, +}; + +static void +transmit(Wifi *wifi, Wnode *wn, Block *b) +{ + uchar c[Tcmdsize], *p; + Ether *edev; + Ctlr *ctlr; + Wifipkt *w; + int flags, nodeid, rate, timeout; + char *err; + + edev = wifi->ether; + ctlr = edev->ctlr; + + qlock(ctlr); + if(ctlr->attached == 0 || ctlr->broken){ + qunlock(ctlr); + freeb(b); + return; + } + + if((wn->channel != ctlr->channel) + || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))) + rxon(edev, wn); + + if(b == nil){ + /* association note has no data to transmit */ + qunlock(ctlr); + return; + } + + flags = 0; + timeout = 3; + nodeid = ctlr->bcastnodeid; + p = wn->minrate; + w = (Wifipkt*)b->rp; + if((w->a1[0] & 1) == 0){ + flags |= TFlagNeedACK; + + if(BLEN(b) > 512-4) + flags |= TFlagNeedRTS|TFlagFullTxOp; + + if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ + timeout = 0; + nodeid = ctlr->bssnodeid; + p = wn->actrate; + } + } + qunlock(ctlr); + + rate = 0; + if(p >= wpirates && p < &wpirates[nelem(ratetab)]) + rate = p - wpirates; + + memset(p = c, 0, sizeof(c)); + put16(p, BLEN(b)), p += 2; + put16(p, 0), p += 2; /* lnext */ + put32(p, flags), p += 4; + *p++ = ratetab[rate].plcp; + *p++ = nodeid; + *p++ = 0; /* tid */ + *p++ = 0; /* security */ + p += 16+8; /* key/iv */ + put32(p, 0), p += 4; /* fnext */ + put32(p, 0xffffffff), p += 4; /* livetime infinite */ + *p++ = 0xff; + *p++ = 0x0f; + *p++ = 7; + *p++ = 15; + put16(p, timeout), p += 2; + put16(p, 0), p += 2; /* txop */ + + if((err = qcmd(ctlr, 0, 28, c, p - c, b)) != nil){ + print("transmit: %s\n", err); + freeb(b); + } +} + +static long +wpictl(Ether *edev, void *buf, long n) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(n >= 5 && memcmp(buf, "reset", 5) == 0){ + ctlr->broken = 1; + return n; + } + if(ctlr->wifi) + return wifictl(ctlr->wifi, buf, n); + return 0; +} + +static long +wpiifstat(Ether *edev, void *buf, long n, ulong off) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->wifi) + return wifistat(ctlr->wifi, buf, n, off); + return 0; +} + +static void +setoptions(Ether *edev) +{ + Ctlr *ctlr; + int i; + + ctlr = edev->ctlr; + for(i = 0; i < edev->nopt; i++) + wificfg(ctlr->wifi, edev->opt[i]); +} + +static void +wpipromiscuous(void *arg, int on) +{ + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + qlock(ctlr); + ctlr->prom = on; + rxon(edev, ctlr->wifi->bss); + qunlock(ctlr); +} + +static void +wpimulticast(void *, uchar*, int) +{ +} + +static void +wpirecover(void *arg) +{ + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + while(waserror()) + ; + for(;;){ + tsleep(&up->sleep, return0, 0, 4000); + + qlock(ctlr); + for(;;){ + if(ctlr->broken == 0) + break; + + if(ctlr->power) + poweroff(ctlr); + + if((csr32r(ctlr, Gpc) & RfKill) == 0) + break; + + if(reset(ctlr) != nil) + break; + if(boot(ctlr) != nil) + break; + + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + ctlr->aid = 0; + rxon(edev, ctlr->wifi->bss); + break; + } + qunlock(ctlr); + } +} + +static void +wpiattach(Ether *edev) +{ + FWImage *fw; + Ctlr *ctlr; + char *err; + + ctlr = edev->ctlr; + qlock(ctlr); + if(waserror()){ + print("#l%d: %s\n", edev->ctlrno, up->errstr); + if(ctlr->power) + poweroff(ctlr); + qunlock(ctlr); + nexterror(); + } + if(ctlr->attached == 0){ + if((csr32r(ctlr, Gpc) & RfKill) == 0) + error("wifi disabled by switch"); + + if(ctlr->wifi == nil){ + ctlr->wifi = wifiattach(edev, transmit); + ctlr->wifi->rates = wpirates; + } + + if(ctlr->fw == nil){ + fw = readfirmware(); + print("#l%d: firmware: %ux, size: %ux+%ux+%ux+%ux+%ux\n", + edev->ctlrno, fw->version, + fw->main.text.size, fw->main.data.size, + fw->init.text.size, fw->init.data.size, + fw->boot.text.size); + ctlr->fw = fw; + } + + if((err = reset(ctlr)) != nil) + error(err); + if((err = boot(ctlr)) != nil) + error(err); + + ctlr->bcastnodeid = -1; + ctlr->bssnodeid = -1; + ctlr->channel = 1; + ctlr->aid = 0; + + setoptions(edev); + + ctlr->attached = 1; + + kproc("wpirecover", wpirecover, edev); + } + qunlock(ctlr); + poperror(); +} + +static void +receive(Ctlr *ctlr) +{ + Block *b, *bb; + uchar *d; + RXQ *rx; + TXQ *tx; + u32int hw; + + rx = &ctlr->rx; + if(ctlr->broken || ctlr->shared == nil || rx->b == nil) + return; + + bb = nil; + for(hw = ctlr->shared->next % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){ + uchar type, flags, idx, qid; + u32int len; + + b = rx->b[rx->i]; + if(b == nil) + continue; + + d = b->rp; + len = get32(d); d += 4; + type = *d++; + flags = *d++; + idx = *d++; + qid = *d++; + + USED(len); + USED(flags); + +if(0) iprint("rxdesc[%d] type=%d len=%d idx=%d qid=%d\n", rx->i, type, len, idx, qid); + + if(bb != nil){ + freeb(bb); + bb = nil; + } + if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){ + tx = &ctlr->tx[qid]; + if(tx->n > 0){ + bb = tx->b[idx]; + tx->b[idx] = nil; + tx->n--; + wakeup(tx); + } + } + + switch(type){ + case 1: /* uc ready */ + break; + + case 24: /* add node done */ + break; + + case 27: /* rx done */ + if(d + 1 > b->lim) + break; + d += d[0]; + d += 8; + if(d + 6 + 2 > b->lim){ + break; + } + len = get16(d+6); + d += 8; + if(d + len + 4 > b->lim){ + break; + } + if((get32(d + len) & 3) != 3){ + break; + } + if(ctlr->wifi == nil) + break; + if(rbplant(ctlr, rx->i) < 0) + break; + b->rp = d; + b->wp = d + len; + wifiiq(ctlr->wifi, b); + continue; + + case 28: /* tx done */ + if(len <= 8 || d[8] == 1) + break; + wifitxfail(ctlr->wifi, bb); + break; + + case 130: /* start scan */ + break; + + case 132: /* stop scan */ + break; + + case 161: /* state change */ + break; + } + } + csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7); + if(bb != nil) + freeb(bb); +} + +static void +wpiinterrupt(Ureg*, void *arg) +{ + u32int isr, fhisr; + Ether *edev; + Ctlr *ctlr; + + edev = arg; + ctlr = edev->ctlr; + ilock(ctlr); + csr32w(ctlr, Imr, 0); + isr = csr32r(ctlr, Isr); + fhisr = csr32r(ctlr, FhIsr); + if(isr == 0xffffffff || (isr & 0xfffffff0) == 0xa5a5a5a0){ + iunlock(ctlr); + return; + } + if(isr == 0 && fhisr == 0) + goto done; + csr32w(ctlr, Isr, isr); + csr32w(ctlr, FhIsr, fhisr); + if((isr & (Iswrx | Ifhrx)) || (fhisr & Ifhrx)) + receive(ctlr); + if(isr & Ierr){ + ctlr->broken = 1; + iprint("#l%d: fatal firmware error, lastcmd %ud\n", edev->ctlrno, ctlr->tx[4].lastcmd); + } + ctlr->wait.m |= isr; + if(ctlr->wait.m & ctlr->wait.w) + wakeup(&ctlr->wait); +done: + csr32w(ctlr, Imr, ctlr->ie); + iunlock(ctlr); +} + +static void +wpishutdown(Ether *edev) +{ + Ctlr *ctlr; + + ctlr = edev->ctlr; + if(ctlr->power) + poweroff(ctlr); + ctlr->broken = 0; +} + +static Ctlr *wpihead, *wpitail; + +static void +wpipci(void) +{ + Pcidev *pdev; + + pdev = nil; + while(pdev = pcimatch(pdev, 0x8086, 0)){ + Ctlr *ctlr; + void *mem; + switch(pdev->did){ + default: + continue; + case 0x4227: + break; + } + + /* Clear device-specific "PCI retry timeout" register (41h). */ + if(pcicfgr8(pdev, 0x41) != 0) + pcicfgw8(pdev, 0x41, 0); + + pcisetbme(pdev); + pcisetpms(pdev, 0); + + ctlr = malloc(sizeof(Ctlr)); + if(ctlr == nil) { + print("wpi: unable to alloc Ctlr\n"); + continue; + } + ctlr->port = pdev->mem[0].bar & ~0x0F; + mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size); + if(mem == nil) { + print("wpi: can't map %8.8luX\n", pdev->mem[0].bar); + free(ctlr); + continue; + } + ctlr->nic = mem; + ctlr->pdev = pdev; + + if(wpihead != nil) + wpitail->link = ctlr; + else + wpihead = ctlr; + wpitail = ctlr; + } +} + +static int +wpipnp(Ether *edev) +{ + Ctlr *ctlr; + + if(wpihead == nil) + wpipci(); + +again: + for(ctlr = wpihead; ctlr != nil; ctlr = ctlr->link){ + if(ctlr->active) + continue; + if(edev->port == 0 || edev->port == ctlr->port){ + ctlr->active = 1; + break; + } + } + + if(ctlr == nil) + return -1; + + edev->ctlr = ctlr; + edev->port = ctlr->port; + edev->irq = ctlr->pdev->intl; + edev->tbdf = ctlr->pdev->tbdf; + edev->arg = edev; + edev->interrupt = wpiinterrupt; + edev->attach = wpiattach; + edev->ifstat = wpiifstat; + edev->ctl = wpictl; + edev->shutdown = wpishutdown; + edev->promiscuous = wpipromiscuous; + edev->multicast = wpimulticast; + edev->mbps = 54; + + if(wpiinit(edev) < 0){ + edev->ctlr = nil; + goto again; + } + + return 0; +} + +void +etherwpilink(void) +{ + addethercard("wpi", wpipnp); +} diff --git a/sys/src/9/pc/wifi.c b/sys/src/9/pc/wifi.c new file mode 100644 index 0000000000..6f0cad7b30 --- /dev/null +++ b/sys/src/9/pc/wifi.c @@ -0,0 +1,1690 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "wifi.h" + +#include + +typedef struct SNAP SNAP; +struct SNAP +{ + uchar dsap; + uchar ssap; + uchar control; + uchar orgcode[3]; + uchar type[2]; +}; + +enum { + WIFIHDRSIZE = 2+2+3*6+2, + SNAPHDRSIZE = 8, +}; + +static char Sconn[] = "connecting"; +static char Sauth[] = "authenticated"; +static char Sneedauth[] = "need authentication"; +static char Sunauth[] = "unauthenticated"; + +static char Sassoc[] = "associated"; +static char Sunassoc[] = "unassociated"; +static char Sblocked[] = "blocked"; /* no keys negotiated. only pass EAPOL frames */ + +static uchar basicrates[] = { + 0x80 | 2, /* 1.0 Mb/s */ + 0x80 | 4, /* 2.0 Mb/s */ + 0x80 | 11, /* 5.5 Mb/s */ + 0x80 | 22, /* 11.0 Mb/s */ + + 0 +}; + +static Block* wifidecrypt(Wifi *, Wnode *, Block *); +static Block* wifiencrypt(Wifi *, Wnode *, Block *); +static void freewifikeys(Wifi *, Wnode *); + +static uchar* +srcaddr(Wifipkt *w) +{ + if((w->fc[1] & 0x02) == 0) + return w->a2; + if((w->fc[1] & 0x01) == 0) + return w->a3; + return w->a4; +} +static uchar* +dstaddr(Wifipkt *w) +{ + if((w->fc[1] & 0x01) != 0) + return w->a3; + return w->a1; +} + +int +wifihdrlen(Wifipkt *w) +{ + int n; + + n = WIFIHDRSIZE; + if((w->fc[0] & 0x0c) == 0x08) + if((w->fc[0] & 0xf0) == 0x80){ /* QOS */ + n += 2; + if(w->fc[1] & 0x80) + n += 4; + } + if((w->fc[1] & 3) == 0x03) + n += Eaddrlen; + return n; +} + +void +wifiiq(Wifi *wifi, Block *b) +{ + SNAP s; + Wifipkt h, *w; + Etherpkt *e; + int hdrlen; + + if(BLEN(b) < WIFIHDRSIZE) + goto drop; + w = (Wifipkt*)b->rp; + hdrlen = wifihdrlen(w); + if(BLEN(b) < hdrlen) + goto drop; + if(w->fc[1] & 0x40){ + /* encrypted */ + qpass(wifi->iq, b); + return; + } + switch(w->fc[0] & 0x0c){ + case 0x00: /* management */ + if((w->fc[1] & 3) != 0x00) /* STA->STA */ + break; + qpass(wifi->iq, b); + return; + case 0x04: /* control */ + break; + case 0x08: /* data */ + b->rp += hdrlen; + switch(w->fc[0] & 0xf0){ + default: + goto drop; + case 0x80: /* QOS */ + case 0x00: + break; + } + if(BLEN(b) < SNAPHDRSIZE) + break; + memmove(&s, b->rp, SNAPHDRSIZE); + if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3) + break; + if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0) + break; + b->rp += SNAPHDRSIZE-ETHERHDRSIZE; + h = *w; + e = (Etherpkt*)b->rp; + memmove(e->d, dstaddr(&h), Eaddrlen); + memmove(e->s, srcaddr(&h), Eaddrlen); + memmove(e->type, s.type, 2); + etheriq(wifi->ether, b, 1); + return; + } +drop: + freeb(b); +} + +static void +wifitx(Wifi *wifi, Wnode *wn, Block *b) +{ + Wifipkt *w; + uint seq; + + wn->lastsend = MACHP(0)->ticks; + + seq = incref(&wifi->txseq); + seq <<= 4; + + w = (Wifipkt*)b->rp; + w->dur[0] = 0; + w->dur[1] = 0; + w->seq[0] = seq; + w->seq[1] = seq>>8; + + if((w->fc[0] & 0x0c) != 0x00){ + b = wifiencrypt(wifi, wn, b); + if(b == nil) + return; + } + + if((wn->txcount++ & 255) == 255){ + if(wn->actrate != nil && wn->actrate < wn->maxrate) + wn->actrate++; + } + + (*wifi->transmit)(wifi, wn, b); +} + +static Wnode* +nodelookup(Wifi *wifi, uchar *bssid, int new) +{ + Wnode *wn, *nn; + + if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0) + return nil; + if((wn = wifi->bss) != nil){ + if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){ + wn->lastseen = MACHP(0)->ticks; + return wn; + } + } + if((nn = wifi->node) == wn) + nn++; + for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){ + if(wn == wifi->bss) + continue; + if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){ + wn->lastseen = MACHP(0)->ticks; + return wn; + } + if((long)(wn->lastseen - nn->lastseen) < 0) + nn = wn; + } + if(!new) + return nil; + freewifikeys(wifi, nn); + memset(nn, 0, sizeof(Wnode)); + memmove(nn->bssid, bssid, Eaddrlen); + nn->lastseen = MACHP(0)->ticks; + return nn; +} + +void +wifitxfail(Wifi *wifi, Block *b) +{ + Wifipkt *w; + Wnode *wn; + + if(b == nil) + return; + w = (Wifipkt*)b->rp; + wn = nodelookup(wifi, w->a1, 0); + if(wn == nil) + return; + wn->txerror++; + if(wn->actrate != nil && wn->actrate > wn->minrate) + wn->actrate--; +} + +static uchar* +putrates(uchar *p, uchar *rates) +{ + int n, m; + + n = m = strlen((char*)rates); + if(n > 8) + n = 8; + /* supported rates */ + *p++ = 1; + *p++ = n; + memmove(p, rates, n); + p += n; + if(m > 8){ + /* extended supported rates */ + *p++ = 50; + *p++ = m; + memmove(p, rates, m); + p += m; + } + return p; +} + +static void +wifiprobe(Wifi *wifi, Wnode *wn) +{ + Wifipkt *w; + Block *b; + uchar *p; + int n; + + n = strlen(wifi->essid); + if(n == 0){ + /* no specific essid, just tell driver to tune channel */ + (*wifi->transmit)(wifi, wn, nil); + return; + } + + b = allocb(WIFIHDRSIZE + 512); + w = (Wifipkt*)b->wp; + w->fc[0] = 0x40; /* probe request */ + w->fc[1] = 0x00; /* STA->STA */ + memmove(w->a1, wifi->ether->bcast, Eaddrlen); /* ??? */ + memmove(w->a2, wifi->ether->ea, Eaddrlen); + memmove(w->a3, wifi->ether->bcast, Eaddrlen); + b->wp += WIFIHDRSIZE; + p = b->wp; + + *p++ = 0; /* set */ + *p++ = n; + memmove(p, wifi->essid, n); + p += n; + + p = putrates(p, wifi->rates); + + *p++ = 3; /* ds parameter set */ + *p++ = 1; + *p++ = wn->channel; + + b->wp = p; + wifitx(wifi, wn, b); +} + +static void +sendauth(Wifi *wifi, Wnode *bss) +{ + Wifipkt *w; + Block *b; + uchar *p; + + b = allocb(WIFIHDRSIZE + 3*2); + w = (Wifipkt*)b->wp; + w->fc[0] = 0xB0; /* auth request */ + w->fc[1] = 0x00; /* STA->STA */ + memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */ + memmove(w->a2, wifi->ether->ea, Eaddrlen); + memmove(w->a3, bss->bssid, Eaddrlen); + b->wp += WIFIHDRSIZE; + p = b->wp; + *p++ = 0; /* alg */ + *p++ = 0; + *p++ = 1; /* seq */ + *p++ = 0; + *p++ = 0; /* status */ + *p++ = 0; + b->wp = p; + + bss->aid = 0; + + wifitx(wifi, bss, b); +} + +static void +sendassoc(Wifi *wifi, Wnode *bss) +{ + Wifipkt *w; + Block *b; + uchar *p; + int cap, n; + + b = allocb(WIFIHDRSIZE + 512); + w = (Wifipkt*)b->wp; + w->fc[0] = 0x00; /* assoc request */ + w->fc[1] = 0x00; /* STA->STA */ + memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */ + memmove(w->a2, wifi->ether->ea, Eaddrlen); + memmove(w->a3, bss->bssid, Eaddrlen); + b->wp += WIFIHDRSIZE; + p = b->wp; + + /* capinfo */ + cap = 1; // ESS + cap |= (1<<5); // Short Preamble + cap |= (1<<10) & bss->cap; // Short Slot Time + *p++ = cap; + *p++ = cap>>8; + + /* interval */ + *p++ = 16; + *p++ = 16>>8; + + n = strlen(bss->ssid); + *p++ = 0; /* SSID */ + *p++ = n; + memmove(p, bss->ssid, n); + p += n; + + p = putrates(p, wifi->rates); + + n = bss->rsnelen; + if(n > 0){ + memmove(p, bss->rsne, n); + p += n; + } + + b->wp = p; + wifitx(wifi, bss, b); +} + +static void +setstatus(Wifi *wifi, Wnode *wn, char *new) +{ + char *old; + + old = wn->status; + wn->status = new; + if(wifi->debug && new != old) + print("#l%d: status %E: %.12ld %.12ld: %s -> %s (from pc=%#p)\n", + wifi->ether->ctlrno, + wn->bssid, + TK2MS(MACHP(0)->ticks), TK2MS(MACHP(0)->ticks - wn->lastsend), + old, new, + getcallerpc(&wifi)); +} + +static void +recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len) +{ + uint s; + + if(len < 2+2+2) + return; + + d += 2; /* caps */ + s = d[0] | d[1]<<8; + d += 2; + switch(s){ + case 0x00: + wn->aid = d[0] | d[1]<<8; + if(wn->rsnelen > 0) + setstatus(wifi, wn, Sblocked); + else + setstatus(wifi, wn, Sassoc); + break; + default: + wn->aid = 0; + setstatus(wifi, wn, Sunassoc); + } +} + +static void +recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len) +{ + static uchar wpa1oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + uchar *e, *x, *p, t; + int rsnset; + + len -= 8+2+2; + if(len < 0) + return; + + d += 8; /* timestamp */ + wn->ival = d[0] | d[1]<<8; + d += 2; + wn->cap = d[0] | d[1]<<8; + d += 2; + + rsnset = 0; + for(e = d + len; d+2 <= e; d = x){ + d += 2; + x = d + d[-1]; + if(x > e) + break; /* truncated */ + t = d[-2]; + switch(t){ + case 0: /* SSID */ + len = 0; + while(len < Essidlen && d+len < x && d[len] != 0) + len++; + if(len == 0) + continue; + if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){ + strncpy(wn->ssid, (char*)d, len); + wn->ssid[len] = 0; + } + break; + case 1: /* supported rates */ + case 50: /* extended rates */ + if(wn->minrate != nil || wn->maxrate != nil || wifi->rates == nil) + break; /* already set */ + while(d < x){ + t = *d++ & 0x7f; + for(p = wifi->rates; *p != 0; p++){ + if((*p & 0x7f) == t){ + if(wn->minrate == nil || t < (*wn->minrate & 0x7f)) + wn->minrate = p; + if(wn->maxrate == nil || t > (*wn->maxrate & 0x7f)) + wn->maxrate = p; + break; + } + } + wn->actrate = wn->maxrate; + } + break; + case 3: /* DSPARAMS */ + if(d != x) + wn->channel = d[0]; + break; + case 221: /* vendor specific */ + len = x - d; + if(rsnset || len < sizeof(wpa1oui) || memcmp(d, wpa1oui, sizeof(wpa1oui)) != 0) + break; + /* no break */ + case 48: /* RSN information */ + len = x - &d[-2]; + memmove(wn->brsne, &d[-2], len); + wn->brsnelen = len; + rsnset = 1; + break; + } + } +} + +static void +freewifikeys(Wifi *wifi, Wnode *wn) +{ + int i; + + wlock(&wifi->crypt); + for(i=0; irxkey); i++){ + free(wn->rxkey[i]); + wn->rxkey[i] = nil; + } + for(i=0; itxkey); i++){ + free(wn->txkey[i]); + wn->txkey[i] = nil; + } + wunlock(&wifi->crypt); +} + +static void +wifideauth(Wifi *wifi, Wnode *wn) +{ + Ether *ether; + Netfile *f; + int i; + + /* deassociate node, clear keys */ + setstatus(wifi, wn, Sunauth); + freewifikeys(wifi, wn); + wn->aid = 0; + + if(wn == wifi->bss){ + /* notify driver about node aid association */ + (*wifi->transmit)(wifi, wn, nil); + + /* notify aux/wpa with a zero length packet that we got deassociated from the ap */ + ether = wifi->ether; + for(i=0; infile; i++){ + f = ether->f[i]; + if(f == nil || f->in == nil || f->inuse == 0 || f->type != 0x888e) + continue; + qflush(f->in); + qwrite(f->in, 0, 0); + } + qflush(ether->oq); + } +} + +/* check if a node qualifies as our bss matching bssid and essid */ +static int +goodbss(Wifi *wifi, Wnode *wn) +{ + if(memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) != 0){ + if(memcmp(wifi->bssid, wn->bssid, Eaddrlen) != 0) + return 0; /* bssid doesnt match */ + } else if(wifi->essid[0] == 0) + return 0; /* both bssid and essid unspecified */ + if(wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) != 0) + return 0; /* essid doesnt match */ + return 1; +} + +static void +wifiproc(void *arg) +{ + Wifi *wifi; + Wifipkt *w; + Wnode *wn; + Block *b; + + b = nil; + wifi = arg; + while(waserror()) + ; + for(;;){ + if(b != nil){ + freeb(b); + b = nil; + continue; + } + if((b = qbread(wifi->iq, 100000)) == nil) + break; + w = (Wifipkt*)b->rp; + if(w->fc[1] & 0x40){ + /* encrypted */ + if((wn = nodelookup(wifi, w->a2, 0)) == nil) + continue; + if((b = wifidecrypt(wifi, wn, b)) != nil){ + w = (Wifipkt*)b->rp; + if(w->fc[1] & 0x40) + continue; + wifiiq(wifi, b); + b = nil; + } + continue; + } + /* management */ + if((w->fc[0] & 0x0c) != 0x00) + continue; + + switch(w->fc[0] & 0xf0){ + case 0x50: /* probe response */ + if(wifi->debug) + print("#l%d: got probe from %E\n", wifi->ether->ctlrno, w->a3); + /* no break */ + case 0x80: /* beacon */ + if((wn = nodelookup(wifi, w->a3, 1)) == nil) + continue; + b->rp += wifihdrlen(w); + recvbeacon(wifi, wn, b->rp, BLEN(b)); + + if(wifi->bss == nil + && TK2MS(MACHP(0)->ticks - wn->lastsend) > 1000 + && goodbss(wifi, wn)){ + setstatus(wifi, wn, Sconn); + sendauth(wifi, wn); + wifi->lastauth = wn->lastsend; + } + continue; + } + + if(memcmp(w->a1, wifi->ether->ea, Eaddrlen)) + continue; + if((wn = nodelookup(wifi, w->a3, 0)) == nil) + continue; + switch(w->fc[0] & 0xf0){ + case 0x10: /* assoc response */ + case 0x30: /* reassoc response */ + b->rp += wifihdrlen(w); + recvassoc(wifi, wn, b->rp, BLEN(b)); + /* notify driver about node aid association */ + if(wn == wifi->bss) + (*wifi->transmit)(wifi, wn, nil); + break; + case 0xb0: /* auth */ + if(wifi->debug) + print("#l%d: got auth from %E\n", wifi->ether->ctlrno, wn->bssid); + if(wn->brsnelen > 0 && wn->rsnelen == 0) + setstatus(wifi, wn, Sneedauth); + else + setstatus(wifi, wn, Sauth); + if(wifi->bss == nil && goodbss(wifi, wn)){ + wifi->bss = wn; + if(wn->status == Sauth) + sendassoc(wifi, wn); + } + break; + case 0xc0: /* deauth */ + if(wifi->debug) + print("#l%d: got deauth from %E\n", wifi->ether->ctlrno, wn->bssid); + wifideauth(wifi, wn); + break; + } + } + pexit("wifi in queue closed", 1); +} + +static void +wifietheroq(Wifi *wifi, Block *b) +{ + Etherpkt e; + Wifipkt h; + int hdrlen; + Wnode *wn; + SNAP *s; + + if(BLEN(b) < ETHERHDRSIZE) + goto drop; + if((wn = wifi->bss) == nil) + goto drop; + + memmove(&e, b->rp, ETHERHDRSIZE); + b->rp += ETHERHDRSIZE; + + if(wn->status == Sblocked){ + /* only pass EAPOL frames when port is blocked */ + if((e.type[0]<<8 | e.type[1]) != 0x888e) + goto drop; + } else if(wn->status != Sassoc) + goto drop; + + h.fc[0] = 0x08; /* data */ + memmove(h.a1, wn->bssid, Eaddrlen); + if(memcmp(e.s, wifi->ether->ea, Eaddrlen) == 0) { + h.fc[1] = 0x01; /* STA->AP */ + } else { + h.fc[1] = 0x03; /* AP->AP (WDS) */ + memmove(h.a2, wifi->ether->ea, Eaddrlen); + } + memmove(dstaddr(&h), e.d, Eaddrlen); + memmove(srcaddr(&h), e.s, Eaddrlen); + + hdrlen = wifihdrlen(&h); + b = padblock(b, hdrlen + SNAPHDRSIZE); + memmove(b->rp, &h, hdrlen); + s = (SNAP*)(b->rp + hdrlen); + s->dsap = s->ssap = 0xAA; + s->control = 0x03; + s->orgcode[0] = 0; + s->orgcode[1] = 0; + s->orgcode[2] = 0; + memmove(s->type, e.type, 2); + + wifitx(wifi, wn, b); + return; +drop: + freeb(b); +} + +static void +wifoproc(void *arg) +{ + Ether *ether; + Wifi *wifi; + Block *b; + + wifi = arg; + ether = wifi->ether; + while(waserror()) + ; + while((b = qbread(ether->oq, 1000000)) != nil) + wifietheroq(wifi, b); + pexit("ether out queue closed", 1); +} + +static void +wifsproc(void *arg) +{ + Ether *ether; + Wifi *wifi; + Wnode wnscan; + Wnode *wn; + ulong now, tmout; + uchar *rate; + + wifi = arg; + ether = wifi->ether; + + wn = &wnscan; + memset(wn, 0, sizeof(*wn)); + memmove(wn->bssid, ether->bcast, Eaddrlen); + + while(waserror()) + ; +Scan: + /* scan for access point */ + while(wifi->bss == nil){ + ether->link = 0; + wnscan.channel = 1 + ((wnscan.channel+4) % 13); + wifiprobe(wifi, &wnscan); + do { + tsleep(&up->sleep, return0, 0, 200); + now = MACHP(0)->ticks; + } while(TK2MS(now-wifi->lastauth) < 1000); + } + + /* maintain access point */ + tmout = 0; + while((wn = wifi->bss) != nil){ + ether->link = (wn->status == Sassoc) || (wn->status == Sblocked); + if(ether->link && (rate = wn->actrate) != nil) + ether->mbps = ((*rate & 0x7f)+1)/2; + now = MACHP(0)->ticks; + if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){ + wifideauth(wifi, wn); + wifi->bss = nil; + break; + } + if(TK2MS(now - wn->lastsend) > 1000){ + if((wn->status == Sauth || wn->status == Sblocked) && (++tmout & 7) == 0) + wifideauth(wifi, wn); /* stuck in auth, start over */ + if(wn->status == Sconn || wn->status == Sunauth) + sendauth(wifi, wn); + if(wn->status == Sauth) + sendassoc(wifi, wn); + } + tsleep(&up->sleep, return0, 0, 500); + } + goto Scan; +} + +Wifi* +wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)) +{ + char name[32]; + Wifi *wifi; + + wifi = malloc(sizeof(Wifi)); + if(wifi == nil) + error(Enomem); + wifi->iq = qopen(ether->limit, 0, 0, 0); + if(wifi->iq == nil){ + free(wifi); + error(Enomem); + } + wifi->ether = ether; + wifi->transmit = transmit; + + wifi->rates = basicrates; + + wifi->essid[0] = 0; + memmove(wifi->bssid, ether->bcast, Eaddrlen); + + wifi->lastauth = MACHP(0)->ticks; + + snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno); + kproc(name, wifiproc, wifi); + snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno); + kproc(name, wifoproc, wifi); + snprint(name, sizeof(name), "#l%dwifs", ether->ctlrno); + kproc(name, wifsproc, wifi); + + return wifi; +} + +static int +hextob(char *s, char **sp, uchar *b, int n) +{ + int r; + + n <<= 1; + for(r = 0; r < n && *s; s++){ + *b <<= 4; + if(*s >= '0' && *s <= '9') + *b |= (*s - '0'); + else if(*s >= 'a' && *s <= 'f') + *b |= 10+(*s - 'a'); + else if(*s >= 'A' && *s <= 'F') + *b |= 10+(*s - 'A'); + else break; + if((++r & 1) == 0) + b++; + } + if(sp != nil) + *sp = s; + return r >> 1; +} + +static char *ciphers[] = { + [0] "clear", + [TKIP] "tkip", + [CCMP] "ccmp", +}; + +static Wkey* +parsekey(char *s) +{ + char buf[256], *p; + uchar key[32]; + int i, n; + Wkey *k; + + strncpy(buf, s, sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + if((p = strchr(buf, ':')) != nil) + *p++ = 0; + else + p = buf; + n = hextob(p, &p, key, sizeof(key)); + for(i=0; ikey, key, n); + break; + case CCMP: + if(n != 16) + return nil; + k = malloc(sizeof(Wkey) + sizeof(AESstate)); + setupAESstate((AESstate*)k->key, key, n, nil); + break; + default: + return nil; + } + memset(key, 0, sizeof(key)); + if(*p == '@') + k->tsc = strtoull(++p, nil, 16); + k->len = n; + k->cipher = i; + return k; +} + +void +wificfg(Wifi *wifi, char *opt) +{ + char *p, buf[64]; + int n; + + if(strncmp(opt, "debug=", 6)) + if(strncmp(opt, "essid=", 6)) + if(strncmp(opt, "bssid=", 6)) + return; + if((p = strchr(opt, '=')) == nil) + return; + if(waserror()) + return; + n = snprint(buf, sizeof(buf), "%.*s %q", (int)(p - opt), opt, p+1); + wifictl(wifi, buf, n); + poperror(); +} + +enum { + CMdebug, + CMessid, + CMauth, + CMbssid, + CMrxkey0, + CMrxkey1, + CMrxkey2, + CMrxkey3, + CMrxkey4, + CMtxkey0, +}; + +static Cmdtab wifictlmsg[] = +{ + CMdebug, "debug", 0, + CMessid, "essid", 0, + CMauth, "auth", 0, + CMbssid, "bssid", 0, + + CMrxkey0, "rxkey0", 0, /* group keys */ + CMrxkey1, "rxkey1", 0, + CMrxkey2, "rxkey2", 0, + CMrxkey3, "rxkey3", 0, + + CMrxkey4, "rxkey", 0, /* peerwise keys */ + CMtxkey0, "txkey", 0, + + CMtxkey0, "txkey0", 0, +}; + +long +wifictl(Wifi *wifi, void *buf, long n) +{ + uchar addr[Eaddrlen]; + Cmdbuf *cb; + Cmdtab *ct; + Wnode *wn; + Wkey *k, **kk; + + cb = nil; + if(waserror()){ + free(cb); + nexterror(); + } + if(wifi->debug) + print("#l%d: wifictl: %.*s\n", wifi->ether->ctlrno, (int)n, buf); + memmove(addr, wifi->ether->bcast, Eaddrlen); + wn = wifi->bss; + cb = parsecmd(buf, n); + ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg)); + if(ct->index >= CMauth){ + if(cb->nf > 1 && (ct->index == CMbssid || ct->index >= CMrxkey0)){ + if(parseether(addr, cb->f[1]) == 0){ + cb->f++; + cb->nf--; + wn = nodelookup(wifi, addr, 0); + } + } + if(wn == nil && ct->index != CMbssid) + error("missing node"); + } + switch(ct->index){ + case CMdebug: + if(cb->f[1] != nil) + wifi->debug = atoi(cb->f[1]); + else + wifi->debug ^= 1; + print("#l%d: debug: %d\n", wifi->ether->ctlrno, wifi->debug); + break; + case CMessid: + if(cb->f[1] != nil) + strncpy(wifi->essid, cb->f[1], Essidlen); + else + wifi->essid[0] = 0; + Findbss: + wn = wifi->bss; + if(wn != nil){ + if(goodbss(wifi, wn)) + break; + wifideauth(wifi, wn); + } + wifi->bss = nil; + if(wifi->essid[0] == 0 && memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) == 0) + break; + for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++) + if(goodbss(wifi, wn)){ + setstatus(wifi, wn, Sconn); + sendauth(wifi, wn); + } + break; + case CMbssid: + memmove(wifi->bssid, addr, Eaddrlen); + goto Findbss; + case CMauth: + freewifikeys(wifi, wn); + if(cb->f[1] == nil) + wn->rsnelen = 0; + else + wn->rsnelen = hextob(cb->f[1], nil, wn->rsne, sizeof(wn->rsne)); + if(wn->aid == 0){ + setstatus(wifi, wn, Sconn); + sendauth(wifi, wn); + } else { + setstatus(wifi, wn, Sauth); + sendassoc(wifi, wn); + } + break; + case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4: + case CMtxkey0: + if(cb->f[1] == nil) + error(Ebadarg); + k = parsekey(cb->f[1]); + if(k == nil) + error("bad key"); + memset(cb->f[1], 0, strlen(cb->f[1])); + if(k->cipher == 0){ + free(k); + k = nil; + } + if(ct->index < CMtxkey0) + kk = &wn->rxkey[ct->index - CMrxkey0]; + else + kk = &wn->txkey[ct->index - CMtxkey0]; + wlock(&wifi->crypt); + free(*kk); + *kk = k; + wunlock(&wifi->crypt); + if(ct->index >= CMtxkey0 && wn->status == Sblocked) + setstatus(wifi, wn, Sassoc); + break; + } + poperror(); + free(cb); + return n; +} + +long +wifistat(Wifi *wifi, void *buf, long n, ulong off) +{ + static uchar zeros[Eaddrlen]; + char essid[Essidlen+1]; + char *s, *p, *e; + Wnode *wn; + Wkey *k; + long now; + int i; + + p = s = smalloc(4096); + e = s + 4096; + + wn = wifi->bss; + if(wn != nil){ + strncpy(essid, wn->ssid, Essidlen); + essid[Essidlen] = 0; + p = seprint(p, e, "essid: %s\n", essid); + p = seprint(p, e, "bssid: %E\n", wn->bssid); + p = seprint(p, e, "status: %s\n", wn->status); + p = seprint(p, e, "channel: %.2d\n", wn->channel); + + /* only print key ciphers and key length */ + rlock(&wifi->crypt); + for(i = 0; irxkey); i++){ + if((k = wn->rxkey[i]) != nil) + p = seprint(p, e, "rxkey%d: %s:[%d]\n", i, + ciphers[k->cipher], k->len); + } + for(i = 0; itxkey); i++){ + if((k = wn->txkey[i]) != nil) + p = seprint(p, e, "txkey%d: %s:[%d]\n", i, + ciphers[k->cipher], k->len); + } + runlock(&wifi->crypt); + + if(wn->brsnelen > 0){ + p = seprint(p, e, "brsne: "); + for(i=0; ibrsnelen; i++) + p = seprint(p, e, "%.2X", wn->brsne[i]); + p = seprint(p, e, "\n"); + } + } else { + p = seprint(p, e, "essid: %s\n", wifi->essid); + p = seprint(p, e, "bssid: %E\n", wifi->bssid); + } + + now = MACHP(0)->ticks; + for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){ + if(wn->lastseen == 0) + continue; + strncpy(essid, wn->ssid, Essidlen); + essid[Essidlen] = 0; + p = seprint(p, e, "node: %E %.4x %-11ld %.2d %s\n", + wn->bssid, wn->cap, TK2MS(now - wn->lastseen), wn->channel, essid); + } + n = readstr(off, buf, n, s); + free(s); + return n; +} + +static void tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); +static int tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); +static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); +static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); + +static Block* +wifiencrypt(Wifi *wifi, Wnode *wn, Block *b) +{ + uvlong tsc; + int n, kid; + Wifipkt *w; + Wkey *k; + + rlock(&wifi->crypt); + + kid = 0; + k = wn->txkey[kid]; + if(k == nil){ + runlock(&wifi->crypt); + return b; + } + + n = wifihdrlen((Wifipkt*)b->rp); + + b = padblock(b, 8); + b = padblock(b, -(8+4)); + + w = (Wifipkt*)b->rp; + memmove(w, b->rp+8, n); + b->rp += n; + + tsc = ++k->tsc; + + switch(k->cipher){ + case TKIP: + b->rp[0] = tsc>>8; + b->rp[1] = (b->rp[0] | 0x20) & 0x7f; + b->rp[2] = tsc; + b->rp[3] = kid<<6 | 0x20; + b->rp[4] = tsc>>16; + b->rp[5] = tsc>>24; + b->rp[6] = tsc>>32; + b->rp[7] = tsc>>40; + b->rp += 8; + tkipencrypt(k, w, b, tsc); + break; + case CCMP: + b->rp[0] = tsc; + b->rp[1] = tsc>>8; + b->rp[2] = 0; + b->rp[3] = kid<<6 | 0x20; + b->rp[4] = tsc>>16; + b->rp[5] = tsc>>24; + b->rp[6] = tsc>>32; + b->rp[7] = tsc>>40; + b->rp += 8; + ccmpencrypt(k, w, b, tsc); + break; + } + runlock(&wifi->crypt); + + b->rp = (uchar*)w; + w->fc[1] |= 0x40; + return b; +} + +static Block* +wifidecrypt(Wifi *wifi, Wnode *wn, Block *b) +{ + uvlong tsc; + int n, kid; + Wifipkt *w; + Wkey *k; + + rlock(&wifi->crypt); + + w = (Wifipkt*)b->rp; + n = wifihdrlen(w); + b->rp += n; + if(BLEN(b) < 8+8) + goto drop; + + kid = b->rp[3]>>6; + if((b->rp[3] & 0x20) == 0) + goto drop; + if((w->a1[0] & 1) == 0) + kid = 4; /* use peerwise key for non-unicast */ + + k = wn->rxkey[kid]; + if(k == nil) + goto drop; + switch(k->cipher){ + case TKIP: + tsc = (uvlong)b->rp[7]<<40 | + (uvlong)b->rp[6]<<32 | + (uvlong)b->rp[5]<<24 | + (uvlong)b->rp[4]<<16 | + (uvlong)b->rp[0]<<8 | + (uvlong)b->rp[2]; + b->rp += 8; + if(tsc <= k->tsc) + goto drop; + if(tkipdecrypt(k, w, b, tsc) != 0) + goto drop; + break; + case CCMP: + tsc = (uvlong)b->rp[7]<<40 | + (uvlong)b->rp[6]<<32 | + (uvlong)b->rp[5]<<24 | + (uvlong)b->rp[4]<<16 | + (uvlong)b->rp[1]<<8 | + (uvlong)b->rp[0]; + b->rp += 8; + if(tsc <= k->tsc) + goto drop; + if(ccmpdecrypt(k, w, b, tsc) != 0) + goto drop; + break; + default: + drop: + runlock(&wifi->crypt); + freeb(b); + return nil; + } + runlock(&wifi->crypt); + + k->tsc = tsc; + b->rp -= n; + memmove(b->rp, w, n); + w = (Wifipkt*)b->rp; + w->fc[1] &= ~0x40; + return b; +} + +static u16int Sbox[256] = { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A +}; + +static void +tkipk2tk(uchar key[16], u16int tk[8]) +{ + tk[0] = (u16int)key[1]<<8 | key[0]; + tk[1] = (u16int)key[3]<<8 | key[2]; + tk[2] = (u16int)key[5]<<8 | key[4]; + tk[3] = (u16int)key[7]<<8 | key[6]; + tk[4] = (u16int)key[9]<<8 | key[8]; + tk[5] = (u16int)key[11]<<8 | key[10]; + tk[6] = (u16int)key[13]<<8 | key[12]; + tk[7] = (u16int)key[15]<<8 | key[14]; +} + +static void +tkipphase1(u32int tscu, uchar ta[Eaddrlen], u16int tk[8], u16int p1k[5]) +{ + u16int *k, i, x0, x1, x2; + + p1k[0] = tscu; + p1k[1] = tscu>>16; + p1k[2] = (u16int)ta[1]<<8 | ta[0]; + p1k[3] = (u16int)ta[3]<<8 | ta[2]; + p1k[4] = (u16int)ta[5]<<8 | ta[4]; + + for(i=0; i<8; i++){ + k = &tk[i & 1]; + + x0 = p1k[4] ^ k[0]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + p1k[0] += x2; + x0 = p1k[0] ^ k[2]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + p1k[1] += x2; + x0 = p1k[1] ^ k[4]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + p1k[2] += x2; + x0 = p1k[2] ^ k[6]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + p1k[3] += x2; + x0 = p1k[3] ^ k[0]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + p1k[4] += x2; + + p1k[4] += i; + } +} + +static void +tkipphase2(u16int tscl, u16int p1k[5], u16int tk[8], uchar rc4key[16]) +{ + u16int ppk[6], x0, x1, x2; + + ppk[0] = p1k[0]; + ppk[1] = p1k[1]; + ppk[2] = p1k[2]; + ppk[3] = p1k[3]; + ppk[4] = p1k[4]; + ppk[5] = p1k[4] + tscl; + + x0 = ppk[5] ^ tk[0]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[0] += x2; + x0 = ppk[0] ^ tk[1]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[1] += x2; + x0 = ppk[1] ^ tk[2]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[2] += x2; + x0 = ppk[2] ^ tk[3]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[3] += x2; + x0 = ppk[3] ^ tk[4]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[4] += x2; + x0 = ppk[4] ^ tk[5]; + x1 = Sbox[x0 >> 8]; + x2 = Sbox[x0 & 0xFF] ^ ((x1>>8) | (x1<<8)); + ppk[5] += x2; + + x2 = ppk[5] ^ tk[6]; + ppk[0] += (x2 >> 1) | (x2 << 15); + x2 = ppk[0] ^ tk[7]; + ppk[1] += (x2 >> 1) | (x2 << 15); + + x2 = ppk[1]; + ppk[2] += (x2 >> 1) | (x2 << 15); + x2 = ppk[2]; + ppk[3] += (x2 >> 1) | (x2 << 15); + x2 = ppk[3]; + ppk[4] += (x2 >> 1) | (x2 << 15); + x2 = ppk[4]; + ppk[5] += (x2 >> 1) | (x2 << 15); + + rc4key[0] = tscl >> 8; + rc4key[1] = (rc4key[0] | 0x20) & 0x7F; + rc4key[2] = tscl; + rc4key[3] = (ppk[5] ^ tk[0]) >> 1; + rc4key[4] = ppk[0]; + rc4key[5] = ppk[0] >> 8; + rc4key[6] = ppk[1]; + rc4key[7] = ppk[1] >> 8; + rc4key[8] = ppk[2]; + rc4key[9] = ppk[2] >> 8; + rc4key[10] = ppk[3]; + rc4key[11] = ppk[3] >> 8; + rc4key[12] = ppk[4]; + rc4key[13] = ppk[4] >> 8; + rc4key[14] = ppk[5]; + rc4key[15] = ppk[5] >> 8; +} + +typedef struct MICstate MICstate; +struct MICstate +{ + u32int l; + u32int r; + u32int m; + u32int n; +}; + +static void +micsetup(MICstate *s, uchar key[8]) +{ + s->l = (u32int)key[0] | + (u32int)key[1]<<8 | + (u32int)key[2]<<16 | + (u32int)key[3]<<24; + s->r = (u32int)key[4] | + (u32int)key[5]<<8 | + (u32int)key[6]<<16 | + (u32int)key[7]<<24; + s->m = 0; + s->n = 0; +} + +static void +micupdate(MICstate *s, uchar *data, ulong len) +{ + u32int l, r, m, n, e; + + l = s->l; + r = s->r; + m = s->m; + n = s->n; + e = n + len; + while(n != e){ + m >>= 8; + m |= (u32int)*data++ << 24; + if(++n & 3) + continue; + l ^= m; + r ^= (l << 17) | (l >> 15); + l += r; + r ^= ((l & 0x00FF00FFUL)<<8) | ((l & 0xFF00FF00UL)>>8); + l += r; + r ^= (l << 3) | (l >> 29); + l += r; + r ^= (l >> 2) | (l << 30); + l += r; + } + s->l = l; + s->r = r; + s->m = m; + s->n = n; +} + +static void +micfinish(MICstate *s, uchar mic[8]) +{ + static uchar pad[8] = { 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + + micupdate(s, pad, sizeof(pad)); + + mic[0] = s->l; + mic[1] = s->l>>8; + mic[2] = s->l>>16; + mic[3] = s->l>>24; + mic[4] = s->r; + mic[5] = s->r>>8; + mic[6] = s->r>>16; + mic[7] = s->r>>24; +} + +static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, }; + +static void +tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +{ + u16int tk[8], p1k[5]; + uchar seed[16]; + RC4state rs; + MICstate ms; + ulong crc; + + micsetup(&ms, k->key+24); + micupdate(&ms, dstaddr(w), Eaddrlen); + micupdate(&ms, srcaddr(w), Eaddrlen); + micupdate(&ms, pad4, 4); + micupdate(&ms, b->rp, BLEN(b)); + micfinish(&ms, b->wp); + b->wp += 8; + + crc = ethercrc(b->rp, BLEN(b)); + crc = ~crc; + b->wp[0] = crc; + b->wp[1] = crc>>8; + b->wp[2] = crc>>16; + b->wp[3] = crc>>24; + b->wp += 4; + + tkipk2tk(k->key, tk); + tkipphase1(tsc >> 16, w->a2, tk, p1k); + tkipphase2(tsc & 0xFFFF, p1k, tk, seed); + setupRC4state(&rs, seed, sizeof(seed)); + rc4(&rs, b->rp, BLEN(b)); +} + +static int +tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +{ + uchar seed[16], mic[8]; + u16int tk[8], p1k[5]; + RC4state rs; + MICstate ms; + ulong crc; + + if(BLEN(b) < 8+4) + return -1; + + tkipk2tk(k->key, tk); + tkipphase1(tsc >> 16, w->a2, tk, p1k); + tkipphase2(tsc & 0xFFFF, p1k, tk, seed); + setupRC4state(&rs, seed, sizeof(seed)); + rc4(&rs, b->rp, BLEN(b)); + + b->wp -= 4; + crc = (ulong)b->wp[0] | + (ulong)b->wp[1]<<8 | + (ulong)b->wp[2]<<16 | + (ulong)b->wp[3]<<24; + crc = ~crc; + crc ^= ethercrc(b->rp, BLEN(b)); + + b->wp -= 8; + micsetup(&ms, k->key+16); + micupdate(&ms, dstaddr(w), Eaddrlen); + micupdate(&ms, srcaddr(w), Eaddrlen); + micupdate(&ms, pad4, 4); + micupdate(&ms, b->rp, BLEN(b)); + micfinish(&ms, mic); + + return memcmp(b->wp, mic, 8) | crc; +} + +static uchar* +putbe(uchar *p, int L, uint v) +{ + while(--L >= 0) + *p++ = (v >> L*8) & 0xFF; + return p; +} + +static void +xblock(int L, int M, uchar *N, uchar *a, int la, int lm, uchar t[16], AESstate *s) +{ + uchar l[8], *p, *x, *e; + + assert(M >= 4 && M <= 16); + assert(L >= 2 && L <= 4); + + t[0] = ((la > 0)<<6) | ((M-2)/2)<<3 | (L-1); /* flags */ + memmove(&t[1], N, 15-L); + putbe(&t[16-L], L, lm); + aes_encrypt(s->ekey, s->rounds, t, t); + + if(la > 0){ + assert(la < 0xFF00); + for(p = l, e = putbe(l, 2, la), x = t; p < e; x++, p++) + *x ^= *p; + for(e = a + la; a < e; x = t){ + for(; a < e && x < &t[16]; x++, a++) + *x ^= *a; + aes_encrypt(s->ekey, s->rounds, t, t); + } + } +} + +static uchar* +sblock(int L, uchar *N, uint i, uchar b[16], AESstate *s) +{ + b[0] = L-1; /* flags */ + memmove(&b[1], N, 15-L); + putbe(&b[16-L], L, i); + aes_encrypt(s->ekey, s->rounds, b, b); + return b; +}; + +static void +aesCCMencrypt(int L, int M, uchar *N /* N[15-L] */, + uchar *a /* a[la] */, int la, + uchar *m /* m[lm+M] */, int lm, + AESstate *s) +{ + uchar t[16], b[16], *p, *x; + uint i; + + xblock(L, M, N, a, la, lm, t, s); + + for(i = 1; lm >= 16; i++, m += 16, lm -= 16){ + sblock(L, N, i, b, s); + + *((u32int*)&t[0]) ^= *((u32int*)&m[0]); + *((u32int*)&m[0]) ^= *((u32int*)&b[0]); + *((u32int*)&t[4]) ^= *((u32int*)&m[4]); + *((u32int*)&m[4]) ^= *((u32int*)&b[4]); + *((u32int*)&t[8]) ^= *((u32int*)&m[8]); + *((u32int*)&m[8]) ^= *((u32int*)&b[8]); + *((u32int*)&t[12]) ^= *((u32int*)&m[12]); + *((u32int*)&m[12]) ^= *((u32int*)&b[12]); + + aes_encrypt(s->ekey, s->rounds, t, t); + } + if(lm > 0){ + for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){ + *x ^= *m; + *m ^= *p; + } + aes_encrypt(s->ekey, s->rounds, t, t); + } + + for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++) + *x ^= *p; + + memmove(m, t, M); +} + +static int +aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */, + uchar *a /* a[la] */, int la, + uchar *m /* m[lm+M] */, int lm, + AESstate *s) +{ + uchar t[16], b[16], *p, *x; + uint i; + + xblock(L, M, N, a, la, lm, t, s); + + for(i = 1; lm >= 16; i++, m += 16, lm -= 16){ + sblock(L, N, i, b, s); + + *((u32int*)&m[0]) ^= *((u32int*)&b[0]); + *((u32int*)&t[0]) ^= *((u32int*)&m[0]); + *((u32int*)&m[4]) ^= *((u32int*)&b[4]); + *((u32int*)&t[4]) ^= *((u32int*)&m[4]); + *((u32int*)&m[8]) ^= *((u32int*)&b[8]); + *((u32int*)&t[8]) ^= *((u32int*)&m[8]); + *((u32int*)&m[12]) ^= *((u32int*)&b[12]); + *((u32int*)&t[12]) ^= *((u32int*)&m[12]); + + aes_encrypt(s->ekey, s->rounds, t, t); + } + if(lm > 0){ + for(p = sblock(L, N, i, b, s), x = t; p < &b[lm]; x++, m++, p++){ + *m ^= *p; + *x ^= *m; + } + aes_encrypt(s->ekey, s->rounds, t, t); + } + + for(p = sblock(L, N, 0, b, s), x = t; p < &b[M]; x++, p++) + *x ^= *p; + + return memcmp(m, t, M); +} + +static int +setupCCMP(Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32]) +{ + uchar *p; + + nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4; + memmove(&nonce[1], w->a2, Eaddrlen); + nonce[7] = tsc >> 40; + nonce[8] = tsc >> 32; + nonce[9] = tsc >> 24; + nonce[10] = tsc >> 16; + nonce[11] = tsc >> 8; + nonce[12] = tsc; + + p = auth; + *p++ = (w->fc[0] & (((w->fc[0] & 0x0c) == 0x08) ? 0x0f : 0xff)); + *p++ = (w->fc[1] & ~0x38) | 0x40; + memmove(p, w->a1, Eaddrlen); p += Eaddrlen; + memmove(p, w->a2, Eaddrlen); p += Eaddrlen; + memmove(p, w->a3, Eaddrlen); p += Eaddrlen; + *p++ = w->seq[0] & 0x0f; + *p++ = 0; + if((w->fc[1] & 3) == 0x03) { + memmove(p, w->a4, Eaddrlen); + p += Eaddrlen; + } + + return p - auth; +} + +static void +ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +{ + uchar auth[32], nonce[13]; + + aesCCMencrypt(2, 8, nonce, auth, + setupCCMP(w, tsc, nonce, auth), + b->rp, BLEN(b), (AESstate*)k->key); + b->wp += 8; +} + +static int +ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +{ + uchar auth[32], nonce[13]; + + if(BLEN(b) < 8) + return -1; + + b->wp -= 8; + return aesCCMdecrypt(2, 8, nonce, auth, + setupCCMP(w, tsc, nonce, auth), + b->rp, BLEN(b), (AESstate*)k->key); +} diff --git a/sys/src/9/pc/wifi.h b/sys/src/9/pc/wifi.h new file mode 100644 index 0000000000..2171afd21b --- /dev/null +++ b/sys/src/9/pc/wifi.h @@ -0,0 +1,99 @@ +typedef struct Wkey Wkey; +typedef struct Wnode Wnode; +typedef struct Wifi Wifi; +typedef struct Wifipkt Wifipkt; + +enum { + Essidlen = 32, +}; + +/* cipher */ +enum { + TKIP = 1, + CCMP = 2, +}; + +struct Wkey +{ + int cipher; + int len; + uvlong tsc; + uchar key[]; +}; + +struct Wnode +{ + uchar bssid[Eaddrlen]; + char ssid[Essidlen+2]; + + char *status; + + int rsnelen; + uchar rsne[258]; + Wkey *txkey[1]; + Wkey *rxkey[5]; + + int aid; /* association id */ + ulong lastsend; + ulong lastseen; + + uchar *minrate; /* pointers into wifi->rates */ + uchar *maxrate; + uchar *actrate; + + ulong txcount; /* statistics for rate adaption */ + ulong txerror; + + /* stuff from beacon */ + int ival; + int cap; + int channel; + int brsnelen; + uchar brsne[258]; +}; + +struct Wifi +{ + Ether *ether; + + int debug; + + RWlock crypt; + Queue *iq; + ulong watchdog; + ulong lastauth; + Ref txseq; + void (*transmit)(Wifi*, Wnode*, Block*); + + /* for searching */ + uchar bssid[Eaddrlen]; + char essid[Essidlen+2]; + + /* supported data rates by hardware */ + uchar *rates; + + /* effective base station */ + Wnode *bss; + + Wnode node[32]; +}; + +struct Wifipkt +{ + uchar fc[2]; + uchar dur[2]; + uchar a1[Eaddrlen]; + uchar a2[Eaddrlen]; + uchar a3[Eaddrlen]; + uchar seq[2]; + uchar a4[Eaddrlen]; +}; + +Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)); +void wifiiq(Wifi*, Block*); +int wifihdrlen(Wifipkt*); +void wifitxfail(Wifi*, Block*); + +long wifistat(Wifi*, void*, long, ulong); +long wifictl(Wifi*, void*, long); +void wificfg(Wifi*, char*); From f50ea115cd6b8646aa9631dc52dae69e8a26da69 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 15 Jan 2022 14:55:01 +0000 Subject: [PATCH 087/402] sys/src/9/pc: add etheriwl, etherrt2860 and etherwpi to pcf kernel configuration --- sys/src/9/pc/pcf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf index 9915b575bf..061bf3fce0 100644 --- a/sys/src/9/pc/pcf +++ b/sys/src/9/pc/pcf @@ -70,6 +70,9 @@ link etherwavelan wavelan devi82365 cis pci ethervirtio pci ethervirtio10 pci + etheriwl pci wifi + etherwpi pci wifi + etherrt2860 pci wifi ethermedium pcmciamodem From fe5d7c9a27d49c24c128e9f450494e784ec36196 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 13 Feb 2021 14:35:09 +0000 Subject: [PATCH 088/402] sys/src/aux: add aux/wpa tool (thanks Cinap Lenrek) --- sys/man/8/wpa | 72 ++ sys/src/cmd/aux/mkfile | 1 + sys/src/cmd/aux/wpa.c | 1523 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1596 insertions(+) create mode 100644 sys/man/8/wpa create mode 100644 sys/src/cmd/aux/wpa.c diff --git a/sys/man/8/wpa b/sys/man/8/wpa new file mode 100644 index 0000000000..d6f8372d29 --- /dev/null +++ b/sys/man/8/wpa @@ -0,0 +1,72 @@ +.TH WPA 8 +.SH NAME +wpa \- Wi-Fi Protected Access setup +.SH SYNOPSIS +.B aux/wpa +[ +.B -dp12 +] [ +.B -s +.I essid +] +.I dev +.SH DESCRIPTION +.I Wpa +handles the authentication and key exchange with WPA +protected wireless networks. +.PP +The +.I dev +parameter specifies the network interface that needs +to be setup with WPA. +The +.I essid +can be set with the +.I -s +option. Otherwise, the previously configured essid +on the interface will be used. +The +.B -p +option will prompt and install the preshared key or +pap/chap credentials into factotum, otherwise the key has to be +already present in factotum or an interactive key prompter like +auth/fgui (see +.IR factotum (4)) +needs to provide it. +.PP +The authentication protocol is initiated by the +wireless access point so +.I wpa +will background itself after the keyprompt and establish +the encryption automatically as needed. +The optional +.B -1 +or +.B -2 +arguments can be used to select between WPA1/TKIP +(default) or WPA2/CCMP encryption with WPA PSK. +.PP +The +.B -d +option enables debugging and causes +.I wpa +to stay in foreground writing protocol messages to +standard error. +.SH EXAMPLES +Setup wireless encryption: +.EX +% bind -a '#l1' /net +% aux/wpa -s 9HAL -p /net/ether1 +!Adding key: proto=wpapsk essid=9HAL +password: ***** +! +% ip/ipconfig ether /net/ether1 +.EE +.SH SOURCE +.B /sys/src/cmd/aux/wpa.c +.SH SEE ALSO +.IR factotum (4), +.IR ipconfig (8) +.SH HISTORY +.I Wpa +first appeared in 9front (March, 2013). diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index 654f1b92c8..5ab65c9169 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -35,6 +35,7 @@ TARG=\ trampoline\ usage\ watchdog\ + wpa\ write\ zerotrunc\ diff --git a/sys/src/cmd/aux/wpa.c b/sys/src/cmd/aux/wpa.c new file mode 100644 index 0000000000..45b3a5b791 --- /dev/null +++ b/sys/src/cmd/aux/wpa.c @@ -0,0 +1,1523 @@ +#include +#include +#include +#include +#include +#include + +enum { + PMKlen = 256/8, + PTKlen = 512/8, + GTKlen = 256/8, + + MIClen = 16, + + Noncelen = 32, + Eaddrlen = 6, +}; + +enum { + Fptk = 1<<3, + Fins = 1<<6, + Fack = 1<<7, + Fmic = 1<<8, + Fsec = 1<<9, + Ferr = 1<<10, + Freq = 1<<11, + Fenc = 1<<12, + + Keydescrlen = 1+2+2+8+32+16+8+8+16+2, +}; + +typedef struct Keydescr Keydescr; +struct Keydescr +{ + uchar type[1]; + uchar flags[2]; + uchar keylen[2]; + uchar repc[8]; + uchar nonce[32]; + uchar eapoliv[16]; + uchar rsc[8]; + uchar id[8]; + uchar mic[16]; + uchar datalen[2]; + uchar data[]; +}; + +typedef struct Cipher Cipher; +struct Cipher +{ + char *name; + int keylen; +}; + +typedef struct Eapconn Eapconn; +typedef struct TLStunn TLStunn; + +struct Eapconn +{ + int fd; + int version; + + uchar type; + uchar smac[Eaddrlen]; + uchar amac[Eaddrlen]; + + TLStunn *tunn; + + void (*write)(Eapconn*, uchar *data, int datalen); +}; + +struct TLStunn +{ + int fd; + + int clientpid; + int readerpid; + + uchar id; + uchar tp; +}; + +Cipher tkip = { "tkip", 32 }; +Cipher ccmp = { "ccmp", 16 }; + +Cipher *peercipher; +Cipher *groupcipher; + +int forked; +int prompt; +int debug; +int fd, cfd; +char *dev; +enum { + AuthNone, + AuthPSK, + AuthWPA, +}; +int authtype; +char devdir[40]; +uchar ptk[PTKlen]; +char essid[32+1]; +uvlong lastrepc; + +uchar rsntkipoui[4] = {0x00, 0x0F, 0xAC, 0x02}; +uchar rsnccmpoui[4] = {0x00, 0x0F, 0xAC, 0x04}; +uchar rsnapskoui[4] = {0x00, 0x0F, 0xAC, 0x02}; +uchar rsnawpaoui[4] = {0x00, 0x0F, 0xAC, 0x01}; + +uchar rsnie[] = { + 0x30, /* RSN */ + 0x14, /* length */ + 0x01, 0x00, /* version 1 */ + 0x00, 0x0F, 0xAC, 0x04, /* group cipher suite CCMP */ + 0x01, 0x00, /* pairwise cipher suite count 1 */ + 0x00, 0x0F, 0xAC, 0x04, /* pairwise cipher suite CCMP */ + 0x01, 0x00, /* authentication suite count 1 */ + 0x00, 0x0F, 0xAC, 0x02, /* authentication suite PSK */ + 0x00, 0x00, /* capabilities */ +}; + +uchar wpa1oui[4] = {0x00, 0x50, 0xF2, 0x01}; +uchar wpatkipoui[4] = {0x00, 0x50, 0xF2, 0x02}; +uchar wpaapskoui[4] = {0x00, 0x50, 0xF2, 0x02}; +uchar wpaawpaoui[4] = {0x00, 0x50, 0xF2, 0x01}; + +uchar wpaie[] = { + 0xdd, /* vendor specific */ + 0x16, /* length */ + 0x00, 0x50, 0xf2, 0x01, /* WPAIE type 1 */ + 0x01, 0x00, /* version 1 */ + 0x00, 0x50, 0xf2, 0x02, /* group cipher suite TKIP */ + 0x01, 0x00, /* pairwise cipher suite count 1 */ + 0x00, 0x50, 0xf2, 0x02, /* pairwise cipher suite TKIP */ + 0x01, 0x00, /* authentication suite count 1 */ + 0x00, 0x50, 0xf2, 0x02, /* authentication suite PSK */ +}; + +void* +emalloc(int len) +{ + void *v; + + if((v = mallocz(len, 1)) == nil) + sysfatal("malloc: %r"); + return v; +} + +int +hextob(char *s, char **sp, uchar *b, int n) +{ + int r; + + n <<= 1; + for(r = 0; r < n && *s; s++){ + *b <<= 4; + if(*s >= '0' && *s <= '9') + *b |= (*s - '0'); + else if(*s >= 'a' && *s <= 'f') + *b |= 10+(*s - 'a'); + else if(*s >= 'A' && *s <= 'F') + *b |= 10+(*s - 'A'); + else break; + if((++r & 1) == 0) + b++; + } + if(sp != nil) + *sp = s; + return r >> 1; +} + +char* +getifstats(char *key, char *val, int nval) +{ + char buf[8*1024], *f[2], *p, *e; + int fd, n; + + snprint(buf, sizeof(buf), "%s/ifstats", devdir); + if((fd = open(buf, OREAD)) < 0) + return nil; + n = readn(fd, buf, sizeof(buf)-1); + close(fd); + if(n <= 0) + return nil; + buf[n] = 0; + for(p = buf; (e = strchr(p, '\n')) != nil; p = e){ + *e++ = 0; + if(gettokens(p, f, 2, "\t\r\n ") != 2) + continue; + if(strcmp(f[0], key) != 0) + continue; + strncpy(val, f[1], nval); + val[nval-1] = 0; + return val; + } + return nil; +} + +char* +getessid(void) +{ + return getifstats("essid:", essid, sizeof(essid)); +} + +int +getbssid(uchar mac[Eaddrlen]) +{ + char buf[64]; + + if(getifstats("bssid:", buf, sizeof(buf)) != nil) + return parseether(mac, buf); + return -1; +} + +int +connected(void) +{ + char status[1024]; + + if(getifstats("status:", status, sizeof(status)) == nil) + return 0; + if(strcmp(status, "connecting") == 0) + return 0; + if(strcmp(status, "unauthenticated") == 0) + return 0; + if(debug) + fprint(2, "status: %s\n", status); + return 1; +} + +int +buildrsne(uchar rsne[258]) +{ + char buf[1024]; + uchar brsne[258]; + int brsnelen; + uchar *p, *w, *e; + int i, n; + + if(getifstats("brsne:", buf, sizeof(buf)) == nil) + return 0; /* not an error, might be old kernel */ + + brsnelen = hextob(buf, nil, brsne, sizeof(brsne)); + if(brsnelen <= 4){ +trunc: sysfatal("invalid or truncated RSNE; brsne: %s", buf); + return 0; + } + + w = rsne; + p = brsne; + e = p + brsnelen; + if(p[0] == 0x30){ + p += 2; + + /* RSN */ + *w++ = 0x30; + *w++ = 0; /* length */ + } else if(p[0] == 0xDD){ + p += 2; + if((e - p) < 4 || memcmp(p, wpa1oui, 4) != 0){ + sysfatal("unrecognized WPAIE type; brsne: %s", buf); + return 0; + } + + /* WPA */ + *w++ = 0xDD; + *w++ = 0; /* length */ + + memmove(w, wpa1oui, 4); + w += 4; + p += 4; + } else { + sysfatal("unrecognized RSNE type; brsne: %s", buf); + return 0; + } + + if((e - p) < 6) + goto trunc; + + *w++ = *p++; /* version */ + *w++ = *p++; + + if(rsne[0] == 0x30){ + if(memcmp(p, rsnccmpoui, 4) == 0) + groupcipher = &ccmp; + else if(memcmp(p, rsntkipoui, 4) == 0) + groupcipher = &tkip; + else { + sysfatal("unrecognized RSN group cipher; brsne: %s", buf); + return 0; + } + } else { + if(memcmp(p, wpatkipoui, 4) != 0){ + sysfatal("unrecognized WPA group cipher; brsne: %s", buf); + return 0; + } + groupcipher = &tkip; + } + + memmove(w, p, 4); /* group cipher */ + w += 4; + p += 4; + + if((e - p) < 6) + goto trunc; + + *w++ = 0x01; /* # of peer ciphers */ + *w++ = 0x00; + n = *p++; + n |= *p++ << 8; + + if(n <= 0) + goto trunc; + + peercipher = &tkip; + for(i=0; i= n){ + sysfatal("auth suite is not PSK or WPA; brsne: %s", buf); + return 0; + } + + memmove(w, p, 4); + w += 4; + + if(rsne[0] == 0x30){ + /* RSN caps */ + *w++ = 0x00; + *w++ = 0x00; + } + + rsne[1] = (w - rsne) - 2; + return w - rsne; +} + +char* +factotumattr(char *attr, char *fmt, ...) +{ + char buf[1024]; + va_list list; + AuthRpc *rpc; + char *val; + Attr *a; + int afd; + + if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) + return nil; + if((rpc = auth_allocrpc(afd)) == nil){ + close(afd); + return nil; + } + va_start(list, fmt); + vsnprint(buf, sizeof(buf), fmt, list); + va_end(list); + val = nil; + if(auth_rpc(rpc, "start", buf, strlen(buf)) == 0){ + if((a = auth_attr(rpc)) != nil){ + if((val = _strfindattr(a, attr)) != nil) + val = strdup(val); + _freeattr(a); + } + } + auth_freerpc(rpc); + close(afd); + + return val; +} + +void +freeup(UserPasswd *up) +{ + memset(up->user, 0, strlen(up->user)); + memset(up->passwd, 0, strlen(up->passwd)); + free(up); +} + +char* +getidentity(void) +{ + static char *identity; + char *s; + + s = nil; + for(;;){ + if(getessid() == nil) + break; + if((s = factotumattr("user", "proto=pass service=wpa essid=%q", essid)) != nil) + break; + if((s = factotumattr("user", "proto=mschapv2 role=client service=wpa essid=%q", essid)) != nil) + break; + break; + } + if(s != nil){ + free(identity); + identity = s; + } else if(identity == nil) + identity = strdup("anonymous"); + if(debug) + fprint(2, "identity: %s\n", identity); + return identity; +} + +int +factotumctl(char *fmt, ...) +{ + va_list list; + int fd, r, n; + char *s; + + r = -1; + if((fd = open("/mnt/factotum/ctl", OWRITE)) >= 0){ + va_start(list, fmt); + s = vsmprint(fmt, list); + va_end(list); + if(s != nil){ + n = strlen(s); + r = write(fd, s, n); + memset(s, 0, n); + free(s); + } + close(fd); + } + return r; +} + +int +setpmk(uchar pmk[PMKlen]) +{ + if(getessid() == nil) + return -1; + return factotumctl("key proto=wpapsk role=client essid=%q !password=%.*H\n", essid, PMKlen, pmk); +} + +int +getptk(AuthGetkey *getkey, + uchar smac[Eaddrlen], uchar amac[Eaddrlen], + uchar snonce[Noncelen], uchar anonce[Noncelen], + uchar ptk[PTKlen]) +{ + uchar buf[2*Eaddrlen + 2*Noncelen], *p; + AuthRpc *rpc; + int afd, ret; + char *s; + + ret = -1; + s = nil; + rpc = nil; + if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) + goto out; + if((rpc = auth_allocrpc(afd)) == nil) + goto out; + if((s = getessid()) == nil) + goto out; + if((s = smprint("proto=wpapsk role=client essid=%q", s)) == nil) + goto out; + if((ret = auth_rpc(rpc, "start", s, strlen(s))) != ARok) + goto out; + p = buf; + memmove(p, smac, Eaddrlen); p += Eaddrlen; + memmove(p, amac, Eaddrlen); p += Eaddrlen; + memmove(p, snonce, Noncelen); p += Noncelen; + memmove(p, anonce, Noncelen); p += Noncelen; + if((ret = auth_rpc(rpc, "write", buf, p - buf)) != ARok) + goto out; + if((ret = auth_rpc(rpc, "read", nil, 0)) != ARok) + goto out; + if(rpc->narg != PTKlen){ + ret = -1; + goto out; + } + memmove(ptk, rpc->arg, PTKlen); + ret = 0; +out: + if(getkey != nil){ + switch(ret){ + case ARneedkey: + case ARbadkey: + (*getkey)(rpc->arg); + break; + } + } + free(s); + if(afd >= 0) close(afd); + if(rpc != nil) auth_freerpc(rpc); + return ret; +} + +void +dumpkeydescr(Keydescr *kd) +{ + static struct { + int flag; + char *name; + } flags[] = { + Fptk, "ptk", + Fins, "ins", + Fack, "ack", + Fmic, "mic", + Fsec, "sec", + Ferr, "err", + Freq, "req", + Fenc, "enc", + }; + int i, f; + + f = kd->flags[0]<<8 | kd->flags[1]; + fprint(2, "type=%.*H vers=%d flags=%.*H ( ", + sizeof(kd->type), kd->type, kd->flags[1] & 7, + sizeof(kd->flags), kd->flags); + for(i=0; ikeylen), kd->keylen, + sizeof(kd->repc), kd->repc, + sizeof(kd->nonce), kd->nonce, + sizeof(kd->eapoliv), kd->eapoliv, + sizeof(kd->rsc), kd->rsc, + sizeof(kd->id), kd->id, + sizeof(kd->mic), kd->mic); + i = kd->datalen[0]<<8 | kd->datalen[1]; + fprint(2, "data[%.4x]=%.*H\n", i, i, kd->data); +} + +int +rc4unwrap(uchar key[16], uchar iv[16], uchar *data, int len) +{ + uchar seed[32]; + RC4state rs; + + memmove(seed, iv, 16); + memmove(seed+16, key, 16); + setupRC4state(&rs, seed, sizeof(seed)); + rc4skip(&rs, 256); + rc4(&rs, data, len); + return len; +} + +int +aesunwrap(uchar *key, int nkey, uchar *data, int len) +{ + static uchar IV[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, }; + uchar B[16], *R; + AESstate s; + uint t; + int n; + + len -= 8; + if(len < 16 || (len % 8) != 0) + return -1; + n = len/8; + t = n*6; + setupAESstate(&s, key, nkey, 0); + memmove(B, data, 8); + memmove(data, data+8, n*8); + do { + for(R = data + (n - 1)*8; R >= data; t--, R -= 8){ + memmove(B+8, R, 8); + B[7] ^= (t >> 0); + B[6] ^= (t >> 8); + B[5] ^= (t >> 16); + B[4] ^= (t >> 24); + aes_decrypt(s.dkey, s.rounds, B, B); + memmove(R, B+8, 8); + } + } while(t > 0); + if(memcmp(B, IV, 8) != 0) + return -1; + return n*8; +} + +int +calcmic(Keydescr *kd, uchar *msg, int msglen) +{ + int vers; + + vers = kd->flags[1] & 7; + memset(kd->mic, 0, MIClen); + if(vers == 1){ + uchar digest[MD5dlen]; + + hmac_md5(msg, msglen, ptk, 16, digest, nil); + memmove(kd->mic, digest, MIClen); + return 0; + } + if(vers == 2){ + uchar digest[SHA1dlen]; + + hmac_sha1(msg, msglen, ptk, 16, digest, nil); + memmove(kd->mic, digest, MIClen); + return 0; + } + return -1; +} + +int +checkmic(Keydescr *kd, uchar *msg, int msglen) +{ + uchar tmp[MIClen]; + + memmove(tmp, kd->mic, MIClen); + if(calcmic(kd, msg, msglen) != 0) + return -1; + return memcmp(tmp, kd->mic, MIClen) != 0; +} + +void +fdwrite(Eapconn *conn, uchar *data, int len) +{ + if(write(conn->fd, data, len) != len) + sysfatal("write: %r"); +} + +void +etherwrite(Eapconn *conn, uchar *data, int len) +{ + uchar *buf, *p; + int n; + + if(debug) + fprint(2, "\nreply(v%d,t%d) %E -> %E: ", conn->version, conn->type, conn->smac, conn->amac); + n = 2*Eaddrlen + 2 + len; + if(n < 60) n = 60; /* ETHERMINTU */ + p = buf = emalloc(n); + /* ethernet header */ + memmove(p, conn->amac, Eaddrlen); p += Eaddrlen; + memmove(p, conn->smac, Eaddrlen); p += Eaddrlen; + *p++ = 0x88; + *p++ = 0x8e; + /* eapol data */ + memmove(p, data, len); + fdwrite(conn, buf, n); + free(buf); +} + +void +eapwrite(Eapconn *conn, uchar *data, int len) +{ + uchar *buf, *p; + + p = buf = emalloc(len + 4); + /* eapol header */ + *p++ = conn->version; + *p++ = conn->type; + *p++ = len >> 8; + *p++ = len; + /* eap data */ + memmove(p, data, len); p += len; + etherwrite(conn, buf, p - buf); + free(buf); +} + +void +replykey(Eapconn *conn, int flags, Keydescr *kd, uchar *data, int datalen) +{ + uchar buf[4096], *p = buf; + + /* eapol hader */ + *p++ = conn->version; + *p++ = conn->type; + datalen += Keydescrlen; + *p++ = datalen >> 8; + *p++ = datalen; + datalen -= Keydescrlen; + /* key header */ + memmove(p, kd, Keydescrlen); + kd = (Keydescr*)p; + kd->flags[0] = flags >> 8; + kd->flags[1] = flags; + kd->datalen[0] = datalen >> 8; + kd->datalen[1] = datalen; + /* key data */ + p = kd->data; + memmove(p, data, datalen); + p += datalen; + /* mic */ + memset(kd->mic, 0, MIClen); + if(flags & Fmic) + calcmic(kd, buf, p - buf); + etherwrite(conn, buf, p - buf); + if(debug) + dumpkeydescr(kd); +} + +void +eapresp(Eapconn *conn, int code, int id, uchar *data, int len) +{ + uchar *buf, *p; + + len += 4; + p = buf = emalloc(len); + /* eap header */ + *p++ = code; + *p++ = id; + *p++ = len >> 8; + *p++ = len; + memmove(p, data, len-4); + (*conn->write)(conn, buf, len); + free(buf); + + if(debug) + fprint(2, "eapresp(code=%d, id=%d, data=%.*H)\n", code, id, len-4, data); +} + +void +tlsreader(TLStunn *tunn, Eapconn *conn) +{ + enum { + Tlshdrsz = 5, + TLStunnhdrsz = 6, + }; + uchar *rec, *w, *p; + int fd, n, css; + + fd = tunn->fd; + rec = nil; + css = 0; +Reset: + w = rec; + w += TLStunnhdrsz; + for(;;w += n){ + if((p = realloc(rec, (w - rec) + Tlshdrsz)) == nil) + break; + w = p + (w - rec), rec = p; + if(readn(fd, w, Tlshdrsz) != Tlshdrsz) + break; + n = w[3]<<8 | w[4]; + if(n < 1) + break; + if((p = realloc(rec, (w - rec) + Tlshdrsz+n)) == nil) + break; + w = p + (w - rec), rec = p; + if(readn(fd, w+Tlshdrsz, n) != n) + break; + n += Tlshdrsz; + + /* batch records that need to be send together */ + if(!css){ + /* Client Certificate */ + if(w[0] == 22 && w[5] == 11) + continue; + /* Client Key Exchange */ + if(w[0] == 22 && w[5] == 16) + continue; + /* Change Cipher Spec */ + if(w[0] == 20){ + css = 1; + continue; + } + } + + /* do not forward alert, close connection */ + if(w[0] == 21) + break; + + /* check if we'r still the tunnel for this connection */ + if(conn->tunn != tunn) + break; + + /* flush records in encapsulation */ + p = rec + TLStunnhdrsz; + w += n; + n = w - p; + *(--p) = n; + *(--p) = n >> 8; + *(--p) = n >> 16; + *(--p) = n >> 24; + *(--p) = 0x80; /* flags: Length included */ + *(--p) = tunn->tp; + + eapresp(conn, 2, tunn->id, p, w - p); + goto Reset; + } + free(rec); +} + +void ttlsclient(int); +void peapclient(int); + +void +eapreset(Eapconn *conn) +{ + TLStunn *tunn; + + tunn = conn->tunn; + if(tunn == nil) + return; + if(debug) + fprint(2, "eapreset: kill client %d\n", tunn->clientpid); + conn->tunn = nil; + postnote(PNPROC, tunn->clientpid, "kill"); +} + +int +tlswrap(int fd, char *label) +{ + TLSconn *tls; + + tls = emalloc(sizeof(TLSconn)); + if(debug) + tls->trace = print; + if(label != nil){ + /* tls client computes the 1024 bit MSK for us */ + tls->sessionType = "ttls"; + tls->sessionConst = label; + tls->sessionKeylen = 128; + tls->sessionKey = emalloc(tls->sessionKeylen); + } + fd = tlsClient(fd, tls); + if(fd < 0) + sysfatal("tlsClient: %r"); + if(label != nil && tls->sessionKey != nil){ + /* + * PMK is derived from MSK by taking the first 256 bits. + * we store the PMK into factotum with setpmk() associated + * with the current essid. + */ + if(setpmk(tls->sessionKey) < 0) + sysfatal("setpmk: %r"); + + /* destroy session key */ + memset(tls->sessionKey, 0, tls->sessionKeylen); + } + free(tls->cert); /* TODO: check cert */ + free(tls->sessionID); + free(tls->sessionKey); + free(tls); + return fd; +} + +void +eapreq(Eapconn *conn, int code, int id, uchar *data, int datalen) +{ + TLStunn *tunn; + int tp, frag; + char *user; + + if(debug) + fprint(2, "eapreq(code=%d, id=%d, data=%.*H)\n", code, id, datalen, data); + + switch(code){ + case 1: /* Request */ + break; + case 4: /* NAK */ + case 3: /* Success */ + eapreset(conn); + if(code == 4 || debug) + fprint(2, "%s: eap code %s\n", argv0, code == 3 ? "Success" : "NAK"); + return; + default: + unhandled: + if(debug) + fprint(2, "unhandled: %.*H\n", datalen < 0 ? 0 : datalen, data); + return; + } + if(datalen < 1) + goto unhandled; + + tp = data[0]; + switch(tp){ + case 1: /* Identity */ + user = getidentity(); + datalen = 1+strlen(user); + memmove(data+1, user, datalen-1); + eapresp(conn, 2, id, data, datalen); + return; + case 2: + fprint(2, "%s: eap error: %.*s\n", + argv0, utfnlen((char*)data+1, datalen-1), (char*)data+1); + return; + case 33: /* EAP Extensions (AVP) */ + if(debug) + fprint(2, "eap extension: %.*H\n", datalen, data); + eapresp(conn, 2, id, data, datalen); + return; + case 26: /* MS-CHAP-V2 */ + data++; + datalen--; + if(datalen < 1) + break; + + /* OpCode */ + switch(data[0]){ + case 1: /* Challenge */ + if(datalen > 4) { + uchar cid, chal[16], resp[48]; + char user[256+1]; + int len; + + cid = data[1]; + len = data[2]<<8 | data[3]; + if(data[4] != sizeof(chal)) + break; + if(len > datalen || (5 + data[4]) > len) + break; + memmove(chal, data+5, sizeof(chal)); + memset(user, 0, sizeof(user)); + memset(resp, 0, sizeof(resp)); + if(auth_respond(chal, sizeof(chal), user, sizeof(user), resp, sizeof(resp), nil, + "proto=mschapv2 role=client service=wpa essid=%q", essid) < 0){ + fprint(2, "%s: eap mschapv2: auth_respond: %r\n", argv0); + break; + } + len = 5 + sizeof(resp) + 1 + strlen(user); + data[0] = 2; /* OpCode - Response */ + data[1] = cid; /* Identifier */ + data[2] = len >> 8; + data[3] = len; + data[4] = sizeof(resp)+1; /* ValueSize */ + memmove(data+5, resp, sizeof(resp)); + data[5 + sizeof(resp)] = 0; /* flags */ + strcpy((char*)&data[5 + sizeof(resp) + 1], user); + + *(--data) = tp, len++; + eapresp(conn, 2, id, data, len); + return; + } + break; + + case 3: /* Success */ + case 4: /* Failure */ + if(debug || data[0] == 4) + fprint(2, "%s: eap mschapv2 %s: %.*s\n", argv0, + data[0] == 3 ? "Success" : "Failure", + datalen < 4 ? 0 : utfnlen((char*)data+4, datalen-4), (char*)data+4); + *(--data) = tp; + eapresp(conn, 2, id, data, 2); + return; + } + break; + + case 21: /* EAP-TTLS */ + case 25: /* PEAP */ + if(datalen < 2) + break; + datalen -= 2; + data++; + tunn = conn->tunn; + if(*data & 0x20){ /* flags: start */ + int p[2], pid; + + if(tunn != nil){ + if(tunn->id == id && tunn->tp == tp) + break; /* is retransmit, ignore */ + eapreset(conn); + } + if(pipe(p) < 0) + sysfatal("pipe: %r"); + if((pid = fork()) == -1) + sysfatal("fork: %r"); + if(pid == 0){ + close(p[0]); + switch(tp){ + case 21: + ttlsclient(p[1]); + break; + case 25: + peapclient(p[1]); + break; + } + exits(nil); + } + close(p[1]); + tunn = emalloc(sizeof(TLStunn)); + tunn->tp = tp; + tunn->id = id; + tunn->fd = p[0]; + tunn->clientpid = pid; + conn->tunn = tunn; + if((pid = rfork(RFPROC|RFMEM)) == -1) + sysfatal("fork: %r"); + if(pid == 0){ + tunn->readerpid = getpid(); + tlsreader(tunn, conn); + if(conn->tunn == tunn) + conn->tunn = nil; + close(tunn->fd); + free(tunn); + exits(nil); + } + return; + } + if(tunn == nil) + break; + if(id <= tunn->id || tunn->tp != tp) + break; + tunn->id = id; + frag = *data & 0x40; /* flags: more fragments */ + if(*data & 0x80){ /* flags: length included */ + datalen -= 4; + data += 4; + } + data++; + if(datalen > 0) + write(tunn->fd, data, datalen); + if(frag || (tp == 25 && data[0] == 20)){ /* ack change cipher spec */ + data -= 2; + data[0] = tp; + data[1] = 0; + eapresp(conn, 2, id, data, 2); + } + return; + } + goto unhandled; +} + +int +avp(uchar *p, int n, int code, void *val, int len, int pad) +{ + pad = 8 + ((len + pad) & ~pad); /* header + data + data pad */ + assert(((pad + 3) & ~3) <= n); + p[0] = code >> 24; + p[1] = code >> 16; + p[2] = code >> 8; + p[3] = code; + p[4] = 2; + p[5] = pad >> 16; + p[6] = pad >> 8; + p[7] = pad; + memmove(p+8, val, len); + len += 8; + pad = (pad + 3) & ~3; /* packet padding */ + memset(p+len, 0, pad - len); + return pad; +} + +enum { + /* Avp Code */ + AvpUserName = 1, + AvpUserPass = 2, + AvpChapPass = 3, + AvpChapChal = 60, +}; + +void +ttlsclient(int fd) +{ + uchar buf[4096]; + UserPasswd *up; + int n; + + fd = tlswrap(fd, "ttls keying material"); + if((up = auth_getuserpasswd(nil, "proto=pass service=wpa essid=%q", essid)) == nil) + sysfatal("auth_getuserpasswd: %r"); + n = avp(buf, sizeof(buf), AvpUserName, up->user, strlen(up->user), 0); + n += avp(buf+n, sizeof(buf)-n, AvpUserPass, up->passwd, strlen(up->passwd), 15); + freeup(up); + write(fd, buf, n); + memset(buf, 0, n); +} + +void +peapwrite(Eapconn *conn, uchar *data, int len) +{ + assert(len >= 4); + fdwrite(conn, data + 4, len - 4); +} + +void +peapclient(int fd) +{ + static Eapconn conn; + uchar buf[4096], *p; + int n, id, code; + + conn.fd = fd = tlswrap(fd, "client EAP encryption"); + while((n = read(fd, p = buf, sizeof(buf))) > 0){ + if(n > 4 && (p[2] << 8 | p[3]) == n && p[4] == 33){ + code = p[0]; + id = p[1]; + p += 4, n -= 4; + conn.write = fdwrite; + } else { + code = 1; + id = 0; + conn.write = peapwrite; + } + eapreq(&conn, code, id, p, n); + } +} + +void +usage(void) +{ + fprint(2, "%s: [-dp12] [-s essid] dev\n", argv0); + exits("usage"); +} + +void +background(void) +{ + if(forked || debug) + return; + switch(rfork(RFNOTEG|RFREND|RFPROC|RFNOWAIT)){ + default: + exits(nil); + case -1: + sysfatal("fork: %r"); + return; + case 0: + break; + } + forked = 1; +} + +void +main(int argc, char *argv[]) +{ + uchar mac[Eaddrlen], buf[4096], snonce[Noncelen], anonce[Noncelen]; + static uchar brsne[258]; + static Eapconn conn; + char addr[128]; + uchar *rsne; + int newptk; /* gate key reinstallation */ + int rsnelen; + int n, try; + + quotefmtinstall(); + fmtinstall('H', encodefmt); + fmtinstall('E', eipfmt); + + rsne = nil; + rsnelen = -1; + peercipher = nil; + groupcipher = nil; + + ARGBEGIN { + case 'd': + debug = 1; + break; + case 'p': + prompt = 1; + break; + case 's': + strncpy(essid, EARGF(usage()), 32); + break; + case '1': + rsne = wpaie; + rsnelen = sizeof(wpaie); + peercipher = &tkip; + groupcipher = &tkip; + break; + case '2': + rsne = rsnie; + rsnelen = sizeof(rsnie); + peercipher = &ccmp; + groupcipher = &ccmp; + break; + default: + usage(); + } ARGEND; + + if(*argv != nil) + dev = *argv++; + + if(*argv != nil || dev == nil) + usage(); + + if(myetheraddr(mac, dev) < 0) + sysfatal("can't get mac address: %r"); + + snprint(addr, sizeof(addr), "%s!0x888e", dev); + if((fd = dial(addr, nil, devdir, &cfd)) < 0) + sysfatal("dial: %r"); + + if(essid[0] != 0){ + if(fprint(cfd, "essid %q", essid) < 0) + sysfatal("write essid: %r"); + } else if(prompt) { + getessid(); + if(essid[0] == 0) + sysfatal("no essid set"); + } + if(!prompt) + background(); + +Connect: + /* bss scan might not be complete yet, so check for 10 seconds. */ + for(try = 100; (forked || try >= 0) && !connected(); try--) + sleep(100); + + authtype = AuthPSK; + if(rsnelen <= 0 || rsne == brsne){ + rsne = brsne; + rsnelen = buildrsne(rsne); + } + if(rsnelen > 0){ + if(debug) + fprint(2, "rsne: %.*H\n", rsnelen, rsne); + /* + * we use write() instead of fprint so the message gets written + * at once and not chunked up on fprint buffer. + */ + n = sprint((char*)buf, "auth %.*H", rsnelen, rsne); + if(write(cfd, buf, n) != n) + sysfatal("write auth: %r"); + } else { + authtype = AuthNone; + } + + conn.fd = fd; + conn.write = eapwrite; + conn.type = 1; /* Start */ + conn.version = 1; + memmove(conn.smac, mac, Eaddrlen); + getbssid(conn.amac); + + if(prompt){ + UserPasswd *up; + prompt = 0; + switch(authtype){ + case AuthNone: + print("no authentication required\n"); + break; + case AuthPSK: + /* dummy to for factotum keyprompt */ + genrandom(anonce, sizeof(anonce)); + genrandom(snonce, sizeof(snonce)); + getptk(auth_getkey, conn.smac, conn.amac, snonce, anonce, ptk); + break; + case AuthWPA: + up = auth_getuserpasswd(auth_getkey, "proto=pass service=wpa essid=%q", essid); + if(up != nil){ + factotumctl("key proto=mschapv2 role=client service=wpa" + " essid=%q user=%q !password=%q\n", + essid, up->user, up->passwd); + freeup(up); + } + break; + } + background(); + } + + genrandom(ptk, sizeof(ptk)); + newptk = 0; + + lastrepc = 0ULL; + for(;;){ + uchar *p, *e, *m; + int proto, flags, vers, datalen; + uvlong repc, rsc, tsc; + Keydescr *kd; + + if((n = read(fd, buf, sizeof(buf))) < 0) + sysfatal("read: %r"); + + if(n == 0){ + if(debug) + fprint(2, "got deassociation\n"); + eapreset(&conn); + goto Connect; + } + + p = buf; + e = buf+n; + if(n < 2*Eaddrlen + 2) + continue; + + memmove(conn.smac, p, Eaddrlen); p += Eaddrlen; + memmove(conn.amac, p, Eaddrlen); p += Eaddrlen; + proto = p[0]<<8 | p[1]; p += 2; + + if(proto != 0x888e || memcmp(conn.smac, mac, Eaddrlen) != 0) + continue; + + m = p; + n = e - p; + if(n < 4) + continue; + + conn.version = p[0]; + if(conn.version != 0x01 && conn.version != 0x02) + continue; + conn.type = p[1]; + n = p[2]<<8 | p[3]; + p += 4; + if(p+n > e) + continue; + e = p + n; + + if(debug) + fprint(2, "\nrecv(v%d,t%d) %E <- %E: ", conn.version, conn.type, conn.smac, conn.amac); + + if(authtype == AuthNone) + continue; + + if(conn.type == 0x00 && authtype == AuthWPA){ + uchar code, id; + + if(n < 4) + continue; + code = p[0]; + id = p[1]; + n = p[3] | p[2]<<8; + if(n < 4 || p + n > e) + continue; + p += 4, n -= 4; + eapreq(&conn, code, id, p, n); + continue; + } + + if(conn.type != 0x03) + continue; + + if(n < Keydescrlen){ + if(debug) + fprint(2, "bad kd size\n"); + continue; + } + kd = (Keydescr*)p; + if(debug) + dumpkeydescr(kd); + + if(kd->type[0] != 0xFE && kd->type[0] != 0x02) + continue; + + vers = kd->flags[1] & 7; + flags = kd->flags[0]<<8 | kd->flags[1]; + datalen = kd->datalen[0]<<8 | kd->datalen[1]; + if(kd->data + datalen > e) + continue; + + if((flags & Fmic) == 0){ + if((flags & (Fptk|Fack)) != (Fptk|Fack)) + continue; + + memmove(anonce, kd->nonce, sizeof(anonce)); + genrandom(snonce, sizeof(snonce)); + if(getptk(nil, conn.smac, conn.amac, snonce, anonce, ptk) != 0){ + if(debug) + fprint(2, "getptk: %r\n"); + continue; + } + /* allow installation of new keys */ + newptk = 1; + + /* ack key exchange with mic */ + memset(kd->rsc, 0, sizeof(kd->rsc)); + memset(kd->eapoliv, 0, sizeof(kd->eapoliv)); + memmove(kd->nonce, snonce, sizeof(kd->nonce)); + replykey(&conn, (flags & ~(Fack|Fins)) | Fmic, kd, rsne, rsnelen); + } else { + uchar gtk[GTKlen]; + int gtklen, gtkkid; + + if(checkmic(kd, m, e - m) != 0){ + if(debug) + fprint(2, "bad mic\n"); + continue; + } + + repc = (uvlong)kd->repc[7] | + (uvlong)kd->repc[6]<<8 | + (uvlong)kd->repc[5]<<16 | + (uvlong)kd->repc[4]<<24 | + (uvlong)kd->repc[3]<<32 | + (uvlong)kd->repc[2]<<40 | + (uvlong)kd->repc[1]<<48 | + (uvlong)kd->repc[0]<<56; + if(repc <= lastrepc){ + if(debug) + fprint(2, "bad repc: %llux <= %llux\n", repc, lastrepc); + continue; + } + lastrepc = repc; + + rsc = (uvlong)kd->rsc[0] | + (uvlong)kd->rsc[1]<<8 | + (uvlong)kd->rsc[2]<<16 | + (uvlong)kd->rsc[3]<<24 | + (uvlong)kd->rsc[4]<<32 | + (uvlong)kd->rsc[5]<<40; + + if(datalen > 0 && (flags & Fenc) != 0){ + if(vers == 1) + datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen); + else + datalen = aesunwrap(ptk+16, 16, kd->data, datalen); + if(datalen <= 0){ + if(debug) + fprint(2, "bad keywrap\n"); + continue; + } + if(debug) + fprint(2, "unwraped keydata[%.4x]=%.*H\n", datalen, datalen, kd->data); + } + + gtklen = 0; + gtkkid = -1; + + if(kd->type[0] != 0xFE || (flags & (Fptk|Fack)) == (Fptk|Fack)){ + uchar *p, *x, *e; + + p = kd->data; + e = p + datalen; + for(; p+2 <= e; p = x){ + if((x = p+2+p[1]) > e) + break; + if(debug) + fprint(2, "ie=%.2x data[%.2x]=%.*H\n", p[0], p[1], p[1], p+2); + if(p[0] == 0x30){ /* RSN */ + } + if(p[0] == 0xDD){ /* WPA */ + static uchar oui[] = { 0x00, 0x0f, 0xac, 0x01, }; + + if(p+2+sizeof(oui) > x || memcmp(p+2, oui, sizeof(oui)) != 0) + continue; + if((flags & Fenc) == 0) + continue; /* ignore gorup key if unencrypted */ + gtklen = x - (p + 8); + if(gtklen <= 0) + continue; + if(gtklen > sizeof(gtk)) + gtklen = sizeof(gtk); + memmove(gtk, p + 8, gtklen); + gtkkid = p[6] & 3; + } + } + } + + if((flags & (Fptk|Fack)) == (Fptk|Fack)){ + if(!newptk) /* a retransmit, already installed PTK */ + continue; + if(vers != 1) /* in WPA2, RSC is for group key only */ + tsc = 0LL; + else { + tsc = rsc; + rsc = 0LL; + } + /* install pairwise receive key (PTK) */ + if(fprint(cfd, "rxkey %E %s:%.*H@%llux", conn.amac, + peercipher->name, peercipher->keylen, ptk+32, tsc) < 0) + sysfatal("write rxkey: %r"); + + memset(kd->rsc, 0, sizeof(kd->rsc)); + memset(kd->eapoliv, 0, sizeof(kd->eapoliv)); + memset(kd->nonce, 0, sizeof(kd->nonce)); + replykey(&conn, flags & ~(Fack|Fenc|Fins), kd, nil, 0); + sleep(100); + + tsc = 0LL; + /* install pairwise transmit key (PTK) */ + if(fprint(cfd, "txkey %E %s:%.*H@%llux", conn.amac, + peercipher->name, peercipher->keylen, ptk+32, tsc) < 0) + sysfatal("write txkey: %r"); + newptk = 0; /* prevent PTK re-installation on (replayed) retransmits */ + } else + if((flags & (Fptk|Fsec|Fack)) == (Fsec|Fack)){ + if(kd->type[0] == 0xFE){ + /* WPA always RC4 encrypts the GTK, even tho the flag isnt set */ + if((flags & Fenc) == 0) + datalen = rc4unwrap(ptk+16, kd->eapoliv, kd->data, datalen); + gtklen = datalen; + if(gtklen > sizeof(gtk)) + gtklen = sizeof(gtk); + memmove(gtk, kd->data, gtklen); + gtkkid = (flags >> 4) & 3; + } + memset(kd->rsc, 0, sizeof(kd->rsc)); + memset(kd->eapoliv, 0, sizeof(kd->eapoliv)); + memset(kd->nonce, 0, sizeof(kd->nonce)); + replykey(&conn, flags & ~(Fenc|Fack), kd, nil, 0); + } else + continue; + /* install group key (GTK) */ + if(gtklen >= groupcipher->keylen && gtkkid != -1) + if(fprint(cfd, "rxkey%d %E %s:%.*H@%llux", + gtkkid, conn.amac, + groupcipher->name, groupcipher->keylen, gtk, rsc) < 0) + sysfatal("write rxkey%d: %r", gtkkid); + } + } +} From b3122f91ddffd9bb52bee321ab82c7efcbd7e863 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 17 Apr 2017 16:22:28 +0000 Subject: [PATCH 089/402] sys/src/libsec/port: add PBKDF2 support (thanks Cinap Lenrek) --- sys/include/libsec.h | 4 ++++ sys/src/libsec/port/mkfile | 1 + sys/src/libsec/port/pbkdf2.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 sys/src/libsec/port/pbkdf2.c diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 59592f1d2b..28d9862920 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -402,3 +402,7 @@ int okThumbprint(uchar *sha1, Thumbprint *ok); /* readcert.c */ uchar *readcert(char *filename, int *pcertlen); PEMChain*readcertchain(char *filename); + +/* password-based key derivation function 2 (rfc2898) */ +void pbkdf2_x(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d, ulong dlen, + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index 41d1f0c785..b749e11653 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -17,6 +17,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ egsign.c egverify.c \ dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \ tlshand.c thumb.c readcert.c \ + pbkdf2.c\ ALLOFILES=${CFILES:%.c=%.$O} diff --git a/sys/src/libsec/port/pbkdf2.c b/sys/src/libsec/port/pbkdf2.c new file mode 100644 index 0000000000..da3a646640 --- /dev/null +++ b/sys/src/libsec/port/pbkdf2.c @@ -0,0 +1,34 @@ +#include "os.h" +#include + +/* rfc2898 */ +void +pbkdf2_x(p, plen, s, slen, rounds, d, dlen, x, xlen) + uchar *p, *s, *d; + ulong plen, slen, dlen, rounds; + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); + int xlen; +{ + uchar block[256], tmp[256]; + ulong i, j, k, n; + DigestState *ds; + + assert(xlen <= sizeof(tmp)); + + for(i = 1; dlen > 0; i++, d += n, dlen -= n){ + tmp[3] = i; + tmp[2] = i >> 8; + tmp[1] = i >> 16; + tmp[0] = i >> 24; + ds = (*x)(s, slen, p, plen, nil, nil); + (*x)(tmp, 4, p, plen, block, ds); + memmove(tmp, block, xlen); + for(j = 1; j < rounds; j++){ + (*x)(tmp, xlen, p, plen, tmp, nil); + for(k=0; k xlen ? xlen : dlen; + memmove(d, block, n); + } +} From 829256bd2d0bee1d79f0e05f597c96184e46774b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 17:40:50 +0000 Subject: [PATCH 090/402] sys/src/cmd/auth/factotum: add WPA-PSK support in factotum (thanks Cinap Lenrek) --- sys/man/4/factotum | 12 ++ sys/src/cmd/auth/factotum/dat.h | 1 + sys/src/cmd/auth/factotum/fs.c | 1 + sys/src/cmd/auth/factotum/mkfile | 1 + sys/src/cmd/auth/factotum/wpapsk.c | 189 +++++++++++++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 sys/src/cmd/auth/factotum/wpapsk.c diff --git a/sys/man/4/factotum b/sys/man/4/factotum index a66f19a4c2..03a11c7d08 100644 --- a/sys/man/4/factotum +++ b/sys/man/4/factotum @@ -133,6 +133,10 @@ passwords in the clear. .IR vnc (1)'s challenge/response. .TP +.B wpapsk +the WPA-PSK challenge/response protocol used in wireless networks +(client side only). +.TP .B wep WEP passwords for wireless ethernet cards. .PD @@ -322,6 +326,14 @@ attribute set to or .BR tls . .PP +.B Wpapsk +requires a key with +.B proto=wpapsk +and attributes +.B essid +and +.BR !password . +.PP .B Wep requires a .BR key1 , diff --git a/sys/src/cmd/auth/factotum/dat.h b/sys/src/cmd/auth/factotum/dat.h index 841365774e..b1c702f3ad 100644 --- a/sys/src/cmd/auth/factotum/dat.h +++ b/sys/src/cmd/auth/factotum/dat.h @@ -236,3 +236,4 @@ extern Proto rsa; /* rsa.c */ extern Proto wep; /* wep.c */ /* extern Proto srs; /* srs.c */ extern Proto httpdigest; /* httpdigest.c */ +extern Proto wpapsk; /* wpapsk.c */ diff --git a/sys/src/cmd/auth/factotum/fs.c b/sys/src/cmd/auth/factotum/fs.c index 7d204aa09b..611b363605 100644 --- a/sys/src/cmd/auth/factotum/fs.c +++ b/sys/src/cmd/auth/factotum/fs.c @@ -40,6 +40,7 @@ prototab[] = &rsa, &vnc, &wep, + &wpapsk, nil, }; diff --git a/sys/src/cmd/auth/factotum/mkfile b/sys/src/cmd/auth/factotum/mkfile index 1bdf31a629..f90f09e988 100644 --- a/sys/src/cmd/auth/factotum/mkfile +++ b/sys/src/cmd/auth/factotum/mkfile @@ -13,6 +13,7 @@ PROTO=\ pass.$O\ rsa.$O\ wep.$O\ + wpapsk.$O\ FOFILES=\ $PROTO\ diff --git a/sys/src/cmd/auth/factotum/wpapsk.c b/sys/src/cmd/auth/factotum/wpapsk.c new file mode 100644 index 0000000000..ee8dd805da --- /dev/null +++ b/sys/src/cmd/auth/factotum/wpapsk.c @@ -0,0 +1,189 @@ +/* + * WPA-PSK + * + * Client protocol: + * write challenge: smac[6] + amac[6] + snonce[32] + anonce[32] + * read response: ptk[64] + * + * Server protocol: + * unimplemented + */ +#include "dat.h" + +enum { + PMKlen = 256/8, + PTKlen = 512/8, + + Eaddrlen = 6, + Noncelen = 32, +}; + +enum +{ + CNeedChal, + CHaveResp, + Maxphase, +}; + +static char *phasenames[Maxphase] = { +[CNeedChal] "CNeedChal", +[CHaveResp] "CHaveResp", +}; + +struct State +{ + uchar resp[PTKlen]; +}; + +static void +pass2pmk(char *pass, char *ssid, uchar pmk[PMKlen]) +{ + int npass = strlen(pass); + if(npass == 2*PMKlen && dec16(pmk, PMKlen, pass, npass) == PMKlen) + return; + pbkdf2_x((uchar*)pass, npass, (uchar*)ssid, strlen(ssid), 4096, pmk, PMKlen, hmac_sha1, SHA1dlen); +} + +static void +prfn(uchar *k, int klen, char *a, uchar *b, int blen, uchar *d, int dlen) +{ + uchar r[SHA1dlen], i; + DigestState *ds; + int n; + + i = 0; + while(dlen > 0){ + ds = hmac_sha1((uchar*)a, strlen(a)+1, k, klen, nil, nil); + hmac_sha1(b, blen, k, klen, nil, ds); + hmac_sha1(&i, 1, k, klen, r, ds); + i++; + n = dlen; + if(n > sizeof(r)) + n = sizeof(r); + memmove(d, r, n); d += n; + dlen -= n; + } +} + +static void +calcptk(uchar pmk[PMKlen], uchar smac[Eaddrlen], uchar amac[Eaddrlen], + uchar snonce[Noncelen], uchar anonce[Noncelen], + uchar ptk[PTKlen]) +{ + uchar b[2*Eaddrlen + 2*Noncelen]; + + if(memcmp(smac, amac, Eaddrlen) > 0){ + memmove(b + Eaddrlen*0, amac, Eaddrlen); + memmove(b + Eaddrlen*1, smac, Eaddrlen); + } else { + memmove(b + Eaddrlen*0, smac, Eaddrlen); + memmove(b + Eaddrlen*1, amac, Eaddrlen); + } + if(memcmp(snonce, anonce, Eaddrlen) > 0){ + memmove(b + Eaddrlen*2 + Noncelen*0, anonce, Noncelen); + memmove(b + Eaddrlen*2 + Noncelen*1, snonce, Noncelen); + } else { + memmove(b + Eaddrlen*2 + Noncelen*0, snonce, Noncelen); + memmove(b + Eaddrlen*2 + Noncelen*1, anonce, Noncelen); + } + prfn(pmk, PMKlen, "Pairwise key expansion", b, sizeof(b), ptk, PTKlen); +} + +static int +wpapskinit(Proto *p, Fsstate *fss) +{ + int iscli; + State *s; + + if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0) + return failure(fss, nil); + if(!iscli) + return failure(fss, "%s server not supported", p->name); + + s = emalloc(sizeof *s); + fss->phasename = phasenames; + fss->maxphase = Maxphase; + fss->phase = CNeedChal; + fss->ps = s; + return RpcOk; +} + +static int +wpapskwrite(Fsstate *fss, void *va, uint n) +{ + uchar pmk[PMKlen], *smac, *amac, *snonce, *anonce; + char *pass, *essid; + State *s; + int ret; + Key *k; + Keyinfo ki; + Attr *attr; + + s = fss->ps; + + if(fss->phase != CNeedChal) + return phaseerror(fss, "write"); + if(n != (2*Eaddrlen + 2*Noncelen)) + return phaseerror(fss, "bad write size"); + + attr = _delattr(_copyattr(fss->attr), "role"); + mkkeyinfo(&ki, fss, attr); + ret = findkey(&k, &ki, "%s", fss->proto->keyprompt); + _freeattr(attr); + if(ret != RpcOk) + return ret; + + pass = _strfindattr(k->privattr, "!password"); + if(pass == nil) + return failure(fss, "key has no password"); + essid = _strfindattr(k->attr, "essid"); + if(essid == nil) + return failure(fss, "key has no essid"); + setattrs(fss->attr, k->attr); + closekey(k); + + pass2pmk(pass, essid, pmk); + + smac = va; + amac = smac + Eaddrlen; + snonce = amac + Eaddrlen; + anonce = snonce + Noncelen; + calcptk(pmk, smac, amac, snonce, anonce, s->resp); + + fss->phase = CHaveResp; + return RpcOk; +} + +static int +wpapskread(Fsstate *fss, void *va, uint *n) +{ + State *s; + + s = fss->ps; + if(fss->phase != CHaveResp) + return phaseerror(fss, "read"); + if(*n > sizeof(s->resp)) + *n = sizeof(s->resp); + memmove(va, s->resp, *n); + fss->phase = Established; + fss->haveai = 0; + return RpcOk; +} + +static void +wpapskclose(Fsstate *fss) +{ + State *s; + s = fss->ps; + free(s); +} + +Proto wpapsk = { +.name= "wpapsk", +.init= wpapskinit, +.write= wpapskwrite, +.read= wpapskread, +.close= wpapskclose, +.addkey= replacekey, +.keyprompt= "!password? essid?" +}; From 401c441192fad541d763ffb700c945d06a673650 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 29 Jan 2022 15:12:32 +0000 Subject: [PATCH 091/402] sys/src/nboot: import nboot (thanks Cinap Lenrek) --- sys/man/8/nboot | 188 ++++++++ sys/src/nboot/bcm/mkfile | 16 + sys/src/nboot/bitsy/donprint.c | 332 +++++++++++++ sys/src/nboot/bitsy/fns.h | 7 + sys/src/nboot/bitsy/il.s | 99 ++++ sys/src/nboot/bitsy/imain.c | 48 ++ sys/src/nboot/bitsy/inflate.c | 208 +++++++++ sys/src/nboot/bitsy/io.h | 261 +++++++++++ sys/src/nboot/bitsy/l.s | 454 ++++++++++++++++++ sys/src/nboot/bitsy/lib.h | 143 ++++++ sys/src/nboot/bitsy/map | 10 + sys/src/nboot/bitsy/mem.h | 213 +++++++++ sys/src/nboot/bitsy/mkfile | 45 ++ sys/src/nboot/bitsy/print.c | 56 +++ sys/src/nboot/bitsy/uart.c | 69 +++ sys/src/nboot/efi/efi.c | 308 ++++++++++++ sys/src/nboot/efi/efi.h | 256 ++++++++++ sys/src/nboot/efi/fns.h | 39 ++ sys/src/nboot/efi/fs.c | 166 +++++++ sys/src/nboot/efi/iso.c | 226 +++++++++ sys/src/nboot/efi/mem.h | 47 ++ sys/src/nboot/efi/mkfile | 105 +++++ sys/src/nboot/efi/pe32.s | 159 +++++++ sys/src/nboot/efi/pe64.s | 237 ++++++++++ sys/src/nboot/efi/pxe.c | 487 +++++++++++++++++++ sys/src/nboot/efi/sub.c | 373 +++++++++++++++ sys/src/nboot/mkfile | 23 + sys/src/nboot/pc/a20.s | 84 ++++ sys/src/nboot/pc/apm.s | 51 ++ sys/src/nboot/pc/e820.s | 32 ++ sys/src/nboot/pc/fat.c | 405 ++++++++++++++++ sys/src/nboot/pc/fns.h | 46 ++ sys/src/nboot/pc/iso.c | 200 ++++++++ sys/src/nboot/pc/l.s | 299 ++++++++++++ sys/src/nboot/pc/mbr.s | 259 ++++++++++ sys/src/nboot/pc/mem.h | 46 ++ sys/src/nboot/pc/mkfile | 107 +++++ sys/src/nboot/pc/pbs.s | 292 ++++++++++++ sys/src/nboot/pc/pxe.c | 362 ++++++++++++++ sys/src/nboot/pc/sub.c | 554 ++++++++++++++++++++++ sys/src/nboot/pc/uart.s | 35 ++ sys/src/nboot/pc/x16.h | 163 +++++++ sys/src/nboot/zynq/boothead.c | 71 +++ sys/src/nboot/zynq/dat.h | 11 + sys/src/nboot/zynq/ddr.s | 258 ++++++++++ sys/src/nboot/zynq/fns.h | 15 + sys/src/nboot/zynq/fsbl.s | 310 ++++++++++++ sys/src/nboot/zynq/jtagload.c | 647 +++++++++++++++++++++++++ sys/src/nboot/zynq/main.c | 203 ++++++++ sys/src/nboot/zynq/mem.h | 107 +++++ sys/src/nboot/zynq/mkfile | 38 ++ sys/src/nboot/zynq/mkfile.port | 14 + sys/src/nboot/zynq/mmc.c | 832 +++++++++++++++++++++++++++++++++ sys/src/nboot/zynq/net.c | 577 +++++++++++++++++++++++ sys/src/nboot/zynq/qspi.c | 45 ++ 55 files changed, 10638 insertions(+) create mode 100644 sys/man/8/nboot create mode 100644 sys/src/nboot/bcm/mkfile create mode 100644 sys/src/nboot/bitsy/donprint.c create mode 100644 sys/src/nboot/bitsy/fns.h create mode 100644 sys/src/nboot/bitsy/il.s create mode 100644 sys/src/nboot/bitsy/imain.c create mode 100644 sys/src/nboot/bitsy/inflate.c create mode 100644 sys/src/nboot/bitsy/io.h create mode 100644 sys/src/nboot/bitsy/l.s create mode 100644 sys/src/nboot/bitsy/lib.h create mode 100644 sys/src/nboot/bitsy/map create mode 100644 sys/src/nboot/bitsy/mem.h create mode 100644 sys/src/nboot/bitsy/mkfile create mode 100644 sys/src/nboot/bitsy/print.c create mode 100644 sys/src/nboot/bitsy/uart.c create mode 100644 sys/src/nboot/efi/efi.c create mode 100644 sys/src/nboot/efi/efi.h create mode 100644 sys/src/nboot/efi/fns.h create mode 100644 sys/src/nboot/efi/fs.c create mode 100644 sys/src/nboot/efi/iso.c create mode 100644 sys/src/nboot/efi/mem.h create mode 100644 sys/src/nboot/efi/mkfile create mode 100644 sys/src/nboot/efi/pe32.s create mode 100644 sys/src/nboot/efi/pe64.s create mode 100644 sys/src/nboot/efi/pxe.c create mode 100644 sys/src/nboot/efi/sub.c create mode 100644 sys/src/nboot/mkfile create mode 100644 sys/src/nboot/pc/a20.s create mode 100644 sys/src/nboot/pc/apm.s create mode 100644 sys/src/nboot/pc/e820.s create mode 100644 sys/src/nboot/pc/fat.c create mode 100644 sys/src/nboot/pc/fns.h create mode 100644 sys/src/nboot/pc/iso.c create mode 100644 sys/src/nboot/pc/l.s create mode 100644 sys/src/nboot/pc/mbr.s create mode 100644 sys/src/nboot/pc/mem.h create mode 100644 sys/src/nboot/pc/mkfile create mode 100644 sys/src/nboot/pc/pbs.s create mode 100644 sys/src/nboot/pc/pxe.c create mode 100644 sys/src/nboot/pc/sub.c create mode 100644 sys/src/nboot/pc/uart.s create mode 100644 sys/src/nboot/pc/x16.h create mode 100644 sys/src/nboot/zynq/boothead.c create mode 100644 sys/src/nboot/zynq/dat.h create mode 100644 sys/src/nboot/zynq/ddr.s create mode 100644 sys/src/nboot/zynq/fns.h create mode 100644 sys/src/nboot/zynq/fsbl.s create mode 100644 sys/src/nboot/zynq/jtagload.c create mode 100644 sys/src/nboot/zynq/main.c create mode 100644 sys/src/nboot/zynq/mem.h create mode 100644 sys/src/nboot/zynq/mkfile create mode 100644 sys/src/nboot/zynq/mkfile.port create mode 100644 sys/src/nboot/zynq/mmc.c create mode 100644 sys/src/nboot/zynq/net.c create mode 100644 sys/src/nboot/zynq/qspi.c diff --git a/sys/man/8/nboot b/sys/man/8/nboot new file mode 100644 index 0000000000..8103acc402 --- /dev/null +++ b/sys/man/8/nboot @@ -0,0 +1,188 @@ +.TH 9BOOT 8 +.SH NAME +9bootfat, 9bootiso, 9boothyb, 9bootpxe, bootia32.efi, bootx64.efi, efiboot.fat \- PC bootloader for FAT, ISO and PXE network booting +.SH SYNOPSIS +Started by PC BIOS/EFI or chainloaded by partition bootsector +.SH DESCRIPTION +9boot is the bootloader used on PCs to start the Plan 9 kernel. +Its task is to read and parse the +.IR plan9.ini (8) +configuration file, gather some basic system information like +the amount of usable system memory, do some basic system +initialization and load the kernel from the boot media into memory. + +After reading the configuration, the loader will automatically +attempt to boot the kernel that was specified by the +.B bootfile= +parameter. If there is no such parameter, a key +gets pressed on the keyboard or the kernel file was not +found then the loader enters the interactive +boot console. + +The syntax of the boot console is the same as in the +.IR plan9.ini (8) +file with +.IB key = value +pairs setting boot parameters. In addition a few command +words are recognized that are intended for interactive use: +.TP +.BI clear [prefix] +can be used to remove parameters from the configuration. +If a +.IR prefix +is specified, the first parameter that matches the prefix +is removed. If the +.IR prefix +argument is omitted, the whole configuration will be reset. +.TP +.B show +displays the current configuration in memory. +.TP +.B wait +will return to the console prompt after processing the +configuration file preventing automatic boot. +.TP +.B boot +will end the console and attempt booting the kernel. +.SS +There are many ways to boot a PC so +.IR 9boot +was split into a number of distinct programs, one for each boot +method. +.SH FAT BOOTING +When booting Plan 9 from a harddisk or USB pen drive, a +FAT16/32 partition +.IR (9fat) +is used to store the kernel and +.IR plan9.ini (8) +configuration. Due to size limitations, instead of loading +the kernel directly, the bootsector +.IR (pbs) +of the FAT partition loads +a 2nd stage bootloader +.IR (9bootfat) +from the root directory of the filesystem. +.SH CD-ROM BOOTING +Booting from CD-ROM requires only the +.IR 9bootiso +bootloader to be included in the ISO-9660 image under +.BR /386/9bootiso , +set as a non-emulation bootblock (see +.B -B +in +.IR mk9660 (8)). +Boot parameters are read from +.BR /cfg/plan9.ini . +.SH ISO HYBRID BOOTING +With the +.I 9boothyb +loader, an ISO image can be made into a bootable disk by +creating a MBR and appending a bootable DOS partition containing +.I 9boothyb +renamed to +.IR 9bootfat . +The loader will read the ISO filesystem as if it were stored +on a CD-ROM drive. +.SH NETWORK BOOTING +With a PXE capable BIOS and network card one can download +.IR 9bootpxe +and boot the kernel from a TFTP server (see +.IR dhcpd (8) +and +.IR ndb (6) +for details). Once started, +.IR 9bootpxe +will read the file +.B /cfg/pxe/$ether +or, if this file is not present, +.B /cfg/pxe/default +from the tftp server, where +.B $ether +is the MAC address of the client's network card +in lower case hex, and uses this as its +.IR plan9.ini (8) +file. +.SH EFI BOOTING +EFI firmware looks for the files +.I bootia32.efi +(for 386) +or +.I bootx64.efi +(for amd64) +in the boot media and executes them. +For local disk media, these files are located in the directory +.B /efi/boot +of the +.B FAT +formatted boot partition. +For +.B CD-ROM +media, the boot partition is provided +as a embedded +.B FAT +filesystem image +.I efiboot.fat +(see +.B -E +in +.IR mk9660 (8)). +In the network boot case, the +.I bootia32.efi +or +.I bootx64.efi +files are used as the +.B BSP +program instead of +.IR 9bootpxe . +Once started, the boot media +.RB ( PXE , +.BR ISO , +.BR FAT ) +is discovered and +.IR plan9.ini (8) +configuration is read from it in the same way as +with the BIOS-based +.I 9boot* +loaders. If the EFI loader was executed from a +.B FAT +partition, it will first search for +.IR plan9.ini (8) +in the same +.B FAT +filesystem that it was loaded from, and if not found, will search for +.IR plan9.ini (8) +in any other partition in an implementation-defined order. The kernel +is always loaded from the same partition that +.IR plan9.ini (8) +is read from. +.SH FILES +.B /386/pbs +.br +.B /386/9bootfat +.br +.B /386/9bootiso +.br +.B /386/9boothyb +.br +.B /386/9bootpxe +.br +.B /386/bootia32.efi +.br +.B /386/bootx64.efi +.br +.B /386/efiboot.fat +.SH SOURCE +.BR /sys/src/boot/pc +.br +.BR /sys/src/boot/efi +.br +.SH "SEE ALSO" +.IR plan9.ini (8), +.IR mk9660 (8), +.IR dhcpd (8), +.IR ndb (6) +.br +.I https://uefi.org +.SH HISTORY +9boot first appeared in 9front (April, 2011). +EFI support first appeared in 9front (Oct, 2014). diff --git a/sys/src/nboot/bcm/mkfile b/sys/src/nboot/bcm/mkfile new file mode 100644 index 0000000000..587e8ba0aa --- /dev/null +++ b/sys/src/nboot/bcm/mkfile @@ -0,0 +1,16 @@ +URL=https://github.com/raspberrypi/firmware/raw/master/boot +FILES=bootcode.bin fixup_cd.dat start_cd.elf fixup4cd.dat start4cd.elf \ + bcm2711-rpi-4-b.dtb \ + bcm2711-rpi-400.dtb \ + bcm2711-rpi-cm4.dtb \ + LICENCE.broadcom + +all:V: $FILES + +clean:V: + rm -f $FILES + +$FILES: + for(i in $target){ + hget -o $i $URL/$i + } diff --git a/sys/src/nboot/bitsy/donprint.c b/sys/src/nboot/bitsy/donprint.c new file mode 100644 index 0000000000..4125e6904c --- /dev/null +++ b/sys/src/nboot/bitsy/donprint.c @@ -0,0 +1,332 @@ +#include "u.h" +#include "lib.h" + +#define PTR sizeof(char*) +#define SHORT sizeof(int) +#define INT sizeof(int) +#define LONG sizeof(long) +#define IDIGIT 30 +#define MAXCON 30 + +#define FLONG (1<<0) +#define FSHORT (1<<1) +#define FUNSIGN (1<<2) + +typedef struct Op Op; +struct Op +{ + char *p; + char *ep; + void *argp; + int f1; + int f2; + int f3; +}; + +static int noconv(Op*); +static int cconv(Op*); +static int dconv(Op*); +static int hconv(Op*); +static int lconv(Op*); +static int oconv(Op*); +static int sconv(Op*); +static int uconv(Op*); +static int xconv(Op*); +static int Xconv(Op*); +static int percent(Op*); + +static +int (*fmtconv[MAXCON])(Op*) = +{ + noconv, + cconv, dconv, hconv, lconv, + oconv, sconv, uconv, xconv, + Xconv, percent, +}; +static +char fmtindex[128] = +{ + ['c'] 1, + ['d'] 2, + ['h'] 3, + ['l'] 4, + ['o'] 5, + ['s'] 6, + ['u'] 7, + ['x'] 8, + ['X'] 9, + ['%'] 10, +}; + +static int convcount = { 11 }; +static int ucase; + +static void +PUT(Op *o, int c) +{ + static int pos; + int opos; + + if(c == '\t'){ + opos = pos; + pos = (opos+8) & ~7; + while(opos++ < pos && o->p < o->ep) + *o->p++ = ' '; + return; + } + if(o->p < o->ep){ + *o->p++ = c; + pos++; + } + if(c == '\n') + pos = 0; +} + +int +fmtinstall(char c, int (*f)(Op*)) +{ + + c &= 0177; + if(fmtindex[c] == 0) { + if(convcount >= MAXCON) + return 1; + fmtindex[c] = convcount++; + } + fmtconv[fmtindex[c]] = f; + return 0; +} + +char* +donprint(char *p, char *ep, char *fmt, void *argp) +{ + int sf1, c; + Op o; + + o.p = p; + o.ep = ep; + o.argp = argp; + +loop: + c = *fmt++; + if(c != '%') { + if(c == 0) { + if(o.p < o.ep) + *o.p = 0; + return o.p; + } + PUT(&o, c); + goto loop; + } + o.f1 = 0; + o.f2 = -1; + o.f3 = 0; + c = *fmt++; + sf1 = 0; + if(c == '-') { + sf1 = 1; + c = *fmt++; + } + while(c >= '0' && c <= '9') { + o.f1 = o.f1*10 + c-'0'; + c = *fmt++; + } + if(sf1) + o.f1 = -o.f1; + if(c != '.') + goto l1; + c = *fmt++; + while(c >= '0' && c <= '9') { + if(o.f2 < 0) + o.f2 = 0; + o.f2 = o.f2*10 + c-'0'; + c = *fmt++; + } +l1: + if(c == 0) + fmt--; + c = (*fmtconv[fmtindex[c&0177]])(&o); + if(c < 0) { + o.f3 |= -c; + c = *fmt++; + goto l1; + } + o.argp = (char*)o.argp + c; + goto loop; +} + +void +strconv(char *o, Op *op, int f1, int f2) +{ + int n, c; + char *p; + + n = strlen(o); + if(f1 >= 0) + while(n < f1) { + PUT(op, ' '); + n++; + } + for(p=o; c = *p++;) + if(f2 != 0) { + PUT(op, c); + f2--; + } + if(f1 < 0) { + f1 = -f1; + while(n < f1) { + PUT(op, ' '); + n++; + } + } +} + +int +numbconv(Op *op, int base) +{ + char b[IDIGIT]; + int i, f, n, r; + long v; + short h; + + f = 0; + switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) { + case FLONG: + v = *(long*)op->argp; + r = LONG; + break; + + case FUNSIGN|FLONG: + v = *(ulong*)op->argp; + r = LONG; + break; + + case FSHORT: + h = *(int*)op->argp; + v = h; + r = SHORT; + break; + + case FUNSIGN|FSHORT: + h = *(int*)op->argp; + v = (ushort)h; + r = SHORT; + break; + + default: + v = *(int*)op->argp; + r = INT; + break; + + case FUNSIGN: + v = *(unsigned*)op->argp; + r = INT; + break; + } + if(!(op->f3 & FUNSIGN) && v < 0) { + v = -v; + f = 1; + } + b[IDIGIT-1] = 0; + for(i = IDIGIT-2;; i--) { + n = (ulong)v % base; + n += '0'; + if(n > '9'){ + n += 'a' - ('9'+1); + if(ucase) + n += 'A'-'a'; + } + b[i] = n; + if(i < 2) + break; + v = (ulong)v / base; + if(op->f2 >= 0 && i >= IDIGIT-op->f2) + continue; + if(v <= 0) + break; + } + if(f) + b[--i] = '-'; + strconv(b+i, op, op->f1, -1); + return r; +} + +static int +noconv(Op *op) +{ + + strconv("***", op, 0, -1); + return 0; +} + +static int +cconv(Op *op) +{ + char b[2]; + + b[0] = *(int*)op->argp; + b[1] = 0; + strconv(b, op, op->f1, -1); + return INT; +} + +static int +dconv(Op *op) +{ + return numbconv(op, 10); +} + +static int +hconv(Op*) +{ + return -FSHORT; +} + +static int +lconv(Op*) +{ + return -FLONG; +} + +static int +oconv(Op *op) +{ + return numbconv(op, 8); +} + +static int +sconv(Op *op) +{ + strconv(*(char**)op->argp, op, op->f1, op->f2); + return PTR; +} + +static int +uconv(Op*) +{ + return -FUNSIGN; +} + +static int +xconv(Op *op) +{ + return numbconv(op, 16); +} + +static int +Xconv(Op *op) +{ + int r; + + ucase = 1; + r = numbconv(op, 16); + ucase = 0; + return r; +} + +static int +percent(Op *op) +{ + + PUT(op, '%'); + return 0; +} diff --git a/sys/src/nboot/bitsy/fns.h b/sys/src/nboot/bitsy/fns.h new file mode 100644 index 0000000000..53af19bf04 --- /dev/null +++ b/sys/src/nboot/bitsy/fns.h @@ -0,0 +1,7 @@ +/* + * functions defined locally + */ +extern int gunzip(uchar *out, int outn, uchar *in, int inn); +extern void delay(int ms); +extern void serialputs(char *str, int n); +extern void draincache(void); diff --git a/sys/src/nboot/bitsy/il.s b/sys/src/nboot/bitsy/il.s new file mode 100644 index 0000000000..c75ad987d4 --- /dev/null +++ b/sys/src/nboot/bitsy/il.s @@ -0,0 +1,99 @@ +#include "mem.h" +/* + * Entered here from Compaq's bootldr. First relocate to + * the location we're linked for and then copy back the + * decompressed kernel. + * + * All + */ +TEXT _start(SB), $-4 + MOVW $setR12(SB), R12 /* load the SB */ + MOVW $1, R0 /* dance to make 5l think that the magic */ + MOVW $1, R1 /* numbers in WORDs below are being used */ + CMP.S R0, R1 /* and to align them to where bootldr wants */ + BEQ _start2 + WORD $0x016f2818 /* magic number to say we are a kernel */ + WORD $0xc0008000 /* entry point address */ + WORD $0 /* size?, or end of data? */ + +_start2: + + /* SVC mode, interrupts disabled */ + MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 + MOVW R1, CPSR + + /* disable the MMU */ + MOVW $0x130, R1 + MCR CpMMU, 0, R1, C(CpControl), C(0x0) + + /* enable caches */ + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + ORR $(CpCdcache|CpCicache|CpCwb), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + + /* flush caches */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 + /* drain prefetch */ + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + + /* drain write buffer */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + + /* relocate to where we expect to be */ + MOVW $(512*1024),R3 + MOVW $0xC0008000,R1 + MOVW $0xC0200000,R2 + ADD R1,R3 +_relloop: + MOVW (R1),R0 + MOVW R0,(R2) + ADD $4,R1 + ADD $4,R2 + CMP.S R1,R3 + BNE _relloop + + MOVW $(MACHADDR+BY2PG), R13 /* stack */ + SUB $4, R13 /* link */ + + /* jump to where we've been relocated */ + MOVW $_relocated(SB),R15 + +TEXT _relocated(SB),$-4 + BL main(SB) + BL exit(SB) + /* we shouldn't get here */ +_mainloop: + B _mainloop + BL _div(SB) /* hack to get _div etc loaded */ + +TEXT mypc(SB),$-4 + MOVW R14,R0 + RET + +TEXT draincache(SB),$-4 + /* write back any dirty data */ + MOVW $0xe0000000,R0 + ADD $(8*1024),R0,R1 +_cfloop: + MOVW.P 32(R0),R2 + CMP.S R0,R1 + BNE _cfloop + + /* drain write buffer and invalidate i&d cache contents */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 + + /* drain prefetch */ + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + + /* disable caches */ + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + BIC $(CpCdcache|CpCicache|CpCwb), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + RET diff --git a/sys/src/nboot/bitsy/imain.c b/sys/src/nboot/bitsy/imain.c new file mode 100644 index 0000000000..4b8ef2ef2c --- /dev/null +++ b/sys/src/nboot/bitsy/imain.c @@ -0,0 +1,48 @@ +#include "u.h" +#include "lib.h" +#include "fns.h" +#include "dat.h" +#include "mem.h" + +void +main(void) +{ + void (*f)(void); + ulong *kernel; + + print("inflating kernel\n"); + + kernel = (ulong*)(0xc0200000+20*1024); + if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, 512*1024) > 0){ + f = (void (*)(void))0xc0008010; + draincache(); + } else { + print("inflation failed\n"); + f = nil; + } + (*f)(); +} + +void +exit(void) +{ + + void (*f)(void); + + delay(1000); + + print("it's a wonderful day to die\n"); + f = nil; + (*f)(); +} + +void +delay(int ms) +{ + int i; + + while(ms-- > 0){ + for(i = 0; i < 1000; i++) + ; + } +} diff --git a/sys/src/nboot/bitsy/inflate.c b/sys/src/nboot/bitsy/inflate.c new file mode 100644 index 0000000000..abfed034ec --- /dev/null +++ b/sys/src/nboot/bitsy/inflate.c @@ -0,0 +1,208 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include + +typedef struct Biobuf Biobuf; + +struct Biobuf +{ + uchar *bp; + uchar *p; + uchar *ep; +}; + +static int header(Biobuf*); +static int trailer(Biobuf*, Biobuf*); +static int getc(void*); +static ulong offset(Biobuf*); +static int crcwrite(void *out, void *buf, int n); +static ulong get4(Biobuf *b); +static ulong Boffset(Biobuf *bp); + +/* GZIP flags */ +enum { + Ftext= (1<<0), + Fhcrc= (1<<1), + Fextra= (1<<2), + Fname= (1<<3), + Fcomment= (1<<4), + + GZCRCPOLY = 0xedb88320UL, +}; + +static ulong *crctab; +static ulong crc; + +int +gunzip(uchar *out, int outn, uchar *in, int inn) +{ + Biobuf bin, bout; + int err; + + crc = 0; + crctab = mkcrctab(GZCRCPOLY); + err = inflateinit(); + if(err != FlateOk) + print("inflateinit failed: %s\n", flateerr(err)); + + bin.bp = bin.p = in; + bin.ep = in+inn; + bout.bp = bout.p = out; + bout.ep = out+outn; + + err = header(&bin); + if(err != FlateOk) + return err; + + err = inflate(&bout, crcwrite, &bin, getc); + if(err != FlateOk) + print("inflate failed: %s\n", flateerr(err)); + + err = trailer(&bout, &bin); + if(err != FlateOk) + return err; + + return Boffset(&bout); +} + +static int +header(Biobuf *bin) +{ + int i, flag; + + if(getc(bin) != 0x1f || getc(bin) != 0x8b){ + print("bad magic\n"); + return FlateCorrupted; + } + if(getc(bin) != 8){ + print("unknown compression type\n"); + return FlateCorrupted; + } + + flag = getc(bin); + + /* mod time */ + get4(bin); + + /* extra flags */ + getc(bin); + + /* OS type */ + getc(bin); + + if(flag & Fextra) + for(i=getc(bin); i>0; i--) + getc(bin); + + /* name */ + if(flag&Fname) + while(getc(bin) != 0) + ; + + /* comment */ + if(flag&Fcomment) + while(getc(bin) != 0) + ; + + /* crc16 */ + if(flag&Fhcrc) { + getc(bin); + getc(bin); + } + + return FlateOk; +} + +static int +trailer(Biobuf *bout, Biobuf *bin) +{ + /* crc32 */ + ulong x; + + x = get4(bin); + if(crc != x){ + print("crc mismatch %lux %lux\n", crc, x); + return FlateCorrupted; + } + + /* length */ + if(get4(bin) != Boffset(bout)){ + print("bad output len\n"); + return FlateCorrupted; + } + return FlateOk; +} + +static ulong +get4(Biobuf *b) +{ + ulong v; + int i, c; + + v = 0; + for(i = 0; i < 4; i++){ + c = getc(b); + v |= c << (i * 8); + } + return v; +} + +static int +getc(void *in) +{ + Biobuf *bp = in; + + if((bp->p - bp->bp) % 10000 == 0) + print("."); + if(bp->p >= bp->ep) + return -1; + return *bp->p++; +} + +static ulong +Boffset(Biobuf *bp) +{ + return bp->p - bp->bp; +} + +static int +crcwrite(void *out, void *buf, int n) +{ + Biobuf *bp; + + crc = blockcrc(crctab, crc, buf, n); + bp = out; + if(n > bp->ep-bp->p) + n = bp->ep-bp->p; + memmove(bp->p, buf, n); + bp->p += n; + return n; +} + +#undef malloc +#undef free + +static ulong ibrkp = ~0; + +void * +malloc(ulong n) +{ + ulong rv; + + if(ibrkp == ~0) + ibrkp = ((ulong)end)+1024*1024; + n = (n+3)>>2; + n <<= 2; + rv = ibrkp; + ibrkp += n; + return (void*)rv; +} + +void +free(void *) +{ +} diff --git a/sys/src/nboot/bitsy/io.h b/sys/src/nboot/bitsy/io.h new file mode 100644 index 0000000000..6791a66253 --- /dev/null +++ b/sys/src/nboot/bitsy/io.h @@ -0,0 +1,261 @@ +/* + * Definitions for IO devices. Used only in C. + */ + +enum +{ + /* hardware counter frequency */ + ClockFreq= 3686400, +}; + +/* + * IRQ's defined by SA1100 + */ +enum +{ + IRQgpio0= 0, + IRQgpio1= 1, + IRQgpio2= 2, + IRQgpio3= 3, + IRQgpio4= 4, + IRQgpio5= 5, + IRQgpio6= 6, + IRQgpio7= 7, + IRQgpio8= 8, + IRQgpio9= 9, + IRQgpio10= 10, + IRQgpiohi= 11, + IRQlcd= 12, + IRQudc= 13, + IRQuart1b= 15, + IRQuart2= 16, + IRQuart3= 17, + IRQmcp= 18, + IRQssp= 19, + IRQdma0= 20, + IRQdma1= 21, + IRQdma2= 22, + IRQdma3= 23, + IRQdma4= 24, + IRQdma5= 25, + IRQtimer0= 26, + IRQtimer1= 27, + IRQtimer2= 28, + IRQtimer3= 29, + IRQsecond= 30, + IRQrtc= 31, +}; + +/* + * GPIO lines (signal names from compaq document). _i indicates input + * and _o output. + */ +enum +{ + GPIO_PWR_ON_i= 1<<0, /* power button */ + GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */ + GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */ + GPIO_LDD9_o= 1<<3, + GPIO_LDD10_o= 1<<4, + GPIO_LDD11_o= 1<<5, + GPIO_LDD12_o= 1<<6, + GPIO_LDD13_o= 1<<7, + GPIO_LDD14_o= 1<<8, + GPIO_LDD15_o= 1<<9, + GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */ + GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */ + GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */ + GPIO_CLK_SET1_o= 1<<13, + GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */ + GPIO_L3_MODE_o= 1<<15, + GPIO_L3_SCLK_o= 1<<16, + GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */ + GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */ + GPIO_SYS_CLK_i= 1<<19, /* clock from codec */ + GPIO_BAT_FAULT_i= 1<<20, /* battery fault */ + GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */ + GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */ + GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */ + GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */ + GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */ + GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */ + GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */ + +/* Peripheral Unit GPIO pin assignments: alternate functions */ + GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */ + GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */ + GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */ + GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */ + /* ser. port 1: */ + GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */ + GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */ + GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */ + GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */ + GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */ + /* ser. port 4: */ + GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */ + /* ser. port 3: */ + GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */ + /* ser. port 4: */ + GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */ + /* test controller: */ + GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */ + GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */ + GPIO_TREQA_i= 1<<22, /* TIC REQuest A */ + GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */ + GPIO_TREQB_i= 1<<23, /* TIC REQuest B */ + GPIO_1Hz_o= 1<<25, /* 1 Hz clock */ + GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */ + GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */ +}; + +/* + * types of interrupts + */ +enum +{ + GPIOrising, + GPIOfalling, + GPIOboth, + IRQ, +}; + +/* hardware registers */ +typedef struct Uartregs Uartregs; +struct Uartregs +{ + ulong ctl[4]; + ulong dummya; + ulong data; + ulong dummyb; + ulong status[2]; +}; +Uartregs *uart3regs; + +/* general purpose I/O lines control registers */ +typedef struct GPIOregs GPIOregs; +struct GPIOregs +{ + ulong level; /* 1 == high */ + ulong direction; /* 1 == output */ + ulong set; /* a 1 sets the bit, 0 leaves it alone */ + ulong clear; /* a 1 clears the bit, 0 leaves it alone */ + ulong rising; /* rising edge detect enable */ + ulong falling; /* falling edge detect enable */ + ulong edgestatus; /* writing a 1 bit clears */ + ulong altfunc; /* turn on alternate function for any set bits */ +}; + +extern GPIOregs *gpioregs; + +/* extra general purpose I/O bits, output only */ +enum +{ + EGPIO_prog_flash= 1<<0, + EGPIO_pcmcia_reset= 1<<1, + EGPIO_exppack_reset= 1<<2, + EGPIO_codec_reset= 1<<3, + EGPIO_exp_nvram_power= 1<<4, + EGPIO_exp_full_power= 1<<5, + EGPIO_lcd_3v= 1<<6, + EGPIO_rs232_power= 1<<7, + EGPIO_lcd_ic_power= 1<<8, + EGPIO_ir_power= 1<<9, + EGPIO_audio_power= 1<<10, + EGPIO_audio_ic_power= 1<<11, + EGPIO_audio_mute= 1<<12, + EGPIO_fir= 1<<13, /* not set is sir */ + EGPIO_lcd_5v= 1<<14, + EGPIO_lcd_9v= 1<<15, +}; +extern ulong *egpioreg; + +/* Peripheral pin controller registers */ +typedef struct PPCregs PPCregs; +struct PPCregs { + ulong direction; + ulong state; + ulong assignment; + ulong sleepdir; + ulong flags; +}; +extern PPCregs *ppcregs; + +/* Synchronous Serial Port controller registers */ +typedef struct SSPregs SSPregs; +struct SSPregs { + ulong control0; + ulong control1; + ulong dummy0; + ulong data; + ulong dummy1; + ulong status; +}; +extern SSPregs *sspregs; + +/* Multimedia Communications Port controller registers */ +typedef struct MCPregs MCPregs; +struct MCPregs { + ulong control0; + ulong reserved0; + ulong data0; + ulong data1; + ulong data2; + ulong reserved1; + ulong status; + ulong reserved[11]; + ulong control1; +}; +extern MCPregs *mcpregs; + +/* + * memory configuration + */ +enum +{ + /* bit shifts for pcmcia access time counters */ + MECR_io0= 0, + MECR_attr0= 5, + MECR_mem0= 10, + MECR_fast0= 11, + MECR_io1= MECR_io0+16, + MECR_attr1= MECR_attr0+16, + MECR_mem1= MECR_mem0+16, + MECR_fast1= MECR_fast0+16, +}; + +typedef struct MemConfRegs MemConfRegs; +struct MemConfRegs +{ + ulong mdcnfg; /* dram */ + ulong mdcas00; /* dram banks 0/1 */ + ulong mdcas01; + ulong mdcas02; + ulong msc0; /* static */ + ulong msc1; + ulong mecr; /* pcmcia */ + ulong mdrefr; /* dram refresh */ + ulong mdcas20; /* dram banks 2/3 */ + ulong mdcas21; + ulong mdcas22; + ulong msc2; /* static */ + ulong smcnfg; /* SMROM config */ +}; +extern MemConfRegs *memconfregs; + +/* + * power management + */ +typedef struct PowerRegs PowerRegs; +struct PowerRegs +{ + ulong pmcr; /* Power manager control register */ + ulong pssr; /* Power manager sleep status register */ + ulong pspr; /* Power manager scratch pad register */ + ulong pwer; /* Power manager wakeup enable register */ + ulong pcfr; /* Power manager general configuration register */ + ulong ppcr; /* Power manager PPL configuration register */ + ulong pgsr; /* Power manager GPIO sleep state register */ + ulong posr; /* Power manager oscillator status register */ +}; +extern PowerRegs *powerregs; diff --git a/sys/src/nboot/bitsy/l.s b/sys/src/nboot/bitsy/l.s new file mode 100644 index 0000000000..0afdb8bafe --- /dev/null +++ b/sys/src/nboot/bitsy/l.s @@ -0,0 +1,454 @@ +#include "mem.h" + +/* + * Entered here from Compaq's bootldr with MMU disabled. + */ +TEXT _start(SB), $-4 + MOVW $setR12(SB), R12 /* load the SB */ +_main: + /* SVC mode, interrupts disabled */ + MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 + MOVW R1, CPSR + + /* disable the MMU */ + MOVW $0x130, R1 + MCR CpMMU, 0, R1, C(CpControl), C(0x0) + + /* flush caches */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 + /* drain prefetch */ + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + + /* drain write buffer */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + + MOVW $(MACHADDR+BY2PG), R13 /* stack */ + SUB $4, R13 /* link */ + BL main(SB) + BL exit(SB) + /* we shouldn't get here */ +_mainloop: + B _mainloop + BL _div(SB) /* hack to get _div etc loaded */ + +/* flush tlb's */ +TEXT mmuinvalidate(SB), $-4 + MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7) + RET + +/* flush tlb's */ +TEXT mmuinvalidateaddr(SB), $-4 + MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1 + RET + +/* write back and invalidate i and d caches */ +TEXT cacheflush(SB), $-4 + /* write back any dirty data */ + MOVW $0xe0000000,R0 + ADD $(8*1024),R0,R1 +_cfloop: + MOVW.P 32(R0),R2 + CMP.S R0,R1 + BNE _cfloop + + /* drain write buffer and invalidate i&d cache contents */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0 + + /* drain prefetch */ + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + RET + +/* write back d cache */ +TEXT cachewb(SB), $-4 + /* write back any dirty data */ +_cachewb: + MOVW $0xe0000000,R0 + ADD $(8*1024),R0,R1 +_cwbloop: + MOVW.P 32(R0),R2 + CMP.S R0,R1 + BNE _cwbloop + + /* drain write buffer */ + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + RET + +/* write back a single cache line */ +TEXT cachewbaddr(SB), $-4 + BIC $31,R0 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1 + B _wbflush + +/* write back a region of cache lines */ +TEXT cachewbregion(SB), $-4 + MOVW 4(FP),R1 + CMP.S $(4*1024),R1 + BGT _cachewb + ADD R0,R1 + BIC $31,R0 +_cwbrloop: + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1 + ADD $32,R0 + CMP.S R0,R1 + BGT _cwbrloop + B _wbflush + +/* invalidate the dcache */ +TEXT dcacheinvalidate(SB), $-4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6) + RET + +/* invalidate the icache */ +TEXT icacheinvalidate(SB), $-4 + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9) + RET + +/* drain write buffer */ +TEXT wbflush(SB), $-4 +_wbflush: + MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4 + RET + +/* return cpu id */ +TEXT getcpuid(SB), $-4 + MRC CpMMU, 0, R0, C(CpCPUID), C(0x0) + RET + +/* return fault status */ +TEXT getfsr(SB), $-4 + MRC CpMMU, 0, R0, C(CpFSR), C(0x0) + RET + +/* return fault address */ +TEXT getfar(SB), $-4 + MRC CpMMU, 0, R0, C(CpFAR), C(0x0) + RET + +/* return fault address */ +TEXT putfar(SB), $-4 + MRC CpMMU, 0, R0, C(CpFAR), C(0x0) + RET + +/* set the translation table base */ +TEXT putttb(SB), $-4 + MCR CpMMU, 0, R0, C(CpTTB), C(0x0) + RET + +/* + * enable mmu, i and d caches + */ +TEXT mmuenable(SB), $-4 + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + RET + +TEXT mmudisable(SB), $-4 + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + RET + +/* + * use exception vectors at 0xffff0000 + */ +TEXT mappedIvecEnable(SB), $-4 + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + ORR $(CpCvivec), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + RET +TEXT mappedIvecDisable(SB), $-4 + MRC CpMMU, 0, R0, C(CpControl), C(0x0) + BIC $(CpCvivec), R0 + MCR CpMMU, 0, R0, C(CpControl), C(0x0) + RET + +/* set the translation table base */ +TEXT putdac(SB), $-4 + MCR CpMMU, 0, R0, C(CpDAC), C(0x0) + RET + +/* set address translation pid */ +TEXT putpid(SB), $-4 + MCR CpMMU, 0, R0, C(CpPID), C(0x0) + RET + +/* + * set the stack value for the mode passed in R0 + */ +TEXT setr13(SB), $-4 + MOVW 4(FP), R1 + + MOVW CPSR, R2 + BIC $PsrMask, R2, R3 + ORR R0, R3 + MOVW R3, CPSR + + MOVW R13, R0 + MOVW R1, R13 + + MOVW R2, CPSR + RET + +/* + * exception vectors, copied by trapinit() to somewhere useful + */ + +TEXT vectors(SB), $-4 + MOVW 0x18(R15), R15 /* reset */ + MOVW 0x18(R15), R15 /* undefined */ + MOVW 0x18(R15), R15 /* SWI */ + MOVW 0x18(R15), R15 /* prefetch abort */ + MOVW 0x18(R15), R15 /* data abort */ + MOVW 0x18(R15), R15 /* reserved */ + MOVW 0x18(R15), R15 /* IRQ */ + MOVW 0x18(R15), R15 /* FIQ */ + +TEXT vtable(SB), $-4 + WORD $_vsvc(SB) /* reset, in svc mode already */ + WORD $_vund(SB) /* undefined, switch to svc mode */ + WORD $_vsvc(SB) /* swi, in svc mode already */ + WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */ + WORD $_vdabt(SB) /* data abort, switch to svc mode */ + WORD $_vsvc(SB) /* reserved */ + WORD $_virq(SB) /* IRQ, switch to svc mode */ + WORD $_vfiq(SB) /* FIQ, switch to svc mode */ + +TEXT _vrst(SB), $-4 + BL resettrap(SB) + +TEXT _vsvc(SB), $-4 /* SWI */ + MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */ + MOVW SPSR, R14 /* ureg->psr = SPSR */ + MOVW.W R14, -4(R13) /* ... */ + MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ + MOVW.W R14, -4(R13) /* ... */ + MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */ + MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ + MOVW R13, R0 /* first arg is pointer to ureg */ + SUB $8, R13 /* space for argument+link */ + + BL syscall(SB) + + ADD $(8+4*15), R13 /* make r13 point to ureg->type */ + MOVW 8(R13), R14 /* restore link */ + MOVW 4(R13), R0 /* restore SPSR */ + MOVW R0, SPSR /* ... */ + MOVM.DB.S (R13), [R0-R14] /* restore registers */ + ADD $8, R13 /* pop past ureg->{type+psr} */ + RFE /* MOVM.IA.S.W (R13), [R15] */ + +TEXT _vund(SB), $-4 /* undefined */ + MOVM.IA [R0-R4], (R13) /* free some working space */ + MOVW $PsrMund, R0 + B _vswitch + +TEXT _vpabt(SB), $-4 /* prefetch abort */ + MOVM.IA [R0-R4], (R13) /* free some working space */ + MOVW $PsrMabt, R0 /* r0 = type */ + B _vswitch + +TEXT _vdabt(SB), $-4 /* prefetch abort */ + MOVM.IA [R0-R4], (R13) /* free some working space */ + MOVW $(PsrMabt+1), R0 /* r0 = type */ + B _vswitch + +TEXT _virq(SB), $-4 /* IRQ */ + MOVM.IA [R0-R4], (R13) /* free some working space */ + MOVW $PsrMirq, R0 /* r0 = type */ + B _vswitch + + /* + * come here with type in R0 and R13 pointing above saved [r0-r4] + * and type in r0. we'll switch to SVC mode and then call trap. + */ +_vswitch: + MOVW SPSR, R1 /* save SPSR for ureg */ + MOVW R14, R2 /* save interrupted pc for ureg */ + MOVW R13, R3 /* save pointer to where the original [R0-R3] are */ + + /* switch to svc mode */ + MOVW CPSR, R14 + BIC $PsrMask, R14 + ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 + MOVW R14, CPSR + + /* interupted code kernel or user? */ + AND.S $0xf, R1, R4 + BEQ _userexcep + + /* here for trap from SVC mode */ + MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ + MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ + MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */ + MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ + MOVW R13, R0 /* first arg is pointer to ureg */ + SUB $8, R13 /* space for argument+link (for debugger) */ + MOVW $0xdeaddead,R11 /* marker */ + + BL trap(SB) + + ADD $(8+4*15), R13 /* make r13 point to ureg->type */ + MOVW 8(R13), R14 /* restore link */ + MOVW 4(R13), R0 /* restore SPSR */ + MOVW R0, SPSR /* ... */ + MOVM.DB (R13), [R0-R14] /* restore registers */ + ADD $8, R13 /* pop past ureg->{type+psr} */ + RFE /* MOVM.IA.S.W (R13), [R15] */ + + /* here for trap from USER mode */ +_userexcep: + MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ + MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ + MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */ + MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ + MOVW R13, R0 /* first arg is pointer to ureg */ + SUB $8, R13 /* space for argument+link (for debugger) */ + + BL trap(SB) + + ADD $(8+4*15), R13 /* make r13 point to ureg->type */ + MOVW 8(R13), R14 /* restore link */ + MOVW 4(R13), R0 /* restore SPSR */ + MOVW R0, SPSR /* ... */ + MOVM.DB.S (R13), [R0-R14] /* restore registers */ + ADD $8, R13 /* pop past ureg->{type+psr} */ + RFE /* MOVM.IA.S.W (R13), [R15] */ + +TEXT _vfiq(SB), $-4 /* FIQ */ + RFE /* FIQ is special, ignore it for now */ + +/* + * This is the first jump from kernel to user mode. + * Fake a return from interrupt. + * + * Enter with R0 containing the user stack pointer. + * UTZERO + 0x20 is always the entry point. + * + */ +TEXT touser(SB),$-4 + /* store the user stack pointer into the USR_r13 */ + MOVM.DB.W [R0], (R13) + MOVM.S.IA.W (R13),[R13] + + /* set up a PSR for user level */ + MOVW $(PsrMusr), R0 + MOVW R0,SPSR + + /* save the PC on the stack */ + MOVW $(UTZERO+0x20), R0 + MOVM.DB.W [R0],(R13) + + /* return from interrupt */ + RFE /* MOVM.IA.S.W (R13), [R15] */ + +/* + * here to jump to a newly forked process + */ +TEXT forkret(SB),$-4 + ADD $(4*15), R13 /* make r13 point to ureg->type */ + MOVW 8(R13), R14 /* restore link */ + MOVW 4(R13), R0 /* restore SPSR */ + MOVW R0, SPSR /* ... */ + MOVM.DB.S (R13), [R0-R14] /* restore registers */ + ADD $8, R13 /* pop past ureg->{type+psr} */ + RFE /* MOVM.IA.S.W (R13), [R15] */ + +TEXT splhi(SB), $-4 + /* save caller pc in Mach */ + MOVW $(MACHADDR+0x04),R2 + MOVW R14,0(R2) + /* turn off interrupts */ + MOVW CPSR, R0 + ORR $(PsrDfiq|PsrDirq), R0, R1 + MOVW R1, CPSR + RET + +TEXT spllo(SB), $-4 + MOVW CPSR, R0 + BIC $(PsrDfiq|PsrDirq), R0, R1 + MOVW R1, CPSR + RET + +TEXT splx(SB), $-4 + /* save caller pc in Mach */ + MOVW $(MACHADDR+0x04),R2 + MOVW R14,0(R2) + /* reset interrupt level */ + MOVW R0, R1 + MOVW CPSR, R0 + MOVW R1, CPSR + RET + +TEXT splxpc(SB), $-4 /* for iunlock */ + MOVW R0, R1 + MOVW CPSR, R0 + MOVW R1, CPSR + RET + +TEXT spldone(SB), $0 + RET + +TEXT islo(SB), $-4 + MOVW CPSR, R0 + AND $(PsrDfiq|PsrDirq), R0 + EOR $(PsrDfiq|PsrDirq), R0 + RET + +TEXT cpsrr(SB), $-4 + MOVW CPSR, R0 + RET + +TEXT spsrr(SB), $-4 + MOVW SPSR, R0 + RET + +TEXT getcallerpc(SB), $-4 + MOVW 0(R13), R0 + RET + +TEXT tas(SB), $-4 + MOVW R0, R1 + MOVW $0xDEADDEAD, R2 + SWPW R2, (R1), R0 + RET + +TEXT setlabel(SB), $-4 + MOVW R13, 0(R0) /* sp */ + MOVW R14, 4(R0) /* pc */ + MOVW $0, R0 + RET + +TEXT gotolabel(SB), $-4 + MOVW 0(R0), R13 /* sp */ + MOVW 4(R0), R14 /* pc */ + MOVW $1, R0 + RET + + +/* The first MCR instruction of this function needs to be on a cache-line + * boundary; to make this happen, it will be copied (in trap.c). + * + * Doze puts the machine into idle mode. Any interrupt will get it out + * at the next instruction (the RET, to be precise). + */ +TEXT _doze(SB), $-4 + MOVW $UCDRAMZERO, R1 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MOVW R0,R0 + MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2 + MOVW (R1), R0 + MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2 + RET diff --git a/sys/src/nboot/bitsy/lib.h b/sys/src/nboot/bitsy/lib.h new file mode 100644 index 0000000000..5c99d1fe97 --- /dev/null +++ b/sys/src/nboot/bitsy/lib.h @@ -0,0 +1,143 @@ +/* + * functions (possibly) linked in, complete, from libc. + */ + +/* + * mem routines + */ +extern void *memccpy(void*, void*, int, long); +extern void *memset(void*, int, long); +extern int memcmp(void*, void*, long); +extern void *memmove(void*, void*, long); +extern void *memchr(void*, int, long); + +/* + * string routines + */ +extern char *strcat(char*, char*); +extern char *strchr(char*, char); +extern char *strrchr(char*, char); +extern int strcmp(char*, char*); +extern char *strcpy(char*, char*); +extern char *strncat(char*, char*, long); +extern char *strncpy(char*, char*, long); +extern int strncmp(char*, char*, long); +extern long strlen(char*); +extern char* strstr(char*, char*); +extern int atoi(char*); + +enum +{ + UTFmax = 3, /* maximum bytes per rune */ + Runesync = 0x80, /* cannot represent part of a UTF sequence */ + Runeself = 0x80, /* rune and UTF sequences are the same (<) */ + Runeerror = 0x80, /* decoding error in UTF */ +}; + +/* + * rune routines + */ +extern int runetochar(char*, Rune*); +extern int chartorune(Rune*, char*); +extern char* utfrune(char*, long); +extern int utflen(char*); +extern int runelen(long); + +extern int abs(int); + +/* + * print routines + */ +typedef struct Cconv Fconv; +extern char* donprint(char*, char*, char*, void*); +extern int sprint(char*, char*, ...); +extern char* seprint(char*, char*, char*, ...); +extern int snprint(char*, int, char*, ...); +extern int print(char*, ...); + +/* + * one-of-a-kind + */ +extern char* cleanname(char*); +extern uintptr getcallerpc(void*); +extern long strtol(char*, char**, int); +extern ulong strtoul(char*, char**, int); +extern vlong strtoll(char*, char**, int); +extern uvlong strtoull(char*, char**, int); +extern char etext[]; +extern char edata[]; +extern char end[]; +extern int getfields(char*, char**, int, int, char*); + +/* + * Syscall data structures + */ +#define MORDER 0x0003 /* mask for bits defining order of mounting */ +#define MREPL 0x0000 /* mount replaces object */ +#define MBEFORE 0x0001 /* mount goes before others in union directory */ +#define MAFTER 0x0002 /* mount goes after others in union directory */ +#define MCREATE 0x0004 /* permit creation in mounted directory */ +#define MCACHE 0x0010 /* cache some data */ +#define MMASK 0x001F /* all bits on */ + +#define OREAD 0 /* open for read */ +#define OWRITE 1 /* write */ +#define ORDWR 2 /* read and write */ +#define OEXEC 3 /* execute, == read but check execute permission */ +#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ +#define OCEXEC 32 /* or'ed in, close on exec */ +#define ORCLOSE 64 /* or'ed in, remove on close */ + +#define NCONT 0 /* continue after note */ +#define NDFLT 1 /* terminate after note */ +#define NSAVE 2 /* clear note but hold state */ +#define NRSTR 3 /* restore saved state */ + +typedef struct Qid Qid; +typedef struct Dir Dir; +typedef struct Waitmsg Waitmsg; + +#define ERRLEN 64 +#define DIRLEN 116 +#define NAMELEN 28 + +struct Qid +{ + ulong path; + ulong vers; +}; + +struct Dir +{ + char name[NAMELEN]; + char uid[NAMELEN]; + char gid[NAMELEN]; + Qid qid; + ulong mode; + long atime; + long mtime; + vlong length; + short type; + short dev; +}; + +struct Waitmsg +{ + char pid[12]; /* of loved one */ + char time[3*12]; /* of loved one and descendants */ + char msg[ERRLEN]; +}; + +/* + * locks + */ +typedef +struct Lock { + int val; +} Lock; + +extern int _tas(int*); + +extern void lock(Lock*); +extern void unlock(Lock*); +extern int canlock(Lock*); diff --git a/sys/src/nboot/bitsy/map b/sys/src/nboot/bitsy/map new file mode 100644 index 0000000000..87f67bece4 --- /dev/null +++ b/sys/src/nboot/bitsy/map @@ -0,0 +1,10 @@ +defn acidmap() +{ + local dfoffset; + + dfoffset = map()[1][3]; + map({"text", _start, etext, 0x20}); + map({"data", etext+1, edata, dfoffset}); + print("Set map for plan 9 kernel image\n"); + print("btext ", _start, " etext ", etext, "\n"); +} diff --git a/sys/src/nboot/bitsy/mem.h b/sys/src/nboot/bitsy/mem.h new file mode 100644 index 0000000000..2be6e705cf --- /dev/null +++ b/sys/src/nboot/bitsy/mem.h @@ -0,0 +1,213 @@ +/* + * Memory and machine-specific definitions. Used in C and assembler. + */ + +/* + * Sizes + */ +#define BI2BY 8 /* bits per byte */ +#define BI2WD 32 /* bits per word */ +#define BY2WD 4 /* bytes per word */ +#define BY2V 8 /* bytes per double word */ +#define BY2PG 4096 /* bytes per page */ +#define WD2PG (BY2PG/BY2WD) /* words per page */ +#define PGSHIFT 12 /* log(BY2PG) */ +#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1)) +#define PGROUND(s) ROUND(s, BY2PG) +#define BLOCKALIGN 8 + +#define MAXMACH 1 /* max # cpus system can run */ + +/* + * Time + */ +#define HZ (20) /* clock frequency */ +#define MS2HZ (1000/HZ) /* millisec per clock tick */ +#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ +#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */ +#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */ + +/* + * Virtual addresses: + * + * We direct map all discovered DRAM and the area twixt 0xe0000000 and + * 0xe8000000 used to provide zeros for cache flushing. + * + * Flash is mapped to 0xb0000000 and special registers are mapped + * on demand to areas starting at 0xa0000000. + * + * The direct mapping is convenient but not necessary. It means + * that we don't have to turn on the MMU till well into the + * kernel. This can be changed by providing a mapping in l.s + * before calling main. + */ +#define UZERO 0 /* base of user address space */ +#define UTZERO (UZERO+BY2PG) /* first address in user text */ +#define KZERO 0xC0000000 /* base of kernel address space */ +#define KTZERO 0xC0008000 /* first address in kernel text */ +#define EMEMZERO 0x90000000 /* 256 meg for add on memory */ +#define EMEMTOP 0xA0000000 /* ... */ +#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */ +#define REGTOP 0xA8000000 /* ... */ +#define FLASHZERO 0xB0000000 /* 128 meg for flash */ +#define FLASHTOP 0xB8000000 /* ... */ +#define DRAMZERO 0xC0000000 /* 128 meg for dram */ +#define DRAMTOP 0xC8000000 /* ... */ +#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */ +#define UCDRAMTOP 0xD0000000 /* ... */ +#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */ +#define NULLTOP 0xE8000000 /* ... */ +#define USTKTOP 0x2000000 /* byte just beyond user stack */ +#define USTKSIZE (8*1024*1024) /* size of user stack */ +#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */ +#define TSTKSIZ 100 +#define MACHADDR (KZERO+0x00001000) +#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */ + +#define KSTACK (16*1024) /* Size of kernel stack */ + +/* + * Offsets into flash + */ +#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */ +#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */ +#define Flash_tar (FLASHZERO+0x100000) /* tar file containing fs.sac */ + +/* + * virtual MMU + */ +#define PTEMAPMEM (1024*1024) +#define PTEPERTAB (PTEMAPMEM/BY2PG) +#define SEGMAPSIZE 1984 +#define SSEGMAPSIZE 16 +#define PPN(x) ((x)&~(BY2PG-1)) + +/* + * SA1110 definitions + */ + +/* + * memory physical addresses + */ +#define PHYSFLASH0 0x00000000 +#define PHYSDRAM0 0xC0000000 +#define PHYSNULL0 0xE0000000 + +/* + * peripheral control module physical addresses + */ +#define USBREGS 0x80000000 /* serial port 0 - USB */ +#define UART1REGS 0x80010000 /* serial port 1 - UART */ +#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */ +#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */ +#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */ +#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */ +#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */ +#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */ +#define OSTIMERREGS 0x90000000 /* operating system timer registers */ +#define POWERREGS 0x90020000 /* power management */ +#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */ +#define INTRREGS 0x90050000 /* interrupt registers */ +#define PPCREGS 0x90060000 /* peripheral pin controller */ +#define MEMCONFREGS 0xA0000000 /* memory configuration */ +#define LCDREGS 0xB0100000 /* display */ + +/* + * PCMCIA addresses + */ +#define PHYSPCM0REGS 0x20000000 +#define PYHSPCM0ATTR 0x28000000 +#define PYHSPCM0MEM 0x2C000000 +#define PHYSPCM1REGS 0x30000000 +#define PYHSPCM1ATTR 0x38000000 +#define PYHSPCM1MEM 0x3C000000 + +/* + * Program Status Registers + */ +#define PsrMusr 0x00000010 /* mode */ +#define PsrMfiq 0x00000011 +#define PsrMirq 0x00000012 +#define PsrMsvc 0x00000013 +#define PsrMabt 0x00000017 +#define PsrMund 0x0000001B +#define PsrMask 0x0000001F + +#define PsrDfiq 0x00000040 /* disable FIQ interrupts */ +#define PsrDirq 0x00000080 /* disable IRQ interrupts */ + +#define PsrV 0x10000000 /* overflow */ +#define PsrC 0x20000000 /* carry/borrow/extend */ +#define PsrZ 0x40000000 /* zero */ +#define PsrN 0x80000000 /* negative/less than */ + +/* + * Coprocessors + */ +#define CpMMU 15 +#define CpPWR 15 + +/* + * Internal MMU coprocessor registers + */ +#define CpCPUID 0 /* R: */ +#define CpControl 1 /* R: */ +#define CpTTB 2 /* RW: translation table base */ +#define CpDAC 3 /* RW: domain access control */ +#define CpFSR 5 /* RW: fault status */ +#define CpFAR 6 /* RW: fault address */ +#define CpCacheFlush 7 /* W: cache flushing, wb draining*/ +#define CpTLBFlush 8 /* W: TLB flushing */ +#define CpRBFlush 9 /* W: Read Buffer ops */ +#define CpPID 13 /* RW: PID for virtual mapping */ +#define CpBpt 14 /* W: Breakpoint register */ +#define CpTest 15 /* W: Test, Clock and Idle Control */ + +/* + * CpControl + */ +#define CpCmmuena 0x00000001 /* M: MMU enable */ +#define CpCalign 0x00000002 /* A: alignment fault enable */ +#define CpCdcache 0x00000004 /* C: data cache on */ +#define CpCwb 0x00000008 /* W: write buffer turned on */ +#define CpCi32 0x00000010 /* P: 32-bit program space */ +#define CpCd32 0x00000020 /* D: 32-bit data space */ +#define CpCbe 0x00000080 /* B: big-endian operation */ +#define CpCsystem 0x00000100 /* S: system permission */ +#define CpCrom 0x00000200 /* R: ROM permission */ +#define CpCicache 0x00001000 /* I: instruction cache on */ +#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */ + +/* + * fault codes + */ +#define FCterm 0x2 /* terminal */ +#define FCvec 0x0 /* vector */ +#define FCalignf 0x1 /* unaligned full word data access */ +#define FCalignh 0x3 /* unaligned half word data access */ +#define FCl1abort 0xc /* level 1 external abort on translation */ +#define FCl2abort 0xe /* level 2 external abort on translation */ +#define FCtransSec 0x5 /* section translation */ +#define FCtransPage 0x7 /* page translation */ +#define FCdomainSec 0x9 /* section domain */ +#define FCdomainPage 0x11 /* page domain */ +#define FCpermSec 0x9 /* section permissions */ +#define FCpermPage 0x11 /* page permissions */ +#define FCabortLFSec 0x4 /* external abort on linefetch for section */ +#define FCabortLFPage 0x6 /* external abort on linefetch for page */ +#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */ +#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */ + +/* + * PTE bits used by fault.h. mmu.c translates them to real values. + */ +#define PTEVALID (1<<0) +#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */ +#define PTEWRITE (1<<1) +#define PTEUNCACHED (1<<2) +#define PTEKERNEL (1<<3) /* no user access */ + +/* + * H3650 specific definitions + */ +#define EGPIOREGS 0x49000000 /* Additional GPIO register */ diff --git a/sys/src/nboot/bitsy/mkfile b/sys/src/nboot/bitsy/mkfile new file mode 100644 index 0000000000..fe32e68806 --- /dev/null +++ b/sys/src/nboot/bitsy/mkfile @@ -0,0 +1,45 @@ +objtype=arm + 0){ + /* wait for output ready */ + while((ur->status[1] & Tnotfull) == 0) + ; + ur->data = *str++; + } + while((ur->status[1] & Tbusy)) + ; +} diff --git a/sys/src/nboot/efi/efi.c b/sys/src/nboot/efi/efi.c new file mode 100644 index 0000000000..ee13ba9b81 --- /dev/null +++ b/sys/src/nboot/efi/efi.c @@ -0,0 +1,308 @@ +#include +#include "fns.h" +#include "efi.h" + +UINTN MK; +EFI_HANDLE IH; +EFI_SYSTEM_TABLE *ST; + +void* (*open)(char *name); +int (*read)(void *f, void *data, int len); +void (*close)(void *f); + +void +putc(int c) +{ + CHAR16 w[2]; + + w[0] = c; + w[1] = 0; + eficall(ST->ConOut->OutputString, ST->ConOut, w); +} + +int +getc(void) +{ + EFI_INPUT_KEY k; + + if(eficall(ST->ConIn->ReadKeyStroke, ST->ConIn, &k)) + return 0; + return k.UnicodeChar; +} + +void +usleep(int us) +{ + eficall(ST->BootServices->Stall, (UINTN)us); +} + +void +unload(void) +{ + eficall(ST->BootServices->ExitBootServices, IH, MK); +} + +static void +memconf(char **cfg) +{ + static uchar memtype[EfiMaxMemoryType] = { + [EfiReservedMemoryType] 2, + [EfiLoaderCode] 1, + [EfiLoaderData] 1, + [EfiBootServicesCode] 2, + [EfiBootServicesData] 2, + [EfiRuntimeServicesCode] 2, + [EfiRuntimeServicesData] 2, + [EfiConventionalMemory] 1, + [EfiUnusableMemory] 2, + [EfiACPIReclaimMemory] 3, + [EfiACPIMemoryNVS] 4, + [EfiMemoryMappedIO] 2, + [EfiMemoryMappedIOPortSpace] 2, + [EfiPalCode] 2, + }; + UINTN mapsize, entsize; + EFI_MEMORY_DESCRIPTOR *t; + uchar mapbuf[96*1024], *p, m; + UINT32 entvers; + char *s; + + mapsize = sizeof(mapbuf); + entsize = sizeof(EFI_MEMORY_DESCRIPTOR); + entvers = 1; + if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers)) + return; + + s = *cfg; + for(p = mapbuf; mapsize >= entsize; p += entsize, mapsize -= entsize){ + t = (EFI_MEMORY_DESCRIPTOR*)p; + + m = 0; + if(t->Type < EfiMaxMemoryType) + m = memtype[t->Type]; + + if(m == 0) + continue; + + if(s == *cfg) + memmove(s, "*e820=", 6), s += 6; + s = hexfmt(s, 1, m), *s++ = ' '; + s = hexfmt(s, 16, t->PhysicalStart), *s++ = ' '; + s = hexfmt(s, 16, t->PhysicalStart + t->NumberOfPages * 4096ULL), *s++ = ' '; + } + *s = '\0'; + if(s > *cfg){ + s[-1] = '\n'; + print(*cfg); + *cfg = s; + } +} + +static void +acpiconf(char **cfg) +{ + static EFI_GUID ACPI_20_TABLE_GUID = { + 0x8868e871, 0xe4f1, 0x11d3, + 0xbc, 0x22, 0x00, 0x80, + 0xc7, 0x3c, 0x88, 0x81, + }; + static EFI_GUID ACPI_10_TABLE_GUID = { + 0xeb9d2d30, 0x2d88, 0x11d3, + 0x9a, 0x16, 0x00, 0x90, + 0x27, 0x3f, 0xc1, 0x4d, + }; + EFI_CONFIGURATION_TABLE *t; + uintptr pa; + char *s; + int n; + + pa = 0; + t = ST->ConfigurationTable; + n = ST->NumberOfTableEntries; + while(--n >= 0){ + if(memcmp(&t->VendorGuid, &ACPI_10_TABLE_GUID, sizeof(EFI_GUID)) == 0){ + if(pa == 0) + pa = (uintptr)t->VendorTable; + } else if(memcmp(&t->VendorGuid, &ACPI_20_TABLE_GUID, sizeof(EFI_GUID)) == 0) + pa = (uintptr)t->VendorTable; + t++; + } + + if(pa){ + s = *cfg; + memmove(s, "*acpi=0x", 8), s += 8; + s = hexfmt(s, 0, pa), *s++ = '\n'; + *s = '\0'; + print(*cfg); + *cfg = s; + } +} + + +static int +topbit(ulong mask) +{ + int bit = 0; + + while(mask != 0){ + mask >>= 1; + bit++; + } + return bit; +} + +static int +lowbit(ulong mask) +{ + int bit = 0; + + while((mask & 1) == 0){ + mask >>= 1; + bit++; + } + return bit; +} + +static void +screenconf(char **cfg) +{ + static EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = { + 0x9042a9de, 0x23dc, 0x4a38, + 0x96, 0xfb, 0x7a, 0xde, + 0xd0, 0x80, 0x51, 0x6a, + }; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + EFI_HANDLE *Handles; + UINTN Count; + + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + ulong mr, mg, mb, mx, mc; + int i, bits, depth; + char *s; + + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles)) + return; + + for(i=0; iBootServices->HandleProtocol, + Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop)) + continue; + + if(gop == nil) + continue; + if((info = gop->Mode->Info) == nil) + continue; + + switch(info->PixelFormat){ + default: + continue; /* unsupported */ + + case PixelRedGreenBlueReserved8BitPerColor: + mr = 0x000000ff; + mg = 0x0000ff00; + mb = 0x00ff0000; + mx = 0xff000000; + break; + + case PixelBlueGreenRedReserved8BitPerColor: + mb = 0x000000ff; + mg = 0x0000ff00; + mr = 0x00ff0000; + mx = 0xff000000; + break; + + case PixelBitMask: + mr = info->PixelInformation.RedMask; + mg = info->PixelInformation.GreenMask; + mb = info->PixelInformation.BlueMask; + mx = info->PixelInformation.ReservedMask; + break; + } + + if((depth = topbit(mr | mg | mb | mx)) == 0) + continue; + + /* make sure we have linear framebuffer */ + if(gop->Mode->FrameBufferBase == 0) + continue; + if(gop->Mode->FrameBufferSize == 0) + continue; + + goto Found; + } + return; + +Found: + s = *cfg; + memmove(s, "*bootscreen=", 12), s += 12; + s = decfmt(s, 0, info->PixelsPerScanLine), *s++ = 'x'; + s = decfmt(s, 0, info->VerticalResolution), *s++ = 'x'; + s = decfmt(s, 0, depth), *s++ = ' '; + + while(depth > 0){ + if(depth == topbit(mr)){ + mc = mr; + *s++ = 'r'; + } else if(depth == topbit(mg)){ + mc = mg; + *s++ = 'g'; + } else if(depth == topbit(mb)){ + mc = mb; + *s++ = 'b'; + } else if(depth == topbit(mx)){ + mc = mx; + *s++ = 'x'; + } else { + break; + } + bits = depth - lowbit(mc); + s = decfmt(s, 0, bits); + depth -= bits; + } + *s++ = ' '; + + *s++ = '0', *s++ = 'x'; + s = hexfmt(s, 0, gop->Mode->FrameBufferBase), *s++ = '\n'; + *s = '\0'; + + print(*cfg); + *cfg = s; +} + +void +eficonfig(char **cfg) +{ + memconf(cfg); + acpiconf(cfg); + screenconf(cfg); +} + +EFI_STATUS +efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) +{ + char path[MAXPATH], *kern; + void *f; + + IH = ih; + ST = st; + + f = nil; + if(pxeinit(&f) && isoinit(&f) && fsinit(&f)) + print("no boot devices\n"); + + for(;;){ + kern = configure(f, path); + f = open(kern); + if(f == nil){ + print("not found\n"); + continue; + } + print(bootkern(f)); + print("\n"); + f = nil; + } +} diff --git a/sys/src/nboot/efi/efi.h b/sys/src/nboot/efi/efi.h new file mode 100644 index 0000000000..aa411c63b7 --- /dev/null +++ b/sys/src/nboot/efi/efi.h @@ -0,0 +1,256 @@ +typedef ushort CHAR16; + +typedef uchar UINT8; +typedef ushort UINT16; +typedef ulong UINT32; +typedef uvlong UINT64; +typedef UINT8 BOOLEAN; + +typedef uintptr UINTN; + +typedef void* EFI_HANDLE; +typedef UINT32 EFI_STATUS; + +enum { + AllHandles, + ByRegisterNotify, + ByProtocol, +}; + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +typedef struct { + void *Reset; + void *ReadKeyStroke; + void *WaitForKey; +} EFI_SIMPLE_TEXT_INPUT_PROTOCOL; + +typedef struct { + void *Reset; + void *OutputString; + void *TestString; + void *QueryMode; + void *SetMode; + void *SetAttribute; + void *ClearScreen; + void *SetCursorPosition; + void *EnableCursor; + void *Mode; +} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + void *SystemTable; + EFI_HANDLE DeviceHandle; + void *FilePath; + void *Reserved; + UINT32 LoadOptionsSize; + void *LoadOptions; + void *ImageBase; + UINT64 ImageSize; + UINT32 ImageCodeType; + UINT32 ImageDataType; + void *Unload; +} EFI_LOADED_IMAGE_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax, +}; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + UINT64 FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +typedef struct { + void *QueryMode; + void *SetMode; + void *Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +} EFI_GRAPHICS_OUTPUT_PROTOCOL; + +enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiMaxMemoryType, +}; + +typedef struct { + UINT32 Type; + UINT32 Reserved; + UINT64 PhysicalStart; + UINT64 VirtualStart; + UINT64 NumberOfPages; + UINT64 Attribute; +} EFI_MEMORY_DESCRIPTOR; + + +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + +typedef struct { + EFI_TABLE_HEADER; + + void *RaiseTPL; + void *RestoreTPL; + void *AllocatePages; + void *FreePages; + void *GetMemoryMap; + void *AllocatePool; + void *FreePool; + + void *CreateEvent; + void *SetTimer; + void *WaitForEvent; + void *SignalEvent; + void *CloseEvent; + void *CheckEvent; + + void **InstallProtocolInterface; + void **ReinstallProtocolInterface; + void **UninstallProtocolInterface; + + void *HandleProtocol; + void *Reserved; + void *RegisterProtocolNotify; + + void *LocateHandle; + void *LocateDevicePath; + void *InstallConfigurationTable; + + void *LoadImage; + void *StartImage; + void *Exit; + void *UnloadImage; + void *ExitBootServices; + + void *GetNextMonotonicCount; + void *Stall; + void *SetWatchdogTimer; + + void *ConnectController; + void *DisconnectController; + + void *OpenProtocol; + void *CloseProtocol; + + void *OpenProtocolInformation; + void *ProtocolsPerHandle; + void *LocateHandleBuffer; + void *LocateProtocol; + + void *InstallMultipleProtocolInterfaces; + void *UninstallMultipleProtocolInterfaces; + + void *CalculateCrc32; + + void *CopyMem; + void *SetMem; + void *CreateEventEx; +} EFI_BOOT_SERVICES; + +typedef struct { + EFI_TABLE_HEADER; + + void *GetTime; + void *SetTime; + void *GetWakeupTime; + void *SetWakeupTime; + + void *SetVirtualAddressMap; + void *ConvertPointer; + + void *GetVariable; + void *GetNextVariableName; + void *SetVariable; + + void *GetNextHighMonotonicCount; + void *ResetSystem; + + void *UpdateCapsule; + void *QueryCapsuleCapabilities; + + void *QueryVariableInfo; +} EFI_RUNTIME_SERVICES; + +typedef struct { + EFI_GUID VendorGuid; + void *VendorTable; +} EFI_CONFIGURATION_TABLE; + +typedef struct { + EFI_TABLE_HEADER; + + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + + EFI_HANDLE ConsoleInHandle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + + EFI_HANDLE StandardErrorHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; + +extern EFI_SYSTEM_TABLE *ST; +extern EFI_HANDLE IH; diff --git a/sys/src/nboot/efi/fns.h b/sys/src/nboot/efi/fns.h new file mode 100644 index 0000000000..e029ebdb6b --- /dev/null +++ b/sys/src/nboot/efi/fns.h @@ -0,0 +1,39 @@ +enum { + MAXPATH = 128, +}; + +extern char hex[]; + +void usleep(int t); +void jump(void *pc); + +int pxeinit(void **pf); +int isoinit(void **pf); +int fsinit(void **pf); + +void* (*open)(char *name); +int (*read)(void *f, void *data, int len); +void (*close)(void *f); + +int readn(void *f, void *data, int len); +void unload(void); + +int getc(void); +void putc(int c); + +void memset(void *p, int v, int n); +void memmove(void *dst, void *src, int n); +int memcmp(void *src, void *dst, int n); +int strlen(char *s); +char *strchr(char *s, int c); +char *strrchr(char *s, int c); +void print(char *s); + +char *configure(void *f, char *path); +char *bootkern(void *f); + +char *hexfmt(char *s, int i, uvlong a); +char *decfmt(char *s, int i, ulong a); + +uintptr eficall(void *proc, ...); +void eficonfig(char **cfg); diff --git a/sys/src/nboot/efi/fs.c b/sys/src/nboot/efi/fs.c new file mode 100644 index 0000000000..807dbdbcbe --- /dev/null +++ b/sys/src/nboot/efi/fs.c @@ -0,0 +1,166 @@ +#include +#include "fns.h" +#include "efi.h" + +typedef struct { + UINT64 Revision; + void *Open; + void *Close; + void *Delete; + void *Read; + void *Write; + void *GetPosition; + void *SetPosition; + void *GetInfo; + void *SetInfo; + void *Flush; + void *OpenEx; + void *ReadEx; + void *WriteEx; + void *FlushEx; +} EFI_FILE_PROTOCOL; + +typedef struct { + UINT64 Revision; + void *OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +static +EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = { + 0x0964e5b22, 0x6459, 0x11d2, + 0x8e, 0x39, 0x00, 0xa0, + 0xc9, 0x69, 0x72, 0x3b, +}; + +static EFI_GUID EFI_LOADED_IMAGE_PROTOCOL_GUID = { + 0x5b1b31a1, 0x9562, 0x11d2, + 0x8e, 0x3f, 0x00, 0xa0, + 0xc9, 0x69, 0x72, 0x3b, +}; + +static +EFI_FILE_PROTOCOL *fsroot; + +static void +towpath(CHAR16 *w, int nw, char *s) +{ + int i; + + for(i=0; *s && iOpen, fsroot, &fp, wname, (UINT64)1, (UINT64)1)) + return nil; + return fp; +} + +static int +fsread(void *f, void *data, int len) +{ + UINTN size; + + size = len > 4096 ? 4096 : len; + if(eficall(((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data)) + return 0; + return (int)size; +} + +static void +fsclose(void *f) +{ + eficall(((EFI_FILE_PROTOCOL*)f)->Close, f); +} + +int +fsinit(void **pf) +{ + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs; + EFI_LOADED_IMAGE_PROTOCOL *image; + EFI_FILE_PROTOCOL *root; + EFI_HANDLE *Handles; + void *f; + UINTN Count; + int i; + + image = nil; + + /* locate kernel and plan9.ini by deriving a fs protocol + * from the device the loader was read from. + * if that fails, fall back to old method. + */ + if(eficall(ST->BootServices->HandleProtocol, IH, + &EFI_LOADED_IMAGE_PROTOCOL_GUID, &image) == 0 && + eficall(ST->BootServices->HandleProtocol, image->DeviceHandle, + &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &fs) == 0 && + eficall(fs->OpenVolume, fs, &root) == 0){ + + fsroot = root; + f = fsopen("/plan9.ini"); + if(f != nil){ + if(pf != nil) + *pf = f; + else + fsclose(f); + + goto gotit; + } + } + + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &Count, &Handles)) + return -1; + + /* + * assuming the ESP is the first entry in the handle buffer, so go backwards + * to scan for plan9.ini in other (9fat) filesystems first. if nothing is found + * we'll be defaulting to the ESP. + */ + fsroot = nil; + for(i=Count-1; i>=0; i--){ + root = nil; + fs = nil; + if(eficall(ST->BootServices->HandleProtocol, + Handles[i], &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &fs)) + continue; + if(eficall(fs->OpenVolume, fs, &root)) + continue; + fsroot = root; + f = fsopen("/plan9.ini"); + if(f != nil){ + if(pf != nil) + *pf = f; + else + fsclose(f); + break; + } + } + if(fsroot == nil) + return -1; + +gotit: + read = fsread; + close = fsclose; + open = fsopen; + + return 0; +} diff --git a/sys/src/nboot/efi/iso.c b/sys/src/nboot/efi/iso.c new file mode 100644 index 0000000000..6a878667b9 --- /dev/null +++ b/sys/src/nboot/efi/iso.c @@ -0,0 +1,226 @@ +#include +#include "fns.h" +#include "efi.h" + +enum { + Sectsz = 0x800, + Dirsz = 33, +}; + +typedef struct Extend Extend; +typedef struct Dir Dir; + +struct Extend +{ + ulong lba; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + uchar dirlen; + uchar extlen; + + uchar lba[8]; + uchar len[8]; + + uchar date[7]; + + uchar flags[3]; + + uchar seq[4]; + + uchar namelen; +}; + +typedef struct { + UINT32 MediaId; + + BOOLEAN RemovableMedia; + BOOLEAN MediaPresent; + BOOLEAN LogicalPartition; + BOOLEAN ReadOnly; + + BOOLEAN WriteCaching; + BOOLEAN Pad[3]; + + UINT32 BlockSize; + UINT32 IoAlign; + UINT64 LastBlock; +} EFI_BLOCK_IO_MEDIA; + +typedef struct { + UINT64 Revision; + EFI_BLOCK_IO_MEDIA *Media; + void *Reset; + void *ReadBlocks; + void *WriteBlocks; + void *FlushBlocks; +} EFI_BLOCK_IO_PROTOCOL; + +static EFI_GUID +EFI_BLOCK_IO_PROTOCOL_GUID = { + 0x964e5b21, 0x6459, 0x11d2, + 0x8e, 0x39, 0x00, 0xa0, + 0xc9, 0x69, 0x72, 0x3b, +}; + +static EFI_BLOCK_IO_PROTOCOL *bio; + +static int +readsect(ulong lba, void *buf) +{ + lba *= Sectsz/bio->Media->BlockSize; + return eficall(bio->ReadBlocks, bio, (UINTN)bio->Media->MediaId, (UINT64)lba, (UINTN)Sectsz, buf); +} + +static int +isoread(void *f, void *data, int len) +{ + Extend *ex = f; + + if(ex->len > 0 && ex->rp >= ex->ep) + if(readsect(ex->lba++, ex->rp = ex->buf)) + return -1; + if(ex->len < len) + len = ex->len; + if(len > (ex->ep - ex->rp)) + len = ex->ep - ex->rp; + memmove(data, ex->rp, len); + ex->rp += len; + ex->len -= len; + return len; +} + +void +isoclose(void *f) +{ + Extend *ex = f; + + ex->lba = 0; + ex->len = 0; + ex->rp = ex->ep = ex->buf + Sectsz; +} + +static int +isowalk(Extend *ex, char *path) +{ + char name[MAXPATH], c, *end; + int i; + Dir d; + + isoclose(ex); + + /* find pvd */ + for(i=0x10; i<0x1000; i++){ + if(readsect(i, ex->buf)) + return -1; + if(memcmp(ex->buf, "\001CD001\001", 7) == 0) + goto Foundpvd; + } + return -1; +Foundpvd: + ex->lba = *((ulong*)(ex->buf + 156 + 2)); + ex->len = *((ulong*)(ex->buf + 156 + 10)); + if(*path == 0) + return 0; + + for(;;){ + if(read(ex, &d.dirlen, 1) != 1) + break; + if(d.dirlen == 0) + continue; /* zero padding to next sector */ + if(read(ex, &d.dirlen + 1, Dirsz-1) != Dirsz-1) + break; + if(read(ex, name, d.namelen) != d.namelen) + break; + i = d.dirlen - (Dirsz + d.namelen); + while(i-- > 0){ + if(read(ex, &c, 1) != 1) + break; + } + for(i=0; i= 'A' && c <= 'Z'){ + c -= 'A'; + c += 'a'; + } + name[i] = c; + } + name[i] = 0; + while(*path == '/') + path++; + if((end = strchr(path, '/')) == 0) + end = path + strlen(path); + i = end - path; + if(d.namelen == i && memcmp(name, path, i) == 0){ + ex->rp = ex->ep; + ex->lba = *((ulong*)d.lba); + ex->len = *((ulong*)d.len); + if(*end == 0) + return 0; + else if(d.flags[0] & 2){ + path = end; + continue; + } + break; + } + } + return -1; +} + +static void* +isoopen(char *path) +{ + static uchar buf[sizeof(Extend)+8]; + Extend *ex = (Extend*)((uintptr)(buf+7)&~7); + + if(isowalk(ex, path)) + return nil; + return ex; +} + +int +isoinit(void **fp) +{ + EFI_BLOCK_IO_MEDIA *media; + EFI_HANDLE *Handles; + UINTN Count; + int i; + + bio = nil; + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_BLOCK_IO_PROTOCOL_GUID, nil, &Count, &Handles)) + return -1; + + for(i=0; iBootServices->HandleProtocol, + Handles[i], &EFI_BLOCK_IO_PROTOCOL_GUID, &bio)) + continue; + + media = bio->Media; + if(media != nil + && media->MediaPresent + && media->LogicalPartition == 0 + && media->BlockSize != 0 + && isoopen("") != nil) + goto Found; + } + return -1; + +Found: + open = isoopen; + read = isoread; + close = isoclose; + + if(fp != nil) + *fp = isoopen("/cfg/plan9.ini"); + + return 0; +} diff --git a/sys/src/nboot/efi/mem.h b/sys/src/nboot/efi/mem.h new file mode 100644 index 0000000000..18819590da --- /dev/null +++ b/sys/src/nboot/efi/mem.h @@ -0,0 +1,47 @@ +/* + * Memory and machine-specific definitions. Used in C and assembler. + */ + +/* + * Sizes + */ +#define BI2BY 8 /* bits per byte */ +#define BI2WD 32 /* bits per word */ +#define BY2WD 4 /* bytes per word */ +#define BY2PG 4096 /* bytes per page */ +#define WD2PG (BY2PG/BY2WD) /* words per page */ +#define PGSHIFT 12 /* log(BY2PG) */ +#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1)) + +/* + * Fundamental addresses + */ +#define CONFADDR 0x1200 /* info passed from boot loader */ +#define BIOSXCHG 0x6000 /* To exchange data with the BIOS */ + +#define SELGDT (0<<3) /* selector is in gdt */ +#define SELLDT (1<<3) /* selector is in ldt */ + +#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) + +/* + * fields in segment descriptors + */ +#define SEGDATA (0x10<<8) /* data/stack segment */ +#define SEGEXEC (0x18<<8) /* executable segment */ +#define SEGTSS (0x9<<8) /* TSS segment */ +#define SEGCG (0x0C<<8) /* call gate */ +#define SEGIG (0x0E<<8) /* interrupt gate */ +#define SEGTG (0x0F<<8) /* trap gate */ +#define SEGLDT (0x02<<8) /* local descriptor table */ +#define SEGTYPE (0x1F<<8) + +#define SEGP (1<<15) /* segment present */ +#define SEGPL(x) ((x)<<13) /* priority level */ +#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ +#define SEGD (1<<22) /* default 1==32bit (for code) */ +#define SEGE (1<<10) /* expand down */ +#define SEGW (1<<9) /* writable (for data/stack) */ +#define SEGR (1<<9) /* readable (for code) */ +#define SEGL (1<<21) /* 64 bit */ +#define SEGG (1<<23) /* granularity 1==4k (for other) */ diff --git a/sys/src/nboot/efi/mkfile b/sys/src/nboot/efi/mkfile new file mode 100644 index 0000000000..b19754d76e --- /dev/null +++ b/sys/src/nboot/efi/mkfile @@ -0,0 +1,105 @@ +TARG=bootia32.efi bootx64.efi efiboot.fat +HFILES=fns.h mem.h +IMAGEBASE=0x8000 +CFLAGS=-FTVw +PEFLAGS=$CFLAGS '-DIMAGEBASE='$IMAGEBASE + +all:V: $TARG + +install:V: $TARG + cp $prereq /386 + +bootia32.efi: pe32.8 efi.8 fs.8 pxe.8 iso.8 sub.8 + 8l -l -H3 -T$IMAGEBASE -o $target $prereq + +pe32.8: pe32.s + 8a $PEFLAGS pe32.s + +efi.8: efi.c efi.h + 8c $CFLAGS efi.c + +fs.8: fs.c efi.h + 8c $CFLAGS fs.c + +pxe.8: pxe.c efi.h + 8c $CFLAGS pxe.c + +iso.8: iso.c efi.h + 8c $CFLAGS iso.c + +sub.8: sub.c + 8c $CFLAGS sub.c + +%.8: $HFILES + + +bootx64.efi: pe64.6 efi.6 fs.6 pxe.6 iso.6 sub.6 + 6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq + dd -if bootx64.out -bs 1 -iseek 40 >$target + +pe64.6: pe64.s + 6a $PEFLAGS pe64.s + +efi.6: efi.c efi.h + 6c $CFLAGS efi.c + +fs.6: fs.c efi.h + 6c $CFLAGS fs.c + +pxe.6: pxe.c efi.h + 6c $CFLAGS pxe.c + +iso.6: iso.c efi.h + 6c $CFLAGS iso.c + +sub.6: sub.c + 6c $CFLAGS sub.c + +%.6: $HFILES + +efiboot.fat:D: bootia32.efi bootx64.efi + s = $target.$pid + rm -f $target + dd -if /dev/zero -of $target -bs 1024 -count 1024 + disk/format -xd -t hard $target + dossrv -f $target $s + mount -c /srv/$s /n/esp + mkdir /n/esp/efi + mkdir /n/esp/efi/boot + cp bootia32.efi /n/esp/efi/boot + cp bootx64.efi /n/esp/efi/boot + unmount /n/esp + rm /srv/$s + + +test.iso:D: efiboot.fat + rm -fr tmp + mkdir tmp + mkdir tmp/cfg + mkdir tmp/386 + cp efiboot.fat tmp/386 + cp /386/9bootiso tmp/386 + cp /386/9pc tmp/386 + echo 'bootfile=/386/9pc' >tmp/cfg/plan9.ini + disk/mk9660 -B 386/9bootiso -E 386/efiboot.fat -p <{echo +} -s tmp $target + rm -r tmp + +test.fat:D: bootia32.efi bootx64.efi + s = $target.$pid + rm -f $target + dd -if /dev/zero -of $target -bs 65536 -count 128 + disk/format -xd -t hard $target + dossrv -f $target $s + mount -c /srv/$s /n/esp + mkdir /n/esp/efi + mkdir /n/esp/efi/boot + cp bootia32.efi /n/esp/efi/boot + cp bootx64.efi /n/esp/efi/boot + cp /386/9pc /n/esp + echo 'bootfile=9pc' >/n/esp/plan9.ini + unmount /n/esp + rm /srv/$s + + +clean:V: + rm -f *.[68] *.out $TARG test.* diff --git a/sys/src/nboot/efi/pe32.s b/sys/src/nboot/efi/pe32.s new file mode 100644 index 0000000000..35891db1b6 --- /dev/null +++ b/sys/src/nboot/efi/pe32.s @@ -0,0 +1,159 @@ +TEXT mzhdr(SB), 1, $0 + BYTE $'M'; BYTE $'Z' + + WORD $0 /* e_cblp UNUSED */ + WORD $0 /* e_cp UNUSED */ + WORD $0 /* e_crlc UNUSED */ + WORD $0 /* e_cparhdr UNUSED */ + WORD $0 /* e_minalloc UNUSED */ + WORD $0 /* e_maxalloc UNUSED */ + WORD $0 /* e_ss UNUSED */ + WORD $0 /* e_sp UNUSED */ + WORD $0 /* e_csum UNUSED */ + WORD $0 /* e_ip UNUSED */ + WORD $0 /* e_cs UNUSED */ + WORD $0 /* e_lsarlc UNUSED */ + WORD $0 /* e_ovno UNUSED */ + + WORD $0 /* e_res UNUSED */ + WORD $0 + WORD $0 + WORD $0 + WORD $0 + + WORD $0 /* e_oemid UNUSED */ + + WORD $0 /* e_res2 UNUSED */ + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + + LONG $pehdr-IMAGEBASE(SB) /* offset to pe header */ + +TEXT pehdr(SB), 1, $0 + BYTE $'P'; BYTE $'E'; BYTE $0; BYTE $0 + + WORD $0x014C /* Machine (Intel 386) */ + WORD $1 /* NumberOfSections */ + LONG $0 /* TimeDateStamp UNUSED */ + LONG $0 /* PointerToSymbolTable UNUSED */ + LONG $0 /* NumberOfSymbols UNUSED */ + WORD $0xE0 /* SizeOfOptionalHeader */ + WORD $2103 /* Characteristics (no relocations, executable, 32 bit) */ + + WORD $0x10B /* Magic (PE32) */ + BYTE $9 /* MajorLinkerVersion UNUSED */ + BYTE $0 /* MinorLinkerVersion UNUSED */ + LONG $0 /* SizeOfCode UNUSED */ + LONG $0 /* SizeOfInitializedData UNUSED */ + LONG $0 /* SizeOfUninitializedData UNUSED */ + LONG $start-IMAGEBASE(SB)/* AddressOfEntryPoint */ + LONG $0 /* BaseOfCode UNUSED */ + LONG $0 /* BaseOfData UNUSED */ + LONG $IMAGEBASE /* ImageBase */ + LONG $0x200 /* SectionAlignment */ + LONG $0x200 /* FileAlignment */ + WORD $4 /* MajorOperatingSystemVersion UNUSED */ + WORD $0 /* MinorOperatingSystemVersion UNUSED */ + WORD $0 /* MajorImageVersion UNUSED */ + WORD $0 /* MinorImageVersion UNUSED */ + WORD $4 /* MajorSubsystemVersion */ + WORD $0 /* MinorSubsystemVersion UNUSED */ + LONG $0 /* Win32VersionValue UNUSED */ + LONG $end-IMAGEBASE(SB) /* SizeOfImage */ + LONG $start-IMAGEBASE(SB)/* SizeOfHeaders */ + LONG $0 /* CheckSum UNUSED */ + WORD $10 /* Subsystem (10 = efi application) */ + WORD $0 /* DllCharacteristics UNUSED */ + LONG $0 /* SizeOfStackReserve UNUSED */ + LONG $0 /* SizeOfStackCommit UNUSED */ + LONG $0 /* SizeOfHeapReserve UNUSED */ + LONG $0 /* SizeOfHeapCommit UNUSED */ + LONG $0 /* LoaderFlags UNUSED */ + LONG $16 /* NumberOfRvaAndSizes UNUSED */ + + LONG $0; LONG $0 + LONG $0; LONG $0 + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + + BYTE $'.'; BYTE $'t'; BYTE $'e'; BYTE $'x' + BYTE $'t'; BYTE $0; BYTE $0; BYTE $0 + LONG $edata-(IMAGEBASE+0x200)(SB) /* VirtualSize */ + LONG $start-IMAGEBASE(SB) /* VirtualAddress */ + LONG $edata-(IMAGEBASE+0x200)(SB) /* SizeOfData */ + LONG $start-IMAGEBASE(SB) /* PointerToRawData */ + LONG $0 /* PointerToRelocations UNUSED */ + LONG $0 /* PointerToLinenumbers UNUSED */ + WORD $0 /* NumberOfRelocations UNUSED */ + WORD $0 /* NumberOfLinenumbers UNUSED */ + LONG $0x86000020 /* Characteristics (code, execute, read, write) */ + + /* padding to get start(SB) at IMAGEBASE+0x200 */ + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + +TEXT start(SB), 1, $0 + CALL reloc(SP) + +TEXT reloc(SB), 1, $0 + MOVL 0(SP), SI + SUBL $reloc-IMAGEBASE(SB), SI + MOVL $IMAGEBASE, DI + MOVL $edata-IMAGEBASE(SB), CX + CLD + REP; MOVSB + MOVL $efimain(SB), DI + MOVL DI, (SP) + RET + +TEXT jump(SB), $0 + CLI + MOVL 4(SP), AX + JMP *AX + +TEXT eficall(SB), 1, $0 + MOVL SP, SI + MOVL SP, DI + MOVL $(4*16), CX + SUBL CX, DI + ANDL $~15ULL, DI + SUBL $8, DI + + MOVL 4(SI), AX + LEAL 8(DI), SP + + CLD + REP; MOVSB + SUBL $(4*16), SI + + CALL AX + + MOVL SI, SP + RET diff --git a/sys/src/nboot/efi/pe64.s b/sys/src/nboot/efi/pe64.s new file mode 100644 index 0000000000..a2a3d12398 --- /dev/null +++ b/sys/src/nboot/efi/pe64.s @@ -0,0 +1,237 @@ +TEXT mzhdr(SB), 1, $0 + BYTE $'M'; BYTE $'Z' + + WORD $0 /* e_cblp UNUSED */ + WORD $0 /* e_cp UNUSED */ + WORD $0 /* e_crlc UNUSED */ + WORD $0 /* e_cparhdr UNUSED */ + WORD $0 /* e_minalloc UNUSED */ + WORD $0 /* e_maxalloc UNUSED */ + WORD $0 /* e_ss UNUSED */ + WORD $0 /* e_sp UNUSED */ + WORD $0 /* e_csum UNUSED */ + WORD $0 /* e_ip UNUSED */ + WORD $0 /* e_cs UNUSED */ + WORD $0 /* e_lsarlc UNUSED */ + WORD $0 /* e_ovno UNUSED */ + + WORD $0 /* e_res UNUSED */ + WORD $0 + WORD $0 + WORD $0 + WORD $0 + + WORD $0 /* e_oemid UNUSED */ + + WORD $0 /* e_res2 UNUSED */ + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + WORD $0 + + LONG $pehdr-IMAGEBASE(SB) /* offset to pe header */ + +TEXT pehdr(SB), 1, $0 + BYTE $'P'; BYTE $'E'; BYTE $0; BYTE $0 + + WORD $0x8664 /* Machine (AMD64) */ + WORD $1 /* NumberOfSections */ + LONG $0 /* TimeDateStamp UNUSED */ + LONG $0 /* PointerToSymbolTable UNUSED */ + LONG $0 /* NumberOfSymbols UNUSED */ + WORD $0xF0 /* SizeOfOptionalHeader */ + WORD $2223 /* Characteristics */ + + WORD $0x20B /* Magic (PE32+) */ + BYTE $9 /* MajorLinkerVersion UNUSED */ + BYTE $0 /* MinorLinkerVersion UNUSED */ + LONG $0 /* SizeOfCode UNUSED */ + LONG $0 /* SizeOfInitializedData UNUSED */ + LONG $0 /* SizeOfUninitializedData UNUSED */ + LONG $start-IMAGEBASE(SB)/* AddressOfEntryPoint */ + LONG $0 /* BaseOfCode UNUSED */ + + QUAD $IMAGEBASE /* ImageBase */ + LONG $0x200 /* SectionAlignment */ + LONG $0x200 /* FileAlignment */ + WORD $4 /* MajorOperatingSystemVersion UNUSED */ + WORD $0 /* MinorOperatingSystemVersion UNUSED */ + WORD $0 /* MajorImageVersion UNUSED */ + WORD $0 /* MinorImageVersion UNUSED */ + WORD $4 /* MajorSubsystemVersion */ + WORD $0 /* MinorSubsystemVersion UNUSED */ + LONG $0 /* Win32VersionValue UNUSED */ + LONG $end-IMAGEBASE(SB) /* SizeOfImage */ + LONG $start-IMAGEBASE(SB)/* SizeOfHeaders */ + LONG $0 /* CheckSum UNUSED */ + WORD $10 /* Subsystem (10 = efi application) */ + WORD $0 /* DllCharacteristics UNUSED */ + QUAD $0 /* SizeOfStackReserve UNUSED */ + QUAD $0 /* SizeOfStackCommit UNUSED */ + QUAD $0 /* SizeOfHeapReserve UNUSED */ + QUAD $0 /* SizeOfHeapCommit UNUSED */ + LONG $0 /* LoaderFlags UNUSED */ + LONG $16 /* NumberOfRvaAndSizes UNUSED */ + + LONG $0; LONG $0 + LONG $0; LONG $0 + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + LONG $0; LONG $0 /* RVA */ + + BYTE $'.'; BYTE $'t'; BYTE $'e'; BYTE $'x' + BYTE $'t'; BYTE $0; BYTE $0; BYTE $0 + LONG $edata-(IMAGEBASE+0x200)(SB) /* VirtualSize */ + LONG $start-IMAGEBASE(SB) /* VirtualAddress */ + LONG $edata-(IMAGEBASE+0x200)(SB) /* SizeOfData */ + LONG $start-IMAGEBASE(SB) /* PointerToRawData */ + LONG $0 /* PointerToRelocations UNUSED */ + LONG $0 /* PointerToLinenumbers UNUSED */ + WORD $0 /* NumberOfRelocations UNUSED */ + WORD $0 /* NumberOfLinenumbers UNUSED */ + LONG $0x86000020 /* Characteristics (code, execute, read, write) */ + + /* padding to get start(SB) at IMAGEBASE+0x200 */ + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0; + LONG $0; LONG $0; LONG $0; LONG $0 + +MODE $64 + +TEXT start(SB), 1, $-4 + /* spill arguments */ + MOVQ CX, 8(SP) + MOVQ DX, 16(SP) + + CALL reloc(SP) + +TEXT reloc(SB), 1, $-4 + MOVQ 0(SP), SI + SUBQ $reloc-IMAGEBASE(SB), SI + MOVQ $IMAGEBASE, DI + MOVQ $edata-IMAGEBASE(SB), CX + CLD + REP; MOVSB + + MOVQ 16(SP), BP + MOVQ $efimain(SB), DI + MOVQ DI, (SP) + RET + +TEXT eficall(SB), 1, $-4 + MOVQ SP, SI + MOVQ SP, DI + MOVL $(8*16), CX + SUBQ CX, DI + ANDQ $~15ULL, DI + LEAQ 16(DI), SP + CLD + REP; MOVSB + SUBQ $(8*16), SI + + MOVQ 0(SP), CX + MOVQ 8(SP), DX + MOVQ 16(SP), R8 + MOVQ 24(SP), R9 + CALL BP + + MOVQ SI, SP + RET + +#include "mem.h" + +TEXT jump(SB), 1, $-4 + CLI + + /* load zero length idt */ + MOVL $_idtptr64p<>(SB), AX + MOVL (AX), IDTR + + /* load temporary gdt */ + MOVL $_gdtptr64p<>(SB), AX + MOVL (AX), GDTR + + /* load CS with 32bit code segment */ + PUSHQ $SELECTOR(3, SELGDT, 0) + PUSHQ $_warp32<>(SB) + RETFQ + +MODE $32 + +TEXT _warp32<>(SB), 1, $-4 + + /* load 32bit data segments */ + MOVL $SELECTOR(2, SELGDT, 0), AX + MOVW AX, DS + MOVW AX, ES + MOVW AX, FS + MOVW AX, GS + MOVW AX, SS + + /* turn off paging */ + MOVL CR0, AX + ANDL $0x7fffffff, AX /* ~(PG) */ + MOVL AX, CR0 + + MOVL $0, AX + MOVL AX, CR3 + + /* disable long mode */ + MOVL $0xc0000080, CX /* Extended Feature Enable */ + RDMSR + ANDL $0xfffffeff, AX /* Long Mode Disable */ + WRMSR + + /* diable pae */ + MOVL CR4, AX + ANDL $0xffffff5f, AX /* ~(PAE|PGE) */ + MOVL AX, CR4 + + JMP *BP + +TEXT _gdt<>(SB), 1, $-4 + /* null descriptor */ + LONG $0 + LONG $0 + + /* (KESEG) 64 bit long mode exec segment */ + LONG $(0xFFFF) + LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR) + + /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */ + LONG $(0xFFFF) + LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) + + /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */ + LONG $(0xFFFF) + LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + +TEXT _gdtptr64p<>(SB), 1, $-4 + WORD $(4*8-1) + QUAD $_gdt<>(SB) + +TEXT _idtptr64p<>(SB), 1, $-4 + WORD $0 + QUAD $0 diff --git a/sys/src/nboot/efi/pxe.c b/sys/src/nboot/efi/pxe.c new file mode 100644 index 0000000000..5c99935030 --- /dev/null +++ b/sys/src/nboot/efi/pxe.c @@ -0,0 +1,487 @@ +#include +#include "fns.h" +#include "efi.h" + +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + + UINT8 TTL; + UINT8 ToS; + + UINT8 Reserved; + + UINT8 StationIp[16]; + UINT8 SubnetMask[16]; + + UINT8 DhcpDiscover[1472]; + UINT8 DhcpAck[1472]; + UINT8 ProxyOffer[1472]; + UINT8 PxeDiscover[1472]; + UINT8 PxeReply[1472]; + UINT8 PxeBisReply[1472]; + +} EFI_PXE_BASE_CODE_MODE; + +typedef struct { + UINT64 Revision; + void *Start; + void *Stop; + void *Dhcp; + void *Discover; + void *Mtftp; + void *UdpWrite; + void *UdpRead; + void *SetIpFilter; + void *Arp; + void *SetParameters; + void *SetStationIp; + void *SetPackets; + EFI_PXE_BASE_CODE_MODE *Mode; +} EFI_PXE_BASE_CODE_PROTOCOL; + + +enum { + Tftp_READ = 1, + Tftp_WRITE = 2, + Tftp_DATA = 3, + Tftp_ACK = 4, + Tftp_ERROR = 5, + Tftp_OACK = 6, + + TftpPort = 69, + + Segsize = 512, +}; + +static +EFI_GUID EFI_PXE_BASE_CODE_PROTOCOL_GUID = { + 0x03C4E603, 0xAC28, 0x11D3, + 0x9A, 0x2D, 0x00, 0x90, + 0x27, 0x3F, 0xC1, 0x4D, +}; + +static +EFI_PXE_BASE_CODE_PROTOCOL *pxe; + +static uchar mymac[6]; +static uchar myip[16]; +static uchar serverip[16]; + +typedef struct Tftp Tftp; +struct Tftp +{ + EFI_IP_ADDRESS sip; + EFI_IP_ADDRESS dip; + + EFI_PXE_BASE_CODE_UDP_PORT sport; + EFI_PXE_BASE_CODE_UDP_PORT dport; + + char *rp; + char *ep; + + int seq; + int eof; + + char pkt[2+2+Segsize]; + char nul; +}; + +static void +puts(void *x, ushort v) +{ + uchar *p = x; + + p[1] = (v>>8) & 0xFF; + p[0] = v & 0xFF; +} + +static ushort +gets(void *x) +{ + uchar *p = x; + + return p[1]<<8 | p[0]; +} + +static void +hnputs(void *x, ushort v) +{ + uchar *p = x; + + p[0] = (v>>8) & 0xFF; + p[1] = v & 0xFF; +} + +static ushort +nhgets(void *x) +{ + uchar *p = x; + + return p[0]<<8 | p[1]; +} + +enum { + ANY_SRC_IP = 0x0001, + ANY_SRC_PORT = 0x0002, + ANY_DEST_IP = 0x0004, + ANY_DEST_PORT = 0x0008, + USE_FILTER = 0x0010, + MAY_FRAGMENT = 0x0020, +}; + +static int +udpread(EFI_IP_ADDRESS *sip, EFI_IP_ADDRESS *dip, + EFI_PXE_BASE_CODE_UDP_PORT *sport, + EFI_PXE_BASE_CODE_UDP_PORT dport, + int *len, void *data) +{ + UINTN size; + + size = *len; + if(eficall(pxe->UdpRead, pxe, (UINTN)ANY_SRC_PORT, dip, &dport, sip, sport, nil, nil, &size, data)) + return -1; + + *len = size; + return 0; +} + +static int +udpwrite(EFI_IP_ADDRESS *dip, + EFI_PXE_BASE_CODE_UDP_PORT sport, + EFI_PXE_BASE_CODE_UDP_PORT dport, + int len, void *data) +{ + UINTN size; + + size = len; + if(eficall(pxe->UdpWrite, pxe, (UINTN)MAY_FRAGMENT, dip, &dport, nil, nil, &sport, nil, nil, &size, data)) + return -1; + + return 0; +} + +static int +pxeread(void *f, void *data, int len) +{ + Tftp *t = f; + int seq, n; + + while(!t->eof && t->rp >= t->ep){ + for(;;){ + n = sizeof(t->pkt); + if(udpread(&t->dip, &t->sip, &t->dport, t->sport, &n, t->pkt)) + continue; + if(n >= 4) + break; + } + switch(nhgets(t->pkt)){ + case Tftp_DATA: + seq = nhgets(t->pkt+2); + if(seq > t->seq){ + putc('?'); + continue; + } + hnputs(t->pkt, Tftp_ACK); + while(udpwrite(&t->dip, t->sport, t->dport, 4, t->pkt)) + putc('!'); + if(seq < t->seq){ + putc('@'); + continue; + } + t->seq = seq+1; + n -= 4; + t->rp = t->pkt + 4; + t->ep = t->rp + n; + t->eof = n < Segsize; + break; + case Tftp_ERROR: + print(t->pkt+4); + print("\n"); + default: + t->eof = 1; + return -1; + } + break; + } + n = t->ep - t->rp; + if(len > n) + len = n; + memmove(data, t->rp, len); + t->rp += len; + return len; +} + +static void +pxeclose(void *f) +{ + Tftp *t = f; + t->eof = 1; +} + + +static int +tftpopen(Tftp *t, char *path) +{ + static EFI_PXE_BASE_CODE_UDP_PORT xport = 6666; + int r, n; + char *p; + + t->sport = xport++; + t->dport = 0; + t->rp = t->ep = 0; + t->seq = 1; + t->eof = 0; + t->nul = 0; + p = t->pkt; + hnputs(p, Tftp_READ); p += 2; + n = strlen(path)+1; + memmove(p, path, n); p += n; + memmove(p, "octet", 6); p += 6; + n = p - t->pkt; + for(;;){ + if(r = udpwrite(&t->dip, t->sport, TftpPort, n, t->pkt)) + break; + if(r = pxeread(t, 0, 0)) + break; + return 0; + } + pxeclose(t); + return r; +} + +static void* +pxeopen(char *name) +{ + static uchar buf[sizeof(Tftp)+8]; + Tftp *t = (Tftp*)((uintptr)(buf+7)&~7); + + memset(t, 0, sizeof(Tftp)); + memmove(&t->sip, myip, sizeof(myip)); + memmove(&t->dip, serverip, sizeof(serverip)); + if(tftpopen(t, name)) + return nil; + return t; +} + +static int +parseipv6(uchar to[16], char *from) +{ + int i, dig, elipsis; + char *p; + + elipsis = 0; + memset(to, 0, 16); + for(i = 0; i < 16; i += 2){ + dig = 0; + for(p = from;; p++){ + if(*p >= '0' && *p <= '9') + dig = (dig << 4) | (*p - '0'); + else if(*p >= 'a' && *p <= 'f') + dig = (dig << 4) | (*p - 'a'+10); + else if(*p >= 'A' && *p <= 'F') + dig = (dig << 4) | (*p - 'A'+10); + else + break; + if(dig > 0xFFFF) + return -1; + } + to[i] = dig>>8; + to[i+1] = dig; + if(*p == ':'){ + if(*++p == ':'){ /* :: is elided zero short(s) */ + if (elipsis) + return -1; /* second :: */ + elipsis = i+2; + p++; + } + } else if (p == from) + break; + from = p; + } + if(i < 16){ + memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis); + memset(&to[elipsis], 0, 16-i); + } + return 0; +} + +static void +parsedhcp(EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp) +{ + uchar *p, *e; + char *x; + int opt; + int len; + uint type; + + memset(mymac, 0, sizeof(mymac)); + memset(serverip, 0, sizeof(serverip)); + + /* DHCPv4 */ + if(pxe->Mode->UsingIpv6 == 0){ + memmove(mymac, dhcp->BootpHwAddr, 6); + memmove(serverip, dhcp->BootpSiAddr, 4); + return; + } + + /* DHCPv6 */ + + /* + * some UEFI implementations use random UUID based DUID instead of + * ethernet address, but use ethernet derived link-local addresses. + * so extract the MAC from our IPv6 address as a fallback. + */ + p = pxe->Mode->StationIp; + mymac[0] = p[8] ^ 2; + mymac[1] = p[9]; + mymac[2] = p[10]; + mymac[3] = p[13]; + mymac[4] = p[14]; + mymac[5] = p[15]; + + e = (uchar*)dhcp + sizeof(*dhcp); + p = (uchar*)dhcp + 4; + while(p+4 <= e){ + opt = p[0]<<8 | p[1]; + len = p[2]<<8 | p[3]; + p += 4; + if(p + len > e) + break; + switch(opt){ + case 1: /* Client DUID */ + if(len < 4+6) + break; + type = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]; + switch(type){ + case 0x00010001: + case 0x00030001: + memmove(mymac, p+len-6, 6); + break; + } + break; + case 59: /* Boot File URL */ + for(x = (char*)p; x < (char*)p+len; x++){ + if(*x == '['){ + parseipv6(serverip, x+1); + break; + } + } + break; + } + p += len; + } +} + +int +pxeinit(void **pf) +{ + EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp; + EFI_PXE_BASE_CODE_MODE *mode; + EFI_HANDLE *Handles; + UINTN Count; + int i; + + pxe = nil; + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_PXE_BASE_CODE_PROTOCOL_GUID, nil, &Count, &Handles)) + return -1; + + for(i=0; iBootServices->HandleProtocol, + Handles[i], &EFI_PXE_BASE_CODE_PROTOCOL_GUID, &pxe)) + continue; + mode = pxe->Mode; + if(mode == nil || mode->Started == 0) + continue; + if(mode->DhcpAckReceived){ + dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)mode->DhcpAck; + goto Found; + } + if(mode->PxeReplyReceived){ + dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)mode->PxeReply; + goto Found; + } + } + return -1; + +Found: + parsedhcp(dhcp); + memmove(myip, mode->StationIp, 16); + + open = pxeopen; + read = pxeread; + close = pxeclose; + + if(pf != nil){ + char ini[24]; + + memmove(ini, "/cfg/pxe/", 9); + for(i=0; i<6; i++){ + ini[9+i*2+0] = hex[mymac[i] >> 4]; + ini[9+i*2+1] = hex[mymac[i] & 0xF]; + } + ini[9+12] = '\0'; + if((*pf = pxeopen(ini)) == nil) + *pf = pxeopen("/cfg/pxe/default"); + } + + return 0; +} diff --git a/sys/src/nboot/efi/sub.c b/sys/src/nboot/efi/sub.c new file mode 100644 index 0000000000..8e73c361fc --- /dev/null +++ b/sys/src/nboot/efi/sub.c @@ -0,0 +1,373 @@ +#include +#include +#include "fns.h" +#include "mem.h" + +char hex[] = "0123456789abcdef"; + +void +print(char *s) +{ + while(*s != 0){ + if(*s == '\n') + putc('\r'); + putc(*s++); + } +} + +int +readn(void *f, void *data, int len) +{ + uchar *p, *e; + + p = data; + e = p + len; + while(p < e){ + if((len = read(f, p, e - p)) <= 0) + break; + p += len; + } + + return p - (uchar*)data; +} + +void +memmove(void *dst, void *src, int n) +{ + uchar *d = dst; + uchar *s = src; + + if(d < s){ + while(n-- > 0) + *d++ = *s++; + } else if(d > s){ + s += n; + d += n; + while(n-- > 0) + *--d = *--s; + } +} + +int +memcmp(void *src, void *dst, int n) +{ + uchar *d = dst; + uchar *s = src; + int r = 0; + + while(n-- > 0){ + r = *d++ - *s++; + if(r != 0) + break; + } + + return r; +} + +int +strlen(char *s) +{ + char *p = s; + + while(*p != '\0') + p++; + + return p - s; +} + +char* +strchr(char *s, int c) +{ + for(; *s != 0; s++) + if(*s == c) + return s; + + return nil; +} + +void +memset(void *dst, int v, int n) +{ + uchar *d = dst; + + while(n > 0){ + *d++ = v; + n--; + } +} + +static int +readline(void *f, char *buf) +{ + static char white[] = "\t "; + char *p; + + p = buf; + do{ + if(f == nil) + putc('>'); + for(;;){ + if(f == nil){ + while((*p = getc()) == 0) + ; + if(p == buf && (*p == '\b' || strchr(white, *p) != nil)) + continue; + putc(*p); + if(*p == '\r') + putc('\n'); + else if(*p == '\b'){ + p--; + putc(' '); + putc('\b'); + continue; + } + }else if(read(f, p, 1) <= 0) + return 0; + if(strchr("\r\n", *p) != nil) + break; + if(p == buf && strchr(white, *p) != nil) + continue; /* whitespace on start of line */ + p++; + } + while(p > buf && strchr(white, p[-1])) + p--; + }while(p == buf); + *p = 0; + + return p - buf; +} + +static int +timeout(int ms) +{ + while(ms > 0){ + if(getc() != 0) + return 1; + usleep(100000); + ms -= 100; + } + return 0; +} + +#define BOOTLINE ((char*)CONFADDR) +#define BOOTLINELEN 64 +#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN)) +#define BOOTARGSLEN (4096-0x200-BOOTLINELEN) + +char *confend; + +static char* +getconf(char *s, char *buf) +{ + char *p, *e; + int n; + + n = strlen(s); + for(p = BOOTARGS; p < confend; p = e+1){ + for(e = p+1; e < confend; e++) + if(*e == '\n') + break; + if(memcmp(p, s, n) == 0){ + p += n; + n = e - p; + buf[n] = 0; + memmove(buf, p, n); + return buf; + } + } + return nil; +} + +static int +delconf(char *s) +{ + char *p, *e; + + for(p = BOOTARGS; p < confend; p = e){ + for(e = p+1; e < confend; e++){ + if(*e == '\n'){ + e++; + break; + } + } + if(memcmp(p, s, strlen(s)) == 0){ + memmove(p, e, confend - e); + confend -= e - p; + *confend = 0; + return 1; + } + } + return 0; +} + +char* +configure(void *f, char *path) +{ + char *line, *kern, *s, *p; + int inblock, nowait, n; + static int once = 1; + + if(once){ + once = 0; +Clear: + memset(BOOTLINE, 0, BOOTLINELEN); + + confend = BOOTARGS; + memset(confend, 0, BOOTARGSLEN); + eficonfig(&confend); + } + nowait = 1; + inblock = 0; +Loop: + while(readline(f, line = confend+1) > 0){ + if(*line == 0 || strchr("#;=", *line) != nil) + continue; + if(*line == '['){ + inblock = memcmp("[common]", line, 8) != 0; + continue; + } + if(memcmp("boot", line, 5) == 0){ + nowait=1; + break; + } + if(memcmp("wait", line, 5) == 0){ + nowait=0; + continue; + } + if(memcmp("show", line, 5) == 0){ + print(BOOTARGS); + continue; + } + if(memcmp("clear", line, 5) == 0){ + if(line[5] == '\0'){ + print("ok\n"); + goto Clear; + } else if(line[5] == ' ' && delconf(line+6)) + print("ok\n"); + continue; + } + if(inblock != 0 || (p = strchr(line, '=')) == nil) + continue; + *p++ = 0; + delconf(line); + s = confend; + memmove(confend, line, n = strlen(line)); confend += n; + *confend++ = '='; + memmove(confend, p, n = strlen(p)); confend += n; + *confend++ = '\n'; + *confend = 0; + print(s); + } + kern = getconf("bootfile=", path); + + if(f != nil){ + close(f); + f = nil; + + if(kern != nil && (nowait==0 || timeout(1000))) + goto Loop; + } + + if(kern == nil){ + print("no bootfile\n"); + goto Loop; + } + while((p = strchr(kern, '!')) != nil) + kern = p+1; + + return kern; +} + +static char* +numfmt(char *s, ulong b, ulong i, ulong a) +{ + char *r; + + if(i == 0){ + ulong v = a; + while(v != 0){ + v /= b; + i++; + } + if(i == 0) + i = 1; + } + + s += i; + r = s; + while(i > 0){ + *--s = hex[a % b]; + a /= b; + i--; + } + return r; +} + +char* +hexfmt(char *s, int i, uvlong a) +{ + if(i > 8 || i == 0 && (a>>32) != 0){ + s = numfmt(s, 16, i ? i-8 : 0, a>>32); + i = 8; + } + return numfmt(s, 16, i, a); +} + +char* +decfmt(char *s, int i, ulong a) +{ + return numfmt(s, 10, i, a); +} + +static ulong +beswal(ulong l) +{ + uchar *p = (uchar*)&l; + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} + +char* +bootkern(void *f) +{ + uchar *e, *d, *t; + ulong n; + Exec ex; + + if(readn(f, &ex, sizeof(ex)) != sizeof(ex)) + return "bad header"; + + e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL); + switch(beswal(ex.magic)){ + case S_MAGIC: + if(readn(f, e, 8) != 8) + goto Error; + case I_MAGIC: + break; + default: + return "bad magic"; + } + + t = e; + n = beswal(ex.text); + if(readn(f, t, n) != n) + goto Error; + t += n; + d = (uchar*)PGROUND((uintptr)t); + memset(t, 0, d - t); + n = beswal(ex.data); + if(readn(f, d, n) != n) + goto Error; + d += n; + t = (uchar*)PGROUND((uintptr)d); + t += PGROUND(beswal(ex.bss)); + memset(d, 0, t - d); + + close(f); + print("boot\n"); + unload(); + + jump(e); + +Error: + return "i/o error"; +} diff --git a/sys/src/nboot/mkfile b/sys/src/nboot/mkfile new file mode 100644 index 0000000000..384bc9f285 --- /dev/null +++ b/sys/src/nboot/mkfile @@ -0,0 +1,23 @@ +ARCH=\ + bitsy\ + efi\ + pc\ + zynq\ + +all:V: + for(i in $ARCH)@{ + cd $i + mk + } + +installall install:V: + for(i in $ARCH) @{ + cd $i + mk install + } + +clean:V: + for(i in $ARCH) @{ + cd $i + mk clean + } diff --git a/sys/src/nboot/pc/a20.s b/sys/src/nboot/pc/a20.s new file mode 100644 index 0000000000..70933110e6 --- /dev/null +++ b/sys/src/nboot/pc/a20.s @@ -0,0 +1,84 @@ +#include "x16.h" + +#undef ORB + +TEXT a20test(SB), $0 + LONG $1234567 + +TEXT a20check(SB), $0 + MOVL $10000, CX +_loop: + LEAL a20test(SB), AX + MOVL (AX), BX + ADDL $12345, BX + MOVL BX, (AX) + ORL $(1<<20), AX + MOVL (AX), AX + CMPL AX, BX + JNZ _done + LOOP _loop + RET +_done: + /* return directly to caller of a20() */ + ADDL $4, SP + XORL AX, AX + RET + +TEXT a20(SB), $0 + CALL a20check(SB) + + /* try bios */ + CALL rmode16(SB) + STI + LWI(0x2401, rAX) + BIOSCALL(0x15) + CALL16(pmode32(SB)) + + CALL a20check(SB) + + /* try fast a20 */ + MOVL $0x92, DX + INB + TESTB $2, AL + JNZ _no92 + ORB $2, AL + ANDB $0xfe, AL + OUTB +_no92: + CALL a20check(SB) + + /* try keyboard */ + CALL kbdempty(SB) + MOVL $0x64, DX + MOVB $0xd1, AL /* command write */ + OUTB + CALL kbdempty(SB) + MOVL $0x60, DX + MOVB $0xdf, AL /* a20 on */ + OUTB + CALL kbdempty(SB) + MOVL $0x64, DX + MOVB $0xff, AL /* magic */ + OUTB + CALL kbdempty(SB) + + CALL a20check(SB) + + /* fail */ + XORL AX, AX + DECL AX + RET + +TEXT kbdempty(SB), $0 +_kbdwait: + MOVL $0x64, DX + INB + TESTB $1, AL + JZ _kbdempty + MOVL $0x60, DX + INB + JMP _kbdwait +_kbdempty: + TESTB $2, AL + JNZ _kbdwait + RET diff --git a/sys/src/nboot/pc/apm.s b/sys/src/nboot/pc/apm.s new file mode 100644 index 0000000000..b6a9104b1a --- /dev/null +++ b/sys/src/nboot/pc/apm.s @@ -0,0 +1,51 @@ +#include "x16.h" +#include "mem.h" + +TEXT apm(SB), $0 + MOVL id+4(SP), BX + CALL rmode16(SB) + + PUSHR(rBX) + LWI(0x5300, rAX) + BIOSCALL(0x15) + POPR(rBX) + JC noapm + + PUSHR(rBX) + LWI(0x5304, rAX) + BIOSCALL(0x15) + POPR(rBX) + CLC + + /* connect */ + LWI(0x5303, rAX) + BIOSCALL(0x15) + JC noapm + + OPSIZE; PUSHR(rSI) + OPSIZE; PUSHR(rBX) + PUSHR(rDI) + PUSHR(rDX) + PUSHR(rCX) + PUSHR(rAX) + + LWI(CONFADDR, rDI) + + /* + * write APM data. first four bytes are APM\0. + */ + LWI(0x5041, rAX) + STOSW + + LWI(0x004d, rAX) + STOSW + + LWI(8, rCX) +apmmove: + POPR(rAX) + STOSW + LOOP apmmove + +noapm: + CALL16(pmode32(SB)) + RET diff --git a/sys/src/nboot/pc/e820.s b/sys/src/nboot/pc/e820.s new file mode 100644 index 0000000000..370861c9f3 --- /dev/null +++ b/sys/src/nboot/pc/e820.s @@ -0,0 +1,32 @@ +#include "x16.h" +#include "mem.h" + +TEXT e820(SB), $0 + MOVL bx+4(SP), BX + MOVL p+8(SP), DI + MOVL $0xE820, AX + MOVL $0x534D4150, DX + CALL rmode16(SB) + LWI(24, rCX) + BIOSCALL(0x15) + JC _bad + CALL16(pmode32(SB)) + CMPB CL, $24 + JZ _ret + MOVL $1, AX + MOVL p+8(SP), DI + MOVL AX, 20(DI) +_ret: + MOVL BX, AX + RET +_bad: + CALL16(pmode32(SB)) + XORL AX, AX + MOVL p+8(SP), DI + MOVL AX, 0(DI) + MOVL AX, 4(DI) + MOVL AX, 8(DI) + MOVL AX, 12(DI) + MOVL AX, 16(DI) + MOVL AX, 20(DI) + RET diff --git a/sys/src/nboot/pc/fat.c b/sys/src/nboot/pc/fat.c new file mode 100644 index 0000000000..99218d155c --- /dev/null +++ b/sys/src/nboot/pc/fat.c @@ -0,0 +1,405 @@ +#include +#include "fns.h" + +#define GETSHORT(p) (*(ushort *)(p)) +#define GETLONG(p) (*(uint *)(p)) + +enum { + Sectsz = 0x200, + Dirsz = 0x20, + Maxpath = 64, + Fat12 = 1, + Fat16 = 2, + Fat32 = 4, +}; + +typedef struct File File; +typedef struct Dir Dir; +typedef struct Pbs Pbs; +typedef struct Pbs32 Pbs32; +typedef struct Fat Fat; + +struct Fat +{ + ulong ver; + int drive; + ulong clustsize; + ulong eofmark; + ulong partlba; + ulong fatlba; + ulong dirstart; /* LBA for FAT16, cluster for FAT32 */ + ulong dirents; + ulong datalba; +}; + +struct File +{ + Fat *fat; + ulong lba; + ulong clust; + ulong lbaoff; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + char name[11]; + uchar attr; + uchar reserved; + uchar ctime; + uchar ctime[2]; + uchar cdate[2]; + uchar adate[2]; + uchar starthi[2]; + uchar mtime[2]; + uchar mdate[2]; + uchar startlo[2]; + uchar len[4]; +}; + +struct Pbs +{ + uchar magic[3]; + uchar version[8]; + uchar sectsize[2]; + uchar clustsize; + uchar nreserv[2]; + uchar nfats; + uchar rootsize[2]; + uchar volsize[2]; + uchar mediadesc; + uchar fatsize[2]; + uchar trksize[2]; + uchar nheads[2]; + uchar nhidden[4]; + uchar bigvolsize[4]; + uchar driveno; + uchar reserved0; + uchar bootsig; + uchar volid[4]; + uchar label[11]; + uchar type[8]; +}; + +struct Pbs32 +{ + uchar common[36]; + uchar fatsize[4]; + uchar flags[2]; + uchar ver[2]; + uchar rootclust[4]; + uchar fsinfo[2]; + uchar bootbak[2]; + uchar reserved0[12]; + uchar driveno; + uchar reserved1; + uchar bootsig; + uchar volid[4]; + uchar label[11]; + uchar type[8]; +}; + +int readsect(ulong drive, ulong lba, void *buf); + +void +unload(void) +{ +} + +static ulong +readnext(File *fp, ulong clust) +{ + Fat *fat = fp->fat; + uchar tmp[2], *p; + ulong idx, lba; + + if(fat->ver == Fat12) + idx = (3*clust)/2; + else + idx = clust*fat->ver; + lba = fat->fatlba + (idx / Sectsz); + if(readsect(fat->drive, lba, fp->buf)) + memset(fp->buf, 0xff, Sectsz); + p = &fp->buf[idx % Sectsz]; + if(p == &fp->buf[Sectsz-1]){ + tmp[0] = *p; + if(readsect(fat->drive, ++lba, fp->buf)) + memset(fp->buf, 0xff, Sectsz); + tmp[1] = fp->buf[0]; + p = tmp; + } + if(fat->ver == Fat32) + return GETLONG(p) & 0xfffffff; + idx = GETSHORT(p); + if(fat->ver == Fat12){ + if(clust & 1) + idx >>= 4; + idx &= 0xfff; + } + return idx; +} + +int +read(void *f, void *data, int len) +{ + File *fp = f; + Fat *fat = fp->fat; + + if(fp->len > 0 && fp->rp >= fp->ep){ + if(fp->clust != ~0U){ + if(fp->lbaoff % fat->clustsize == 0){ + if(fp->clust < 2 || fp->clust >= fat->eofmark) + return -1; + fp->lbaoff = (fp->clust - 2) * fat->clustsize; + fp->clust = readnext(fp, fp->clust); + fp->lba = fp->lbaoff + fat->datalba; + } + fp->lbaoff++; + } + if(readsect(fat->drive, fp->lba++, fp->rp = fp->buf)) + return -1; + } + if(fp->len < len) + len = fp->len; + if(len > (fp->ep - fp->rp)) + len = fp->ep - fp->rp; + memmove(data, fp->rp, len); + fp->rp += len; + fp->len -= len; + return len; +} + +void +close(void *) +{ +} + +static int +dirname(Dir *d, char buf[Maxpath]) +{ + char c, *x; + + if(d->attr == 0x0F || *d->name <= 0) + return -1; + memmove(buf, d->name, 8); + x = buf+8; + while(x > buf && x[-1] == ' ') + x--; + if(d->name[8] != ' '){ + *x++ = '.'; + memmove(x, d->name+8, 3); + x += 3; + } + while(x > buf && x[-1] == ' ') + x--; + *x = 0; + x = buf; + while(c = *x){ + if(c >= 'A' && c <= 'Z'){ + c -= 'A'; + c += 'a'; + } + *x++ = c; + } + return x - buf; +} + +static ulong +dirclust(Dir *d) +{ + return *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo); +} + +static void +fileinit(File *fp, Fat *fat, ulong lba) +{ + fp->fat = fat; + fp->lba = lba; + fp->len = 0; + fp->lbaoff = 0; + fp->clust = ~0U; + fp->rp = fp->ep = fp->buf + Sectsz; +} + +static int +fatwalk(File *fp, Fat *fat, char *path) +{ + char name[Maxpath], *end; + int i, j; + Dir d; + + if(fat->ver == Fat32){ + fileinit(fp, fat, 0); + fp->clust = fat->dirstart; + fp->len = ~0U; + }else{ + fileinit(fp, fat, fat->dirstart); + fp->len = fat->dirents * Dirsz; + } + for(;;){ + if(readn(fp, &d, Dirsz) != Dirsz) + break; + if((i = dirname(&d, name)) <= 0) + continue; + while(*path == '/') + path++; + if((end = strchr(path, '/')) == 0) + end = path + strlen(path); + j = end - path; + if(i == j && memcmp(name, path, j) == 0){ + fileinit(fp, fat, 0); + fp->clust = dirclust(&d); + fp->len = GETLONG(d.len); + if(*end == 0) + return 0; + else if(d.attr & 0x10){ + fp->len = fat->clustsize * Sectsz; + path = end; + continue; + } + break; + } + } + return -1; +} + +static int +conffat(Fat *fat, void *buf) +{ + Pbs *p = buf; + uint fatsize, volsize, datasize, reserved; + uint ver, dirsize, dirents, clusters; + + if(GETSHORT(p->sectsize) != Sectsz) + return -1; + if(memcmp(p->type, "FAT", 3) && memcmp(((Pbs32*)buf)->type, "FAT", 3)) + return -1; + + /* load values from fat */ + ver = 0; + fatsize = GETSHORT(p->fatsize); + if(fatsize == 0){ + fatsize = GETLONG(((Pbs32*)buf)->fatsize); + ver = Fat32; + } + volsize = GETSHORT(p->volsize); + if(volsize == 0) + volsize = GETLONG(p->bigvolsize); + reserved = GETSHORT(p->nreserv); + dirents = GETSHORT(p->rootsize); + dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz; + datasize = volsize - (reserved + fatsize * p->nfats + dirsize); + clusters = datasize / p->clustsize; + if(ver != Fat32) + if(clusters < 0xff7) + ver = Fat12; + else + ver = Fat16; + + /* fill FAT descriptor */ + fat->ver = ver; + fat->dirents = dirents; + fat->clustsize = p->clustsize; + fat->fatlba = fat->partlba + reserved; + fat->dirstart = fat->fatlba + fatsize * p->nfats; + if(ver == Fat32){ + fat->datalba = fat->dirstart; + fat->dirstart = GETLONG(((Pbs32*)buf)->rootclust); + fat->eofmark = 0xffffff7; + }else{ + fat->datalba = fat->dirstart + dirsize; + if(ver == Fat16) + fat->eofmark = 0xfff7; + else + fat->eofmark = 0xff7; + } + return 0; +} + +static int +findfat(Fat *fat, int drive, ulong xbase, ulong lba) +{ + struct { + uchar status; + uchar bchs[3]; + uchar typ; + uchar echs[3]; + uchar lba[4]; + uchar len[4]; + } p[4]; + uchar buf[Sectsz]; + int i; + + if(xbase == 0) + xbase = lba; + if(readsect(drive, lba, buf)) + return -1; + if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA) + return -1; + if(lba == 0 && (drive & 0x80) == 0){ /* floppy */ + fat->drive = drive; + fat->partlba = 0; + if(!conffat(fat, buf)) + return 0; + } + memmove(p, &buf[0x1be], sizeof(p)); + for(i=0; i<4; i++){ + switch(p[i].typ){ + case 0x05: + case 0x0f: + case 0x85: + /* extended partitions */ + if(!findfat(fat, drive, xbase, xbase + GETLONG(p[i].lba))) + return 0; + /* no break */ + case 0x00: + continue; + default: + if(p[i].status != 0x80) + continue; + case 0x39: /* always try plan9 partition */ + fat->drive = drive; + fat->partlba = lba + GETLONG(p[i].lba); + if(readsect(drive, fat->partlba, buf)) + continue; + if(!conffat(fat, buf)) + return 0; + } + } + return -1; +} + +void +start(void *sp) +{ + char path[Maxpath], *kern; + int drive; + File fi; + Fat fat; + void *f; + + /* drive passed in DL */ + drive = ((ushort*)sp)[5] & 0xFF; + + if(findfat(&fat, drive, 0, 0)){ + print("no fat\n"); + halt(); + } + if(fatwalk(f = &fi, &fat, "plan9.ini")){ + print("no config\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(fatwalk(&fi, &fat, kern)){ + print("not found\n"); + continue; + } + print(bootkern(&fi)); + print("\n"); + } +} + diff --git a/sys/src/nboot/pc/fns.h b/sys/src/nboot/pc/fns.h new file mode 100644 index 0000000000..8f80c38e6b --- /dev/null +++ b/sys/src/nboot/pc/fns.h @@ -0,0 +1,46 @@ +/* handy strings in l.s */ +extern char origin[]; +extern char uart; +extern char hex[]; +extern char bootname[]; + +/* l.s */ +void start(void *sp); +void cgaputc(int c); +int kbdgetc(void); +void usleep(int t); +void halt(void); +void jump(void *pc); + +int read(void *f, void *data, int len); +int readn(void *f, void *data, int len); +void close(void *f); +void unload(void); + +int getc(void); +void putc(int c); + +void memset(void *p, int v, int n); +void memmove(void *dst, void *src, int n); +int memcmp(void *src, void *dst, int n); +int strlen(char *s); +char *strchr(char *s, int c); +char *strrchr(char *s, int c); +void print(char *s); + +char *configure(void *f, char *path); +char *bootkern(void *f); + +/* a20.s */ +int a20(void); + +/* e820.s */ +ulong e820(ulong bx, void *p); + +/* apm.s */ +void apm(int id); + +/* uart.s */ +void uartinit(int p, int c); +void uartputc(int p, int c); +int uartgetc(int p); diff --git a/sys/src/nboot/pc/iso.c b/sys/src/nboot/pc/iso.c new file mode 100644 index 0000000000..d43ad4231c --- /dev/null +++ b/sys/src/nboot/pc/iso.c @@ -0,0 +1,200 @@ +#include +#include "fns.h" + +enum { + Sectsz = 0x800, + Maxpath = 256, + Dirsz = 33, +}; + +typedef struct Extend Extend; +typedef struct Dir Dir; + +struct Extend +{ + int drive; + ulong lba; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + uchar dirlen; + uchar extlen; + + uchar lba[8]; + uchar len[8]; + + uchar date[7]; + + uchar flags[3]; + + uchar seq[4]; + + uchar namelen; +}; + +int readsect(ulong drive, ulong lba, void *buf); + +#ifdef FAT +int +readsect4(ulong drive, ulong lba, void *buf) +{ + int i; + + lba *= Sectsz/512; + for(i = 0; ilen > 0 && ex->rp >= ex->ep) + if(readsect(ex->drive, ex->lba++, ex->rp = ex->buf)) + return -1; + if(ex->len < len) + len = ex->len; + if(len > (ex->ep - ex->rp)) + len = ex->ep - ex->rp; + memmove(data, ex->rp, len); + ex->rp += len; + ex->len -= len; + return len; +} + +void +close(void *f) +{ + Extend *ex = f; + + ex->drive = 0; + ex->lba = 0; + ex->len = 0; + ex->rp = ex->ep = ex->buf + Sectsz; +} + +static int +isowalk(Extend *ex, int drive, char *path) +{ + char name[Maxpath], c, *end; + int i; + Dir d; + + close(ex); + ex->drive = drive; + + /* find pvd */ + for(i=0x10; i<0x1000; i++){ + if(readsect(drive, i, ex->buf)) + return -1; + if(*ex->buf == 1) + break; + } + ex->lba = *((ulong*)(ex->buf + 156 + 2)); + ex->len = *((ulong*)(ex->buf + 156 + 10)); + + for(;;){ + if(read(ex, &d.dirlen, 1) != 1) + break; + if(d.dirlen == 0) + continue; /* zero padding to next sector */ + if(read(ex, &d.dirlen + 1, Dirsz-1) != Dirsz-1) + break; + if(read(ex, name, d.namelen) != d.namelen) + break; + i = d.dirlen - (Dirsz + d.namelen); + while(i-- > 0){ + if(read(ex, &c, 1) != 1) + break; + } + for(i=0; i= 'A' && c <= 'Z'){ + c -= 'A'; + c += 'a'; + } + name[i] = c; + } + name[i] = 0; + while(*path == '/') + path++; + if((end = strchr(path, '/')) == 0) + end = path + strlen(path); + i = end - path; + if(d.namelen == i && memcmp(name, path, i) == 0){ + ex->rp = ex->ep; + ex->lba = *((ulong*)d.lba); + ex->len = *((ulong*)d.len); + if(*end == 0) + return 0; + else if(d.flags[0] & 2){ + path = end; + continue; + } + break; + } + } + close(ex); + return -1; +} + +void +start(void *sp) +{ + char path[Maxpath], *kern; + int drive; + Extend ex; + void *f; + + /* drive passed in DL */ + drive = ((ushort*)sp)[5] & 0xFF; + +#ifndef FAT + /* + * load full bootblock as only the frist 2K get + * loaded from bios. the code is specially arranged + * to have all the important routines in the first + * 2K of the 9bootiso image. (strings have been + * placed in l.s to make sure they will be < 2K) + */ + if(isowalk(&ex, drive, bootname)){ + print(bootname); + putc('?'); + halt(); + } + readn(&ex, origin, ex.len); + close(&ex); +#endif + + if(isowalk(f = &ex, drive, "/cfg/plan9.ini")){ + print("no config\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(isowalk(&ex, drive, kern)){ + print("not found\n"); + continue; + } + print(bootkern(&ex)); + print("\n"); + } +} + diff --git a/sys/src/nboot/pc/l.s b/sys/src/nboot/pc/l.s new file mode 100644 index 0000000000..44a22a266e --- /dev/null +++ b/sys/src/nboot/pc/l.s @@ -0,0 +1,299 @@ +#include "x16.h" +#include "mem.h" + +#undef ORB + +#define DATA32SEL SELECTOR(1, SELGDT, 0) +#define EXEC32SEL SELECTOR(2, SELGDT, 0) +#define DATA16SEL SELECTOR(3, SELGDT, 0) +#define EXEC16SEL SELECTOR(4, SELGDT, 0) + +#define SEGSS BYTE $0x36 +#define SEGES BYTE $0x26 +#define FARRET BYTE $0xCB + +TEXT origin(SB), $0 + CLI + CLR(rCX) + MTSR(rCX, rSS) + OPSIZE; MOVL $origin(SB), SP + PUSHA + OPSIZE; ADSIZE; PUSHL SP + OPSIZE; ADSIZE; PUSHL CX + PUSHI(start(SB)) + +TEXT pmode32(SB), $0 + CLI + + /* get return pc */ + POPR(rDI) + + /* make sure stack is at 0000: */ + CLR(rCX) + MTSR(rCX, rSS) + OPSIZE; ANDL $0xFFFF, SP + + /* convert 16-bit return pc to far pointer */ + PUSHI(EXEC32SEL) + PUSHR(rDI) + + /* load gdt */ + SEGSS; LGDT(tgdtptr(SB)) + + /* enable protected mode */ + MFCR(rCR0, rCX) + ORB $1, CL + MTCR(rCX, rCR0) + + /* flush */ + FARJUMP16(EXEC16SEL, pmode32flush(SB)); +TEXT pmode32flush(SB), $0 + + /* load 32-bit protected mode data selector */ + LWI(DATA32SEL, rCX) + +_segret: + /* load all data segments */ + MTSR(rCX, rDS) + MTSR(rCX, rES) + MTSR(rCX, rFS) + MTSR(rCX, rGS) + MTSR(rCX, rSS) + FARRET + +TEXT rmode16(SB), $0 + /* setup farret to rmode16x */ + PUSHL $EXEC16SEL + PUSHL $rmode16x(SB) + + /* load 16-bit protected mode data selector */ + MOVL $DATA16SEL, CX + JMP _segret + +TEXT rmode16x(SB), $0 + /* disable protected mode */ + MFCR(rCR0, rCX) + ANDB $0xfe, CL + MTCR(rCX, rCR0) + + /* flush */ + FARJUMP16(0, rmode16flush(SB)); +TEXT rmode16flush(SB), $0 + + /* + * load 16-bit realmode data segment 0000: and + * return to 32 bit return pc interpreted + * as 16 bit far pointer. + */ + CLR(rCX) + JMP _segret + +TEXT tgdt(SB), $0 + /* null descriptor */ + LONG $0 + LONG $0 + + /* data segment descriptor for 4 gigabytes (PL 0) */ + LONG $(0xFFFF) + LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) + + /* exec segment descriptor for 4 gigabytes (PL 0) */ + LONG $(0xFFFF) + LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + + /* data segment descriptor for (PL 0) 16-bit */ + LONG $(0xFFFF) + LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) + + /* exec segment descriptor for (PL 0) 16-bit */ + LONG $(0xFFFF) + LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + +TEXT tgdtptr(SB), $0 + WORD $(5*8) + LONG $tgdt(SB) + +TEXT jump(SB), $0 + MOVL 4(SP), AX + JMP *AX + +TEXT halt(SB), $0 +_halt: + JMP _halt + +TEXT kbdgetc(SB), $0 + CALL rmode16(SB) + STI + MOVB $0x01, AH + BIOSCALL(0x16) + JNZ _gotkey + CLR(rAX) + JMP _pret32 +_gotkey: + CLR(rAX) + BIOSCALL(0x16) + JMP _pret32 + +TEXT cgaputc(SB), $0 + MOVL 4(SP),AX + CALL rmode16(SB) + STI + MOVB $0x0E, AH + BIOSCALL(0x10) +_pret32: + CALL16(pmode32(SB)) + ANDL $0xFFFF, AX + RET + +TEXT usleep(SB), $0 + MOVL t+4(SP), AX + PUSHL AX + CALL rmode16(SB) + STI + POPR(rDX) + POPR(rCX) + MOVB $0x86, AH + BIOSCALL(0x15) + JMP _pret32 + +#ifdef PXE + +TEXT pxeinit(SB), $0 + CALL rmode16(SB) + + /* get pxe env structure in ES:BX */ + LWI(0x5650, rAX) + BIOSCALL(0x1A) + JC _pret32 + + /* !PXE or PXEENV+ signature */ + SEGES; LXW(0, xBX, rAX) + CMPI((('!'<<0)|('P'<<8)), rAX) + JEQ _getentry + CMPI((('P'<<0)|('X'<<8)), rAX) + JNE _pret32 + + SEGES; LXW(0x2A, xBX, rAX) + SEGES; LXW(0x28, xBX, rBX) + MTSR(rAX, rES) + +_getentry: + SEGES; LXW(0x12, xBX, rAX) + SW(rAX, pxepseg(SB)) + SEGES; LXW(0x10, xBX, rAX) + SW(rAX, pxepoff(SB)) + CLR(rAX) + JMP _pret32 + +TEXT pxecallret(SB), $0 + ADDI(6, rSP) + JMP _pret32 + +TEXT pxecall(SB), $0 + MOVL op+4(SP),AX + MOVL buf+8(SP),SI + CALL rmode16(SB) + + CLR(rCX) + PUSHR(rCX) + PUSHR(rSI) + + /* opcode */ + PUSHR(rAX) + + /* farcall */ + PUSHR(rCX) + PUSHI(pxecallret(SB)) + + LW(pxepseg(SB), rAX) + PUSHR(rAX) + LW(pxepoff(SB), rAX) + PUSHR(rAX) + + STI + + CLR(rAX) + CLR(rBX) + CLR(rCX) + CLR(rDX) + CLR(rDI) + CLR(rSI) + FARRET + +TEXT pxepseg(SB), $0 + WORD $0 +TEXT pxepoff(SB), $0 + WORD $0 + +#else /* PXE */ + +/* + * in: + * DL drive + * AX:BX lba32, + * 0000:SI buffer + */ +TEXT readsect16(SB), $0 + PUSHA + CLR(rCX) + + PUSHR(rCX) /* qword lba */ + PUSHR(rCX) + PUSHR(rBX) + PUSHR(rAX) + + PUSHR(rCX) /* dword buffer */ + PUSHR(rSI) + + INC(rCX) + PUSHR(rCX) /* word # of sectors */ + + PUSHI(0x0010) /* byte reserved, byte packet size */ + + MW(rSP, rSI) + LWI(0x4200, rAX) + BIOSCALL(0x13) + JCC _readok + ADDI(0x10, rSP) + POPA + CLR(rAX) + DEC(rAX) + RET +_readok: + ADDI(0x10, rSP) + POPA + CLR(rAX) + RET + +TEXT readsect(SB), $0 + MOVL 4(SP), DX + MOVW 8(SP), AX + MOVW 10(SP), BX + MOVL 12(SP), SI + CALL rmode16(SB) + STI + CALL16(readsect16(SB)) + CALL16(pmode32(SB)) + ANDL $0xFFFF, AX + RET + +#endif + +#ifdef ISO + +TEXT bootname(SB), $0 + BYTE $'3'; BYTE $'8'; BYTE $'6'; BYTE $'/'; + BYTE $'9'; BYTE $'b'; BYTE $'o'; BYTE $'o'; + BYTE $'t'; BYTE $'i'; BYTE $'s'; BYTE $'o'; + BYTE $0 + +#endif + +TEXT uart(SB), $0 + BYTE $0xff + +TEXT hex(SB), $0 + BYTE $'0'; BYTE $'1'; BYTE $'2'; BYTE $'3'; + BYTE $'4'; BYTE $'5'; BYTE $'6'; BYTE $'7'; + BYTE $'8'; BYTE $'9'; BYTE $'a'; BYTE $'b'; + BYTE $'c'; BYTE $'d'; BYTE $'e'; BYTE $'f' diff --git a/sys/src/nboot/pc/mbr.s b/sys/src/nboot/pc/mbr.s new file mode 100644 index 0000000000..fb299584e0 --- /dev/null +++ b/sys/src/nboot/pc/mbr.s @@ -0,0 +1,259 @@ +/* + * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600: + * 8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8 + */ +#include "x16.h" +#include "mem.h" + +/*#define FLOPPY 1 /* test on a floppy */ +#define TRACE(C) PUSHA;\ + CLR(rBX);\ + MOVB $C, AL;\ + LBI(0x0E, rAH);\ + BIOSCALL(0x10);\ + POPA + +/* + * We keep data on the stack, indexed by BP. + */ +#define Xdap 0x00 /* disc address packet */ +#define Xtable 0x10 /* partition table entry */ +#define Xdrive 0x12 /* starting disc */ +#define Xtotal 0x14 /* sum of allocated data above */ + +/* + * Start: loaded at 0000:7C00, relocate to 0000:0600. + * Boot drive is in rDL. + */ +TEXT _start(SB), $0 + CLI + CLR(rAX) + MTSR(rAX, rSS) /* 0000 -> rSS */ + LWI((0x7C00-Xtotal), rSP) /* 7Bxx -> rSP */ + MW(rSP, rBP) /* set the indexed-data pointer */ + + MTSR(rAX, rDS) /* 0000 -> rDS, source segment */ + LWI(0x7C00, rSI) /* 7C00 -> rSI, source offset */ + MTSR(rAX, rES) /* 0000 -> rES, destination segment */ + LWI(0x600, rDI) /* 0600 -> rDI, destination offset */ + LWI(0x100, rCX) /* 0100 -> rCX, loop count (words) */ + + CLD + REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */ + + FARJUMP16(0x0000, _start0600(SB)) + +TEXT _start0600(SB), $0 +#ifdef FLOPPY + LBI(0x80, rDL) +#else + CLRB(rAL) /* some systems pass 0 */ + CMPBR(rAL, rDL) + JNE _save + LBI(0x80, rDL) +#endif /* FLOPPY */ +_save: + SXB(rDL, Xdrive, xBP) /* save disc */ + + LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */ + CALL16(BIOSputs(SB)) + + LWI(_start+0x01BE(SB), rSI) /* address of partition table */ + LWI(0x04, rCX) /* 4 entries in table */ + LBI(0x80, rAH) /* active entry value */ + CLRB(rAL) /* inactive entry value */ + +_activeloop0: + LXB(0x00, xSI, rBL) /* get active entry from table */ + CMPBR(rBL, rAH) /* is this an active entry? */ + JEQ _active + + CMPBR(rBL, rAL) /* if not active it should be 0 */ + JNE _invalidMBR + + ADDI(0x10, rSI) /* next table entry */ + DEC(rCX) + JNE _activeloop0 + + LWI(noentry(SB), rSI) + CALL16(buggery(SB)) + +_active: + MW(rSI, rDI) /* save table address */ + +_activeloop1: + ADDI(0x10, rSI) /* next table entry */ + DEC(rCX) + JEQ _readsector + + LXB(0x00, xSI, rBL) /* get active entry from table */ + CMPBR(rBL, rAH) /* is this an active entry? */ + JNE _activeloop1 /* should only be one active */ + +_invalidMBR: + LWI(invalidMBR(SB), rSI) + CALL16(buggery(SB)) + +_readsector: + LBI(0x41, rAH) /* check extensions present */ + LWI(0x55AA, rBX) + LXB(Xdrive, xBP, rDL) /* drive */ + BIOSCALL(0x13) /* CF set on failure */ + JCS _readsector2 + CMPI(0xAA55, rBX) + JNE _readsector2 + ANDI(0x0001, rCX) + JEQ _readsector2 + +_readsector42: + SBPBI(0x10, Xdap+0) /* packet size */ + SBPBI(0x00, Xdap+1) /* reserved */ + SBPBI(0x01, Xdap+2) /* number of blocks to transfer */ + SBPBI(0x00, Xdap+3) /* reserved */ + SBPWI(0x7C00, Xdap+4) /* transfer buffer :offset */ + SBPWI(0x0000, Xdap+6) /* transfer buffer seg: */ + LXW(0x08, xDI, rAX) /* LBA (64-bits) */ + SBPW(rAX, Xdap+8) + LXW(0x0A, xDI, rAX) + SBPW(rAX, Xdap+10) + SBPWI(0x0000, Xdap+12) + SBPWI(0x0000, Xdap+14) + + MW(rBP, rSI) /* disk address packet */ + LBI(0x42, rAH) /* extended read */ + BIOSCALL(0x13) /* CF set on failure */ + JCC _readsectorok + + LWI(ioerror(SB), rSI) + CALL16(buggery(SB)) + +/* + * Read a sector from a disc using the traditional BIOS call. + * For BIOSCALL(0x13/AH=0x02): + * rAH 0x02 + * rAL number of sectors to read (1) + * rCH low 8 bits of cylinder + * rCL high 2 bits of cylinder (7-6), sector (5-0) + * rDH head + * rDL drive + * rES:rBX buffer address + */ +_readsector2: + LXB(0x01, xDI, rDH) /* head */ + LXW(0x02, xDI, rCX) /* save active cylinder/sector */ + + LWI(0x0201, rAX) /* read one sector */ + LXB(Xdrive, xBP, rDL) /* drive */ + LWI(0x7C00, rBX) /* buffer address (rES already OK) */ + BIOSCALL(0x13) /* CF set on failure */ + JCC _readsectorok + + LWI(ioerror(SB), rSI) + CALL16(buggery(SB)) + +_readsectorok: + LWI(0x7C00, rBX) /* buffer address (rES already OK) */ + LXW(0x1FE, xBX, rAX) + CMPI(0xAA55, rAX) + JNE _bbnotok + + /* + * Jump to the loaded PBS. + * rDL and rSI should still contain the drive + * and partition table pointer respectively. + */ + MW(rDI, rSI) + FARJUMP16(0x0000, 0x7C00) + +_bbnotok: + LWI(invalidPBS(SB), rSI) + +TEXT buggery(SB), $0 + CALL16(BIOSputs(SB)) + LWI(reboot(SB), rSI) + CALL16(BIOSputs(SB)) + +_wait: + CLR(rAX) /* wait for any key */ + BIOSCALL(0x16) + +_reset: + CLR(rBX) /* set ES segment for BIOS area */ + MTSR(rBX, rES) + + LWI(0x0472, rBX) /* warm-start code address */ + LWI(0x1234, rAX) /* warm-start code */ + POKEW /* MOVW AX, ES:[BX] */ + + FARJUMP16(0xFFFF, 0x0000) /* reset */ + +/* + * Output a string to the display. + * String argument is in rSI. + */ +TEXT BIOSputs(SB), $0 + PUSHA + CLR(rBX) +_BIOSputs: + LODSB + ORB(rAL, rAL) + JEQ _BIOSputsret + + LBI(0x0E, rAH) + BIOSCALL(0x10) + JMP _BIOSputs + +_BIOSputsret: + POPA + RET + +/* "No active entry in MBR" */ +TEXT noentry(SB), $0 + BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a'; + BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v'; + BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n'; + BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' '; + BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M'; + BYTE $'B'; BYTE $'R'; + BYTE $'\z'; + +/* "Invalid MBR" */ +TEXT invalidMBR(SB), $0 + BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a'; + BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' '; + BYTE $'M'; BYTE $'B'; BYTE $'R'; + BYTE $'\z'; + +/* "I/O error" */ +TEXT ioerror(SB), $0 + BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' '; + BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o'; + BYTE $'r'; + BYTE $'\z'; + +/* "Invalid PBS" */ +TEXT invalidPBS(SB), $0 + BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a'; + BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' '; + BYTE $'P'; BYTE $'B'; BYTE $'S'; + BYTE $'\z'; + +/* "\r\nPress almost any key to reboot..." */ +TEXT reboot(SB), $0 + BYTE $'\r';BYTE $'\n'; + BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s'; + BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l'; + BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t'; + BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y'; + BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y'; + BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' '; + BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o'; + BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.'; + BYTE $'.'; + BYTE $'\z'; + +/* "MBR..." */ +TEXT confidence(SB), $0 + BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.'; + BYTE $'.'; BYTE $'.'; + BYTE $'\z'; diff --git a/sys/src/nboot/pc/mem.h b/sys/src/nboot/pc/mem.h new file mode 100644 index 0000000000..42f3dc3163 --- /dev/null +++ b/sys/src/nboot/pc/mem.h @@ -0,0 +1,46 @@ +/* + * Memory and machine-specific definitions. Used in C and assembler. + */ + +/* + * Sizes + */ +#define BI2BY 8 /* bits per byte */ +#define BI2WD 32 /* bits per word */ +#define BY2WD 4 /* bytes per word */ +#define BY2PG 4096 /* bytes per page */ +#define WD2PG (BY2PG/BY2WD) /* words per page */ +#define PGSHIFT 12 /* log(BY2PG) */ +#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1)) + +/* + * Fundamental addresses + */ +#define CONFADDR 0x1200 /* info passed from boot loader */ +#define BIOSXCHG 0x6000 /* To exchange data with the BIOS */ + +#define SELGDT (0<<3) /* selector is in gdt */ +#define SELLDT (1<<3) /* selector is in ldt */ + +#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) + +/* + * fields in segment descriptors + */ +#define SEGDATA (0x10<<8) /* data/stack segment */ +#define SEGEXEC (0x18<<8) /* executable segment */ +#define SEGTSS (0x9<<8) /* TSS segment */ +#define SEGCG (0x0C<<8) /* call gate */ +#define SEGIG (0x0E<<8) /* interrupt gate */ +#define SEGTG (0x0F<<8) /* task gate */ +#define SEGTYPE (0x1F<<8) + +#define SEGP (1<<15) /* segment present */ +#define SEGPL(x) ((x)<<13) /* priority level */ +#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ +#define SEGG (1<<23) /* granularity 1==4k (for other) */ +#define SEGE (1<<10) /* expand down */ +#define SEGW (1<<9) /* writable (for data/stack) */ +#define SEGR (1<<9) /* readable (for code) */ +#define SEGD (1<<22) /* default 1==32bit (for code) */ + diff --git a/sys/src/nboot/pc/mkfile b/sys/src/nboot/pc/mkfile new file mode 100644 index 0000000000..ae9e907350 --- /dev/null +++ b/sys/src/nboot/pc/mkfile @@ -0,0 +1,107 @@ +objtype=386 +>tmp/cfg/plan9.ini + disk/mk9660 -B 386/9bootiso -p <{echo +} -s tmp $target + @{rfork n + bind 9boothyb 9bootfat + dd -if /dev/zero -bs 512 -count 4096 >> $target + disk/partfs -m /n/partfs $target + disk=/n/partfs/sdXX + disk/mbr -m mbr $disk/data + @{echo a p1 '$-1' '$' + echo t p1 FAT16 + echo A p1 + echo w + echo q} | disk/fdisk -b $disk/data + disk/format -b pbs -d -r 1 $disk/dos 9bootfat + } + rm -fr tmp + +test.dsk: 9bootfat mbr pbs test.iso + rm -fr tmp $target + mkdir tmp + cp test.iso 9bootfat tmp + mkdir tmp/386 + cp /386/9pc tmp/386 + echo 'bootfile=/386/9pc' >tmp/plan9.ini + dd -if /dev/zero -of $target -bs 512 -count 32768 + disk/partfs -m /n/$target $target + disk=/n/$target/sdXX + disk/mbr -m mbr $disk/data + disk/fdisk -baw $disk/data + disk/prep -bw -a 9fat $disk/plan9 + disk/format -b pbs -d -r 2 $disk/9fat + s=$target.dos + m=/n/$target.9fat + rm -f /srv/$s + dossrv -f $disk/9fat $s + mount -c /srv/$s $m + @{cd tmp; tar c .} | @{cd $m; tar xv} + unmount $m + rm -f /srv/$s + unmount /n/$target + rm -fr tmp diff --git a/sys/src/nboot/pc/pbs.s b/sys/src/nboot/pc/pbs.s new file mode 100644 index 0000000000..e79c619981 --- /dev/null +++ b/sys/src/nboot/pc/pbs.s @@ -0,0 +1,292 @@ +#include "x16.h" +#include "mem.h" + +#define RELOC 0x7c00 + +TEXT _magic(SB), $0 + BYTE $0xEB; BYTE $0x58; /* jmp .+ 0x58 (_start0x5A) */ + BYTE $0x90 /* nop */ +TEXT _version(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 +TEXT _sectsize(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _clustsize(SB), $0 + BYTE $0x00 +TEXT _nresrv(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _nfats(SB), $0 + BYTE $0x00 +TEXT _rootsize(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _volsize(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _mediadesc(SB), $0 + BYTE $0x00 +TEXT _fatsize(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _trksize(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _nheads(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _nhiddenlo(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _nhiddenhi(SB), $0 + BYTE $0x00; BYTE $0x00; +TEXT _bigvolsize(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; +/* FAT32 structure, starting @0x24 */ +TEXT _fatsz32lo(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _fatsz32hi(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _extflags(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _fsver(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _rootclust(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 +TEXT _fsinfo(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _bkboot(SB), $0 + BYTE $0x00; BYTE $0x00 +TEXT _reserved0(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 +TEXT _driveno(SB), $0 + BYTE $0x00 +TEXT _reserved1(SB), $0 + BYTE $0x00 +TEXT _bootsig(SB), $0 + BYTE $0x00 +TEXT _volid(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; +TEXT _label(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 + BYTE $0x00; BYTE $0x00; BYTE $0x00 +TEXT _type(SB), $0 + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; + BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 + +_start0x5A: + CLI + CLR(rAX) + MTSR(rAX, rSS) /* 0000 -> rSS */ + MTSR(rAX, rDS) /* 0000 -> rDS, source segment */ + MTSR(rAX, rES) + + LWI(0x100, rCX) + LWI(RELOC, rSI) + MW(rSI, rSP) + LWI(_magic(SB), rDI) + CLD + REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */ + + MW(rSP, rBP) + + PUSHR(rCX) + PUSHI(start16(SB)) + BYTE $0xCB /* FAR RET */ + +TEXT start16(SB), $0 + STI + + LWI(hello(SB), rSI) + CALL16(print16(SB)) + + STB(rDL, _driveno(SB)) + + CLR(rDX) + LW(_fatsize(SB), rAX) + CLR(rCX) + LB(_nfats(SB), rCL) + MUL(rCX) + OR(rAX, rAX) + JNE _fatszok /* zero? it's FAT32 */ + + LW(_fatsz32hi(SB), rBX) + IMUL(rCX, rBX) + LW(_fatsz32lo(SB), rAX) + MUL(rCX) + ADD(rBX, rDX) + +_fatszok: + LW(_nhiddenlo(SB), rCX) + ADD(rCX, rAX) + LW(_nhiddenhi(SB), rCX) + ADC(rCX, rDX) + + CLR(rBX) + LW(_nresrv(SB), rCX) + ADD(rCX, rAX) + ADC(rDX, rBX) + + SW(rAX, _volid(SB)) /* save for later use */ + SW(rBX, _volid+2(SB)) + + PUSHR(rBP) + LW(_sectsize(SB), rCX) + SUB(rCX, rSP) + MW(rSP, rBP) + MW(rSP, rSI) + +_nextsect: + CALL16(readsect16(SB)) + LW(_sectsize(SB), rCX) + SHRI(5, rCX) + +_nextdir: + PUSHR(rCX) + PUSHR(rSI) /* save for later if it matches */ + LWI(bootname(SB), rDI) + LW(bootnamelen(SB), rCX) + CLD + REP + CMPSB + POPR(rSI) + POPR(rCX) + JEQ _found + ADDI(0x20, rSI) + LOOP _nextdir + ADDI(1, rAX) + ADC(rCX, rBX) + JMP _nextsect + +_found: + CLR(rBX) + LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */ + LWI(0x20, rCX) + MUL(rCX) + LW(_sectsize(SB), rCX) + DEC(rCX) + ADD(rCX, rAX) + ADC(rBX, rDX) + INC(rCX) + DIV(rCX) + PUSHR(rAX) /* Xrootsz */ + + CLR(rCX) + LXW(0x1a, xSI, rAX) /* start cluster low */ + LXW(0x14, xSI, rBX) /* start cluster high */ + SUBI(2, rAX) /* cluster -= 2 */ + SBB(rCX, rBX) + + LB(_clustsize(SB), rCL) /* convert to sectors (AX:DX) */ + IMUL(rCX, rBX) + MUL(rCX) + ADD(rBX, rDX) + + LW(_volid(SB), rCX) /* Xrootlo */ + ADD(rCX, rAX) + LW(_volid+2(SB), rCX) /* Xroothi */ + ADC(rCX, rDX) + + CLR(rBX) + POPR(rCX) /* Xrootsz */ + ADD(rCX, rAX) + ADC(rBX, rDX) + + PUSHR(rAX) /* calculate how many sectors to read (CX) */ + PUSHR(rDX) + LXW(0x1c, xSI, rAX) + LXW(0x1e, xSI, rDX) + LW(_sectsize(SB), rCX) + DEC(rCX) + ADD(rCX, rAX) + ADC(rBX, rDX) + INC(rCX) + DIV(rCX) + MW(rAX, rCX) + POPR(rBX) + POPR(rAX) + + LWI(RELOC, rSI) + PUSHR(rSI) /* entry */ + +_loadnext: + CALL16(readsect16(SB)) + + LW(_sectsize(SB), rDX) + ADD(rDX, rSI) + + CLR(rDX) + ADDI(1, rAX) + ADC(rDX, rBX) + + LOOP _loadnext + + LWI(ok(SB), rSI) + CALL16(print16(SB)) + + LB(_driveno(SB), rDL) + CLI + RET + +TEXT print16(SB), $0 + PUSHA + CLR(rBX) +_printnext: + LODSB + ORB(rAL, rAL) + JEQ _printret + LBI(0x0E, rAH) + BIOSCALL(0x10) + JMP _printnext +_printret: + POPA + RET + +/* + * in: + * AX:BX lba32, + * 0000:SI buffer + */ +TEXT readsect16(SB), $0 +_retry: + PUSHA + CLR(rDX) + + PUSHR(rDX) /* qword lba */ + PUSHR(rDX) + PUSHR(rBX) + PUSHR(rAX) + + PUSHR(rDX) /* dword buffer */ + PUSHR(rSI) + + INC(rDX) + PUSHR(rDX) /* word # of sectors */ + + PUSHI(0x0010) /* byte reserved, byte packet size */ + + MW(rSP, rSI) + LB(_driveno(SB), rDL) + LWI(0x4200, rAX) + BIOSCALL(0x13) + JCC _readok + LWI((0x0E00|'!'), rAX) + BIOSCALL(0x10) + ADDI(0x10, rSP) + POPA + JMP _retry +_readok: + LWI((0x0E00|'.'), rAX) + BIOSCALL(0x10) + ADDI(0x10, rSP) + POPA + RET + +TEXT bootnamelen(SB), $0 + WORD $8 +TEXT bootname(SB), $0 + BYTE $'9'; BYTE $'B'; BYTE $'O'; BYTE $'O'; + BYTE $'T'; BYTE $'F'; BYTE $'A'; BYTE $'T'; + BYTE $0 + +TEXT hello(SB), $0 + BYTE $'p'; BYTE $'b'; BYTE $'s'; BYTE $0 +TEXT ok(SB), $0 + BYTE $'o'; BYTE $'k'; BYTE $'\r'; BYTE $'\n'; + BYTE $0 diff --git a/sys/src/nboot/pc/pxe.c b/sys/src/nboot/pc/pxe.c new file mode 100644 index 0000000000..07e8c9911c --- /dev/null +++ b/sys/src/nboot/pc/pxe.c @@ -0,0 +1,362 @@ +#include +#include "fns.h" + +enum { + Tftp_READ = 1, + Tftp_WRITE = 2, + Tftp_DATA = 3, + Tftp_ACK = 4, + Tftp_ERROR = 5, + Tftp_OACK = 6, + + TftpPort = 69, + + Segsize = 512, + Maxpath = 64, +}; + +typedef uchar IP4[4]; + +typedef struct Tftp Tftp; +typedef struct Dhcp Dhcp; + +struct Tftp +{ + IP4 sip; + IP4 dip; + IP4 gip; + + int sport; + int dport; + + char *rp; + char *ep; + + int seq; + int eof; + + char pkt[2+2+Segsize]; + char nul; +}; + +struct Dhcp +{ + uchar opcode; + uchar hardware; + uchar hardlen; + uchar gatehops; + uchar ident[4]; + uchar seconds[2]; + uchar flags[2]; + uchar cip[4]; + uchar yip[4]; + uchar sip[4]; + uchar gip[4]; + uchar mac[16]; + char sname[64]; + char bootfile[128]; +}; + +int pxeinit(void); +int pxecall(int op, void *buf); + +static void* +unfar(ulong seg, ulong off) +{ + return (void*)((off & 0xFFFF) + (seg & 0xFFFF)*16); +} + +static void +puts(void *x, ushort v) +{ + uchar *p = x; + + p[1] = (v>>8) & 0xFF; + p[0] = v & 0xFF; +} + +static ushort +gets(void *x) +{ + uchar *p = x; + + return p[1]<<8 | p[0]; +} + +static void +hnputs(void *x, ushort v) +{ + uchar *p = x; + + p[0] = (v>>8) & 0xFF; + p[1] = v & 0xFF; +} + +static ushort +nhgets(void *x) +{ + uchar *p = x; + + return p[0]<<8 | p[1]; +} + +static void +moveip(IP4 d, IP4 s) +{ + memmove(d, s, sizeof(d)); +} + +void +unload(void) +{ + struct { + uchar status[2]; + uchar junk[10]; + } buf; + static uchar shutdown[] = { 0x05, 0x070, 0x02, 0 }; + uchar *o; + + for(o = shutdown; *o; o++){ + memset(&buf, 0, sizeof(buf)); + if(pxecall(*o, &buf)) + break; + } +} + +static int +getip(IP4 yip, IP4 sip, IP4 gip, char mac[16]) +{ + struct { + uchar status[2]; + uchar pkttype[2]; + uchar bufsize[2]; + uchar off[2]; + uchar seg[2]; + uchar lim[2]; + } buf; + int i, r; + Dhcp *p; + + memset(&buf, 0, sizeof(buf)); + puts(buf.pkttype, 3); + + if(r = pxecall(0x71, &buf)) + return -r; + if((p = unfar(gets(buf.seg), gets(buf.off))) == 0) + return -1; + moveip(yip, p->yip); + moveip(sip, p->sip); + moveip(gip, p->gip); + mac[12] = 0; + for(i=0; i<6; i++){ + mac[i*2] = hex[p->mac[i]>>4]; + mac[i*2+1] = hex[p->mac[i]&15]; + } + return 0; +} + +static int +udpopen(IP4 sip) +{ + struct { + uchar status[2]; + uchar sip[4]; + } buf; + + puts(buf.status, 0); + moveip(buf.sip, sip); + return pxecall(0x30, &buf); +} + +static int +udpclose(void) +{ + uchar status[2]; + puts(status, 0); + return pxecall(0x31, status); +} + +static int +udpread(IP4 sip, IP4 dip, int *sport, int dport, int *len, void *data) +{ + struct { + uchar status[2]; + uchar sip[4]; + uchar dip[4]; + uchar sport[2]; + uchar dport[2]; + uchar len[2]; + uchar off[2]; + uchar seg[2]; + } buf; + int r; + + puts(buf.status, 0); + moveip(buf.sip, sip); + moveip(buf.dip, dip); + hnputs(buf.sport, *sport); + hnputs(buf.dport, dport); + puts(buf.len, *len); + puts(buf.off, (long)data); + puts(buf.seg, 0); + if(r = pxecall(0x32, &buf)) + return r; + moveip(sip, buf.sip); + *sport = nhgets(buf.sport); + *len = gets(buf.len); + return 0; +} + +static int +udpwrite(IP4 ip, IP4 gw, int sport, int dport, int len, void *data) +{ + struct { + uchar status[2]; + uchar ip[4]; + uchar gw[4]; + uchar sport[2]; + uchar dport[2]; + uchar len[2]; + uchar off[2]; + uchar seg[2]; + } buf; + + puts(buf.status, 0); + moveip(buf.ip, ip); + moveip(buf.gw, gw); + hnputs(buf.sport, sport); + hnputs(buf.dport, dport); + puts(buf.len, len); + puts(buf.off, (long)data); + puts(buf.seg, 0); + return pxecall(0x33, &buf); +} + +int +read(void *f, void *data, int len) +{ + Tftp *t = f; + int seq, n; + + while(!t->eof && t->rp >= t->ep){ + for(;;){ + n = sizeof(t->pkt); + if(udpread(t->dip, t->sip, &t->dport, t->sport, &n, t->pkt)) + continue; + if(n >= 4) + break; + } + switch(nhgets(t->pkt)){ + case Tftp_DATA: + seq = nhgets(t->pkt+2); + if(seq > t->seq){ + putc('?'); + continue; + } + hnputs(t->pkt, Tftp_ACK); + while(udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt)) + putc('!'); + if(seq < t->seq){ + putc('@'); + continue; + } + t->seq = seq+1; + n -= 4; + t->rp = t->pkt + 4; + t->ep = t->rp + n; + t->eof = n < Segsize; + break; + case Tftp_ERROR: + print(t->pkt+4); + print("\n"); + default: + t->eof = 1; + return -1; + } + break; + } + n = t->ep - t->rp; + if(len > n) + len = n; + memmove(data, t->rp, len); + t->rp += len; + return len; +} + +void +close(void *f) +{ + Tftp *t = f; + t->eof = 1; + udpclose(); +} + + +static int +tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip) +{ + static ushort xport = 6666; + int r, n; + char *p; + + moveip(t->sip, sip); + moveip(t->gip, gip); + memset(t->dip, 0, sizeof(t->dip)); + t->sport = xport++; + t->dport = 0; + t->rp = t->ep = 0; + t->seq = 1; + t->eof = 0; + t->nul = 0; + if(r = udpopen(t->sip)) + return r; + p = t->pkt; + hnputs(p, Tftp_READ); p += 2; + n = strlen(path)+1; + memmove(p, path, n); p += n; + memmove(p, "octet", 6); p += 6; + n = p - t->pkt; + for(;;){ + if(r = udpwrite(dip, t->gip, t->sport, TftpPort, n, t->pkt)) + break; + if(r = read(t, 0, 0)) + break; + return 0; + } + close(t); + return r; +} + +void +start(void *) +{ + char mac[16], path[Maxpath], *kern; + IP4 yip, sip, gip; + void *f; + Tftp t; + + if(pxeinit()){ + print("pxe init\n"); + halt(); + } + if(getip(yip, sip, gip, mac)){ + print("bad dhcp\n"); + halt(); + } + memmove(path, "/cfg/pxe/", 9); + memmove(path+9, mac, 13); + if(tftpopen(f = &t, path, yip, sip, gip)) + if(tftpopen(f, "/cfg/pxe/default", yip, sip, gip)){ + print("no config\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(tftpopen(&t, kern, yip, sip, gip)){ + print("not found\n"); + continue; + } + print(bootkern(&t)); + print("\n"); + } +} diff --git a/sys/src/nboot/pc/sub.c b/sys/src/nboot/pc/sub.c new file mode 100644 index 0000000000..0b8380ed7a --- /dev/null +++ b/sys/src/nboot/pc/sub.c @@ -0,0 +1,554 @@ +#include +#include +#include "fns.h" +#include "mem.h" + +void +putc(int c) +{ + cgaputc(c); + if(uart != -1) + uartputc(uart, c); +} + +void +print(char *s) +{ + while(*s != 0){ + if(*s == '\n') + putc('\r'); + putc(*s++); + } +} + +int +readn(void *f, void *data, int len) +{ + uchar *p, *e; + + putc(' '); + p = data; + e = p + len; + while(p < e){ + if(((ulong)p & 0xF000) == 0){ + putc('\b'); + putc(hex[((ulong)p>>16)&0xF]); + } + if((len = read(f, p, e - p)) <= 0) + break; + p += len; + } + putc('\b'); + + return p - (uchar*)data; +} + +void +memmove(void *dst, void *src, int n) +{ + uchar *d = dst; + uchar *s = src; + + if(d < s){ + while(n-- > 0) + *d++ = *s++; + } else if(d > s){ + s += n; + d += n; + while(n-- > 0) + *--d = *--s; + } +} + +int +memcmp(void *src, void *dst, int n) +{ + uchar *d = dst; + uchar *s = src; + int r = 0; + + while(n-- > 0){ + r = *d++ - *s++; + if(r != 0) + break; + } + + return r; +} + +int +strlen(char *s) +{ + char *p = s; + + while(*p != '\0') + p++; + + return p - s; +} + +char* +strchr(char *s, int c) +{ + for(; *s != 0; s++) + if(*s == c) + return s; + + return nil; +} + +void +memset(void *dst, int v, int n) +{ + uchar *d = dst; + + while(n > 0){ + *d++ = v; + n--; + } +} + +int +getc(void) +{ + int c; + + c = kbdgetc(); + if(c == 0 && uart != -1) + c = uartgetc(uart); + return c; +} + +static int +readline(void *f, char *buf) +{ + static char white[] = "\t "; + char *p; + + p = buf; + do{ + if(f == nil) + putc('>'); + for(;;){ + if(f == nil){ + while((*p = getc()) == 0) + ; + if(p == buf && (*p == '\b' || strchr(white, *p) != nil)) + continue; + putc(*p); + if(*p == '\r') + putc('\n'); + else if(*p == '\b'){ + p--; + putc(' '); + putc('\b'); + continue; + } + }else if(read(f, p, 1) <= 0) + return 0; + if(strchr("\r\n", *p) != nil) + break; + if(p == buf && strchr(white, *p) != nil) + continue; /* whitespace on start of line */ + p++; + } + while(p > buf && strchr(white, p[-1])) + p--; + }while(p == buf); + *p = 0; + + return p - buf; +} + +static int +timeout(int ms) +{ + while(ms > 0){ + if(getc() != 0) + return 1; + usleep(100000); + ms -= 100; + } + return 0; +} + +#define BOOTLINE ((char*)CONFADDR) +#define BOOTLINELEN 64 +#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN)) +#define BOOTARGSLEN (4096-0x200-BOOTLINELEN) + +char *confend; + +static void apmconf(int); +static void e820conf(void); +static void ramdiskconf(int); +static void uartconf(char*); + +static char* +getconf(char *s, char *buf) +{ + char *p, *e; + int n; + + n = strlen(s); + for(p = BOOTARGS; p < confend; p = e+1){ + for(e = p+1; e < confend; e++) + if(*e == '\n') + break; + if(memcmp(p, s, n) == 0){ + p += n; + n = e - p; + buf[n] = 0; + memmove(buf, p, n); + return buf; + } + } + return nil; +} + +static int +delconf(char *s) +{ + char *p, *e; + + for(p = BOOTARGS; p < confend; p = e){ + for(e = p+1; e < confend; e++){ + if(*e == '\n'){ + e++; + break; + } + } + if(memcmp(p, s, strlen(s)) == 0){ + memmove(p, e, confend - e); + confend -= e - p; + *confend = 0; + return 1; + } + } + return 0; +} + +char* +configure(void *f, char *path) +{ + char *line, *kern, *s, *p; + int inblock, nowait, n; + static int once = 1; + + if(once){ + once = 0; +Clear: + memset(BOOTLINE, 0, BOOTLINELEN); + + confend = BOOTARGS; + memset(confend, 0, BOOTARGSLEN); + + e820conf(); + ramdiskconf(0); + } + nowait = 1; + inblock = 0; +Loop: + while(readline(f, line = confend+1) > 0){ + if(*line == 0 || strchr("#;=", *line) != nil) + continue; + if(*line == '['){ + inblock = memcmp("[common]", line, 8) != 0; + continue; + } + if(memcmp("boot", line, 5) == 0){ + nowait=1; + break; + } + if(memcmp("wait", line, 5) == 0){ + nowait=0; + continue; + } + if(memcmp("show", line, 5) == 0){ + print(BOOTARGS); + continue; + } + if(memcmp("clear", line, 5) == 0){ + if(line[5] == '\0'){ + print("ok\n"); + goto Clear; + } else if(line[5] == ' ' && delconf(line+6)) + print("ok\n"); + continue; + } + if(inblock != 0 || (p = strchr(line, '=')) == nil) + continue; + *p++ = 0; + delconf(line); + if(memcmp("apm", line, 3) == 0){ + apmconf(line[3] - '0'); + continue; + } + if(memcmp("console", line, 8) == 0) + uartconf(p); + + s = confend; + memmove(confend, line, n = strlen(line)); confend += n; + *confend++ = '='; + memmove(confend, p, n = strlen(p)); confend += n; + *confend++ = '\n'; + *confend = 0; + print(s); + } + kern = getconf("bootfile=", path); + + if(f != nil){ + close(f); + f = nil; + + if(kern != nil && (nowait==0 || timeout(1000))) + goto Loop; + } + + if(kern == nil){ + print("no bootfile\n"); + goto Loop; + } + while((p = strchr(kern, '!')) != nil) + kern = p+1; + + return kern; +} + + +static void +hexfmt(char *s, int i, ulong a) +{ + s += i; + while(i > 0){ + *--s = hex[a&15]; + a >>= 4; + i--; + } +} + +static void +addconfx(char *s, int w, ulong v) +{ + int n; + + n = strlen(s); + memmove(confend, s, n); + hexfmt(confend+n, w, v); + confend += n+w; + *confend = 0; +} + +static void +apmconf(int id) +{ + uchar *a; + char *s; + + a = (uchar*)CONFADDR; + memset(a, 0, 20); + + apm(id); + if(memcmp(a, "APM", 4) != 0) + return; + + s = confend; + + addconfx("apm", 1, id); + addconfx("=ax=", 4, *((ushort*)(a+4))); + addconfx(" ebx=", 8, *((ulong*)(a+12))); + addconfx(" cx=", 4, *((ushort*)(a+6))); + addconfx(" dx=", 4, *((ushort*)(a+8))); + addconfx(" di=", 4, *((ushort*)(a+10))); + addconfx(" esi=", 8, *((ulong*)(a+16))); + + *confend++ = '\n'; + *confend = 0; + + print(s); +} + +static void +e820conf(void) +{ + struct { + uvlong base; + uvlong len; + ulong typ; + ulong ext; + } e; + uvlong v; + ulong bx; + char *s; + + bx=0; + s = confend; + + do{ + bx = e820(bx, &e); + if(e.len != 0 && (e.ext & 3) == 1){ + if(confend == s){ + /* single entry <= 1MB is useless */ + if(bx == 0 && e.typ == 1 && e.len <= 0x100000) + break; + memmove(confend, "*e820=", 6); + confend += 6; + } + addconfx("", 1, e.typ); + v = e.base; + addconfx(" 0x", 8, v>>32); + addconfx("", 8, v&0xffffffff); + v += e.len; + addconfx(" 0x", 8, v>>32); + addconfx("", 8, v&0xffffffff); + *confend++ = ' '; + } + } while(bx); + + if(confend == s) + return; + + *confend++ = '\n'; + *confend = 0; + + print(s); +} + +static int +checksum(void *v, int n) +{ + uchar *p, s; + + s = 0; + p = v; + while(n-- > 0) + s += *p++; + return s; +} + +static void +ramdiskconf(int id) +{ + struct { + /* ACPI header */ + char sig[4]; + u32int len; + uchar revision; + uchar csum; + char oem_id[6]; + char oem_table_id[8]; + u32int oem_revision; + char asl_compiler_id[4]; + u32int asl_compiler_revision; + + u32int safe_hook; + + /* MDI structure */ + u16int bytes; + uchar version_minor; + uchar version_major; + u32int diskbuf; + u32int disksize; + u32int cmdline; + u32int oldint13; + u32int oldint15; + u16int olddosmem; + uchar bootloaderid; + uchar sector_shift; + u16int dpt_ptr; + } *mbft; + int shift; + char *s; + +#define BDA ((uchar*)0x400) + mbft = (void*)((((BDA[0x14]<<8) | BDA[0x13])<<10) - 1024); + for(; (ulong)&mbft->sector_shift < 0xA0000; mbft = (void*)((ulong)mbft + 16)){ + if(memcmp("mBFT", mbft, 4) == 0 + && mbft->len < 1024 && (uchar*)mbft + mbft->len > &mbft->sector_shift + && checksum(mbft, mbft->len) == 0) + goto Found; + } + return; +Found: + shift = mbft->sector_shift; + if(shift == 0) + shift = 9; + + s = confend; + addconfx("ramdisk", 1, id); + addconfx("=0x", 8, mbft->diskbuf); + addconfx(" 0x", 8, mbft->disksize<= '0' && *s <= '3'){ + uart = *s - '0'; + uartinit(uart, (7<<5) | 3); /* b9660 l8 s1 */ + } else + uart = -1; +} + +static ulong +beswal(ulong l) +{ + uchar *p = (uchar*)&l; + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} + +char* +bootkern(void *f) +{ + uchar *e, *d, *t; + ulong n; + Exec ex; + + while(a20() < 0) + print("a20 enable failed\n"); + + if(readn(f, &ex, sizeof(ex)) != sizeof(ex)) + return "bad header"; + + e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL); + switch(beswal(ex.magic)){ + case S_MAGIC: + if(readn(f, e, 8) != 8) + goto Error; + case I_MAGIC: + break; + default: + return "bad magic"; + } + + t = e; + n = beswal(ex.text); + if(readn(f, t, n) != n) + goto Error; + t += n; + d = (uchar*)PGROUND((ulong)t); + memset(t, 0, d - t); + n = beswal(ex.data); + if(readn(f, d, n) != n) + goto Error; + d += n; + t = (uchar*)PGROUND((ulong)d); + t += PGROUND(beswal(ex.bss)); + memset(d, 0, t - d); + + close(f); + unload(); + + print("boot\n"); + + jump(e); + +Error: + return "i/o error"; +} diff --git a/sys/src/nboot/pc/uart.s b/sys/src/nboot/pc/uart.s new file mode 100644 index 0000000000..ac69b0adda --- /dev/null +++ b/sys/src/nboot/pc/uart.s @@ -0,0 +1,35 @@ +#include "x16.h" + +TEXT uartinit(SB), $0 + MOVL c+8(SP), AX + MOVB $0x00, AH + JMP _uartbios + +TEXT uartputc(SB), $0 + MOVL c+8(SP), AX + MOVB $0x01, AH + JMP _uartbios + +TEXT uartgetc(SB), $0 + MOVL p+4(SP), DX + CALL rmode16(SB) + STI + MOVB $0x03, AH + BIOSCALL(0x14) + CALL16(pmode32(SB)) + ANDL $0x8100, AX + MOVL $0x0100, BX + CMPL BX, AX + JE _uartread + XORL AX, AX + RET +_uartread: + MOVB $0x02, AH +_uartbios: + MOVL p+4(SP), DX + CALL rmode16(SB) + STI + BIOSCALL(0x14) + CALL16(pmode32(SB)) + ANDL $0xFF, AX + RET diff --git a/sys/src/nboot/pc/x16.h b/sys/src/nboot/pc/x16.h new file mode 100644 index 0000000000..21edbac46c --- /dev/null +++ b/sys/src/nboot/pc/x16.h @@ -0,0 +1,163 @@ +/* + * Can't write 16-bit code for 8a without getting into + * lots of bother, so define some simple commands and + * output the code directly. + * + * N.B. CALL16(x) kills DI, so don't expect it to be + * saved across calls. + */ +#define rAX 0 /* rX */ +#define rCX 1 +#define rDX 2 +#define rBX 3 +#define rSP 4 /* SP */ +#define rBP 5 /* BP */ +#define rSI 6 /* SI */ +#define rDI 7 /* DI */ + +#define rAL 0 /* rL */ +#define rCL 1 +#define rDL 2 +#define rBL 3 +#define rAH 4 /* rH */ +#define rCH 5 +#define rDH 6 +#define rBH 7 + +#define rES 0 /* rS */ +#define rCS 1 +#define rSS 2 +#define rDS 3 +#define rFS 4 +#define rGS 5 + +#define xSI 4 /* rI (index) */ +#define xDI 5 +#define xBP 6 +#define xBX 7 + +#define rCR0 0 /* rC */ +#define rCR2 2 +#define rCR3 3 +#define rCR4 4 + +#define OP(o, m, ro, rm) BYTE $o; /* op + modr/m byte */ \ + BYTE $(((m)<<6)|((ro)<<3)|(rm)) +#define OPrm(o, r, m) OP(o, 0x00, r, 0x06); /* general r <-> m */ \ + WORD $m; +#define OPrr(o, r0, r1) OP(o, 0x03, r0, r1); /* general r -> r */ + +#define LW(m, rX) OPrm(0x8B, rX, m) /* m -> rX */ +#define LXW(x, rI, r) OP(0x8B, 0x02, r, rI); /* x(rI) -> r */ \ + WORD $x +#define LBPW(x, r) OP(0x8B, 0x02, r, xBP); /* x(rBP) -> r */ \ + WORD $x +#define LB(m, rB) OPrm(0x8A, rB, m) /* m -> r[HL] */ +#define LXB(x, rI, r) OP(0x8A, 0x01, r, rI); /* x(rI) -> r */ \ + BYTE $x +#define LBPB(x, r) OP(0x8A, 0x01, r, xBP); /* x(rBP) -> r */ \ + BYTE $x +#define SW(rX, m) OPrm(0x89, rX, m) /* rX -> m */ +#define SXW(r, x, rI) OP(0x89, 0x02, r, rI); /* r -> x(rI) */ \ + WORD $x +#define SBPW(r, x) OP(0x89, 0x02, r, xBP); /* r -> x(rBP) */ \ + WORD $(x) +#define SBPWI(i, x) OP(0xC7, 0x01, 0, xBP); /* i -> x(rBP) */ \ + BYTE $(x); WORD $(i) +#define STB(rB, m) OPrm(0x88, rB, m) /* rB -> m */ +#define SXB(r, x, rI) OP(0x88, 0x01, r, rI); /* rB -> x(rI) */ \ + BYTE $x +#define SBPB(r, x) OP(0x88, 0x01, r, xBP); /* r -> x(rBP) */ \ + BYTE $x +#define SBPBI(i, x) OP(0xC6, 0x01, 0, xBP); /* i -> x(rBP) */ \ + BYTE $(x); BYTE $(i) +#define LWI(i, rX) BYTE $(0xB8+rX); /* i -> rX */ \ + WORD $i; +#define LBI(i, rB) BYTE $(0xB0+rB); /* i -> r[HL] */ \ + BYTE $i + +#define MW(r0, r1) OPrr(0x89, r0, r1) /* r0 -> r1 */ +#define MFSR(rS, rX) OPrr(0x8C, rS, rX) /* rS -> rX */ +#define MTSR(rX, rS) OPrr(0x8E, rS, rX) /* rX -> rS */ +#define MFCR(rC, rX) BYTE $0x0F; /* rC -> rX */ \ + OP(0x20, 0x03, rC, rX) +#define MTCR(rX, rC) BYTE $0x0F; /* rX -> rC */ \ + OP(0x22, 0x03, rC, rX) + +#define ADC(r0, r1) OPrr(0x11, r0, r1) /* r0 + r1 -> r1 */ +#define ADD(r0, r1) OPrr(0x01, r0, r1) /* r0 + r1 -> r1 */ +#define ADDI(i, r) OP(0x81, 0x03, 0x00, r);/* i+r -> r */ \ + WORD $i; +#define AND(r0, r1) OPrr(0x21, r0, r1) /* r0&r1 -> r1 */ +#define ANDI(i, r) OP(0x81, 0x03, 0x04, r);/* i&r -> r */ \ + WORD $i; +#define CLR(r) OPrr(0x31, r, r) /* r^r -> r */ +#define CLRB(r) OPrr(0x30, r, r) /* r^r -> r */ +#define CMP(r0, r1) OPrr(0x39, r0, r1) /* r1-r0 -> flags */ +#define CMPI(i, r) OP(0x81, 0x03, 0x07, r);/* r-i -> flags */ \ + WORD $i; +#define CMPBR(r0, r1) OPrr(0x38, r0, r1) /* r1-r0 -> flags */ +#define DEC(r) BYTE $(0x48|r) /* r-1 -> r */ +#define DIV(r) OPrr(0xF7, 0x06, r) /* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */ +#define INC(r) BYTE $(0x40|r) /* r+1 -> r */ +#define MUL(r) OPrr(0xF7, 0x04, r) /* r*rAX -> rDX:rAX */ +#define IMUL(r0, r1) BYTE $0x0F; /* r0*r1 -> r1 */ \ + OPrr(0xAF, r1, r0) /* (signed) */ +#define OR(r0, r1) OPrr(0x09, r0, r1) /* r0|r1 -> r1 */ +#define ORB(r0, r1) OPrr(0x08, r0, r1) /* r0|r1 -> r1 */ +#define ORI(i, r) OP(0x81, 0x03, 0x01, r);/* i|r -> r */ \ + WORD $i; +#define ROLI(i, r) OPrr(0xC1, 0x00, r); /* r<<>>i -> r */ \ + BYTE $i; +#define SHLI(i, r) OPrr(0xC1, 0x04, r); /* r< r */ \ + BYTE $i; +#define SHLBI(i, r) OPrr(0xC0, 0x04, r); /* r< r */ \ + BYTE $i; +#define SHRI(i, r) OPrr(0xC1, 0x05, r); /* r>>i -> r */ \ + BYTE $i; +#define SHRBI(i, r) OPrr(0xC0, 0x05, r); /* r>>i -> r */ \ + BYTE $i; +#define SBB(r0, r1) OPrr(0x19, r0, r1) /* r1-r0 -> r1 */ +#define SUB(r0, r1) OPrr(0x29, r0, r1) /* r1-r0 -> r1 */ +#define SUBI(i, r) OP(0x81, 0x03, 0x05, r);/* r-i -> r */ \ + WORD $i; + +#define STOSW STOSL + +#define CALL16(f) LWI(f, rDI); /* &f -> rDI */ \ + BYTE $0xFF; /* (*rDI) */ \ + BYTE $0xD7; +#define FARJUMP16(s, o) BYTE $0xEA; /* jump to ptr16:16 */ \ + WORD $o; WORD $s +#define FARJUMP32(s, o) BYTE $0x66; /* jump to ptr32:16 */ \ + BYTE $0xEA; LONG $o; WORD $s +#define DELAY BYTE $0xEB; /* jmp .+2 */ \ + BYTE $0x00 +#define BIOSCALL(b) INT $b /* INT $b */ + +#define PEEKW BYTE $0x26; /* MOVW rES:[rBX], rAX */ \ + BYTE $0x8B; BYTE $0x07 +#define POKEW BYTE $0x26; /* MOVW rAX, rES:[rBX] */ \ + BYTE $0x89; BYTE $0x07 +#define OUTPORTB(p, d) LBI(d, rAL); /* d -> I/O port p */ \ + BYTE $0xE6; \ + BYTE $p; DELAY +#define PUSHA BYTE $0x60 +#define PUSHR(r) BYTE $(0x50|r) /* r -> (--rSP) */ +#define PUSHS(rS) BYTE $(0x06|((rS)<<3)) /* rS -> (--rSP) */ +#define PUSHI(i) BYTE $0x68; WORD $i; /* i -> --(rSP) */ +#define POPA BYTE $0x61 +#define POPR(r) BYTE $(0x58|r) /* (rSP++) -> r */ +#define POPS(rS) BYTE $(0x07|((rS)<<3)) /* (rSP++) -> r */ +#define NOP BYTE $0x90 /* nop */ + +#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \ + BYTE $0x01; BYTE $0x16; \ + WORD $gdtptr +#define LIDT(idtptr) BYTE $0x0F; /* LIDT */ \ + BYTE $0x01; BYTE $0x1e; \ + WORD $idtptr + +/* operand size switch. */ +#define OPSIZE BYTE $0x66 +#define ADSIZE BYTE $0x67 diff --git a/sys/src/nboot/zynq/boothead.c b/sys/src/nboot/zynq/boothead.c new file mode 100644 index 0000000000..98aed00c77 --- /dev/null +++ b/sys/src/nboot/zynq/boothead.c @@ -0,0 +1,71 @@ +#include +#include + +char *data; +uchar head[0x8c0]; + +void +usage(void) +{ + fprint(2, "usage: %s file\n", argv0); + exits("usage"); +} + +void +u32(int n, u32int p) +{ + head[n] = p; + head[n+1] = p >> 8; + head[n+2] = p >> 16; + head[n+3] = p >> 24; +} + +u32int +gu32(int n) +{ + return head[n] | head[n+1] << 8 | head[n+2] << 16 | head[n+3] << 24; +} + +void +main(int argc, char **argv) +{ + int fd, sz, i; + u32int ck; + + ARGBEGIN { + default: + usage(); + } ARGEND; + + if(argc != 1) + usage(); + fd = open(argv[0], OREAD); + if(fd < 0) + sysfatal("open: %r"); + sz = seek(fd, 0, 2); + if(sz < 0) + sysfatal("seek: %r"); + data = malloc(sz); + if(data == nil) + sysfatal("malloc: %r"); + seek(fd, 0, 0); + if(readn(fd, data, sz) < sz) + sysfatal("read: %r"); + close(fd); + memset(head, 0, sizeof(head)); + + u32(0x20, 0xaa995566); + u32(0x24, 0x584C4E58); + u32(0x30, sizeof(head)); + u32(0x34, sz); + u32(0x40, sz); + ck = 0; + for(i = 0x20; i < 0x48; i += 4) + ck += gu32(i); + u32(0x48, ~ck); + u32(0xa0, -1); + + write(1, head, sizeof(head)); + write(1, data, sz); + exits(nil); +} diff --git a/sys/src/nboot/zynq/dat.h b/sys/src/nboot/zynq/dat.h new file mode 100644 index 0000000000..81cb907498 --- /dev/null +++ b/sys/src/nboot/zynq/dat.h @@ -0,0 +1,11 @@ +enum { + DHCPTIMEOUT = 2000, + ARPTIMEOUT = 1000, + TFTPTIMEOUT = 10000, + + TZERO = 0x80000, + CONFSIZE = 65536, + CONF = TZERO - CONFSIZE, +}; + +#define nelem(x) (sizeof(x)/sizeof(*(x))) diff --git a/sys/src/nboot/zynq/ddr.s b/sys/src/nboot/zynq/ddr.s new file mode 100644 index 0000000000..28686f7026 --- /dev/null +++ b/sys/src/nboot/zynq/ddr.s @@ -0,0 +1,258 @@ +#define OUTPUT_EN (3<<9) +#define DCI_EN (7<<4) +#define INP_VREF (1<<1) +#define INP_DIFF (2<<1) + +TEXT ddriob(SB), $-4 + WORD $(OUTPUT_EN) // DDRIOB_ADDR0 + WORD $(OUTPUT_EN) // DDRIOB_ADDR1 + WORD $(OUTPUT_EN | DCI_EN | INP_VREF) // DDRIOB_DATA0 + WORD $(OUTPUT_EN | DCI_EN | INP_VREF) // DDRIOB_DATA1 + WORD $(OUTPUT_EN | DCI_EN | INP_DIFF) // DDRIOB_DIFF0 + WORD $(OUTPUT_EN | DCI_EN | INP_DIFF) // DDRIOB_DIFF1 + WORD $(OUTPUT_EN) // DDRIOB_CLOCK + WORD $0x0018C61C // DDRIOB_DRIVE_SLEW_ADDR + WORD $0x00F9861C // DDRIOB_DRIVE_SLEW_DATA + WORD $0x00F9861C // DDRIOB_DRIVE_SLEW_DIFF + WORD $0x00F9861C // DDRIOB_DRIVE_SLEW_CLOCK + WORD $0xE60 // DDRIOB_DDR_CTRL + +TEXT ddrdata(SB), $-4 + WORD $0XF8006000 + WORD $0x0001FFFF + WORD $0x00000080 + WORD $0XF8006004 + WORD $0x1FFFFFFF + WORD $0x00081081 + WORD $0XF8006008 + WORD $0x03FFFFFF + WORD $0x03C0780F + WORD $0XF800600C + WORD $0x03FFFFFF + WORD $0x02001001 + WORD $0XF8006010 + WORD $0x03FFFFFF + WORD $0x00014001 + WORD $0XF8006014 + WORD $0x001FFFFF + WORD $0x0004281A + WORD $0XF8006018 + WORD $0xF7FFFFFF + WORD $0x44E458D2 + WORD $0XF800601C + WORD $0xFFFFFFFF + WORD $0x82023965 + WORD $0XF8006020 + WORD $0xFFFFFFFC + WORD $0x2B288290 + WORD $0XF8006024 + WORD $0x0FFFFFFF + WORD $0x0000003C + WORD $0XF8006028 + WORD $0x00003FFF + WORD $0x00002007 + WORD $0XF800602C + WORD $0xFFFFFFFF + WORD $0x00000008 + WORD $0XF8006030 + WORD $0xFFFFFFFF + WORD $0x00040970 + WORD $0XF8006034 + WORD $0x13FF3FFF + WORD $0x00011054 + WORD $0XF8006038 + WORD $0x00001FC3 + WORD $0x00000000 + WORD $0XF800603C + WORD $0x000FFFFF + WORD $0x00000777 + WORD $0XF8006040 + WORD $0xFFFFFFFF + WORD $0xFFF00000 + WORD $0XF8006044 + WORD $0x0FFFFFFF + WORD $0x0F666666 + WORD $0XF8006048 + WORD $0x3FFFFFFF + WORD $0x0003C248 + WORD $0XF8006050 + WORD $0xFF0F8FFF + WORD $0x77010800 + WORD $0XF8006058 + WORD $0x0001FFFF + WORD $0x00000101 + WORD $0XF800605C + WORD $0x0000FFFF + WORD $0x00005003 + WORD $0XF8006060 + WORD $0x000017FF + WORD $0x0000003E + WORD $0XF8006064 + WORD $0x00021FE0 + WORD $0x00020000 + WORD $0XF8006068 + WORD $0x03FFFFFF + WORD $0x00284545 + WORD $0XF800606C + WORD $0x0000FFFF + WORD $0x00001610 + WORD $0XF80060A0 + WORD $0x00FFFFFF + WORD $0x00008000 + WORD $0XF80060A4 + WORD $0xFFFFFFFF + WORD $0x10200802 + WORD $0XF80060A8 + WORD $0x0FFFFFFF + WORD $0x0690CB73 + WORD $0XF80060AC + WORD $0x000001FF + WORD $0x000001FE + WORD $0XF80060B0 + WORD $0x1FFFFFFF + WORD $0x04FFFFFF + WORD $0XF80060B4 + WORD $0x000007FF + WORD $0x00000200 + WORD $0XF80060B8 + WORD $0x01FFFFFF + WORD $0x0020006A + WORD $0XF80060C4 + WORD $0x00000003 + WORD $0x00000003 + WORD $0XF80060C4 + WORD $0x00000003 + WORD $0x00000000 + WORD $0XF80060C8 + WORD $0x000000FF + WORD $0x00000000 + WORD $0XF80060DC + WORD $0x00000001 + WORD $0x00000000 + WORD $0XF80060F0 + WORD $0x0000FFFF + WORD $0x00000000 + WORD $0XF80060F4 + WORD $0x0000000F + WORD $0x00000008 + WORD $0XF8006114 + WORD $0x000000FF + WORD $0x00000000 + WORD $0XF8006118 + WORD $0x7FFFFFFF + WORD $0x40000001 + WORD $0XF800611C + WORD $0x7FFFFFFF + WORD $0x40000001 + WORD $0XF8006120 + WORD $0x7FFFFFFF + WORD $0x40000001 + WORD $0XF8006124 + WORD $0x7FFFFFFF + WORD $0x40000001 + WORD $0XF800612C + WORD $0x000FFFFF + WORD $0x00000000 + WORD $0XF8006130 + WORD $0x000FFFFF + WORD $0x00000000 + WORD $0XF8006134 + WORD $0x000FFFFF + WORD $0x00000000 + WORD $0XF8006138 + WORD $0x000FFFFF + WORD $0x00000000 + WORD $0XF8006140 + WORD $0x000FFFFF + WORD $0x00000035 + WORD $0XF8006144 + WORD $0x000FFFFF + WORD $0x00000035 + WORD $0XF8006148 + WORD $0x000FFFFF + WORD $0x00000035 + WORD $0XF800614C + WORD $0x000FFFFF + WORD $0x00000035 + WORD $0XF8006154 + WORD $0x000FFFFF + WORD $0x00000080 + WORD $0XF8006158 + WORD $0x000FFFFF + WORD $0x00000080 + WORD $0XF800615C + WORD $0x000FFFFF + WORD $0x00000080 + WORD $0XF8006160 + WORD $0x000FFFFF + WORD $0x00000075 + WORD $0XF8006168 + WORD $0x001FFFFF + WORD $0x000000EE + WORD $0XF800616C + WORD $0x001FFFFF + WORD $0x000000E4 + WORD $0XF8006170 + WORD $0x001FFFFF + WORD $0x000000FC + WORD $0XF8006174 + WORD $0x001FFFFF + WORD $0x000000F4 + WORD $0XF800617C + WORD $0x000FFFFF + WORD $0x000000C0 + WORD $0XF8006180 + WORD $0x000FFFFF + WORD $0x000000C0 + WORD $0XF8006184 + WORD $0x000FFFFF + WORD $0x000000C0 + WORD $0XF8006188 + WORD $0x000FFFFF + WORD $0x000000B5 + WORD $0XF8006190 + WORD $0xFFFFFFFF + WORD $0x10040080 + WORD $0XF8006194 + WORD $0x000FFFFF + WORD $0x00007D02 + WORD $0XF8006204 + WORD $0xFFFFFFFF + WORD $0x00000000 + WORD $0XF8006208 + WORD $0x000F03FF + WORD $0x000803FF + WORD $0XF800620C + WORD $0x000F03FF + WORD $0x000803FF + WORD $0XF8006210 + WORD $0x000F03FF + WORD $0x000803FF + WORD $0XF8006214 + WORD $0x000F03FF + WORD $0x000803FF + WORD $0XF8006218 + WORD $0x000F03FF + WORD $0x000003FF + WORD $0XF800621C + WORD $0x000F03FF + WORD $0x000003FF + WORD $0XF8006220 + WORD $0x000F03FF + WORD $0x000003FF + WORD $0XF8006224 + WORD $0x000F03FF + WORD $0x000003FF + WORD $0XF80062A8 + WORD $0x00000FF7 + WORD $0x00000000 + WORD $0XF80062AC + WORD $0xFFFFFFFF + WORD $0x00000000 + WORD $0XF80062B0 + WORD $0x003FFFFF + WORD $0x00005125 + WORD $0xF80062B4 + WORD $0x003FFFFF + WORD $0x000012A8 + WORD $0 diff --git a/sys/src/nboot/zynq/fns.h b/sys/src/nboot/zynq/fns.h new file mode 100644 index 0000000000..283929b9bb --- /dev/null +++ b/sys/src/nboot/zynq/fns.h @@ -0,0 +1,15 @@ +void putc(int); +void puts(char *); +int netboot(void); +int mmcboot(void); +void puthex(u32int); +void memset(void *, char, int); +void memcpy(void *, void *, int); +void print(char *, ...); +u32int u32get(void *); +uchar* u32put(uchar *, u32int); +void jump(void *); +void sleep(int); +void timeren(int); +int timertrig(void); +void flash(void); diff --git a/sys/src/nboot/zynq/fsbl.s b/sys/src/nboot/zynq/fsbl.s new file mode 100644 index 0000000000..4923cdf524 --- /dev/null +++ b/sys/src/nboot/zynq/fsbl.s @@ -0,0 +1,310 @@ +#include "mem.h" + +#define Rb R10 +#define SET(R, V) MOVW $(V), R0 ; MOVW R0, (R)(Rb) +#define RMW(r, m, v) MOVW (r)(Rb), R0; BIC $(m), R0; ORR $(v), R0; MOVW R0, (r)(Rb) + +TEXT _start(SB), $-4 + WORD $0xea000006 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + MOVW $abort(SB), R15 + +TEXT reloc(SB), $-4 + MOVW $(1<<7|1<<6|0x13), R0 + MOVW R0, CPSR + MOVW $STACKTOP, R13 + MOVW $_start(SB), R0 + MCR CpMMU, 0, R0, C(12), C(0) + MOVW $SLCR_BASE, Rb + SET(SLCR_UNLOCK, UNLOCK_KEY) + MOVW $0, R0 + MCR 15, 0, R0, C(8), C(7), 0 + MCR 15, 0, R0, C(7), C(5), 0 + MCR 15, 0, R0, C(7), C(5), 6 + MOVW $0xc5047a, R1 + MCR 15, 0, R1, C(1), C(0), 0 + DSB + ISB + CMP.S $0, R15 + BL.LT reset(SB) + + MOVW $0xf, R1 + MOVW $0xffff0000, R3 + MOVW $0xe58a1910, R0 + MOVW R0, (R3) + MOVW $0xf57ff04f, R0 + MOVW R0, 4(R3) + MOVW $0xf57ff06f, R0 + MOVW R0, 8(R3) + MOVW $0xe28ef000, R0 + MOVW R0, 12(R3) + MOVW $reset(SB), R14 + DSB + ISB + MOVW R3, R15 + +TEXT reset(SB), $-4 + BL pllsetup(SB) + BL miosetup(SB) + BL ddrsetup(SB) + BL uartsetup(SB) + MOVW $SLCR_BASE, Rb + SET(SLCR_LOCK, LOCK_KEY) +// BL memtest(SB) + MOVW $setR12(SB), R12 + BL main(SB) + B abort(SB) + +TEXT pllsetup(SB), $0 + MOVW $SLCR_BASE, Rb + + SET(ARM_PLL_CFG, ARM_PLL_CFG_VAL) + SET(DDR_PLL_CFG, DDR_PLL_CFG_VAL) + SET(IO_PLL_CFG, IO_PLL_CFG_VAL) + + MOVW $(ARM_FDIV | PLL_BYPASS_FORCE), R0 + MOVW R0, ARM_PLL_CTRL(Rb) + ORR $(PLL_RESET), R4 + MOVW R4, ARM_PLL_CTRL(Rb) + MOVW R0, ARM_PLL_CTRL(Rb) + + MOVW $(DDR_FDIV | PLL_BYPASS_FORCE), R0 + MOVW R0, DDR_PLL_CTRL(Rb) + ORR $(PLL_RESET), R4 + MOVW R4, DDR_PLL_CTRL(Rb) + MOVW R0, DDR_PLL_CTRL(Rb) + + MOVW $(IO_FDIV | PLL_BYPASS_FORCE), R0 + MOVW R0, IO_PLL_CTRL(Rb) + ORR $(PLL_RESET), R4 + MOVW R4, IO_PLL_CTRL(Rb) + MOVW R0, IO_PLL_CTRL(Rb) + +_pllsetupl: + MOVW PLL_STATUS(Rb), R0 + AND $7, R0 + CMP.S $7, R0 + BNE _pllsetupl + + SET(ARM_PLL_CTRL, ARM_FDIV) + SET(DDR_PLL_CTRL, DDR_FDIV) + SET(IO_PLL_CTRL, IO_FDIV) + + SET(ARM_CLK_CTRL, 0x1f << 24 | CPU_DIV << 8) + SET(UART_CLK_CTRL, UART_DIV << 8 | 3) + SET(DDR_CLK_CTRL, DDR_DIV3 << 20 | DDR_DIV2 << 26 | 3) + SET(DCI_CLK_CTRL, DCI_DIV0 << 8 | DCI_DIV1 << 20 | 1) + SET(GEM0_RCLK_CTRL, 1) + SET(GEM1_RCLK_CTRL, 0) + SET(GEM0_CLK_CTRL, ETH_DIV0 << 8 | ETH_DIV1 << 20 | 1) + SET(GEM1_CLK_CTRL, 0) + SET(GPIOB_CTRL, VREF_SW_EN) + SET(APER_CLK_CTRL, LQSPI_CLK_EN | GPIO_CLK_EN | UART0_CLK_EN | UART1_CLK_EN | I2C0_CLK_EN | SDIO1_CLK_EN | GEM0_CLK_EN | USB0_CLK_EN | USB1_CLK_EN | DMA_CLK_EN) + SET(SMC_CLK_CTRL, 0x3C20) + SET(LQSPI_CLK_CTRL, QSPI_DIV << 8 | 1) + SET(SDIO_CLK_CTRL, SDIO_DIV << 8 | 2) + SET(SPI_CLK_CTRL, 0x3F00) + SET(CAN_CLK_CTRL, 0x501900) + SET(PCAP_CLK_CTRL, PCAP_DIV << 8 | 1) + RET + +TEXT miosetup(SB), $0 + MOVW $SLCR_BASE, Rb + SET(UART_RST_CTRL, 0xf) + SET(UART_RST_CTRL, 0) + + MOVW $miodata(SB), R1 + ADD $MIO_PIN_0, Rb, R2 + MOVW $54, R3 + BL copy(SB) + + MOVW $0, R0 + MOVW R0, MIO_MST_TRI0(Rb) + MOVW R0, MIO_MST_TRI1(Rb) + RET + +TEXT copy(SB), $0 +_copyl: + MOVW.P 4(R1), R0 + MOVW.P R0, 4(R2) + SUB.S $1, R3 + BNE _copyl + RET + +TEXT ddrsetup(SB), $0 + MOVW $SLCR_BASE, Rb + RMW(DDRIOB_DCI_CTRL, DCI_RESET, DCI_RESET) + RMW(DDRIOB_DCI_CTRL, DCI_RESET, 0) + RMW(DDRIOB_DCI_CTRL, DDRIOB_DCI_CTRL_MASK, DCI_NREF | DCI_ENABLE | DCI_RESET) + + MOVW $ddriob(SB), R1 + ADD $DDRIOB_ADDR0, Rb, R2 + MOVW $12, R3 + BL copy(SB) + + MOVW $ddrdata(SB), R1 +_ddrl1: + MOVW.P 4(R1), R2 + ORR.S $0, R2 + BEQ _ddrl2 + MOVW.P 4(R1), R3 + MOVW.P 4(R1), R4 + AND R3, R4 + MOVW (R2), R0 + BIC R3, R0 + ORR R4, R0 + MOVW R0, (R2) + B _ddrl1 +_ddrl2: + MOVW DDRIOB_DCI_STATUS(Rb), R0 + AND.S $(1<<13), R0 + BEQ _ddrl2 + MOVW $DDR_BASE, Rb + RMW(DDRC_CTRL, 0x1ffff, 0x81) +_ddrl4: + MOVW DDR_MODE_STS(Rb), R0 + AND.S $7, R0 + BEQ _ddrl4 + + MOVW $MP_BASE, Rb + SET(FILTER_START, 0) + RET + +TEXT memtest(SB), $0 + MOVW $0, R0 + ADD $(1024 * 1024 * 10), R0, R1 +_testl: + MOVW R0, (R0) + ADD $4, R0 + CMP.S R0, R1 + BNE _testl + MOVW $0, R0 +_testl2: + MOVW (R0), R2 + CMP.S R0, R2 + BNE _no + ADD $4, R0 + CMP.S R0, R1 + BNE _testl2 + MOVW $'.', R0 + BL putc(SB) + RET +_no: + MOVW $'!', R0 + BL putc(SB) + RET + +TEXT uartsetup(SB), $0 + MOVW $UART1_BASE, Rb + SET(UART_CTRL, 0x17) + SET(UART_MODE, 0x20) + SET(UART_SAMP, 15) + SET(UART_BAUD, 14) + RET + +TEXT putc(SB), $0 + MOVW $UART1_BASE, Rb + CMP.S $10, R0 + BNE _putcl + MOVW R0, R2 + MOVW $13, R0 + BL putc(SB) + MOVW R2, R0 +_putcl: + MOVW UART_STAT(Rb), R1 + AND.S $0x10, R1 + BNE _putcl + AND $0xFF, R0 + MOVW R0, UART_DATA(Rb) + RET + +TEXT jump(SB), $-4 + MOVW R0, R15 + +TEXT abort(SB), $0 + MOVW $'?', R0 + BL putc(SB) +_loop: + WFE + B _loop + +#define TRI 1 +#define LVCMOS18 (1<<9) +#define LVCMOS25 (2<<9) +#define LVCMOS33 (3<<9) +#define HSTL (4<<9) +#define PULLUP (1<<12) +#define NORECV (1<<13) +#define FAST (1<<8) +#define MUX(a, b, c, d) ((a)<<1 | (b)<<2 | (c)<<3 | (d)<<5) + +#define NO (TRI | LVCMOS33) +#define SPI (MUX(1, 0, 0, 0) | LVCMOS33) +#define UART (MUX(0, 0, 0, 7) | LVCMOS33) +#define SD (MUX(0, 0, 0, 4) | LVCMOS33) +#define ETX (MUX(1, 0, 0, 0) | HSTL | NORECV | PULLUP) +#define ERX (MUX(1, 0, 0, 0) | HSTL | TRI | PULLUP) +#define USB (MUX(0, 1, 0, 0) | LVCMOS18) +#define MDCLK (MUX(0, 0, 0, 4) | HSTL) +#define MDDATA (MUX(0, 0, 0, 4) | HSTL) + +TEXT miodata(SB), $-4 + WORD $NO // 0 + WORD $SPI // 1 + WORD $SPI // 2 + WORD $SPI // 3 + WORD $SPI // 4 + WORD $SPI // 5 + WORD $SPI // 6 + WORD $NO // 7 + WORD $UART // 8 + WORD $(UART|TRI) // 9 + WORD $SD // 10 + WORD $SD // 11 + WORD $SD // 12 + WORD $SD // 13 + WORD $SD // 14 + WORD $SD // 15 + WORD $ETX // 16 + WORD $ETX // 17 + WORD $ETX // 18 + WORD $ETX // 19 + WORD $ETX // 20 + WORD $ETX // 21 + WORD $ERX // 22 + WORD $ERX // 23 + WORD $ERX // 24 + WORD $ERX // 25 + WORD $ERX // 26 + WORD $ERX // 27 + WORD $USB // 28 + WORD $USB // 29 + WORD $USB // 30 + WORD $USB // 31 + WORD $USB // 32 + WORD $USB // 33 + WORD $USB // 34 + WORD $USB // 35 + WORD $USB // 36 + WORD $USB // 37 + WORD $USB // 38 + WORD $USB // 39 + WORD $USB // 40 + WORD $USB // 41 + WORD $USB // 42 + WORD $USB // 43 + WORD $USB // 44 + WORD $USB // 45 + WORD $USB // 46 + WORD $USB // 47 + WORD $USB // 48 + WORD $USB // 49 + WORD $USB // 50 + WORD $USB // 51 + WORD $MDCLK // 52 + WORD $MDDATA // 53 diff --git a/sys/src/nboot/zynq/jtagload.c b/sys/src/nboot/zynq/jtagload.c new file mode 100644 index 0000000000..00792b9c3e --- /dev/null +++ b/sys/src/nboot/zynq/jtagload.c @@ -0,0 +1,647 @@ +#include +#include + +typedef struct Tap Tap; +typedef struct Dap Dap; + +struct Tap +{ + int off; + int len; + int delay; + + u32int id; + u32int dapsel; +}; + +struct Dap +{ + Tap *tap; + + uint port; + u32int id; +}; + +int dfd = -1; +int lastbit = -1; + +int irlen; + +int ntaps; +Tap* taps; + +int ndaps; +Dap* daps; + +Dap* ahbap; +Dap* apbap; + +/* MPSSE command bits */ +enum { + FEW = 1<<0, /* -ve CLK on write */ + BITS = 1<<1, /* bits or bytes */ + FER = 1<<2, /* -ve CLK on read */ + LSB = 1<<3, /* LSB first = 1 else MSB first */ + TDI = 1<<4, /* do write TDI */ + TDO = 1<<5, /* do read TDO */ + TMS = 1<<6, /* do write TMS */ +}; + +void +ioinit(char *dev) +{ + uchar b[3]; + + dfd = open(dev, ORDWR); + if(dfd < 0) + sysfatal("open: %r"); + + b[0] = 0x80; + b[1] = 0x08; + b[2] = 0x0B; + write(dfd, b, 3); +} + +void +io(int cmd, int len, uchar *dat) +{ + uchar buf[64]; + uchar *p = buf; + + *p++ = cmd; + *p++ = len-1; + if((cmd & BITS) != 0) + len = 1; + else + *p++ = (len-1)>>8; + if((cmd & (TDI|TMS)) != 0){ + memmove(p, dat, len); + p += len; + } + if(write(dfd, buf, p - buf) != (p - buf)) + sysfatal("io write: %r"); + if((cmd & TDO) != 0) + if(readn(dfd, dat, len) != len) + sysfatal("io read: %r"); +} + +void +dstate(u32int s, int len) +{ + uchar b[1]; + + assert(len < 8); + b[0] = s; + if(lastbit != -1){ + b[0] |= lastbit << 7; + lastbit = -1; + } + io(TMS|LSB|BITS|FEW, len, b); +} +uvlong +dshift(uvlong w, int len) +{ + uchar b[8]; + int c, s, n; + + c = TDI|LSB|FEW; + if(len < 0){ + len = -len; + c |= TDO; + } + s = 0; + n = len/8; + if(n > 0) { + switch(n){ + case 8: b[7] = w >> 56; + case 7: b[6] = w >> 48; + case 6: b[5] = w >> 40; + case 5: b[4] = w >> 32; + case 4: b[3] = w >> 24; + case 3: b[2] = w >> 16; + case 2: b[1] = w >> 8; + case 1: b[0] = w >> 0; + } + io(c, n, b); + s = n*8; + if((c & TDO) != 0){ + w &= ~((1ULL< 0){ + b[0] = w >> s; + c |= BITS; + io(c, len, b); + if((c & TDO) != 0){ + w &= ~((uvlong)((1<> 8-len) << s; + } + s += len; + } + return w & (1ULL<= 64){ + dshift(~0ULL, 64); + len -= 64; + } + dshift(~0ULL, len); +} +int +dshiftdelay(void) +{ + int i; + + /* send ones */ + dshiftones(512); + for(i=0; i<512; i++){ + if(dshift(i != 0, -1) == 0) + return i; + } + return 0; +} + +void +irw(Tap *tap, uvlong w) +{ + /* 0011 -> Shift-IR */ + dstate(0x3, 4); + + dshiftones(tap->off); + if((tap->off + tap->len) == irlen){ + dshift(w, tap->len-1); + lastbit = w >> (tap->len-1); + } else { + dshift(w, tap->len); + dshiftones(irlen - (tap->off + tap->len-1)); + lastbit = 1; + } + + /* 011 -> Idle */ + dstate(0x3, 3); +} +uvlong +drr(Tap *tap, int len) +{ + uvlong w, d; + + /* 001 -> Shift-DR */ + dstate(0x1, 3); + + d = dshift(0, -tap->delay); + w = dshift(0, -len); + dshift(d, tap->delay); + dshift(w, len-1); + lastbit = (w >> len-1) & 1; + + /* 011 -> Idle */ + dstate(0x3, 3); + + return w; +} +void +drw(Tap *tap, uvlong w, int len) +{ + /* 001 -> Shift-DR */ + dstate(0x1, 3); + + dshift(0, tap->delay); + dshift(w, len-1); + lastbit = (w >> len-1) & 1; + + /* 011 -> Idle */ + dstate(0x3, 3); +} + +enum { + ABORT = 0x8, + DPACC = 0xA, + APACC = 0xB, + CTRLSTAT = 0x4, + SELECT = 0x8, + RDBUF = 0xC, +}; + +u32int +dapr(Dap *dap, uchar r, uchar a) +{ + uvlong w; + + irw(dap->tap, r); + w = 1 | (a >> 1) & 0x6; + drw(dap->tap, w, 35); + do { + w = drr(dap->tap, 35); + } while((w & 7) == 1); + return w >> 3; +} +void +dapw(Dap *dap, uchar r, uchar a, u32int v) +{ + uvlong w; + + irw(dap->tap, r); + w = (a >> 1) & 0x6; + w |= (uvlong)v << 3; + drw(dap->tap, w, 35); +} + +void +app(Dap *dap) +{ + enum { + CSYSPWRUPACK = 1<<31, + CSYSPWRUPREQ = 1<<30, + CDBGPWRUPACK = 1<<29, + CDBGPWRUPREQ = 1<<28, + CDBGRSTACK = 1<<27, + CDBGRSTREQ = 1<<26, + }; + u32int s; + + for(;;){ + s = dapr(dap, DPACC, CTRLSTAT); + if((s & (CDBGPWRUPACK|CSYSPWRUPACK)) == (CDBGPWRUPACK|CSYSPWRUPACK)) + break; + s |= CSYSPWRUPREQ|CDBGPWRUPREQ; + dapw(dap, DPACC, CTRLSTAT, s); + } +} +void +apa(Dap *dap, uchar a) +{ + u32int s; + + s = dap->port<<24 | a&0xf0; + if(s != dap->tap->dapsel){ + dap->tap->dapsel = s; + dapw(dap, DPACC, SELECT, s); + app(dap); + } +} +u32int +apr(Dap *dap, uchar a) +{ + apa(dap, a); + return dapr(dap, APACC, a&0xC); +} +void +apw(Dap *dap, uchar a, u32int v) +{ + apa(dap, a); + dapw(dap, APACC, a&0xC, v); +} +u32int +mmr(Dap *ap, u32int addr) +{ + apw(ap, 0x4, addr); + return apr(ap, 0xC); +} +void +mmw(Dap *ap, u32int addr, u32int val) +{ + apw(ap, 0x4, addr); + apw(ap, 0xC, val); +} + +void +tapreset(void) +{ + int i, j, o; + + dstate(0x1F, 6); /* 011111 -> Reset->Idle */ + dstate(0x3, 4); /* 0011 -> Shift-IR */ + + irlen = dshiftdelay(); + lastbit = 1; + + dstate(0x7, 5); /* 00111 -> Shift-IR->Shift-DR */ + + ntaps = dshiftdelay(); + + dstate(0x1F, 6); /* 011111 -> Reset->Idle */ + dstate(0x1, 3); /* 001 -> Shift-DR */ + + taps = realloc(taps, sizeof(taps[0]) * ntaps); + + o = 0; + for(i=ntaps-1; i>=0; i--){ + taps[i].delay = ntaps - i - 1; + taps[i].off = o; + taps[i].id = dshift(0, -32); + switch(taps[i].id){ + default: + sysfatal("unknown tapid %.8ux\n", taps[i].id); + case 0x03727093: + case 0x0373b093: + case 0x23727093: + taps[i].len = 6; + break; + case 0x4ba00477: + taps[i].len = 4; + break; + } + o += taps[i].len; + } + + dstate(0x1F, 6); /* 011111 -> Reset->Idle */ + + if(o != irlen) + sysfatal("wrong tapchain irlen %d %d\n", o, irlen); + + ndaps = 0; + for(i=0; idbgap, arm->dbgbase+reg); +} +void +dbgw(Arm *arm, u32int reg, u32int val) +{ + mmw(arm->dbgap, arm->dbgbase+reg, val); +} +u32int +dbgrpoll(Arm *arm, u32int reg, u32int mask, u32int val) +{ + u32int w; + + for(;;){ + w = dbgr(arm, reg); + if((w & mask) == val) + break; + } + return w; +} + +void +startstop(Arm *arm, int stop) +{ + u32int s; + + s = dbgr(arm, DBGDSCR); + if((s & HALTED) != stop){ + if(!stop){ + s &= ~ITRen; + dbgw(arm, DBGDSCR, s); + } + dbgw(arm, DBGDRCR, stop ? HaltReq : RestartReq); + s = dbgrpoll(arm, DBGDSCR, HALTED, stop); + if(stop){ + s |= ITRen; + dbgw(arm, DBGDSCR, s); + } + fprint(2, "%s: startstop: %.8ux\n", arm->id, s); + } +} + +void +armxec(Arm *arm, u32int instr) +{ + dbgw(arm, DBGITR, instr); + dbgrpoll(arm, DBGDSCR, InstrCompl_1, InstrCompl_1); +} + +#define ARMV4_5_MRC(CP, op1, Rd, CRn, CRm, op2) \ + (0xee100010 | (CRm) | ((op2) << 5) | ((CP) << 8) \ + | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21)) +#define ARMV4_5_MCR(CP, op1, Rd, CRn, CRm, op2) \ + (0xee000010 | (CRm) | ((op2) << 5) | ((CP) << 8) \ + | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21)) + +void +trrxw(Arm *arm, u32int val) +{ + dbgrpoll(arm, DBGDSCR, RXfull_1, 0); + dbgw(arm, DBGDTRRX, val); +} +u32int +trtxr(Arm *arm) +{ + dbgrpoll(arm, DBGDSCR, TXfull_1, TXfull_1); + return dbgr(arm, DBGDTRTX); +} + +void +armrw(Arm *arm, int reg, u32int val); + +u32int +armrr(Arm *arm, int rn) +{ + if(rn == 15){ + u32int r0; + + r0 = armrr(arm, 0); + armxec(arm, 0xE1A0000F); + armxec(arm, ARMV4_5_MCR(14, 0, 0, 0, 5, 0)); + armrw(arm, 0, r0); + } else { + armxec(arm, ARMV4_5_MCR(14, 0, rn, 0, 5, 0)); + } + return trtxr(arm); +} +void +armrw(Arm *arm, int rn, u32int val) +{ + if(rn == 15){ + u32int r0; + + r0 = armrr(arm, 0); + armrw(arm, 0, val); + armxec(arm, 0xE1A0F000); + armrw(arm, 0, r0); + } else { + trrxw(arm, val); + armxec(arm, ARMV4_5_MRC(14, 0, rn, 0, 5, 0)); + } +} + +/* + * mww phys 0xf8000008 0xdf0d + * mww phys 0xf8000910 0xf + * load_image "/sys/src/boot/zynq/fsbl" 0xfffc0000 bin + * reg pc 0xfffc0000 + */ +void +boot(char *file, u32int entry) +{ + u32int *buf, *src; + int fd, size; + u32int dst; + + fprint(2, "load %s", file); + if((fd = open(file, OREAD)) < 0) + sysfatal("open: %r"); + + size = seek(fd, 0, 2); + fprint(2, " [%ud]", size); + seek(fd, 0, 0); + buf = malloc((size+3) & ~3); + if(readn(fd, buf, size) != size) + sysfatal("read: %r"); + close(fd); + + /* map ocm */ + mmw(arm->memap, 0xf8000008, 0xdf0d); + mmw(arm->memap, 0xf8000910, 0xf); + + src = buf; + for(dst = entry; size > 0; dst += 4, size -= 4){ + if((dst & 0xF) == 0) + fprint(2, "."); + mmw(arm->memap, dst, *src++); + } + free(buf); + fprint(2, ".\nentry %.8ux\n", entry); + + armrw(arm, 15, entry); +} + +void +usage(void) +{ + fprint(2, "%s [ -j jtagdev ] entry image\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + char *jtag = "/dev/jtagddd94.0"; + char *image; + u32int entry; + + fmtinstall('H', encodefmt); + + ARGBEGIN { + case 'j': + jtag = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + + if(argc != 2) + usage(); + entry = strtoul(argv[0], nil, 0); + image = argv[1]; + + ioinit(jtag); + tapreset(); + + arm[0].dbgbase = 0x80090000; + arm[0].dbgap = apbap; + arm[0].memap = ahbap; + arm[0].id = "arm0"; + + arm[1].dbgbase = 0x80092000; + arm[1].dbgap = apbap; + arm[1].memap = ahbap; + arm[1].id = "arm1"; + + startstop(arm+0, 1); + startstop(arm+1, 1); + + boot(image, entry); + + startstop(arm+0, 0); + startstop(arm+1, 0); + + exits(nil); +} diff --git a/sys/src/nboot/zynq/main.c b/sys/src/nboot/zynq/main.c new file mode 100644 index 0000000000..f9c0b04dac --- /dev/null +++ b/sys/src/nboot/zynq/main.c @@ -0,0 +1,203 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +void +puts(char *s) +{ + while(*s) + putc(*s++); +} + +void +puthex(u32int u) +{ + static char *dig = "0123456789abcdef"; + int i; + + for(i = 0; i < 8; i++){ + putc(dig[u >> 28]); + u <<= 4; + } +} + +void +putdec(int n) +{ + if(n / 10 != 0) + putdec(n / 10); + putc(n % 10 + '0'); +} + +void +print(char *s, ...) +{ + va_list va; + int n; + u32int u; + + va_start(va, s); + while(*s) + if(*s == '%'){ + switch(*++s){ + case 's': + puts(va_arg(va, char *)); + break; + case 'x': + puthex(va_arg(va, u32int)); + break; + case 'd': + n = va_arg(va, int); + if(n < 0){ + putc('-'); + putdec(-n); + }else + putdec(n); + break; + case 'I': + u = va_arg(va, u32int); + putdec(u >> 24); + putc('.'); + putdec((uchar)(u >> 16)); + putc('.'); + putdec((uchar)(u >> 8)); + putc('.'); + putdec((uchar)u); + break; + case 0: + va_end(va); + return; + } + s++; + }else + putc(*s++); + va_end(va); +} + +void +memset(void *v, char c, int n) +{ + char *vc; + + vc = v; + while(n--) + *vc++ = c; +} + +void +memcpy(void *d, void *s, int n) +{ + char *cd, *cs; + + cd = d; + cs = s; + while(n--) + *cd++ = *cs++; +} + +u32int +u32get(void *pp) +{ + uchar *p; + + p = pp; + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +uchar * +u32put(uchar *p, u32int v) +{ + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v; + return p + 4; +} + +void +run(void) +{ + ulong t, tr; + char *p, *d; + int n; + ulong *h; + + h = (ulong *) TZERO; + if(u32get(&h[0]) != E_MAGIC){ + print("invalid magic: %x != %x\n", u32get(&h[0]), E_MAGIC); + return; + } + t = u32get(&h[1]) + 0x20; + tr = t + 0xfff & ~0xfff; + if(t != tr){ + n = u32get(&h[2]); + p = (char *) (TZERO + t + n); + d = (char *) (TZERO + tr + n); + while(n--) + *--d = *--p; + } + p = (char *) (TZERO + tr + u32get(&h[2])); + memset(p, 0, u32get(&h[3])); + jump((void *) (u32get(&h[5]) & 0xfffffff)); +} + +enum { + TIMERVALL, + TIMERVALH, + TIMERCTL, + TIMERSTAT, + TIMERCOMPL, + TIMERCOMPH, +}; + +void +timeren(int n) +{ + ulong *r; + + r = (ulong *) 0xf8f00200; + if(n < 0){ + r[TIMERSTAT] |= 1; + r[TIMERCTL] = 0; + return; + } + r[TIMERCTL] = 0; + r[TIMERVALL] = 0; + r[TIMERVALH] = 0; + r[TIMERCOMPL] = 1000 * n; + r[TIMERCOMPH] = 0; + r[TIMERSTAT] |= 1; + r[TIMERCTL] = 100 << 8 | 3; +} + +int +timertrig(void) +{ + ulong *r; + + r = (ulong *) 0xf8f00200; + if((r[TIMERSTAT] & 1) != 0){ + r[TIMERCTL] = 0; + r[TIMERSTAT] |= 1; + return 1; + } + return 0; +} + +void +sleep(int n) +{ + timeren(n); + while(!timertrig()) + ; +} + +void +main(void) +{ + puts("Booting ...\n"); + if(mmcboot() > 0 || netboot() > 0) + run(); + print("hjboot: ending\n"); +} diff --git a/sys/src/nboot/zynq/mem.h b/sys/src/nboot/zynq/mem.h new file mode 100644 index 0000000000..9753fc346b --- /dev/null +++ b/sys/src/nboot/zynq/mem.h @@ -0,0 +1,107 @@ +#define STACKTOP 0xFFFFFE00 + +#define ARM_FDIV (40 << PLL_FDIV_SH) +#define DDR_FDIV (32 << PLL_FDIV_SH) +#define IO_FDIV (30 << PLL_FDIV_SH) +#define PLL_CFG_VAL(CP, RES, CNT) ((CP)<<8 | (RES)<<4 | (CNT)<<12) +#define ARM_PLL_CFG_VAL PLL_CFG_VAL(2, 2, 250) +#define DDR_PLL_CFG_VAL PLL_CFG_VAL(2, 2, 300) +#define IO_PLL_CFG_VAL PLL_CFG_VAL(2, 12, 325) +#define PLL_FDIV_SH 12 +#define PLL_BYPASS_FORCE 0x10 +#define PLL_RESET 0x01 + +#define CPU_DIV 2 +#define DDR_DIV3 2 +#define DDR_DIV2 3 +#define UART_DIV 40 +#define DCI_DIV0 20 +#define DCI_DIV1 5 +#define ETH_DIV0 8 +#define ETH_DIV1 1 +#define QSPI_DIV 5 +#define SDIO_DIV 10 +#define PCAP_DIV 5 +#define MDC_DIV 6 /* this value depends on CPU_1xCLK, see TRM GEM.net_cfg description */ + +#define SLCR_BASE 0xF8000000 +#define SLCR_LOCK 0x004 +#define LOCK_KEY 0x767B +#define SLCR_UNLOCK 0x008 +#define UNLOCK_KEY 0xDF0D + +#define ARM_PLL_CTRL 0x100 +#define DDR_PLL_CTRL 0x104 +#define IO_PLL_CTRL 0x108 +#define PLL_STATUS 0x10C +#define ARM_PLL_CFG 0x110 +#define DDR_PLL_CFG 0x114 +#define IO_PLL_CFG 0x118 +#define ARM_CLK_CTRL 0x120 +#define DDR_CLK_CTRL 0x124 +#define DCI_CLK_CTRL 0x128 +#define APER_CLK_CTRL 0x12C +#define GEM0_RCLK_CTRL 0x138 +#define GEM1_RCLK_CTRL 0x13C +#define GEM0_CLK_CTRL 0x140 +#define GEM1_CLK_CTRL 0x144 +#define SMC_CLK_CTRL 0x148 +#define LQSPI_CLK_CTRL 0x14C +#define SDIO_CLK_CTRL 0x150 +#define UART_CLK_CTRL 0x154 +#define SPI_CLK_CTRL 0x158 +#define CAN_CLK_CTRL 0x15C +#define PCAP_CLK_CTRL 0x168 +#define UART_RST_CTRL 0x228 +#define A9_CPU_RST_CTRL 0x244 + +#define LQSPI_CLK_EN (1<<23) +#define GPIO_CLK_EN (1<<22) +#define UART0_CLK_EN (1<<20) +#define UART1_CLK_EN (1<<21) +#define I2C0_CLK_EN (1<<18) +#define SDIO1_CLK_EN (1<<11) +#define GEM0_CLK_EN (1<<6) +#define USB1_CLK_EN (1<<3) +#define USB0_CLK_EN (1<<2) +#define DMA_CLK_EN (1<<0) + +#define MIO_PIN_0 0x00000700 +#define MIO_MST_TRI0 0x80C +#define MIO_MST_TRI1 0x810 +#define OCM_CFG 0x910 +#define GPIOB_CTRL 0xB00 +#define VREF_SW_EN (1<<11) +#define DDRIOB_ADDR0 0xB40 +#define DDRIOB_DCI_CTRL 0xB70 +#define DDRIOB_DCI_CTRL_MASK 0x1ffc3 +#define DDRIOB_DCI_STATUS 0xB74 +#define DCI_RESET 1 +#define DCI_NREF (1<<11) +#define DCI_ENABLE 2 + +#define DDR_BASE 0xF8006000 +#define DDRC_CTRL 0x0 +#define DDR_MODE_STS 0x54 + +#define UART1_BASE 0xE0001000 +#define UART_CTRL 0x0 +#define UART_MODE 0x4 +#define UART_BAUD 0x18 +#define UART_STAT 0x2C +#define UART_DATA 0x30 +#define UART_SAMP 0x34 + +#define QSPI_BASE 0xE000D000 +#define QSPI_CFG 0x0 +#define SPI_EN 0x4 +#define QSPI_TX 0x1c + +#define MP_BASE 0xF8F00000 +#define FILTER_START 0x40 + +#define CpMMU 15 + +#define DSB WORD $0xf57ff04f +#define ISB WORD $0xf57ff06f +#define WFE WORD $0xe320f002 diff --git a/sys/src/nboot/zynq/mkfile b/sys/src/nboot/zynq/mkfile new file mode 100644 index 0000000000..90f503446f --- /dev/null +++ b/sys/src/nboot/zynq/mkfile @@ -0,0 +1,38 @@ +objtype=arm +fsbl.img + +%.$cputype:V: mkfile.port + @{objtype=$cputype mk -f $prereq $target} + +jtagload:V: fsbl jtagload.$cputype + ./jtagload.$cputype -j /dev/jtag*.0 $TEXTBASE fsbl + +div.$O: /sys/src/libc/arm/div.s + $AS /sys/src/libc/arm/div.s + +%.$O: dat.h fns.h mem.h + +%.$O: %.s + $AS $stem.s + +%.$O: %.c + $CC $CFLAGS $stem.c diff --git a/sys/src/nboot/zynq/mkfile.port b/sys/src/nboot/zynq/mkfile.port new file mode 100644 index 0000000000..3b4a019a80 --- /dev/null +++ b/sys/src/nboot/zynq/mkfile.port @@ -0,0 +1,14 @@ + +#include "dat.h" +#include "fns.h" +#include "mem.h" + +enum { + Sectsz = 0x200, + Dirsz = 0x20, + Maxpath = 64, + Fat12 = 1, + Fat16 = 2, + Fat32 = 4, +}; + +typedef struct File File; +typedef struct Dir Dir; +typedef struct Pbs Pbs; +typedef struct Pbs32 Pbs32; +typedef struct Fat Fat; + +struct Fat +{ + ulong ver; + ulong clustsize; + ulong eofmark; + ulong partlba; + ulong fatlba; + ulong dirstart; /* LBA for FAT16, cluster for FAT32 */ + ulong dirents; + ulong datalba; +}; + +struct File +{ + Fat *fat; + ulong lba; + ulong clust; + ulong lbaoff; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + char name[11]; + uchar attr; + uchar reserved; + uchar ctime; + uchar ctime[2]; + uchar cdate[2]; + uchar adate[2]; + uchar starthi[2]; + uchar mtime[2]; + uchar mdate[2]; + uchar startlo[2]; + uchar len[4]; +}; + +struct Pbs +{ + uchar magic[3]; + uchar version[8]; + uchar sectsize[2]; + uchar clustsize; + uchar nreserv[2]; + uchar nfats; + uchar rootsize[2]; + uchar volsize[2]; + uchar mediadesc; + uchar fatsize[2]; + uchar trksize[2]; + uchar nheads[2]; + uchar nhidden[4]; + uchar bigvolsize[4]; + uchar driveno; + uchar reserved0; + uchar bootsig; + uchar volid[4]; + uchar label[11]; + uchar type[8]; +}; + +struct Pbs32 +{ + uchar common[36]; + uchar fatsize[4]; + uchar flags[2]; + uchar ver[2]; + uchar rootclust[4]; + uchar fsinfo[2]; + uchar bootbak[2]; + uchar reserved0[12]; + uchar driveno; + uchar reserved1; + uchar bootsig; + uchar volid[4]; + uchar label[11]; + uchar type[8]; +}; + +enum { + Initfreq = 400000, /* initialisation frequency for MMC */ + SDfreq = 25000000, /* standard SD frequency */ + DTO = 14, /* data timeout exponent (guesswork) */ +}; + +enum { + /* Controller registers */ + Sysaddr = 0x00>>2, + Blksizecnt = 0x04>>2, + Arg1 = 0x08>>2, + Cmdtm = 0x0c>>2, + Resp0 = 0x10>>2, + Resp1 = 0x14>>2, + Resp2 = 0x18>>2, + Resp3 = 0x1c>>2, + Data = 0x20>>2, + Status = 0x24>>2, + Control0 = 0x28>>2, + Control1 = 0x2c>>2, + Interrupt = 0x30>>2, + Irptmask = 0x34>>2, + Irpten = 0x38>>2, + Capabilites = 0x40>>2, + Forceirpt = 0x50>>2, + Boottimeout = 0x60>>2, + Dbgsel = 0x64>>2, + Spiintspt = 0xf0>>2, + Slotisrver = 0xfc>>2, + + /* Control0 */ + Dwidth4 = 1<<1, + Dwidth1 = 0<<1, + + /* Control1 */ + Srstdata = 1<<26, /* reset data circuit */ + Srstcmd = 1<<25, /* reset command circuit */ + Srsthc = 1<<24, /* reset complete host controller */ + Datatoshift = 16, /* data timeout unit exponent */ + Datatomask = 0xF0000, + Clkfreq8shift = 8, /* SD clock base divider LSBs */ + Clkfreq8mask = 0xFF00, + Clkfreqms2shift = 6, /* SD clock base divider MSBs */ + Clkfreqms2mask = 0xC0, + Clkgendiv = 0<<5, /* SD clock divided */ + Clkgenprog = 1<<5, /* SD clock programmable */ + Clken = 1<<2, /* SD clock enable */ + Clkstable = 1<<1, + Clkintlen = 1<<0, /* enable internal EMMC clocks */ + + /* Cmdtm */ + Indexshift = 24, + Suspend = 1<<22, + Resume = 2<<22, + Abort = 3<<22, + Isdata = 1<<21, + Ixchken = 1<<20, + Crcchken = 1<<19, + Respmask = 3<<16, + Respnone = 0<<16, + Resp136 = 1<<16, + Resp48 = 2<<16, + Resp48busy = 3<<16, + Multiblock = 1<<5, + Host2card = 0<<4, + Card2host = 1<<4, + Autocmd12 = 1<<2, + Autocmd23 = 2<<2, + Blkcnten = 1<<1, + Dmaen = 1<<0, + + /* Interrupt */ + Acmderr = 1<<24, + Denderr = 1<<22, + Dcrcerr = 1<<21, + Dtoerr = 1<<20, + Cbaderr = 1<<19, + Cenderr = 1<<18, + Ccrcerr = 1<<17, + Ctoerr = 1<<16, + Err = 1<<15, + Cardintr = 1<<8, + Cardinsert = 1<<6, + Readrdy = 1<<5, + Writerdy = 1<<4, + Dmaintr = 1<<3, + Datadone = 1<<1, + Cmddone = 1<<0, + + /* Status */ + Present = 1<<18, + Bufread = 1<<11, + Bufwrite = 1<<10, + Readtrans = 1<<9, + Writetrans = 1<<8, + Datactive = 1<<2, + Datinhibit = 1<<1, + Cmdinhibit = 1<<0, + + Inittimeout = 15, +// Multiblock = 1, + + /* Commands */ + GO_IDLE_STATE = 0, + ALL_SEND_CID = 2, + SEND_RELATIVE_ADDR= 3, + SELECT_CARD = 7, + SD_SEND_IF_COND = 8, + SEND_CSD = 9, + STOP_TRANSMISSION= 12, + SEND_STATUS = 13, + SET_BLOCKLEN = 16, + READ_SINGLE_BLOCK= 17, + READ_MULTIPLE_BLOCK= 18, + WRITE_BLOCK = 24, + WRITE_MULTIPLE_BLOCK= 25, + APP_CMD = 55, /* prefix for following app-specific commands */ + SET_BUS_WIDTH = 6, + SD_SEND_OP_COND = 41, + + /* Command arguments */ + /* SD_SEND_IF_COND */ + Voltage = 1<<8, + Checkpattern = 0x42, + + /* SELECT_CARD */ + Rcashift = 16, + + /* SD_SEND_OP_COND */ + Hcs = 1<<30, /* host supports SDHC & SDXC */ + Ccs = 1<<30, /* card is SDHC or SDXC */ + V3_3 = 3<<20, /* 3.2-3.4 volts */ + + /* SET_BUS_WIDTH */ + Width1 = 0<<0, + Width4 = 2<<0, + + /* OCR (operating conditions register) */ + Powerup = 1<<31, +}; + +static int cmdinfo[64] = { +[0] Ixchken, +[2] Resp136, +[3] Resp48 | Ixchken | Crcchken, +[6] Resp48 | Ixchken | Crcchken, +[7] Resp48busy | Ixchken | Crcchken, +[8] Resp48 | Ixchken | Crcchken, +[9] Resp136, +[12] Resp48busy | Ixchken | Crcchken, +[13] Resp48 | Ixchken | Crcchken, +[16] Resp48, +[17] Resp48 | Isdata | Card2host | Ixchken | Crcchken | Dmaen, +[18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken | Dmaen, +[24] Resp48 | Isdata | Host2card | Ixchken | Crcchken | Dmaen, +[25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken | Dmaen, +[41] Resp48, +[55] Resp48 | Ixchken | Crcchken, +}; + +typedef struct Ctlr Ctlr; +struct Ctlr { + u32int *regs; + ulong extclk; + + /* SD card registers */ + u16int rca; + u32int ocr; + u32int cid[4]; + u32int csd[4]; +}; +static Ctlr ctlr = { + .regs = (u32int*)0xE0101000, + .extclk = 100000000, +}; + + +static ushort +GETSHORT(void *v) +{ + uchar *p = v; + return p[0] | p[1]<<8; +} +static ulong +GETLONG(void *v) +{ + uchar *p = v; + return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24; +} + +static int +memcmp(void *src, void *dst, int n) +{ + uchar *d = dst; + uchar *s = src; + int r = 0; + + while(n-- > 0){ + r = *d++ - *s++; + if(r != 0) + break; + } + + return r; +} + +static uint +clkdiv(uint d) +{ + uint v; + + v = (d << Clkfreq8shift) & Clkfreq8mask; + v |= ((d >> 8) << Clkfreqms2shift) & Clkfreqms2mask; + return v; +} + +static int +mmcwait(int mask) +{ + int i, t; + + t = 0; + while(((i=ctlr.regs[Interrupt])&mask) == 0) + if(t++ > 10000000) + break; + + return i; +} + +static int +mmccmd(u32int cmd, u32int arg, u32int *resp) +{ + u32int *r; + u32int c; + int i; + + c = (cmd << Indexshift) | cmdinfo[cmd]; + + r = ctlr.regs; + if(r[Status] & Cmdinhibit){ + print("mmc: need to reset Cmdinhibit intr %x stat %x\n", + r[Interrupt], r[Status]); + r[Control1] |= Srstcmd; + while(r[Control1] & Srstcmd) + ; + while(r[Status] & Cmdinhibit) + ; + } + if((c & Isdata || (c & Respmask) == Resp48busy) && r[Status] & Datinhibit){ + print("mmc: need to reset Datinhibit intr %x stat %x\n", + r[Interrupt], r[Status]); + r[Control1] |= Srstdata; + while(r[Control1] & Srstdata) + ; + while(r[Status] & Datinhibit) + ; + } + r[Arg1] = arg; + if((i = r[Interrupt]) != 0){ + if(i != Cardinsert) + print("mmc: before command, intr was %x\n", i); + r[Interrupt] = i; + } + r[Cmdtm] = c; + + i = mmcwait(Cmddone|Err); + if((i&(Cmddone|Err)) != Cmddone){ + if((i&~Err) != Ctoerr) + print("mmc: CMD%d error intr %x stat %x\n", cmd, i, r[Status]); + r[Interrupt] = i; + if(r[Status]&Cmdinhibit){ + r[Control1] |= Srstcmd; + while(r[Control1]&Srstcmd) + ; + } + return -1; + } + r[Interrupt] = i & ~(Datadone|Readrdy|Writerdy); + switch(c & Respmask){ + case Resp136: + resp[0] = r[Resp0]<<8; + resp[1] = r[Resp0]>>24 | r[Resp1]<<8; + resp[2] = r[Resp1]>>24 | r[Resp2]<<8; + resp[3] = r[Resp2]>>24 | r[Resp3]<<8; + break; + case Resp48: + case Resp48busy: + resp[0] = r[Resp0]; + break; + case Respnone: + resp[0] = 0; + break; + } + if((c & Respmask) == Resp48busy){ + r[Irpten] = Datadone|Err; + i = mmcwait(Cmddone|Err); + if(i) + r[Interrupt] = i; + r[Irpten] = 0; + if((i & Datadone) == 0) + print("mmc: no Datadone after CMD%d\n", cmd); + if(i & Err) + print("mmc: CMD%d error interrupt %x\n", cmd, i); + } + + /* + * Once card is selected, use faster clock + */ + if(cmd == SELECT_CARD){ + sleep(10); + r[Control1] = clkdiv(ctlr.extclk / SDfreq - 1) | + DTO << Datatoshift | Clkgendiv | Clken | Clkintlen; + for(i = 0; i < 1000; i++){ + sleep(1); + if(r[Control1] & Clkstable) + break; + } + sleep(10); + } + + /* + * If card bus width changes, change host bus width + */ + if(cmd == SET_BUS_WIDTH) + switch(arg){ + case 0: + r[Control0] &= ~Dwidth4; + break; + case 2: + r[Control0] |= Dwidth4; + break; + } + return 0; +} + +static int +mmconline(void) +{ + u32int r[4]; + int hcs, i; + + mmccmd(GO_IDLE_STATE, 0, r); + + hcs = 0; + if(mmccmd(SD_SEND_IF_COND, Voltage|Checkpattern, r) == 0){ + if(r[0] == (Voltage|Checkpattern)) /* SD 2.0 or above */ + hcs = Hcs; + } + for(i = 0; i < Inittimeout; i++){ + sleep(100); + mmccmd(APP_CMD, 0, r); + mmccmd(SD_SEND_OP_COND, hcs|V3_3, r); + if(r[0] & Powerup) + break; + } + if(i == Inittimeout){ + print("mmc: card won't power up\n"); + return -1; + } + ctlr.ocr = r[0]; + mmccmd(ALL_SEND_CID, 0, r); + memcpy(ctlr.cid, r, sizeof ctlr.cid); + mmccmd(SEND_RELATIVE_ADDR, 0, r); + ctlr.rca = r[0]>>16; + mmccmd(SEND_CSD, ctlr.rca<attr == 0x0F || *d->name <= 0) + return -1; + memcpy(buf, d->name, 8); + x = buf+8; + while(x > buf && x[-1] == ' ') + x--; + if(d->name[8] != ' '){ + *x++ = '.'; + memcpy(x, d->name+8, 3); + x += 3; + } + while(x > buf && x[-1] == ' ') + x--; + *x = 0; + x = buf; + while(c = *x){ + if(c >= 'A' && c <= 'Z'){ + c -= 'A'; + c += 'a'; + } + *x++ = c; + } + return x - buf; +} + +static ulong +dirclust(Dir *d) +{ + return GETSHORT(d->starthi)<<16 | GETSHORT(d->startlo); +} + +static void +fileinit(File *fp, Fat *fat, ulong lba) +{ + fp->fat = fat; + fp->lba = lba; + fp->len = 0; + fp->lbaoff = 0; + fp->clust = ~0U; + fp->rp = fp->ep = fp->buf + Sectsz; +} + +static ulong +readnext(File *fp, ulong clust) +{ + Fat *fat = fp->fat; + uchar tmp[2], *p; + ulong idx, lba; + + if(fat->ver == Fat12) + idx = (3*clust)/2; + else + idx = clust*fat->ver; + lba = fat->fatlba + (idx / Sectsz); + if(mmcread(lba, fp->buf)) + memset(fp->buf, 0xff, Sectsz); + p = &fp->buf[idx % Sectsz]; + if(p == &fp->buf[Sectsz-1]){ + tmp[0] = *p; + if(mmcread(++lba, fp->buf)) + memset(fp->buf, 0xff, Sectsz); + tmp[1] = fp->buf[0]; + p = tmp; + } + if(fat->ver == Fat32) + return GETLONG(p) & 0xfffffff; + idx = GETSHORT(p); + if(fat->ver == Fat12){ + if(clust & 1) + idx >>= 4; + idx &= 0xfff; + } + return idx; +} + +static int +fileread(File *fp, void *data, int len) +{ + Fat *fat = fp->fat; + + if(fp->len > 0 && fp->rp >= fp->ep){ + if(fp->clust != ~0U){ + if(fp->lbaoff % fat->clustsize == 0){ + if(fp->clust < 2 || fp->clust >= fat->eofmark) + return -1; + fp->lbaoff = (fp->clust - 2) * fat->clustsize; + fp->clust = readnext(fp, fp->clust); + fp->lba = fp->lbaoff + fat->datalba; + } + fp->lbaoff++; + } + if(mmcread(fp->lba++, fp->rp = fp->buf)) + return -1; + } + if(fp->len < len) + len = fp->len; + if(len > (fp->ep - fp->rp)) + len = fp->ep - fp->rp; + memcpy(data, fp->rp, len); + fp->rp += len; + fp->len -= len; + return len; +} + +static int +fatwalk(File *fp, Fat *fat, char *path) +{ + char name[Maxpath], *end; + int i, j; + Dir d; + + if(fat->ver == Fat32){ + fileinit(fp, fat, 0); + fp->clust = fat->dirstart; + fp->len = ~0U; + }else{ + fileinit(fp, fat, fat->dirstart); + fp->len = fat->dirents * Dirsz; + } + for(;;){ + if(fileread(fp, &d, Dirsz) != Dirsz) + break; + if((i = dirname(&d, name)) <= 0) + continue; + while(*path == '/') + path++; + for(end = path; *end != '\0'; end++) + if(*end == '/') + break; + j = end - path; + if(i == j && memcmp(name, path, j) == 0){ + fileinit(fp, fat, 0); + fp->clust = dirclust(&d); + fp->len = GETLONG(d.len); + if(*end == 0) + return 0; + else if(d.attr & 0x10){ + fp->len = fat->clustsize * Sectsz; + path = end; + continue; + } + break; + } + } + return -1; +} + +static int +conffat(Fat *fat, void *buf) +{ + Pbs *p = buf; + uint fatsize, volsize, datasize, reserved; + uint ver, dirsize, dirents, clusters; + + if(GETSHORT(p->sectsize) != Sectsz) + return -1; + if(memcmp(p->type, "FAT", 3) && memcmp(((Pbs32*)buf)->type, "FAT", 3)) + return -1; + + /* load values from fat */ + ver = 0; + fatsize = GETSHORT(p->fatsize); + if(fatsize == 0){ + fatsize = GETLONG(((Pbs32*)buf)->fatsize); + ver = Fat32; + } + volsize = GETSHORT(p->volsize); + if(volsize == 0) + volsize = GETLONG(p->bigvolsize); + reserved = GETSHORT(p->nreserv); + dirents = GETSHORT(p->rootsize); + dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz; + datasize = volsize - (reserved + fatsize * p->nfats + dirsize); + clusters = datasize / p->clustsize; + if(ver != Fat32) + if(clusters < 0xff7) + ver = Fat12; + else + ver = Fat16; + + /* fill FAT descriptor */ + fat->ver = ver; + fat->dirents = dirents; + fat->clustsize = p->clustsize; + fat->fatlba = fat->partlba + reserved; + fat->dirstart = fat->fatlba + fatsize * p->nfats; + if(ver == Fat32){ + fat->datalba = fat->dirstart; + fat->dirstart = GETLONG(((Pbs32*)buf)->rootclust); + fat->eofmark = 0xffffff7; + }else{ + fat->datalba = fat->dirstart + dirsize; + if(ver == Fat16) + fat->eofmark = 0xfff7; + else + fat->eofmark = 0xff7; + } + return 0; +} + +static int +findfat(Fat *fat, ulong xbase, ulong lba) +{ + struct { + uchar status; + uchar bchs[3]; + uchar typ; + uchar echs[3]; + uchar lba[4]; + uchar len[4]; + } p[4]; + uchar buf[Sectsz]; + int i; + + if(xbase == 0) + xbase = lba; + if(mmcread(lba, buf)) + return -1; + if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA) + return -1; + memcpy(p, &buf[0x1be], sizeof(p)); + for(i=0; i<4; i++){ + switch(p[i].typ){ + case 0x05: + case 0x0f: + case 0x85: + /* extended partitions */ + if(!findfat(fat, xbase, xbase + GETLONG(p[i].lba))) + return 0; + /* no break */ + case 0x00: + continue; + default: + fat->partlba = lba + GETLONG(p[i].lba); + if(mmcread(fat->partlba, buf)) + continue; + if(!conffat(fat, buf)) + return 0; + } + } + return -1; +} + +static int +load(Fat *fat, char *path, void *data) +{ + uchar *p; + File fi; + int n; + + print("%s", path); + if(fatwalk(&fi, fat, path)){ + print(": not found\n", path); + return -1; + } + print("..."); + p = data; + while((n = fileread(&fi, p, Sectsz)) > 0) + p += n; + print("\n"); + return p - (uchar*)data; +} + +int +mmcboot(void) +{ + char file[Maxpath], *p; + Fat fat; + + if(mmcinit() < 0) + return 0; + if(findfat(&fat, 0, 0)){ + print("no fat\n"); + return 0; + } + memcpy(file, "9zynq", 6); + memset(p = (char*)CONF, 0, CONFSIZE); + p += load(&fat, "plan9.ini", p); + p -= 9; /* "bootfile=" */ + while(--p >= (char*)CONF){ + while(p > (char*)CONF && p[-1] != '\n') + p--; + if(memcmp("bootfile=", p, 9) == 0){ + p += 9; + memcpy(file, p, sizeof(file)-1); + for(p=file; p < &file[sizeof(file)-1]; p++) + if(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + break; + *p = '\0'; + break; + } + } + return load(&fat, file, (void*)TZERO) > 0; +} diff --git a/sys/src/nboot/zynq/net.c b/sys/src/nboot/zynq/net.c new file mode 100644 index 0000000000..120b0e37d6 --- /dev/null +++ b/sys/src/nboot/zynq/net.c @@ -0,0 +1,577 @@ +#include +#include "dat.h" +#include "fns.h" +#include "mem.h" + +enum { + ETHLEN = 1600, + UDPLEN = 576, + NRX = 64, + RXBASE = 128 * 1024 * 1024, + + ETHHEAD = 14, + IPHEAD = 20, + UDPHEAD = 8, + + BOOTREQ = 1, + DHCPDISCOVER = 1, + DHCPOFFER, + DHCPREQUEST, + DHCPDECLINE, +}; + +enum { + NET_CTRL, + NET_CFG, + NET_STATUS, + DMA_CFG = 4, + TX_STATUS, + RX_QBAR, + TX_QBAR, + RX_STATUS, + INTR_STATUS, + INTR_EN, + INTR_DIS, + INTR_MASK, + PHY_MAINT, + RX_PAUSEQ, + TX_PAUSEQ, + HASH_BOT = 32, + HASH_TOP, + SPEC_ADDR1_BOT, + SPEC_ADDR1_TOP, +}; + +enum { + MDCTRL, + MDSTATUS, + MDID1, + MDID2, + MDAUTOADV, + MDAUTOPART, + MDAUTOEX, + MDAUTONEXT, + MDAUTOLINK, + MDGCTRL, + MDGSTATUS, + MDPHYCTRL = 0x1f, +}; + +enum { + /* NET_CTRL */ + RXEN = 1<<2, + TXEN = 1<<3, + MDEN = 1<<4, + STARTTX = 1<<9, + /* NET_CFG */ + SPEED = 1<<0, + FDEN = 1<<1, + RX1536EN = 1<<8, + GIGE_EN = 1<<10, + RXCHKSUMEN = 1<<24, + /* NET_STATUS */ + PHY_IDLE = 1<<2, + /* DMA_CFG */ + TXCHKSUMEN = 1<<11, + /* TX_STATUS */ + TXCOMPL = 1<<5, + /* MDCTRL */ + MDRESET = 1<<15, + AUTONEG = 1<<12, + FULLDUP = 1<<8, + /* MDSTATUS */ + LINK = 1<<2, + /* MDGSTATUS */ + RECVOK = 3<<12, +}; + +typedef struct { + uchar edest[6]; + uchar esrc[6]; + ulong idest; + ulong isrc; + ushort dport, sport; + ushort len; + uchar data[UDPLEN]; +} udp; + +static ulong *eth0 = (ulong *) 0xe000b000; +static int phyaddr = 7; + +static u32int myip, dhcpip, tftpip, xid; +static uchar mac[6] = {0x0E, 0xA7, 0xDE, 0xAD, 0xBE, 0xEF}; +static uchar tmac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static char file[128]; + +static udp ubuf, urbuf; +static uchar txbuf[ETHLEN]; +static ulong txdesc[4], *txact, *rxact; +static ulong rxdesc[NRX*2]; + +void +mdwrite(ulong *r, int reg, u16int val) +{ + while((r[NET_STATUS] & PHY_IDLE) == 0) + ; + r[PHY_MAINT] = 1<<30 | 1<<28 | 1<<17 | phyaddr << 23 | reg << 18 | val; + while((r[NET_STATUS] & PHY_IDLE) == 0) + ; +} + +u16int +mdread(ulong *r, int reg) +{ + while((r[NET_STATUS] & PHY_IDLE) == 0) + ; + r[PHY_MAINT] = 1<<30 | 1<<29 | 1<<17 | phyaddr << 23 | reg << 18; + while((r[NET_STATUS] & PHY_IDLE) == 0) + ; + return r[PHY_MAINT]; +} + +void +ethinit(ulong *r) +{ + int v; + ulong *p; + ulong d; + + r[NET_CTRL] = 0; + r[RX_STATUS] = 0xf; + r[TX_STATUS] = 0xff; + r[INTR_DIS] = 0x7FFFEFF; + r[RX_QBAR] = r[TX_QBAR] = 0; + r[NET_CFG] = MDC_DIV << 18 | FDEN | SPEED | RX1536EN | GIGE_EN | RXCHKSUMEN; + r[SPEC_ADDR1_BOT] = mac[0] | mac[1] << 8 | mac[2] << 16 | mac[3] << 24; + r[SPEC_ADDR1_TOP] = mac[4] | mac[5] << 8; + r[DMA_CFG] = TXCHKSUMEN | 0x18 << 16 | 1 << 10 | 3 << 8 | 0x10; + + txdesc[0] = 0; + txdesc[1] = 1<<31; + txdesc[2] = 0; + txdesc[3] = 1<<31 | 1<<30; + txact = txdesc; + r[TX_QBAR] = (ulong) txdesc; + for(p = rxdesc, d = RXBASE; p < rxdesc + nelem(rxdesc); d += ETHLEN){ + *p++ = d; + *p++ = 0; + } + p[-2] |= 2; + rxact = rxdesc; + r[RX_QBAR] = (ulong) rxdesc; + + r[NET_CTRL] = MDEN; +// mdwrite(r, MDCTRL, MDRESET); + mdwrite(r, MDCTRL, AUTONEG); + if((mdread(r, MDSTATUS) & LINK) == 0){ + puts("Waiting for Link ...\n"); + while((mdread(r, MDSTATUS) & LINK) == 0) + ; + } + *(u32int*)(SLCR_BASE + SLCR_UNLOCK) = UNLOCK_KEY; + v = mdread(r, MDPHYCTRL); + if((v & 0x40) != 0){ + puts("1000BASE-T"); + while((mdread(r, MDGSTATUS) & RECVOK) != RECVOK) + ; + r[NET_CFG] |= GIGE_EN; + *(u32int*)(SLCR_BASE + GEM0_CLK_CTRL) = 1 << 20 | 8 << 8 | 1; + }else if((v & 0x20) != 0){ + puts("100BASE-TX"); + r[NET_CFG] = r[NET_CFG] & ~GIGE_EN | SPEED; + *(u32int*)(SLCR_BASE + GEM0_CLK_CTRL) = 5 << 20 | 8 << 8 | 1; + }else if((v & 0x10) != 0){ + puts("10BASE-T"); + r[NET_CFG] = r[NET_CFG] & ~(GIGE_EN | SPEED); + *(u32int*)(SLCR_BASE + GEM0_CLK_CTRL) = 20 << 20 | 20 << 8 | 1; + }else + puts("???"); + *(u32int*)(SLCR_BASE + SLCR_UNLOCK) = LOCK_KEY; + if((v & 0x08) != 0) + puts(" Full Duplex\n"); + else{ + puts(" Half Duplex\n"); + r[NET_CFG] &= ~FDEN; + } + r[NET_CTRL] |= TXEN | RXEN; +} + +void +ethtx(ulong *r, uchar *buf, int len) +{ + txact[0] = (ulong) buf; + txact[1] = 1<<15 | len; + if(txact == txdesc + nelem(txdesc) - 2){ + txact[1] |= 1<<30; + txact = txdesc; + }else + txact += 2; + r[TX_STATUS] = -1; + r[NET_CTRL] |= STARTTX; + while((r[TX_STATUS] & TXCOMPL) == 0) + ; +} + +void +udptx(ulong *r, udp *u) +{ + uchar *p, *q; + int n; + + p = q = txbuf; + memcpy(p, u->edest, 6); + memcpy(p + 6, u->esrc, 6); + q += 12; + *q++ = 8; + *q++ = 0; + + *q++ = 5 | 4 << 4; + *q++ = 0; + n = IPHEAD + UDPHEAD + u->len; + *q++ = n >> 8; + *q++ = n; + + *q++ = 0x13; + *q++ = 0x37; + *q++ = 1<<6; + *q++ = 0; + + *q++ = 1; + *q++ = 0x11; + *q++ = 0; + *q++ = 0; + q = u32put(q, u->isrc); + q = u32put(q, u->idest); + + *q++ = u->sport >> 8; + *q++ = u->sport; + *q++ = u->dport >> 8; + *q++ = u->dport; + n = UDPHEAD + u->len; + *q++ = n >> 8; + *q++ = n; + *q++ = 0; + *q++ = 0; + + memcpy(q, u->data, u->len); + ethtx(r, p, ETHHEAD + IPHEAD + UDPHEAD + u->len); +} + +void +dhcppkg(ulong *r, int t) +{ + uchar *p; + udp *u; + + u = &ubuf; + p = u->data; + *p++ = BOOTREQ; + *p++ = 1; + *p++ = 6; + *p++ = 0; + p = u32put(p, xid); + p = u32put(p, 0x8000); + memset(p, 0, 16); + u32put(p + 8, dhcpip); + p += 16; + memcpy(p, mac, 6); + p += 6; + memset(p, 0, 202); + p += 202; + *p++ = 99; + *p++ = 130; + *p++ = 83; + *p++ = 99; + + *p++ = 53; + *p++ = 1; + *p++ = t; + if(t == DHCPREQUEST){ + *p++ = 50; + *p++ = 4; + p = u32put(p, myip); + *p++ = 54; + *p++ = 4; + p = u32put(p, dhcpip); + } + + *p++ = 0xff; + + memset(u->edest, 0xff, 6); + memcpy(u->esrc, mac, 6); + u->sport = 68; + u->dport = 67; + u->idest = -1; + u->isrc = 0; + u->len = p - u->data; + udptx(r, u); +} + +uchar * +ethrx(void) +{ + while((*rxact & 1) == 0) + if(timertrig()) + return nil; + return (uchar *) (*rxact & ~3); +} + +void +ethnext(void) +{ + *rxact &= ~1; + if((*rxact & 2) != 0) + rxact = rxdesc; + else + rxact += 2; +} + +void +arp(int op, uchar *edest, ulong idest) +{ + uchar *p; + static uchar broad[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + p = txbuf; + if(edest == nil) + edest = broad; + memcpy(p, edest, 6); + memcpy(p + 6, mac, 6); + p[12] = 8; + p[13] = 6; + p += 14; + p = u32put(p, 0x00010800); + p = u32put(p, 0x06040000 | op); + memcpy(p, mac, 6); + p = u32put(p + 6, myip); + memcpy(p, edest, 6); + p = u32put(p + 6, idest); + ethtx(eth0, txbuf, p - txbuf); +} + +void +arpc(uchar *p) +{ + p += 14; + if(u32get(p) != 0x00010800 || p[4] != 6 || p[5] != 4 || p[6] != 0) + return; + switch(p[7]){ + case 1: + if(myip != 0 && u32get(p + 24) == myip) + arp(2, p + 8, u32get(p + 14)); + break; + case 2: + if(tftpip != 0 && u32get(p + 14) == tftpip) + memcpy(tmac, p + 8, 6); + break; + } +} + +udp * +udprx(void) +{ + uchar *p; + ulong v; + udp *u; + + u = &urbuf; + for(;; ethnext()){ + p = ethrx(); + if(p == nil) + return nil; + if(p[12] != 8) + continue; + if(p[13] == 6){ + arpc(p); + continue; + } + if(p[13] != 0) + continue; + p += ETHHEAD; + if((p[0] >> 4) != 4 || p[9] != 0x11) + continue; + v = u32get(p + 16); + if(v != (ulong) -1 && v != myip) + continue; + u->idest = v; + u->isrc = u32get(p + 12); + p += (p[0] & 0xf) << 2; + u->sport = p[0] << 8 | p[1]; + u->dport = p[2] << 8 | p[3]; + u->len = p[4] << 8 | p[5]; + if(u->len < 8) + continue; + u->len -= 8; + if(u->len >= sizeof(u->data)) + u->len = sizeof(u->data); + memcpy(u->data, p + 8, u->len); + ethnext(); + return u; + } +} + +void +arpreq(void) +{ + uchar *p; + + arp(1, nil, tftpip); + timeren(ARPTIMEOUT); + for(;; ethnext()){ + p = ethrx(); + if(p == nil){ + print("ARP timeout\n"); + timeren(ARPTIMEOUT); + arp(1, nil, tftpip); + } + if(p[12] != 8 || p[13] != 6) + continue; + arpc(p); + if(tmac[0] != 0xff) + break; + } + timeren(-1); +} + +void +dhcp(ulong *r) +{ + udp *u; + uchar *p; + uchar type; + + xid = 0xdeadbeef; + tftpip = 0; + dhcppkg(r, DHCPDISCOVER); + timeren(DHCPTIMEOUT); + for(;;){ + u = udprx(); + if(u == nil){ + timeren(DHCPTIMEOUT); + dhcppkg(r, DHCPDISCOVER); + print("DHCP timeout\n"); + } + p = u->data; + if(u->dport != 68 || p[0] != 2 || u32get(p + 4) != xid || u32get(p + 236) != 0x63825363) + continue; + p += 240; + type = 0; + dhcpip = 0; + for(; p < u->data + u->len && *p != 0xff; p += 2 + p[1]) + switch(*p){ + case 53: + type = p[2]; + break; + case 54: + dhcpip = u32get(p + 2); + break; + } + if(type != DHCPOFFER) + continue; + p = u->data; + if(p[108] == 0){ + print("Offer from %I for %I with no boot file\n", dhcpip, u32get(p + 16)); + continue; + } + myip = u32get(p + 16); + tftpip = u32get(p + 20); + memcpy(file, p + 108, 128); + print("Offer from %I for %I with boot file '%s' at %I\n", dhcpip, myip, file, tftpip); + break; + } + timeren(-1); + dhcppkg(r, DHCPREQUEST); +} + +udp * +tftppkg(void) +{ + udp *u; + + u = &ubuf; + memcpy(u->edest, tmac, 6); + memcpy(u->esrc, mac, 6); + u->idest = tftpip; + u->isrc = myip; + u->sport = 69; + u->dport = 69; + return u; +} + +void +tftp(ulong *r, char *q, uintptr base) +{ + udp *u, *v; + uchar *p; + int bn, len; + +restart: + u = tftppkg(); + p = u->data; + *p++ = 0; + *p++ = 1; + do + *p++ = *q; + while(*q++ != 0); + memcpy(p, "octet", 6); + p += 6; + u->len = p - u->data; + udptx(r, u); + timeren(TFTPTIMEOUT); + + for(;;){ + v = udprx(); + if(v == nil){ + print("TFTP timeout"); + goto restart; + } + if(v->dport != 69 || v->isrc != tftpip || v->idest != myip) + continue; + if(v->data[0] != 0) + continue; + switch(v->data[1]){ + case 3: + bn = v->data[2] << 8 | v->data[3]; + len = v->len - 4; + if(len < 0) + continue; + if(len > 512) + len = 512; + memcpy((char*)base + ((bn - 1) << 9), v->data + 4, len); + if((bn & 127) == 0) + putc('.'); + p = u->data; + *p++ = 0; + *p++ = 4; + *p++ = bn >> 8; + *p = bn; + u->len = 4; + udptx(r, u); + if(len < 512){ + putc(10); + timeren(-1); + return; + } + timeren(TFTPTIMEOUT); + break; + case 5: + v->data[v->len - 1] = 0; + print("TFTP error: %s\n", v->data + 4); + timeren(-1); + return; + } + } +} + +int +netboot(void) +{ + ethinit(eth0); + myip = 0; + dhcp(eth0); + arpreq(); + tftp(eth0, file, TZERO); + memset((void *) CONF, 0, CONFSIZE); + tftp(eth0, "/cfg/pxe/0ea7deadbeef", CONF); + return 1; +} diff --git a/sys/src/nboot/zynq/qspi.c b/sys/src/nboot/zynq/qspi.c new file mode 100644 index 0000000000..6134592ce4 --- /dev/null +++ b/sys/src/nboot/zynq/qspi.c @@ -0,0 +1,45 @@ +#include +#include "dat.h" +#include "fns.h" + +enum { + QSPI_CFG, + QSPI_STATUS, + QSPI_EN = 5, + QSPI_TXD4 = 7, + QSPI_RXD, + QSPI_TXD1 = 32, + QSPI_TXD2, + QSPI_TXD3 +}; + +#define QSPI0 ((void *) 0xE000D000) + +static u32int +cmd(ulong *r, int sz, u32int c) +{ + if(sz == 4) + r[QSPI_TXD4] = c; + else + r[QSPI_TXD1 + sz - 1] = c; + r[QSPI_CFG] |= 1<<16; + while((r[QSPI_STATUS] & (1<<2|1<<4)) != (1<<2|1<<4)) + ; + return r[QSPI_RXD]; +} + +void +flash(void) +{ + ulong *r; + + r = QSPI0; + r[QSPI_CFG] = 1<<31 | 1<<19 | 3<<6 | 1<<15 | 1<<14 | 1<<10 | 1<<3 | 1; + r[QSPI_CFG] &= ~(1<<10); + r[QSPI_EN] = 1; + cmd(r, 1, 0x06); +// cmd(r, 3, 0xD8); + for(;;) + print("%x\n", cmd(r, 2, 0x05)); + +} From d8e4bf3c64aa24a9cb098d372b809ecacc1eb522 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 18 Jan 2022 03:05:36 +0000 Subject: [PATCH 092/402] sys/src/cmd/aux/realemu: import real mode emulator (thanks Cinap Lenrek) --- sys/man/8/realemu | 108 +++ sys/src/cmd/aux/mkfile | 3 +- sys/src/cmd/aux/realemu/arg.c | 163 ++++ sys/src/cmd/aux/realemu/dat.h | 363 ++++++++ sys/src/cmd/aux/realemu/decode.c | 625 +++++++++++++ sys/src/cmd/aux/realemu/fmt.c | 385 ++++++++ sys/src/cmd/aux/realemu/fns.h | 31 + sys/src/cmd/aux/realemu/loadcom.c | 43 + sys/src/cmd/aux/realemu/main.c | 796 +++++++++++++++++ sys/src/cmd/aux/realemu/mkfile | 9 + sys/src/cmd/aux/realemu/notes | 22 + sys/src/cmd/aux/realemu/pit.c | 357 ++++++++ sys/src/cmd/aux/realemu/vgalist | 9 + sys/src/cmd/aux/realemu/xec.c | 1363 +++++++++++++++++++++++++++++ 14 files changed, 4276 insertions(+), 1 deletion(-) create mode 100644 sys/man/8/realemu create mode 100644 sys/src/cmd/aux/realemu/arg.c create mode 100644 sys/src/cmd/aux/realemu/dat.h create mode 100644 sys/src/cmd/aux/realemu/decode.c create mode 100644 sys/src/cmd/aux/realemu/fmt.c create mode 100644 sys/src/cmd/aux/realemu/fns.h create mode 100644 sys/src/cmd/aux/realemu/loadcom.c create mode 100644 sys/src/cmd/aux/realemu/main.c create mode 100644 sys/src/cmd/aux/realemu/mkfile create mode 100644 sys/src/cmd/aux/realemu/notes create mode 100644 sys/src/cmd/aux/realemu/pit.c create mode 100644 sys/src/cmd/aux/realemu/vgalist create mode 100644 sys/src/cmd/aux/realemu/xec.c diff --git a/sys/man/8/realemu b/sys/man/8/realemu new file mode 100644 index 0000000000..1b0fd3df9f --- /dev/null +++ b/sys/man/8/realemu @@ -0,0 +1,108 @@ +.TH REALEMU 8 +.SH NAME +realemu \- software emulation of /dev/realmode +.SH SYNOPSIS +.B aux/realemu +[ +.B -Dpt +] [ +.B -s +.I srvname +] [ +.B -m +.I mountpoint +] +.SH DESCRIPTION +.PP +Originally, kernel provided +.B /dev/realmode +files with the +.IR arch (3) +device to access and call the +.SM BIOS. +.PP +Interrupts had to be disabled and the processor was switched in the +legacy 16-bit +.SM realmode +with memory protection disabled to execute +.SM BIOS +code. +.PP +This is problematic in case the +.SM BIOS +reprograms hardware currently +used by the operating system or when it reenables interrupts or just +crashes. This will freeze or reboot the machine with no way to +recover or diagnose the problem. +.PP +To avoid this, +.I realemu +is used to emulate the execution of the +.SM BIOS +routines by interpreting the machine instructions and intercepting +dangerous actions that would compromise the systems stability. +.PP +Running +.I realemu +with no arguments, it mounts itself before +.B /dev +and +replaces the original +.B /dev/realmode +file in the current namespace. +.PP +Then programs like +.IR vga (8) +can use it to make their +.SM BIOS +calls. +.PP +The +.B D +flag will enable debug messages for 9P. The +.B p +and +.B t +flags +control tracing of i/o port access and cpu instructions to +stderr (fd 2). +.PP +When a +.I srvname +is given with the +.B s +argument, the default +.I mountpoint +is ignored and a +.SM 9P +channel is created in +.B /srv +that can be used to mount +the filesystem from another namespace. If a +.I mountpoint +is given before +the +.I srvname +argument then it is ignored, otherwise it will be used. +.SH EXAMPLES +The +.I realemu +process is only needed when accessing +.B /dev/realmode. +To invoke a subshell so that +.I realemu +exits normally after +.B aux/vga +completes: +.IP +.EX +% @{rfork n; aux/realemu; aux/vga -m vesa -l $vgasize} +.EE +.SH SOURCE +.B /sys/src/cmd/aux/realemu +.SH "SEE ALSO" +.IR vga (8), +.IR arch (3) +.SH HISTORY +.I Realemu +first appeared in 9front (April, 2011). diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index 5ab65c9169..b5700f0c70 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -54,7 +54,8 @@ DIRS=mnihongo\ gps\ na\ vga\ - vmware + vmware\ + realemu all:V: $DIRS diff --git a/sys/src/cmd/aux/realemu/arg.c b/sys/src/cmd/aux/realemu/arg.c new file mode 100644 index 0000000000..4a67e864bd --- /dev/null +++ b/sys/src/cmd/aux/realemu/arg.c @@ -0,0 +1,163 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +#define ause(cpu) (cpu->abuf + (cpu->iabuf++ % nelem(cpu->abuf))) + +Iarg* +adup(Iarg *x) +{ + Iarg *a; + + a = ause(x->cpu); + *a = *x; + return a; +} + +Iarg* +areg(Cpu *cpu, uchar len, uchar reg) +{ + Iarg *a; + + a = ause(cpu); + a->cpu = cpu; + a->tag = TREG; + a->len = len; + a->reg = reg; + return a; +} + +Iarg* +amem(Cpu *cpu, uchar len, uchar sreg, ulong off) +{ + Iarg *a; + + a = ause(cpu); + a->cpu = cpu; + a->tag = TMEM; + a->len = len; + a->sreg = sreg; + a->seg = cpu->reg[sreg]; + a->off = off; + return a; +} + +Iarg* +afar(Iarg *mem, uchar len, uchar alen) +{ + Iarg *a, *p; + + p = adup(mem); + p->len = alen; + a = amem(mem->cpu, len, R0S, ar(p)); + p->off += alen; + p->len = 2; + a->seg = ar(p); + return a; +} + +Iarg* +acon(Cpu *cpu, uchar len, ulong val) +{ + Iarg *a; + + a = ause(cpu); + a->cpu = cpu; + a->tag = TCON; + a->len = len; + a->val = val; + return a; +} + +ulong +ar(Iarg *a) +{ + ulong w, o; + Bus *io; + + switch(a->tag){ + default: + abort(); + case TMEM: + o = ((a->seg<<4) + (a->off & 0xFFFF)) & 0xFFFFF; + io = a->cpu->mem + (o>>16); + w = io->r(io->aux, o, a->len); + break; + case TREG: + w = a->cpu->reg[a->reg]; + break; + case TREG|TH: + w = a->cpu->reg[a->reg] >> 8; + break; + case TCON: + w = a->val; + break; + } + switch(a->len){ + default: + abort(); + case 1: + w &= 0xFF; + break; + case 2: + w &= 0xFFFF; + break; + case 4: + break; + } + return w; +} + +long +ars(Iarg *a) +{ + ulong w = ar(a); + switch(a->len){ + default: + abort(); + case 1: + return (char)w; + case 2: + return (short)w; + case 4: + return (long)w; + } +} + +void +aw(Iarg *a, ulong w) +{ + ulong *p, o; + Cpu *cpu; + Bus *io; + + cpu = a->cpu; + switch(a->tag){ + default: + abort(); + case TMEM: + o = ((a->seg<<4) + (a->off & 0xFFFF)) & 0xFFFFF; + io = cpu->mem + (o>>16); + io->w(io->aux, o, w, a->len); + break; + case TREG: + p = cpu->reg + a->reg; + switch(a->len){ + case 4: + *p = w; + break; + case 2: + *p = (*p & ~0xFFFF) | (w & 0xFFFF); + break; + case 1: + *p = (*p & ~0xFF) | (w & 0xFF); + break; + } + break; + case TREG|TH: + p = cpu->reg + a->reg; + *p = (*p & ~0xFF00) | (w & 0xFF)<<8; + break; + } +} diff --git a/sys/src/cmd/aux/realemu/dat.h b/sys/src/cmd/aux/realemu/dat.h new file mode 100644 index 0000000000..8a2bb46438 --- /dev/null +++ b/sys/src/cmd/aux/realemu/dat.h @@ -0,0 +1,363 @@ +typedef struct Iarg Iarg; +typedef struct Inst Inst; +typedef struct Bus Bus; +typedef struct Cpu Cpu; +typedef struct Pit Pit; + +enum { + RAX, + RCX, + RDX, + RBX, + RSP, + RBP, + RSI, + RDI, + + RES, + RCS, + RSS, + RDS, + RFS, + RGS, + + R0S, /* 0 segment */ + + RIP, + RFL, + + NREG, +}; + +struct Iarg +{ + Cpu *cpu; + + uchar tag; + uchar len; + uchar atype; + + union { + uchar reg; + struct { + uchar sreg; + ulong seg, off; + }; + ulong val; + }; +}; + +struct Inst +{ + uchar op; + uchar code; + uchar olen; + uchar alen; + + Iarg *a1, *a2, *a3; + + uchar rep; + + uchar mod; + uchar reg; + uchar rm; + + uchar scale; + uchar index; + uchar base; + + uchar sreg; + uchar dsreg; + + ulong off; + long disp; +}; + +struct Bus +{ + void *aux; + ulong (*r)(void *aux, ulong off, int len); + void (*w)(void *aux, ulong off, ulong data, int len); +}; + +struct Cpu +{ + ulong reg[NREG]; + + /* instruction counter */ + ulong ic; + + /* mem[16], one entry for each 64k block */ + Bus *mem; + + /* port[1], in/out */ + Bus *port; + + int trap; + ulong oldip; + jmp_buf jmp; + + /* default operand, address and stack pointer length */ + uchar olen, alen, slen; + + /* argument buffers */ + ulong iabuf; + Iarg abuf[0x80]; +}; + +struct Pit +{ + ulong count; + + /* set by setgate(), cleared by clockpit() */ + uchar gateraised; + + /* signals */ + uchar gate; + uchar out; + + /* mode and flags */ + uchar count0; + + uchar bcd; + uchar amode; + uchar omode; + + /* latch for wpit initial count */ + uchar wcount; + uchar wlatched; + uchar wlatch[2]; + + /* latch for rpit status/count */ + uchar rcount; + uchar rlatched; + uchar rlatch[2]; +}; + +/* processor flags */ +enum { + CF = 1<<0, /* carry flag */ + PF = 1<<2, /* parity flag */ + AF = 1<<4, /* aux carry flag */ + ZF = 1<<6, /* zero flag */ + SF = 1<<7, /* sign flag */ + TF = 1<<8, /* trap flag */ + IF = 1<<9, /* interrupts enabled flag */ + DF = 1<<10, /* direction flag */ + OF = 1<<11, /* overflow flag */ + IOPL= 3<<12, /* I/O privelege level */ + NT = 1<<14, /* nested task */ + RF = 1<<16, /* resume flag */ + VM = 1<<17, /* virtual-8086 mode */ + AC = 1<<18, /* alignment check */ + VIF = 1<<19, /* virtual interrupt flag */ + VIP = 1<<20, /* virtual interrupt pending */ + ID = 1<<21, /* ID flag */ +}; + +/* interrupts/traps */ +enum { + EDIV0, + EDEBUG, + ENMI, + EBRK, + EINTO, + EBOUND, + EBADOP, + ENOFPU, + EDBLF, + EFPUSEG, + EBADTSS, + ENP, + ESTACK, + EGPF, + EPF, + + EHALT = 256, /* pseudo-interrupts */ + EMEM, + EIO, +}; + +/* argument tags */ +enum { + TREG, + TMEM, + TCON, + + TH = 0x80, /* special flag for AH,BH,CH,DH */ +}; + +/* argument types */ +enum { + ANONE, /* no argument */ + A0, /* constant 0 */ + A1, /* constant 1 */ + A2, /* constant 2 */ + A3, /* constant 3 */ + A4, /* constant 4 */ + AAp, /* 32-bit or 48-bit direct address */ + AEb, /* r/m8 from modrm byte */ + AEv, /* r/m16 or r/m32 from modrm byte */ + AEw, /* r/m16 */ + AFv, /* flag word */ + AGb, /* r8 from modrm byte */ + AGv, /* r16 or r32 from modrm byte */ + AGw, /* r/m16 */ + AIb, /* immediate byte */ + AIc, /* immediate byte sign-extended */ + AIw, /* immediate 16-bit word */ + AIv, /* immediate 16-bit or 32-bit word */ + AJb, /* relative offset byte */ + AJv, /* relative offset 16-bit or 32-bit word */ + AJr, /* r/m16 or r/m32 register */ + AM, /* memory address from modrm */ + AMa, /* something for bound */ + AMa2, + AMp, /* 32-bit or 48-bit memory address */ + AOb, /* immediate word-sized offset to a byte */ + AOv, /* immediate word-size offset to a word */ + ASw, /* segment register selected by r field of modrm */ + AXb, /* byte at DS:SI */ + AXv, /* word at DS:SI */ + AYb, /* byte at ES:DI */ + AYv, /* word at ES:DI */ + + AAL, + ACL, + ADL, + ABL, + AAH, + ACH, + ADH, + ABH, + + AAX, + ACX, + ADX, + ABX, + ASP, + ABP, + ASI, + ADI, + + AES, + ACS, + ASS, + ADS, + AFS, + AGS, + + NATYPE, +}; + +/* operators */ +enum { + OBAD, + O0F, + OAAA, + OAAD, + OAAM, + OAAS, + OADC, + OADD, + OAND, + OARPL, + OASIZE, + OBOUND, + OBT, + OBTS, + OBTR, + OBTC, + OBSF, + OBSR, + OCALL, + OCBW, + OCLC, + OCLD, + OCLI, + OCMC, + OCMOV, + OCMP, + OCMPS, + OCPUID, + OCWD, + ODAA, + ODAS, + ODEC, + ODIV, + OENTER, + OGP1, + OGP2, + OGP3b, + OGP3v, + OGP4, + OGP5, + OGP8, + OGP10, + OGP12, + OHLT, + OIDIV, + OIMUL, + OIN, + OINC, + OINS, + OINT, + OIRET, + OJUMP, + OLAHF, + OLEA, + OLEAVE, + OLFP, + OLOCK, + OLODS, + OLOOP, + OLOOPNZ, + OLOOPZ, + OMOV, + OMOVS, + OMOVZX, + OMOVSX, + OMUL, + ONEG, + ONOP, + ONOT, + OOR, + OOSIZE, + OOUT, + OOUTS, + OPOP, + OPOPA, + OPOPF, + OPUSH, + OPUSHA, + OPUSHF, + ORCL, + ORCR, + OREPE, + OREPNE, + ORET, + ORETF, + OROL, + OROR, + OSAHF, + OSAR, + OSBB, + OSCAS, + OSEG, + OSET, + OSHL, + OSHLD, + OSHR, + OSHRD, + OSTC, + OSTD, + OSTI, + OSTOS, + OSUB, + OTEST, + OWAIT, + OXCHG, + OXLAT, + OXOR, + NUMOP, +}; diff --git a/sys/src/cmd/aux/realemu/decode.c b/sys/src/cmd/aux/realemu/decode.c new file mode 100644 index 0000000000..035e449bb4 --- /dev/null +++ b/sys/src/cmd/aux/realemu/decode.c @@ -0,0 +1,625 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +typedef struct Optab Optab; +struct Optab { + uchar op; + uchar a1, a2, a3; +}; + +static Optab optab[256] = { +//00 + {OADD, AEb, AGb}, {OADD, AEv, AGv}, {OADD, AGb, AEb}, {OADD, AGv, AEv}, + {OADD, AAL, AIb}, {OADD, AAX, AIv}, {OPUSH, AES, }, {OPOP, AES }, + {OOR, AEb, AGb}, {OOR, AEv, AGv}, {OOR, AGb, AEb}, {OOR, AGv, AEv}, + {OOR, AAL, AIb}, {OOR, AAX, AIv}, {OPUSH, ACS, }, {O0F, }, +//10 + {OADC, AEb, AGb}, {OADC, AEv, AGv}, {OADC, AGb, AEb}, {OADC, AGv, AEv}, + {OADC, AAL, AIb}, {OADC, AAX, AIv}, {OPUSH, ASS, }, {OPOP, ASS, }, + {OSBB, AEb, AGb}, {OSBB, AEv, AGv}, {OSBB, AGb, AEb}, {OSBB, AGv, AEv}, + {OSBB, AAL, AIb}, {OSBB, AAX, AIv}, {OPUSH, ADS, }, {OPOP, ADS, }, +//20 + {OAND, AEb, AGb}, {OAND, AEv, AGv}, {OAND, AGb, AEb}, {OAND, AGv, AEv}, + {OAND, AAL, AIb}, {OAND, AAX, AIv}, {OSEG, AES, }, {ODAA, }, + {OSUB, AEb, AGb}, {OSUB, AEv, AGv}, {OSUB, AGb, AEb}, {OSUB, AGv, AEv}, + {OSUB, AAL, AIb}, {OSUB, AAX, AIv}, {OSEG, ACS, }, {ODAS, }, +//30 + {OXOR, AEb, AGb}, {OXOR, AEv, AGv}, {OXOR, AGb, AEb}, {OXOR, AGv, AEv}, + {OXOR, AAL, AIb}, {OXOR, AAX, AIv}, {OSEG, ASS, }, {OAAA, }, + {OCMP, AEb, AGb}, {OCMP, AEv, AGv}, {OCMP, AGb, AEb}, {OCMP, AGv, AEv}, + {OCMP, AAL, AIb}, {OCMP, AAX, AIv}, {OSEG, ADS, }, {OAAS, }, +//40 + {OINC, AAX, }, {OINC, ACX, }, {OINC, ADX, }, {OINC, ABX, }, + {OINC, ASP, }, {OINC, ABP, }, {OINC, ASI, }, {OINC, ADI, }, + {ODEC, AAX, }, {ODEC, ACX, }, {ODEC, ADX, }, {ODEC, ABX, }, + {ODEC, ASP, }, {ODEC, ABP, }, {ODEC, ASI, }, {ODEC, ADI, }, +//50 + {OPUSH, AAX, }, {OPUSH, ACX, }, {OPUSH, ADX, }, {OPUSH, ABX, }, + {OPUSH, ASP, }, {OPUSH, ABP, }, {OPUSH, ASI, }, {OPUSH, ADI, }, + {OPOP, AAX, }, {OPOP, ACX, }, {OPOP, ADX, }, {OPOP, ABX, }, + {OPOP, ASP, }, {OPOP, ABP, }, {OPOP, ASI, }, {OPOP, ADI, }, +//60 + {OPUSHA, }, {OPOPA, }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw}, + {OSEG, AFS, }, {OSEG, AGS, }, {OOSIZE, }, {OASIZE, }, + {OPUSH, AIv, }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb, }, {OIMUL,AGv,AEv,AIb}, + {OINS, AYb, ADX}, {OINS, AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv}, +//70 + {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, + {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, + {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, + {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, +//80 + {OGP1, AEb, AIb}, {OGP1, AEv, AIv}, {OGP1, AEb, AIb}, {OGP1, AEv, AIc}, + {OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv}, + {OMOV, AEb, AGb}, {OMOV, AEv, AGv}, {OMOV, AGb, AEb}, {OMOV, AGv, AEv}, + {OMOV, AEw, ASw}, {OLEA, AGv, AM }, {OMOV, ASw, AEw}, {OGP10, }, +//90 + {ONOP, }, {OXCHG, ACX, AAX}, {OXCHG, ADX, AAX}, {OXCHG, ABX, AAX}, + {OXCHG, ASP, AAX}, {OXCHG, ABP, AAX}, {OXCHG, ASI, AAX}, {OXCHG, ADI, AAX}, + {OCBW, }, {OCWD, }, {OCALL, AAp, }, {OWAIT, }, + {OPUSHF,AFv, }, {OPOPF, AFv, }, {OSAHF, AAH, }, {OLAHF, AAH, }, +//A0 + {OMOV, AAL, AOb}, {OMOV, AAX, AOv}, {OMOV, AOb, AAL}, {OMOV, AOv, AAX}, + {OMOVS, AYb, AXb}, {OMOVS, AYv, AXv}, {OCMPS, AYb, AXb}, {OCMPS, AYv, AXv}, + {OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX}, + {OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AYb, AAL}, {OSCAS, AYv, AAX}, +//B0 + {OMOV, AAL, AIb}, {OMOV, ACL, AIb}, {OMOV, ADL, AIb}, {OMOV, ABL, AIb}, + {OMOV, AAH, AIb}, {OMOV, ACH, AIb}, {OMOV, ADH, AIb}, {OMOV, ABH, AIb}, + {OMOV, AAX, AIv}, {OMOV, ACX, AIv}, {OMOV, ADX, AIv}, {OMOV, ABX, AIv}, + {OMOV, ASP, AIv}, {OMOV, ABP, AIv}, {OMOV, ASI, AIv}, {OMOV, ADI, AIv}, +//C0 + {OGP2, AEb, AIb}, {OGP2, AEv, AIb}, {ORET, AIw, }, {ORET, A0, }, + {OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OGP12, AEb, AIb}, {OGP12, AEv, AIv}, + {OENTER,AIw, AIb}, {OLEAVE, }, {ORETF, AIw, }, {ORETF, A0, }, + {OINT, A3, }, {OINT, AIb, }, {OINT, A4, }, {OIRET, }, +//D0 + {OGP2, AEb, A1 }, {OGP2, AEv, A1 }, {OGP2, AEb, ACL}, {OGP2, AEv, ACL}, + {OAAM, AIb, }, {OAAD, AIb, }, {OBAD, }, {OXLAT, AAL, ABX}, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//E0 + {OLOOPNZ,AJb, }, {OLOOPZ,AJb, }, {OLOOP, AJb, }, {OJUMP, AJb, }, + {OIN, AAL, AIb}, {OIN, AAX, AIb}, {OOUT, AIb, AAL}, {OOUT, AIb, AAX}, + {OCALL, AJv, }, {OJUMP, AJv, }, {OJUMP, AAp, }, {OJUMP, AJb, }, + {OIN, AAL, ADX}, {OIN, AAX, ADX}, {OOUT, ADX, AAL}, {OOUT, ADX, AAX}, +//F0 + {OLOCK, }, {OBAD, }, {OREPNE, }, {OREPE, }, + {OHLT, }, {OCMC, }, {OGP3b, }, {OGP3v, }, + {OCLC, }, {OSTC, }, {OCLI, }, {OSTI, }, + {OCLD, }, {OSTD, }, {OGP4, }, {OGP5, }, +}; + +static Optab optab0F[256] = { +//00 + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//10 - mostly floating point and quadword moves + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//20 - doubleword <-> control register moves, other arcana + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//40 - conditional moves + {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, + {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, + {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, + {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, +//50 - floating point, mmx stuff + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//60 - floating point, mmx stuff + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//70 - floating point, mmx stuff + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//80 - long-displacement jumps + {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, + {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, + {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, + {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, +//90 - conditional byte set + {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, + {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, + {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, + {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, +//A0 + {OPUSH, AFS, }, {OPOP, AFS, }, {OCPUID, }, {OBT, AEv, AGv}, + {OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD, }, {OBAD, }, + {OPUSH, AGS, }, {OPOP, AGS, }, {OBAD, }, {OBTS, AEv, AGv}, + {OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD, }, {OIMUL, AGv,AGv,AEv}, +//B0 - mostly arcana + {OBAD, }, {OBAD, }, {OLFP,ASS,AGv,AMp},{OBTR,AEv,AGv }, + {OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OMOVZX,AGv,AEb }, {OMOVZX,AGv,AEw }, + {OBAD, }, {OBAD, }, {OGP8, }, {OBAD, }, + {OBSF,AGv,AEv }, {OBSR,AGv,AEv }, {OMOVSX,AGv,AEb }, {OMOVSX,AGv,AEw }, +//C0 - more arcana + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//D0 - mmx + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//E0 - mmx + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +//F0 - mmx + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +}; + +/* some operands map to whole groups; group numbers from intel opcode map */ +/* args filled in already (in OGP1 entries) */ +static Optab optabgp1[8] = { + {OADD, }, {OOR, }, {OADC, }, {OSBB, }, + {OAND, }, {OSUB, }, {OXOR, }, {OCMP, }, +}; + +/* args filled in already (in OGP2 entries) */ +static Optab optabgp2[8] = { + {OROL, }, {OROR, }, {ORCL, }, {ORCR, }, + {OSHL, }, {OSHR, }, {OBAD, }, {OSAR, }, +}; + +static Optab optabgp3b[8] = { + {OTEST, AEb, AIb}, {OBAD, }, {ONOT, AEb, }, {ONEG, AEb, }, + {OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb, }, {OIDIV, AEb, }, +}; + +static Optab optabgp3v[8] = { + {OTEST, AEv, AIv}, {OBAD, }, {ONOT, AEv, }, {ONEG, AEv, }, + {OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv, }, {OIDIV, AEv, }, +}; + +static Optab optabgp4[8] = { + {OINC, AEb, }, {ODEC, AEb, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +}; + +static Optab optabgp5[8] = { + {OINC, AEv, }, {ODEC, AEv, }, {OCALL, AEv, }, {OCALL, AMp }, + {OJUMP, AEv, }, {OJUMP, AMp, }, {OPUSH, AEv, }, {OBAD, }, +}; + +static Optab optabgp8[8] = { + {OMOV, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBT, AEv, AIb }, {OBTS, AEv, AIb }, {OBTR, AEv, AIb }, {OBTC, AEv, AIb }, +}; + +static Optab optabgp10[8] = { + {OPOP, AEv, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +}; + +static Optab optabgp12[8] = { + {OMOV, }, {OBAD, }, {OBAD, }, {OBAD, }, + {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, }, +}; + +/* optabg6 unimplemented - mostly segment manipulation */ +/* optabg7 unimplemented - more segment manipulation */ +/* optabg8 unimplemented - bit tests */ + +/* + * most of optabg9 - optabg16 decode differently depending on the mod value of + * the modrm byte. they're mostly arcane instructions so they're not + * implemented. + */ + +static Optab *optabgp[NUMOP] = { + [OGP1] optabgp1, + [OGP2] optabgp2, + [OGP3b] optabgp3b, + [OGP3v] optabgp3v, + [OGP4] optabgp4, + [OGP5] optabgp5, + [OGP8] optabgp8, + [OGP10] optabgp10, + [OGP12] optabgp12, +}; + +static uchar modrmarg[NATYPE] = { + [AEb] 1, + [AEw] 1, + [AEv] 1, + [AGb] 1, + [AGw] 1, + [AGv] 1, + [AM] 1, + [AMp] 1, + [AMa] 1, + [AMa2] 1, + [ASw] 1, + [AJr] 1, +}; + +static void +getmodrm16(Iarg *ip, Inst *i) +{ + Iarg *p; + uchar b; + + b = ar(ip); ip->off++; + + i->mod = b>>6; + i->reg = (b>>3)&7; + i->rm = b&7; + + if(i->mod == 3) + return; + + switch(i->rm){ + case 0: + i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RSI)); + i->off &= 0xFFFF; + break; + case 1: + i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RDI)); + i->off &= 0xFFFF; + break; + case 2: + i->dsreg = RSS; + i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RSI)); + i->off &= 0xFFFF; + break; + case 3: + i->dsreg = RSS; + i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RDI)); + i->off &= 0xFFFF; + break; + case 4: + i->off = ar(areg(ip->cpu, 2, RSI)); + break; + case 5: + i->off = ar(areg(ip->cpu, 2, RDI)); + break; + case 6: + if(i->mod == 0){ + p = adup(ip); ip->off += 2; + p->len = 2; + i->off = ar(p); + return; + } + i->dsreg = RSS; + i->off = ar(areg(ip->cpu, 2, RBP)); + break; + case 7: + i->off = ar(areg(ip->cpu, 2, RBX)); + break; + } + switch(i->mod){ + case 1: + i->off += (i->disp = ars(ip)); ip->off++; + i->off &= 0xFFFF; + break; + case 2: + p = adup(ip); ip->off += 2; + p->len = 2; + i->off += (i->disp = ars(p)); + i->off &= 0xFFFF; + break; + } +} + +static void +getmodrm32(Iarg *ip, Inst *i) +{ + static uchar scaler[] = {1, 2, 4, 8}; + Iarg *p; + uchar b; + + b = ar(ip); ip->off++; + + i->mod = b>>6; + i->reg = (b>>3)&7; + i->rm = b&7; + + if(i->mod == 3) + return; + + switch(i->rm){ + case 0: + case 1: + case 2: + case 3: + case 6: + case 7: + i->off = ar(areg(ip->cpu, 4, i->rm + RAX)); + break; + case 4: + b = ar(ip); ip->off++; + i->scale = b>>6; + i->index = (b>>3)&7; + i->base = b&7; + + if(i->base != 5){ + i->off = ar(areg(ip->cpu, 4, i->base + RAX)); + break; + } + case 5: + if(i->mod == 0){ + p = adup(ip); ip->off += 4; + p->len = 4; + i->off = ar(p); + } else { + i->dsreg = RSS; + i->off = ar(areg(ip->cpu, 4, RBP)); + } + break; + } + + if(i->rm == 4 && i->index != 4) + i->off += ar(areg(ip->cpu, 4, i->index + RAX)) * scaler[i->scale]; + + switch(i->mod){ + case 1: + i->off += (i->disp = ars(ip)); ip->off++; + break; + case 2: + p = adup(ip); ip->off += 4; + p->len = 4; + i->off += (i->disp = ars(p)); + break; + } +} + +static Iarg* +getarg(Iarg *ip, Inst *i, uchar atype) +{ + Iarg *a; + uchar len, reg; + + len = i->olen; + switch(atype){ + default: + abort(); + + case A0: + case A1: + case A2: + case A3: + case A4: + a = acon(ip->cpu, len, atype - A0); + break; + + case AEb: + len = 1; + if(0){ + case AEw: + len = 2; + } + case AEv: + if(i->mod == 3){ + reg = i->rm; + goto REG; + } + goto MEM; + + case AM: + case AMp: + case AMa: + case AMa2: + if(i->mod == 3) + trap(ip->cpu, EBADOP); + MEM: + a = amem(ip->cpu, len, i->sreg, i->off); + if(atype == AMa2) + a->off += i->olen; + break; + + case AGb: + len = 1; + if(0){ + case AGw: + len = 2; + } + case AGv: + reg = i->reg; + REG: + a = areg(ip->cpu, len, reg + RAX); + if(len == 1 && reg >= 4){ + a->reg -= 4; + a->tag |= TH; + } + break; + + case AIb: + case AIc: + len = 1; + if(0){ + case AIw: + len = 2; + } + case AIv: + a = adup(ip); ip->off += len; + a->len = len; + break; + + case AJb: + len = 1; + case AJv: + a = adup(ip); ip->off += len; + a->len = len; + a->off = ip->off + ars(a); + break; + + case AJr: + if(i->mod != 3) + trap(ip->cpu, EBADOP); + a = adup(ip); + a->off = ar(areg(ip->cpu, i->olen, i->rm + RAX)); + break; + + case AAp: + a = afar(ip, ip->len, len); ip->off += 2+len; + break; + + case AOb: + len = 1; + case AOv: + a = adup(ip); ip->off += i->alen; + a->len = i->alen; + a = amem(ip->cpu, len, i->sreg, ar(a)); + break; + + case ASw: + reg = i->reg; + SREG: + a = areg(ip->cpu, 2, reg + RES); + break; + + case AXb: + len = 1; + case AXv: + a = amem(ip->cpu, len, i->sreg, ar(areg(ip->cpu, i->alen, RSI))); + break; + + case AYb: + len = 1; + case AYv: + a = amem(ip->cpu, len, RES, ar(areg(ip->cpu, i->alen, RDI))); + break; + + case AFv: + a = areg(ip->cpu, len, RFL); + break; + + case AAL: + case ACL: + case ADL: + case ABL: + case AAH: + case ACH: + case ADH: + case ABH: + len = 1; + reg = atype - AAL; + goto REG; + + case AAX: + case ACX: + case ADX: + case ABX: + case ASP: + case ABP: + case ASI: + case ADI: + reg = atype - AAX; + goto REG; + + case AES: + case ACS: + case ASS: + case ADS: + case AFS: + case AGS: + reg = atype - AES; + goto SREG; + } + a->atype = atype; + return a; +} + +static int +otherlen(int a) +{ + if(a == 2) + return 4; + else if(a == 4) + return 2; + abort(); + return 0; +} + +void +decode(Iarg *ip, Inst *i) +{ + Optab *t, *t2; + Cpu *cpu; + + cpu = ip->cpu; + + i->op = 0; + i->rep = 0; + i->sreg = 0; + i->dsreg = RDS; + i->olen = cpu->olen; + i->alen = cpu->alen; + i->a1 = i->a2 = i->a3 = nil; + + for(;;){ + i->code = ar(ip); ip->off++; + t = optab + i->code; + switch(t->op){ + case OOSIZE: + i->olen = otherlen(cpu->olen); + continue; + case OASIZE: + i->alen = otherlen(cpu->alen); + continue; + case OREPE: + case OREPNE: + i->rep = t->op; + continue; + case OLOCK: + continue; + case OSEG: + i->sreg = t->a1-AES+RES; + continue; + case O0F: + i->code = ar(ip); ip->off++; + t = optab0F + i->code; + break; + } + break; + } + t2 = optabgp[t->op]; + if(t2 || modrmarg[t->a1] || modrmarg[t->a2] || modrmarg[t->a3]) + if(i->alen == 2) + getmodrm16(ip, i); + else + getmodrm32(ip, i); + if(i->sreg == 0) + i->sreg = i->dsreg; + + for(;;){ + if(t->a1) + i->a1 = getarg(ip, i, t->a1); + if(t->a2) + i->a2 = getarg(ip, i, t->a2); + if(t->a3) + i->a3 = getarg(ip, i, t->a3); + if(t2 == nil) + break; + t = t2 + i->reg; + t2 = nil; + } + i->op = t->op; +} diff --git a/sys/src/cmd/aux/realemu/fmt.c b/sys/src/cmd/aux/realemu/fmt.c new file mode 100644 index 0000000000..8d65fe9593 --- /dev/null +++ b/sys/src/cmd/aux/realemu/fmt.c @@ -0,0 +1,385 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +static char *opstr[] = { /* Edit s/O(.*),/[O\1]= "\1",/g */ + [OBAD]= "BAD", + [O0F]= "0F", + [OAAA]= "AAA", + [OAAD]= "AAD", + [OAAM]= "AAM", + [OAAS]= "AAS", + [OADC]= "ADC", + [OADD]= "ADD", + [OAND]= "AND", + [OARPL]= "ARPL", + [OASIZE]= "ASIZE", + [OBOUND]= "BOUND", + [OBT]= "BT", + [OBTC]= "BTC", + [OBTR]= "BTR", + [OBTS]= "BTS", + [OBSF]= "BSF", + [OBSR]= "BSR", + [OCALL]= "CALL", + [OCBW]= "CBW", + [OCLC]= "CLC", + [OCLD]= "CLD", + [OCLI]= "CLI", + [OCMC]= "CMC", + [OCMOV]= "CMOV", + [OCMP]= "CMP", + [OCMPS]= "CMPS", + [OCWD]= "CWD", + [ODAA]= "DAA", + [ODAS]= "DAS", + [ODEC]= "DEC", + [ODIV]= "DIV", + [OENTER]= "ENTER", + [OGP1]= "GP1", + [OGP2]= "GP2", + [OGP3b]= "GP3b", + [OGP3v]= "GP3v", + [OGP4]= "GP4", + [OGP5]= "GP5", + [OHLT]= "HLT", + [OIDIV]= "IDIV", + [OIMUL]= "IMUL", + [OIN]= "IN", + [OINC]= "INC", + [OINS]= "INS", + [OINT]= "INT", + [OIRET]= "IRET", + [OJUMP]= "JUMP", + [OLAHF]= "LAHF", + [OLFP]= "LFP", + [OLEA]= "LEA", + [OLEAVE]= "LEAVE", + [OLOCK]= "LOCK", + [OLODS]= "LODS", + [OLOOP]= "LOOP", + [OLOOPNZ]= "LOOPNZ", + [OLOOPZ]= "LOOPZ", + [OMOV]= "MOV", + [OMOVS]= "MOVS", + [OMOVZX]= "MOVZX", + [OMOVSX]= "MOVSX", + [OMUL]= "MUL", + [ONEG]= "NEG", + [ONOP]= "NOP", + [ONOT]= "NOT", + [OOR]= "OR", + [OOSIZE]= "OSIZE", + [OOUT]= "OUT", + [OOUTS]= "OUTS", + [OPOP]= "POP", + [OPOPA]= "POPA", + [OPOPF]= "POPF", + [OPUSH]= "PUSH", + [OPUSHA]= "PUSHA", + [OPUSHF]= "PUSHF", + [ORCL]= "RCL", + [ORCR]= "RCR", + [OREPE]= "REPE", + [OREPNE]= "REPNE", + [ORET]= "RET", + [ORETF]= "RETF", + [OROL]= "ROL", + [OROR]= "ROR", + [OSAHF]= "SAHF", + [OSAR]= "SAR", + [OSBB]= "SBB", + [OSCAS]= "SCAS", + [OSEG]= "SEG", + [OSET]= "SET", + [OSHL]= "SHL", + [OSHLD]= "SHLD", + [OSHR]= "SHR", + [OSHRD]= "SHRD", + [OSTC]= "STC", + [OSTD]= "STD", + [OSTI]= "STI", + [OSTOS]= "STOS", + [OSUB]= "SUB", + [OTEST]= "TEST", + [OWAIT]= "WAIT", + [OXCHG]= "XCHG", + [OXLAT]= "XLAT", + [OXOR]= "XOR", +}; + +static char *memstr16[] = { + "BX+SI", + "BX+DI", + "BP+SI", + "BP+DI", + "SI", + "DI", + "BP", + "BX", +}; + +static char *memstr32[] = { + "EAX", + "ECX", + "EDX", + "EBX", + "0", + "EBP", + "ESI", + "EDI", +}; + +static int +argconv(char *p, Inst *i, Iarg *a) +{ + jmp_buf jmp; + char *s; + + s = p; + switch(a->tag){ + default: + abort(); + + case TCON: + return sprint(p, "%lud", a->val); + case TREG: + case TREG|TH: + switch(a->len){ + case 1: + return sprint(p, "%c%c", "ACDB"[a->reg], "LH"[(a->tag & TH) != 0]); + case 4: + *p++ = 'E'; + case 2: + p += sprint(p, "%c%c", + "ACDBSBSDECSDFGIF"[a->reg], + "XXXXPPIISSSSSSPL"[a->reg]); + return p - s; + } + case TMEM: + break; + } + + /* setup trap jump in case we dereference bad memory */ + memmove(jmp, a->cpu->jmp, sizeof jmp); + if(setjmp(a->cpu->jmp)){ + p += sprint(p, "<%.4lux:%.4lux>", a->seg, a->off); + goto out; + } + + switch(a->atype){ + default: + abort(); + + case AAp: + p += sprint(p, "[%.4lux:%.4lux]", a->seg, a->off); + break; + + case AJb: + case AJv: + p += sprint(p, "[%.4lux]", a->off); + break; + + case AIc: + p += sprint(p, "$%.2lx", ars(a)); + break; + case AIb: + case AIw: + case AIv: + p += sprint(p, "$%.*lux", (int)a->len*2, ar(a)); + break; + + case AMp: + *p++ = '*'; + case AEb: + case AEw: + case AEv: + case AM: + case AMa: + case AMa2: + case AOb: + case AOv: + if(i->sreg != RDS) + p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]); + if(a->atype == AOb || a->atype == AOv || (i->mod == 0 && + (i->alen == 2 && i->rm == 6) || + (i->alen == 4 && ((i->rm == 5) || + (i->rm == 4 && i->index == 4 && i->base == 5))))){ + p += sprint(p, "[%.*lux]", (int)i->alen*2, a->off); + break; + } + *p++ = '['; + if(i->alen == 2) + p += sprint(p, "%s", memstr16[i->rm]); + else{ + if(i->rm == 4){ + if(i->index != 4) + p += sprint(p, "%c*%s+", "1248"[i->scale], memstr32[i->index]); + if(i->base != 5) + p += sprint(p, "%s", memstr32[i->base]); + else{ + if(i->mod == 0) + p += sprint(p, "%.4lux", i->off); + else + p += sprint(p, "EBP"); + } + } else + p += sprint(p, "%s", memstr32[i->rm]); + } + if(i->mod != 0) + p += sprint(p, "%+lx", i->disp); + *p++ = ']'; + break; + + case AXb: + case AXv: + if(a->sreg != RDS) + p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]); + p += sprint(p, "[SI]"); + break; + case AYb: + case AYv: + if(a->sreg != RDS) + p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]); + p += sprint(p, "[DI]"); + break; + } + +out: + memmove(a->cpu->jmp, jmp, sizeof jmp); + *p = 0; + return p - s; +} + +static char *jmpstr[] = { + "JO", "JNO", "JC", "JNC", "JZ", "JNZ", "JBE", "JA", + "JS", "JNS", "JP", "JNP", "JL", "JGE", "JLE", "JG", +}; + +int +instfmt(Fmt *fmt) +{ + Inst *i; + char *p, buf[256]; + + i = va_arg(fmt->args, Inst*); + p = buf; + + if(i->olen == 4) + p += sprint(p, "O32: "); + if(i->alen == 4) + p += sprint(p, "A32: "); + if(i->rep) + p += sprint(p, "%s: ", opstr[i->rep]); + + if(i->op == OXLAT && i->sreg != RDS) + p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]); + + if(i->op == OJUMP){ + switch(i->code){ + case 0xE3: + p += sprint(p, "%s ", "JCXZ"); + break; + case 0xEB: + case 0xE9: + case 0xEA: + case 0xFF: + p += sprint(p, "%s ", "JMP"); + break; + default: + p += sprint(p, "%s ", jmpstr[i->code&0xF]); + break; + } + } else + p += sprint(p, "%s ", opstr[i->op]); + + + for(;;){ + if(i->a1 == nil) + break; + p += argconv(p, i, i->a1); + if(i->a2 == nil) + break; + *p++ = ','; + *p++ = ' '; + p += argconv(p, i, i->a2); + if(i->a3 == nil) + break; + *p++ = ','; + *p++ = ' '; + p += argconv(p, i, i->a3); + break; + } + *p = 0; + fmtstrcpy(fmt, buf); + return 0; +} + +int +flagfmt(Fmt *fmt) +{ + char buf[16]; + ulong f; + + f = va_arg(fmt->args, ulong); + sprint(buf, "%c%c%c%c%c%c%c", + (f & CF) ? 'C' : 'c', + (f & SF) ? 'S' : 's', + (f & ZF) ? 'Z' : 'z', + (f & OF) ? 'O' : 'o', + (f & PF) ? 'P' : 'p', + (f & DF) ? 'D' : 'd', + (f & IF) ? 'I' : 'i'); + fmtstrcpy(fmt, buf); + return 0; +} + +int +cpufmt(Fmt *fmt) +{ + char buf[512]; + jmp_buf jmp; + Cpu *cpu; + Inst i; + + cpu = va_arg(fmt->args, Cpu*); + + memmove(jmp, cpu->jmp, sizeof jmp); + if(setjmp(cpu->jmp) == 0) + decode(amem(cpu, 1, RCS, cpu->reg[RIP]), &i); + memmove(cpu->jmp, jmp, sizeof jmp); + + snprint(buf, sizeof(buf), + "%.6lux " + "%.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux " + "%.4lux %.4lux %.4lux %.4lux " + "%J %.4lux %.2ux %I", + + cpu->ic, + + cpu->reg[RAX], + cpu->reg[RBX], + cpu->reg[RCX], + cpu->reg[RDX], + + cpu->reg[RDI], + cpu->reg[RSI], + + cpu->reg[RBP], + cpu->reg[RSP], + + cpu->reg[RDS], + cpu->reg[RES], + cpu->reg[RSS], + cpu->reg[RCS], + + cpu->reg[RFL], + cpu->reg[RIP], + + i.code, + &i); + + fmtstrcpy(fmt, buf); + return 0; +} diff --git a/sys/src/cmd/aux/realemu/fns.h b/sys/src/cmd/aux/realemu/fns.h new file mode 100644 index 0000000000..a25f6955ac --- /dev/null +++ b/sys/src/cmd/aux/realemu/fns.h @@ -0,0 +1,31 @@ +/* arg */ +Iarg *adup(Iarg *x); +Iarg *areg(Cpu *cpu, uchar len, uchar reg); +Iarg *amem(Cpu *cpu, uchar len, uchar sreg, ulong off); +Iarg *afar(Iarg *mem, uchar len, uchar alen); +Iarg *acon(Cpu *cpu, uchar len, ulong val); +ulong ar(Iarg *a); +long ars(Iarg *a); +void aw(Iarg *a, ulong w); + +/* decode */ +void decode(Iarg *ip, Inst *i); + +/* xec */ +void trap(Cpu *cpu, int e); +int intr(Cpu *cpu, int v); +int xec(Cpu *cpu, int n); + +#pragma varargck type "I" Inst* +#pragma varargck type "J" ulong +#pragma varargck type "C" Cpu* + +int instfmt(Fmt *fmt); +int flagfmt(Fmt *fmt); +int cpufmt(Fmt *fmt); + +/* pit */ +void clockpit(Pit *pit, vlong cycles); +void setgate(Pit *ch, uchar gate); +uchar rpit(Pit *pit, uchar addr); +void wpit(Pit *pit, uchar addr, uchar data); diff --git a/sys/src/cmd/aux/realemu/loadcom.c b/sys/src/cmd/aux/realemu/loadcom.c new file mode 100644 index 0000000000..28c5bf6e42 --- /dev/null +++ b/sys/src/cmd/aux/realemu/loadcom.c @@ -0,0 +1,43 @@ +#include +#include + +#include "/386/include/ureg.h" + +static uchar buf[0xFF01]; + +void +main(int argc, char *argv[]) +{ + struct Ureg u; + int fd, rreg, rmem, len; + + ARGBEGIN { + } ARGEND; + + if(argc == 0){ + fprint(2, "usage:\t%s file.com\n", argv0); + exits("usage"); + } + if((fd = open(*argv, OREAD)) < 0) + sysfatal("open: %r"); + + if((rreg = open("/dev/realmode", OWRITE)) < 0) + sysfatal("open realmode: %r"); + if((rmem = open("/dev/realmodemem", OWRITE)) < 0) + sysfatal("open realmodemem: %r"); + if((len = readn(fd, buf, sizeof buf)) < 2) + sysfatal("file too small"); + + memset(&u, 0, sizeof u); + u.cs = u.ds = u.es = u.fs = u.gs = 0x1000; + u.ss = 0x0000; + u.sp = 0xfffe; + u.pc = 0x0100; + + seek(rmem, (u.cs<<4) + u.pc, 0); + if(write(rmem, buf, len) != len) + sysfatal("write mem: %r"); + + if(write(rreg, &u, sizeof u) != sizeof u) + sysfatal("write reg: %r"); +} diff --git a/sys/src/cmd/aux/realemu/main.c b/sys/src/cmd/aux/realemu/main.c new file mode 100644 index 0000000000..7283dcbe63 --- /dev/null +++ b/sys/src/cmd/aux/realemu/main.c @@ -0,0 +1,796 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +/* for fs */ +#include +#include +#include +#include <9p.h> + +#include "/386/include/ureg.h" + +enum { + MEMSIZE = 0x100000, + + RMBUF = 0x9000, + RMCODE = 0x8000, + + PITHZ = 1193182, + PITNS = 1000000000/PITHZ, +}; + +static Cpu cpu; +static uchar memory[MEMSIZE+4]; +static uchar pageregtmp[0x10]; +static int portfd[5]; +static int realmemfd; +static int cputrace; +static int porttrace; +static Pit pit[3]; +static uchar rtcaddr; + +static vlong pitclock; + +static void +startclock(void) +{ + pitclock = nsec(); +} + +static void +runclock(void) +{ + vlong now, dt; + + now = nsec(); + dt = now - pitclock; + if(dt >= PITNS){ + clockpit(pit, dt/PITNS); + pitclock = now; + } +} + +static ulong +gw1(uchar *p) +{ + return p[0]; +} +static ulong +gw2(uchar *p) +{ + return (ulong)p[0] | (ulong)p[1]<<8; +} +static ulong +gw4(uchar *p) +{ + return (ulong)p[0] | (ulong)p[1]<<8 | (ulong)p[2]<<16 | (ulong)p[3]<<24; +} +static ulong (*gw[5])(uchar *p) = { + [1] gw1, + [2] gw2, + [4] gw4, +}; + +static void +pw1(uchar *p, ulong w) +{ + p[0] = w & 0xFF; +} +static void +pw2(uchar *p, ulong w) +{ + p[0] = w & 0xFF; + p[1] = (w>>8) & 0xFF; +} +static void +pw4(uchar *p, ulong w) +{ + p[0] = w & 0xFF; + p[1] = (w>>8) & 0xFF; + p[2] = (w>>16) & 0xFF; + p[3] = (w>>24) & 0xFF; +} +static void (*pw[5])(uchar *p, ulong w) = { + [1] pw1, + [2] pw2, + [4] pw4, +}; + +static ulong +rbad(void *, ulong off, int) +{ + fprint(2, "bad mem read %.5lux\n", off); + trap(&cpu, EMEM); + + /* not reached */ + return 0; +} + +static void +wbad(void *, ulong off, ulong, int) +{ + fprint(2, "bad mem write %.5lux\n", off); + trap(&cpu, EMEM); +} + +static ulong +rmem(void *, ulong off, int len) +{ + return gw[len](memory + off); +} + +static void +wmem(void *, ulong off, ulong w, int len) +{ + pw[len](memory + off, w); +} + +static ulong +rrealmem(void *, ulong off, int len) +{ + uchar data[4]; + + if(pread(realmemfd, data, len, off) != len){ + fprint(2, "bad real mem read %.5lux: %r\n", off); + trap(&cpu, EMEM); + } + return gw[len](data); +} + +static void +wrealmem(void *, ulong off, ulong w, int len) +{ + uchar data[4]; + + pw[len](data, w); + if(pwrite(realmemfd, data, len, off) != len){ + fprint(2, "bad real mem write %.5lux: %r\n", off); + trap(&cpu, EMEM); + } +} + + +static ulong +rport(void *, ulong p, int len) +{ + uchar data[4]; + ulong w; + + switch(p){ + case 0x20: /* PIC 1 */ + case 0x21: + w = 0; + break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + runclock(); + w = rpit(pit, p - 0x40); + break; + case 0x60: /* keyboard data output buffer */ + w = 0; + break; + case 0x61: /* keyboard controller port b */ + runclock(); + w = pit[2].out<<5 | pit[2].gate; + break; + case 0x62: /* PPI (XT only) */ + runclock(); + w = pit[2].out<<5; + break; + case 0x63: /* PPI (XT only) read dip switches */ + w = 0; + break; + case 0x65: /* A20 gate */ + w = 1 << 2; + break; + case 0x70: /* RTC addr */ + w = rtcaddr; + break; + case 0x71: /* RTC data */ + w = 0xFF; + break; + case 0x80: /* extra dma registers (temp) */ + case 0x84: + case 0x85: + case 0x86: + case 0x88: + case 0x8c: + case 0x8d: + case 0x8e: + w = pageregtmp[p-0x80]; + break; + case 0x92: /* A20 gate (system control port a) */ + w = 1 << 1; + break; + case 0xa0: /* PIC 2 */ + case 0xa1: + w = 0; + break; + default: + if(pread(portfd[len], data, len, p) != len){ + fprint(2, "bad %d bit port read %.4lux: %r\n", len*8, p); + trap(&cpu, EIO); + } + w = gw[len](data); + } + if(porttrace) + fprint(2, "rport %.4lux %.*lux\n", p, len<<1, w); + return w; +} + +static void +wport(void *, ulong p, ulong w, int len) +{ + uchar data[4]; + + if(porttrace) + fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w); + + switch(p){ + case 0x20: /* PIC 1 */ + case 0x21: + break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + runclock(); + wpit(pit, p - 0x40, w); + break; + case 0x60: /* keyboard controller data port */ + break; + case 0x61: /* keyboard controller port B */ + setgate(&pit[2], w & 1); + break; + case 0x62: /* PPI (XT only) */ + case 0x63: + case 0x64: /* KB controller input buffer (ISA, EISA) */ + case 0x65: /* A20 gate (bit 2) */ + break; + case 0x70: /* RTC addr */ + rtcaddr = w & 0xFF; + break; + case 0x71: /* RTC data */ + break; + case 0x80: + case 0x84: + case 0x85: + case 0x86: + case 0x88: + case 0x8c: + case 0x8d: + case 0x8e: + pageregtmp[p-0x80] = w & 0xFF; + break; + case 0x92: /* system control port a */ + case 0x94: /* system port enable setup register */ + case 0x96: + break; + case 0xA0: /* PIC 2 */ + case 0xA1: + break; + + default: + pw[len](data, w); + if(pwrite(portfd[len], data, len, p) != len){ + fprint(2, "bad %d bit port write %.4lux: %r\n", len*8, p); + trap(&cpu, EIO); + } + } +} + +static Bus memio[] = { + /* 0 */ memory, rmem, wmem, /* RAM: IVT, BIOS data area */ + /* 1 */ memory, rmem, wmem, /* custom */ + /* 2 */ nil, rbad, wbad, + /* 3 */ nil, rbad, wbad, + /* 4 */ nil, rbad, wbad, + /* 5 */ nil, rbad, wbad, + /* 6 */ nil, rbad, wbad, + /* 7 */ nil, rbad, wbad, + /* 8 */ nil, rbad, wbad, + /* 9 */ memory, rmem, wmem, /* RAM: extended BIOS data area */ + /* A */ nil, rrealmem, wrealmem, /* RAM: VGA framebuffer */ + /* B */ nil, rrealmem, wrealmem, /* RAM: VGA framebuffer */ + /* C */ memory, rmem, wmem, /* ROM: VGA BIOS */ + /* D */ nil, rbad, wbad, + /* E */ memory, rmem, wmem, /* ROM: BIOS */ + /* F */ memory, rmem, wbad, /* ROM: BIOS */ +}; + +static Bus portio = { + nil, rport, wport, +}; + +static void +cpuinit(void) +{ + int i; + + fmtinstall('I', instfmt); + fmtinstall('J', flagfmt); + fmtinstall('C', cpufmt); + + if((portfd[1] = open("#P/iob", ORDWR)) < 0) + sysfatal("open iob: %r"); + if((portfd[2] = open("#P/iow", ORDWR)) < 0) + sysfatal("open iow: %r"); + if((portfd[4] = open("#P/iol", ORDWR)) < 0) + sysfatal("open iol: %r"); + + if((realmemfd = open("#P/realmodemem", ORDWR)) < 0) + sysfatal("open realmodemem: %r"); + + for(i=0; ix)]((uchar*)&u->x) +#define PUTUREG(x,y) pw[sizeof(u->x)]((uchar*)&u->x,y) + +static char* +realmode(Cpu *cpu, struct Ureg *u, void *r) +{ + char *err; + int i; + + cpu->reg[RDI] = GETUREG(di); + cpu->reg[RSI] = GETUREG(si); + cpu->reg[RBP] = GETUREG(bp); + cpu->reg[RBX] = GETUREG(bx); + cpu->reg[RDX] = GETUREG(dx); + cpu->reg[RCX] = GETUREG(cx); + cpu->reg[RAX] = GETUREG(ax); + + cpu->reg[RGS] = GETUREG(gs); + cpu->reg[RFS] = GETUREG(fs); + cpu->reg[RES] = GETUREG(es); + cpu->reg[RDS] = GETUREG(ds); + + cpu->reg[RFL] = GETUREG(flags); + + if(i = GETUREG(trap)){ + cpu->reg[RSS] = 0x0000; + cpu->reg[RSP] = 0x7C00; + cpu->reg[RCS] = (RMCODE>>4)&0xF000; + cpu->reg[RIP] = RMCODE & 0xFFFF; + memory[RMCODE] = 0xf4; /* HLT instruction */ + if(intr(cpu, i) < 0) + return Ebadtrap; + } else { + cpu->reg[RSS] = GETUREG(ss); + cpu->reg[RSP] = GETUREG(sp); + cpu->reg[RCS] = GETUREG(cs); + cpu->reg[RIP] = GETUREG(pc); + } + + startclock(); + for(;;){ + if(cputrace) + fprint(2, "%C\n", cpu); + switch(i = xec(cpu, (porttrace | cputrace) ? 1 : 100000)){ + case -1: + if(flushed(r)){ + err = Eintr; + break; + } + runclock(); + continue; + + /* normal interrupts */ + default: + if(intr(cpu, i) < 0){ + err = Ebadtrap; + break; + } + continue; + + /* pseudo-interrupts */ + case EHALT: + err = nil; + break; + case EIO: + err = Eio; + break; + case EMEM: + err = Emem; + break; + + /* processor traps */ + case EDIV0: + case EDEBUG: + case ENMI: + case EBRK: + case EINTO: + case EBOUND: + case EBADOP: + case ENOFPU: + case EDBLF: + case EFPUSEG: + case EBADTSS: + case ENP: + case ESTACK: + case EGPF: + case EPF: + PUTUREG(trap, i); + err = trapstr[i]; + break; + } + + break; + } + + if(err) + fprint(2, "%s\n%C\n", err, cpu); + + PUTUREG(di, cpu->reg[RDI]); + PUTUREG(si, cpu->reg[RSI]); + PUTUREG(bp, cpu->reg[RBP]); + PUTUREG(bx, cpu->reg[RBX]); + PUTUREG(dx, cpu->reg[RDX]); + PUTUREG(cx, cpu->reg[RCX]); + PUTUREG(ax, cpu->reg[RAX]); + + PUTUREG(gs, cpu->reg[RGS]); + PUTUREG(fs, cpu->reg[RFS]); + PUTUREG(es, cpu->reg[RES]); + PUTUREG(ds, cpu->reg[RDS]); + + PUTUREG(flags, cpu->reg[RFL]); + + PUTUREG(pc, cpu->reg[RIP]); + PUTUREG(cs, cpu->reg[RCS]); + PUTUREG(sp, cpu->reg[RSP]); + PUTUREG(ss, cpu->reg[RSS]); + + return err; +} + +enum { + Qroot, + Qcall, + Qmem, + Nqid, +}; + +static struct Qtab { + char *name; + int mode; + int type; + int length; +} qtab[Nqid] = { + "/", + DMDIR|0555, + QTDIR, + 0, + + "realmode", + 0666, + 0, + 0, + + "realmodemem", + 0666, + 0, + MEMSIZE, +}; + +static int +fillstat(ulong qid, Dir *d) +{ + struct Qtab *t; + + memset(d, 0, sizeof(Dir)); + d->uid = "realemu"; + d->gid = "realemu"; + d->muid = ""; + d->qid = (Qid){qid, 0, 0}; + d->atime = time(0); + t = qtab + qid; + d->name = t->name; + d->qid.type = t->type; + d->mode = t->mode; + d->length = t->length; + return 1; +} + +static void +fsattach(Req *r) +{ + char *spec; + + spec = r->ifcall.aname; + if(spec && spec[0]){ + respond(r, Ebadspec); + return; + } + r->fid->qid = (Qid){Qroot, 0, QTDIR}; + r->ofcall.qid = r->fid->qid; + respond(r, nil); +} + +static void +fsstat(Req *r) +{ + fillstat((ulong)r->fid->qid.path, &r->d); + r->d.name = estrdup9p(r->d.name); + r->d.uid = estrdup9p(r->d.uid); + r->d.gid = estrdup9p(r->d.gid); + r->d.muid = estrdup9p(r->d.muid); + respond(r, nil); +} + +static char* +fswalk1(Fid *fid, char *name, Qid *qid) +{ + int i; + ulong path; + + path = fid->qid.path; + switch(path){ + case Qroot: + if (strcmp(name, "..") == 0) { + *qid = (Qid){Qroot, 0, QTDIR}; + fid->qid = *qid; + return nil; + } + for(i = fid->qid.path; iqid = *qid; + return nil; + } + return Enonexist; + + default: + return Ewalk; + } +} + +static void +fsopen(Req *r) +{ + static int need[4] = { 4, 2, 6, 1 }; + struct Qtab *t; + int n; + + t = qtab + r->fid->qid.path; + n = need[r->ifcall.mode & 3]; + if((n & t->mode) != n) + respond(r, Eperm); + else + respond(r, nil); +} + +static int +readtopdir(Fid*, uchar *buf, long off, int cnt, int blen) +{ + int i, m, n; + long pos; + Dir d; + + n = 0; + pos = 0; + for (i = 1; i < Nqid; i++){ + fillstat(i, &d); + m = convD2M(&d, &buf[n], blen-n); + if(off <= pos){ + if(m <= BIT16SZ || m > cnt) + break; + n += m; + cnt -= m; + } + pos += m; + } + return n; +} + +static Channel *reqchan; + +static void +cpuproc(void *) +{ + static struct Ureg rmu; + ulong path; + vlong o; + ulong n; + char *p; + Req *r; + + threadsetname("cpuproc"); + + while(r = recvp(reqchan)){ + if(flushed(r)){ + respond(r, Eintr); + continue; + } + + path = r->fid->qid.path; + + p = r->ifcall.data; + n = r->ifcall.count; + o = r->ifcall.offset; + + switch(((int)r->ifcall.type<<8)|path){ + case (Tread<<8) | Qmem: + readbuf(r, memory, MEMSIZE); + respond(r, nil); + break; + + case (Tread<<8) | Qcall: + readbuf(r, &rmu, sizeof rmu); + respond(r, nil); + break; + + case (Twrite<<8) | Qmem: + if(o < 0 || o >= MEMSIZE || o+n > MEMSIZE){ + respond(r, Ebadoff); + break; + } + memmove(memory + o, p, n); + r->ofcall.count = n; + respond(r, nil); + break; + + case (Twrite<<8) | Qcall: + if(n != sizeof rmu){ + respond(r, Ebadureg); + break; + } + memmove(&rmu, p, n); + if(p = realmode(&cpu, &rmu, r)){ + respond(r, p); + break; + } + r->ofcall.count = n; + respond(r, nil); + break; + } + } +} + +static Channel *flushchan; + +static int +flushed(void *r) +{ + return nbrecvp(flushchan) == r; +} + +static void +fsflush(Req *r) +{ + nbsendp(flushchan, r->oldreq); + respond(r, nil); +} + +static void +dispatch(Req *r) +{ + if(!nbsendp(reqchan, r)) + respond(r, Ebusy); +} + +static void +fsread(Req *r) +{ + switch((ulong)r->fid->qid.path){ + case Qroot: + r->ofcall.count = readtopdir(r->fid, (void*)r->ofcall.data, r->ifcall.offset, + r->ifcall.count, r->ifcall.count); + respond(r, nil); + break; + default: + dispatch(r); + } +} + +static void +fsend(Srv*) +{ + threadexitsall(nil); +} + +static Srv fs = { + .attach= fsattach, + .walk1= fswalk1, + .open= fsopen, + .read= fsread, + .write= dispatch, + .stat= fsstat, + .flush= fsflush, + .end= fsend, +}; + +static void +usage(void) +{ + fprint(2, "usgae:\t%s [-Dpt] [-s srvname] [-m mountpoint]\n", argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + char *mnt = "/dev"; + char *srv = nil; + + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 'p': + porttrace = 1; + break; + case 't': + cputrace = 1; + break; + case 's': + srv = EARGF(usage()); + mnt = nil; + break; + case 'm': + mnt = EARGF(usage()); + break; + default: + usage(); + }ARGEND + + cpuinit(); + + reqchan = chancreate(sizeof(Req*), 8); + flushchan = chancreate(sizeof(Req*), 8); + procrfork(cpuproc, nil, 16*1024, RFNAMEG|RFNOTEG); + threadpostmountsrv(&fs, srv, mnt, MBEFORE); +} diff --git a/sys/src/cmd/aux/realemu/mkfile b/sys/src/cmd/aux/realemu/mkfile new file mode 100644 index 0000000000..dd6d1d5a69 --- /dev/null +++ b/sys/src/cmd/aux/realemu/mkfile @@ -0,0 +1,9 @@ + +#include +#include "dat.h" +#include "fns.h" + +enum { + AC0 = 0, + AC1, + AC2, + Actl, + + Readback = 3, + + RBC0 = 1<<1, + RBC1 = 1<<2, + RBC2 = 1<<3, + RBlatchstatus = 1<<4, + RBlatchcount = 1<<5, + + AMlatchcount = 0, + AMloonly, + AMhionly, + AMlohi, + + OM0 = 0, + OM1, + OM2, + OM3, + OM4, + OM5, + OM2b, + OM3b, +}; + +static void +latchstatus(Pit *ch) +{ + if(ch->rlatched) + return; + ch->rlatch[0] = ch->bcd | ch->omode<<1 | ch->amode<<4 | ch->count0<<6 | ch->out<<7; + ch->rcount = 0; + ch->rlatched = 1; +} + +static void +latchcount(Pit *ch) +{ + ulong w; + + if(ch->rlatched) + return; + w = ch->count & 0xFFFF; + if(ch->bcd) + w = (w % 10) + ((w/10) % 10)<<4 + ((w/100) % 10)<<8 + ((w/1000) % 10)<<12; + ch->rlatch[0] = w & 0xFF; + ch->rlatch[1] = (w >> 8) & 0xFF; + ch->rcount = 0; + ch->rlatched = 1; + switch(ch->amode){ + case AMhionly: + ch->rcount++; + break; + case AMlohi: + ch->rlatched++; + break; + } +} + +static void +setcount(Pit *ch) +{ + ulong w; + + w = (ulong)ch->wlatch[0] | (ulong)ch->wlatch[1] << 8; + if(ch->bcd) + w = (w & 0xF) + 10*((w >> 4)&0xF) + 100*((w >> 8)&0xF) + 1000*((w >> 12)&0xF); + ch->count = w; + ch->count0 = 0; +} + +static int +deccount(Pit *ch, vlong *cycles) +{ + if(ch->count0){ + *cycles = 0; + return 0; + } else { + vlong passed, remain; + + passed = *cycles; + if(ch->count == 0){ + ch->count = ch->bcd ? 9999 : 0xFFFF; + passed--; + } + if(passed <= ch->count){ + remain = 0; + ch->count -= passed; + } else { + remain = passed - ch->count; + ch->count = 0; + } + *cycles = remain; + return ch->count == 0; + } +} + +void +setgate(Pit *ch, uchar gate) +{ + if(ch->gate == 0 && gate) + ch->gateraised = 1; + ch->gate = gate; +} + +static void +clockpit1(Pit *ch, vlong *cycles) +{ + switch(ch->omode){ + case OM0: /* Interrupt On Terminal Count */ + if(ch->count0){ + setcount(ch); + ch->out = 0; + Next: + --*cycles; + return; + } + if(ch->gate && deccount(ch, cycles)){ + ch->out = 1; + return; + } + break; + + case OM1: /* Hardware Re-triggerable One-shot */ + if(ch->gateraised){ + ch->gateraised = 0; + setcount(ch); + ch->out = 0; + goto Next; + } + if(deccount(ch, cycles) && ch->out == 0){ + ch->out = 1; + return; + } + break; + + case OM2: /* Rate Generator */ + case OM2b: + ch->out = 1; + if(ch->count0){ + setcount(ch); + goto Next; + } + if(ch->gate == 0) + break; + if(ch->gateraised){ + ch->gateraised = 0; + setcount(ch); + goto Next; + } + if(deccount(ch, cycles)){ + setcount(ch); + ch->out = 0; + return; + } + break; + + case OM3: /* Square Wave Generator */ + case OM3b: + if(ch->count0){ + setcount(ch); + goto Next; + } + if(ch->gate == 0) + break; + if(ch->gateraised){ + ch->gateraised = 0; + setcount(ch); + goto Next; + } + if(deccount(ch, cycles)){ + setcount(ch); + ch->out ^= 1; + return; + } + break; + + case OM4: /* Software Triggered Strobe */ + ch->out = 1; + if(ch->count0){ + setcount(ch); + goto Next; + } + if(ch->gate && deccount(ch, cycles)){ + ch->out = 0; + return; + } + break; + + case OM5: /* Hardware Triggered Strobe */ + ch->out = 1; + if(ch->gateraised){ + ch->gateraised = 0; + setcount(ch); + goto Next; + } + if(deccount(ch, cycles)){ + ch->out = 0; + return; + } + break; + } + *cycles = 0; +} + +void +clockpit(Pit *pit, vlong cycles) +{ + Pit *ch; + int i; + + if(cycles <= 0) + return; + for(i = 0; iwlatched){ + vlong c; + + switch(ch->omode){ + case OM3: + case OM3b: + c = cycles * 2; + break; + default: + c = cycles; + } + while(c > 0) + clockpit1(ch, &c); + } + ch->gateraised = 0; + } +} + +uchar +rpit(Pit *pit, uchar addr) +{ + Pit *ch; + uchar data; + + if(addr >= Actl) + return 0; + ch = pit + addr; + if(ch->rlatched){ + data = ch->rlatch[ch->rcount & 1]; + ch->rlatched--; + } else { + data = 0; + switch(ch->amode){ + case AMloonly: + data = ch->count & 0xFF; + break; + case AMhionly: + data = (ch->count >> 8) & 0xFF; + break; + case AMlohi: + data = (ch->count >> ((ch->rcount & 1)<<3)) & 0xFF; + break; + } + } + ch->rcount++; + if(0) fprint(2, "rpit %p: %.2x %.2x\n", pit, (int)addr, (int)data); + return data; +} + +void +wpit(Pit *pit, uchar addr, uchar data) +{ + Pit *ch; + + if(0) fprint(2, "wpit %p: %.2x %.2x\n", pit, (int)addr, (int)data); + if(addr > Actl) + return; + if(addr == Actl){ + uchar sc, amode, omode, bcd; + + bcd = (data & 1); + omode = (data >> 1) & 7; + amode = (data >> 4) & 3; + sc = (data >> 6) & 3; + + if(sc == Readback){ + ch = nil; + for(;;){ + if(data & RBC0){ + ch = pit; + break; + } + if(data & RBC1){ + ch = pit + 1; + break; + } + if(data & RBC2){ + ch = pit + 2; + break; + } + break; + } + if(ch == nil) + return; + if((data & RBlatchcount) == 0) + latchcount(ch); + if((data & RBlatchstatus) == 0) + latchstatus(ch); + return; + } + + ch = pit + sc; + if(amode == AMlatchcount){ + latchcount(ch); + return; + } + ch->bcd = bcd; + + ch->amode = amode; + ch->omode = omode; + + ch->rlatched = 0; + ch->rcount = 0; + ch->rlatch[0] = 0; + ch->rlatch[1] = 0; + + ch->wlatched = 0; + ch->wcount = 0; + ch->wlatch[0] = 0; + ch->wlatch[1] = 0; + + ch->count0 = 1; + ch->out = !!omode; + return; + } + + ch = pit + addr; + switch(ch->amode){ + case AMloonly: + case AMhionly: + ch->wlatch[ch->amode - AMloonly] = data; + ch->wcount++; + break; + case AMlohi: + ch->wlatch[ch->wcount++ & 1] = data; + if(ch->wcount < 2) + return; + break; + } + ch->wlatched = ch->wcount; + ch->wcount = 0; + ch->count0 = 1; +} diff --git a/sys/src/cmd/aux/realemu/vgalist b/sys/src/cmd/aux/realemu/vgalist new file mode 100644 index 0000000000..3a0530584a --- /dev/null +++ b/sys/src/cmd/aux/realemu/vgalist @@ -0,0 +1,9 @@ +#vid did bios wired product name +100b 0030 5.30 STI NSC Geode GX2 +5533 8c2e 1.0 - T23 / S3 savage +1002 791e 01.00 - ATI RS690 +10de 002c B1 STI NVidia RivaTNT +15ad 0405 2.0 - VMware +- - 1.26 - Bochs +102b 0519 00 STI Matrox MILLENNIUM +5333 8901 Rev E - S3 Trio64V2/DX/GX diff --git a/sys/src/cmd/aux/realemu/xec.c b/sys/src/cmd/aux/realemu/xec.c new file mode 100644 index 0000000000..ac79fc56a6 --- /dev/null +++ b/sys/src/cmd/aux/realemu/xec.c @@ -0,0 +1,1363 @@ +#include +#include +#include "dat.h" +#include "fns.h" + +#define sign(s) (1UL<<((s)-1)) +#define mask(s) (sign(s)|(sign(s)-1)) + +static void +push(Iarg *sp, Iarg *a) +{ + Iarg *p; + + p = amem(sp->cpu, a->len, RSS, ar(sp)); + p->off -= a->len; + p->off &= mask(sp->len*8); + aw(p, ar(a)); + aw(sp, p->off); +} + +static void +pop(Iarg *sp, Iarg *a) +{ + Iarg *p; + + p = amem(sp->cpu, a->len, RSS, ar(sp)); + aw(a, ar(p)); + aw(sp, p->off + a->len); +} + +static void +jump(Iarg *to) +{ + Cpu *cpu; + + cpu = to->cpu; + switch(to->atype){ + default: + abort(); + case AMp: + to = afar(to, 1, to->len); + case AAp: + cpu->reg[RCS] = to->seg; + case AJb: + case AJv: + cpu->reg[RIP] = to->off; + break; + case AEv: + cpu->reg[RIP] = ar(to); + break; + } +} + +static void +opcall(Cpu *cpu, Inst *i) +{ + Iarg *sp; + + sp = areg(cpu, cpu->slen, RSP); + switch(i->a1->atype){ + default: + abort(); + case AAp: + case AMp: + push(sp, areg(cpu, i->olen, RCS)); + case AJv: + case AEv: + push(sp, areg(cpu, i->olen, RIP)); + break; + } + jump(i->a1); +} + +static void +opint(Cpu *cpu, Inst *i) +{ + cpu->trap = ar(i->a1); + longjmp(cpu->jmp, 1); +} + +static void +opiret(Cpu *cpu, Inst *i) +{ + Iarg *sp; + + if(i->olen != 2) + trap(cpu, EBADOP); + sp = areg(cpu, cpu->slen, RSP); + pop(sp, areg(cpu, 2, RIP)); + pop(sp, areg(cpu, 2, RCS)); + pop(sp, areg(cpu, 2, RFL)); +} + +static void +opret(Cpu *cpu, Inst *i) +{ + Iarg *sp; + ulong c; + + sp = areg(cpu, cpu->slen, RSP); + pop(sp, areg(cpu, i->olen, RIP)); + if(c = ar(i->a1)) + aw(sp, ar(sp) + c); +} + +static void +opretf(Cpu *cpu, Inst *i) +{ + Iarg *sp; + ulong c; + + sp = areg(cpu, cpu->slen, RSP); + pop(sp, areg(cpu, i->olen, RIP)); + pop(sp, areg(cpu, i->olen, RCS)); + if(c = ar(i->a1)) + aw(sp, ar(sp) + c); +} + +static void +openter(Cpu *cpu, Inst *i) +{ + Iarg *sp, *bp; + ulong oframe, nframe; + int j, n; + + sp = areg(cpu, cpu->slen, RSP); + bp = areg(cpu, cpu->slen, RBP); + push(sp, bp); + oframe = ar(bp); + nframe = ar(sp); + n = ar(i->a2) % 32; + if(n > 0){ + for(j=1; jolen*j); + push(sp, bp); + } + push(sp, acon(cpu, i->olen, nframe)); + } + aw(bp, nframe); + aw(sp, nframe - ar(i->a1)); +} + +static void +opleave(Cpu *cpu, Inst *i) +{ + Iarg *sp; + + sp = areg(cpu, cpu->slen, RSP); + aw(sp, ar(areg(cpu, cpu->slen, RBP))); + pop(sp, areg(cpu, i->olen, RBP)); +} + +static void +oppush(Cpu *cpu, Inst *i) +{ + Iarg *sp; + + sp = areg(cpu, cpu->slen, RSP); + if(i->a1->len == 1) /* 0x6A push imm8 */ + push(sp, acon(cpu, i->olen, ar(i->a1))); + else + push(sp, i->a1); +} + +static void +oppop(Cpu *cpu, Inst *i) +{ + pop(areg(cpu, cpu->slen, RSP), i->a1); +} + +static void +oppusha(Cpu *cpu, Inst *i) +{ + Iarg *sp, *osp; + + sp = areg(cpu, cpu->slen, RSP); + osp = acon(cpu, i->olen, ar(sp)); + push(sp, areg(cpu, i->olen, RAX)); + push(sp, areg(cpu, i->olen, RCX)); + push(sp, areg(cpu, i->olen, RDX)); + push(sp, areg(cpu, i->olen, RBX)); + push(sp, osp); + push(sp, areg(cpu, i->olen, RBP)); + push(sp, areg(cpu, i->olen, RSI)); + push(sp, areg(cpu, i->olen, RDI)); +} + +static void +oppopa(Cpu *cpu, Inst *i) +{ + Iarg *sp; + + sp = areg(cpu, cpu->slen, RSP); + pop(sp, areg(cpu, i->olen, RDI)); + pop(sp, areg(cpu, i->olen, RSI)); + pop(sp, areg(cpu, i->olen, RBP)); + pop(sp, areg(cpu, i->olen, RBX)); // RSP + pop(sp, areg(cpu, i->olen, RBX)); + pop(sp, areg(cpu, i->olen, RDX)); + pop(sp, areg(cpu, i->olen, RCX)); + pop(sp, areg(cpu, i->olen, RAX)); +} + +static void +oppushf(Cpu *cpu, Inst *i) +{ + push(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL)); +} + +static void +oppopf(Cpu *cpu, Inst *i) +{ + ulong *f, o; + + f = cpu->reg + RFL; + o = *f; + pop(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL)); + *f &= ~(VM|RF); + *f |= (o & (VM|RF)); +} + +static void +oplahf(Cpu *cpu, Inst *i) +{ + aw(i->a1, cpu->reg[RFL]); +} + +static void +opsahf(Cpu *cpu, Inst *i) +{ + enum { MASK = SF|ZF|AF|PF|CF }; + ulong *f; + + f = cpu->reg + RFL; + *f &= ~MASK; + *f |= (ar(i->a1) & MASK); +} + +static void +opcli(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] &= ~IF; +} + +static void +opsti(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] |= IF; +} + +static void +opcld(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] &= ~DF; +} + +static void +opstd(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] |= DF; +} + +static void +opclc(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] &= ~CF; +} + +static void +opstc(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] |= CF; +} + +static void +opcmc(Cpu *cpu, Inst *) +{ + cpu->reg[RFL] ^= CF; +} + +static void +parity(ulong *f, ulong r) +{ + static ulong tab[8] = { + 0x96696996, + 0x69969669, + 0x69969669, + 0x96696996, + 0x69969669, + 0x96696996, + 0x96696996, + 0x69969669, + }; + r &= 0xFF; + if((tab[r/32] >> (r%32)) & 1) + *f &= ~PF; + else + *f |= PF; +} + +static ulong +test(ulong *f, long r, int s) +{ + *f &= ~(CF|SF|ZF|OF|PF); + r &= mask(s); + if(r == 0) + *f |= ZF; + if(r & sign(s)) + *f |= SF; + parity(f, r); + return r; +} + +static void +opshl(Cpu *cpu, Inst *i) +{ + ulong *f, r, a, h; + int s, n; + + if((n = ar(i->a2) & 31) == 0) + return; + s = i->a1->len*8; + a = ar(i->a1); + f = cpu->reg + RFL; + r = test(f, a<a1, r); + if((a<<(n-1)) & h) + *f |= CF; + if(n == 1 && ((a^r) & h)) + *f |= OF; +} + +static void +opshr(Cpu *cpu, Inst *i) +{ + ulong *f, a; + int s, n; + + if((n = ar(i->a2) & 31) == 0) + return; + s = i->a1->len*8; + a = ar(i->a1); + f = cpu->reg + RFL; + aw(i->a1, test(f, a>>n, s)); + if(a & sign(n)) + *f |= CF; + if(n == 1 && (a & sign(s))) + *f |= OF; +} + +static void +opsar(Cpu *cpu, Inst *i) +{ + ulong *f; + long a; + int n; + + if((n = ar(i->a2) & 31) == 0) + return; + a = ars(i->a1); + f = cpu->reg + RFL; + aw(i->a1, test(f, a>>n, i->a1->len*8)); + if(a & sign(n)) + *f |= CF; +} + +static void +opshld(Cpu *cpu, Inst *i) +{ + ulong *f, a; + int s, n; + + if((n = ar(i->a3) & 31) == 0) + return; + s = i->a1->len*8; + a = ar(i->a1); + f = cpu->reg + RFL; + aw(i->a1, test(f, (a<a2)>>(s-n)), s)); + if((a<<(n-1)) & sign(s)) + *f |= CF; +} + +static void +opshrd(Cpu *cpu, Inst *i) +{ + ulong *f, a; + int s, n; + + if((n = ar(i->a3) & 31) == 0) + return; + s = i->a1->len*8; + a = ar(i->a1); + f = cpu->reg + RFL; + aw(i->a1, test(f, (a>>n)|(ar(i->a2)<<(s-n)), s)); + if(a & sign(n)) + *f |= CF; +} + + +static void +oprcl(Cpu *cpu, Inst *i) +{ + ulong *f, a, r; + int s, n; + + s = i->a1->len*8; + n = ar(i->a2) % (s+1); + a = ar(i->a1); + r = (a<>(s-n))>>1); + f = cpu->reg + RFL; + if(*f & CF) + r |= sign(n); + aw(i->a1, r); + *f &= ~(CF|OF); + if((a>>(s-n)) & 1) + *f |= CF; + if((a ^ r) & sign(s)) + *f |= OF; + parity(f, r); +} + +static void +oprcr(Cpu *cpu, Inst *i) +{ + ulong *f, a, r, h; + int s, n; + + s = i->a1->len*8; + n = ar(i->a2) % (s+1); + a = ar(i->a1); + h = a<<(s-n); + r = (a>>n) | (h<<1); + f = cpu->reg + RFL; + if(*f & CF) + r |= 1<<(s-n); + aw(i->a1, r); + *f &= ~(CF|OF); + if(h & sign(s)) + *f |= CF; + if((a ^ r) & sign(s)) + *f |= OF; + parity(f, r); +} + +static void +oprol(Cpu *cpu, Inst *i) +{ + ulong *f, a, r; + int s, n; + + s = i->a1->len*8; + n = ar(i->a2) & (s-1); + a = ar(i->a1); + r = (a<>(s-n)); + f = cpu->reg + RFL; + aw(i->a1, r); + *f &= ~(CF|OF); + if(r & 1) + *f |= CF; + if((a ^ r) & sign(s)) + *f |= OF; + parity(f, r); +} + +static void +opror(Cpu *cpu, Inst *i) +{ + ulong *f, a, r; + int s, n; + + s = i->a1->len*8; + n = ar(i->a2) & (s-1); + a = ar(i->a1); + r = (a>>n) | (a<<(s-n)); + aw(i->a1, r); + f = cpu->reg + RFL; + *f &= ~(CF|OF); + if(r & sign(s)) + *f |= CF; + if((a ^ r) & sign(s)) + *f |= OF; + parity(f, r); +} + +static void +opbittest(Cpu *cpu, Inst *i) +{ + ulong a, m; + int n, s; + Iarg *x; + + n = ar(i->a2); + x = i->a1; + s = x->len*8; + if(x->tag == TMEM){ + x = adup(x); + x->off += (n / s) * x->len; + x->off &= mask(i->alen*8); + } + a = ar(x); + n &= s-1; + m = 1<reg[RFL] |= CF; + else + cpu->reg[RFL] &= ~CF; + switch(i->op){ + case OBT: + break; + case OBTS: + aw(x, a | m); + break; + case OBTR: + aw(x, a & ~m); + break; + case OBTC: + aw(x, a ^ m); + break; + } +} + +static void +opbitscan(Cpu *cpu, Inst *i) +{ + ulong a; + + if((a = ar(i->a2)) == 0) + cpu->reg[RFL] |= ZF; + else { + int j; + + if(i->op == OBSF){ + for(j = 0; (a & (1<a2->len*8-1; (a & (1<a1, j); + cpu->reg[RFL] &= ~ZF; + } +} + +static void +opand(Cpu *cpu, Inst *i) +{ + aw(i->a1, test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8)); +} + +static void +opor(Cpu *cpu, Inst *i) +{ + aw(i->a1, test(cpu->reg + RFL, ars(i->a1) | ars(i->a2), i->a1->len*8)); +} + +static void +opxor(Cpu *cpu, Inst *i) +{ + aw(i->a1, test(cpu->reg + RFL, ars(i->a1) ^ ars(i->a2), i->a1->len*8)); +} + +static void +opnot(Cpu *, Inst *i) +{ + aw(i->a1, ~ar(i->a1)); +} + +static void +optest(Cpu *cpu, Inst *i) +{ + test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8); +} + +static ulong +add(ulong *f, long a, long b, int c, int s) +{ + ulong r, cc, m, n; + + *f &= ~(AF|CF|SF|ZF|OF|PF); + + n = sign(s); + m = mask(s); + r = a + b + c; + r &= m; + if(r == 0) + *f |= ZF; + if(r & n) + *f |= SF; + cc = (a & b) | (~r & (a | b)); + if(cc & n) + *f |= CF; + if((cc ^ (cc >> 1)) & (n>>1)) + *f |= OF; + parity(f, r); + return r; +} + +static ulong +sub(ulong *f, long a, long b, int c, int s) +{ + ulong r, bc, n; + + *f &= ~(AF|CF|SF|ZF|OF|PF); + + r = a - b - c; + n = sign(s); + r &= mask(s); + if(r == 0) + *f |= ZF; + if(r & n) + *f |= SF; + a = ~a; + bc = (a & b) | (r & (a | b)); + if(bc & n) + *f |= CF; + if((bc ^ (bc >> 1)) & (n>>1)) + *f |= OF; + parity(f, r); + return r; +} + +static void +opadd(Cpu *cpu, Inst *i) +{ + aw(i->a1, add(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8)); +} + +static void +opadc(Cpu *cpu, Inst *i) +{ + ulong *f = cpu->reg + RFL; + + aw(i->a1, add(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8)); +} + +static void +opsub(Cpu *cpu, Inst *i) +{ + aw(i->a1, sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8)); +} + +static void +opsbb(Cpu *cpu, Inst *i) +{ + ulong *f = cpu->reg + RFL; + + aw(i->a1, sub(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8)); +} + +static void +opneg(Cpu *cpu, Inst *i) +{ + aw(i->a1, sub(cpu->reg + RFL, 0, ars(i->a1), 0, i->a1->len*8)); +} + +static void +opcmp(Cpu *cpu, Inst *i) +{ + sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8); +} + +static void +opinc(Cpu *cpu, Inst *i) +{ + ulong *f, o; + + f = cpu->reg + RFL; + o = *f; + aw(i->a1, add(f, ars(i->a1), 1, 0, i->a1->len*8)); + *f = (*f & ~CF) | (o & CF); +} + +static void +opdec(Cpu *cpu, Inst *i) +{ + ulong *f, o; + + f = cpu->reg + RFL; + o = *f; + aw(i->a1, sub(f, ars(i->a1), 1, 0, i->a1->len*8)); + *f = (*f & ~CF) | (o & CF); +} + +static void +opmul(Cpu *cpu, Inst *i) +{ + Iarg *la, *ha; + ulong l, h, m; + uvlong r; + int s; + + s = i->a2->len*8; + m = mask(s); + r = ar(i->a2) * ar(i->a3); + l = r & m; + h = (r >> s) & m; + if(i->a1->atype != AAX) + abort(); + la = areg(cpu, i->a2->len, RAX); + if(s == 8){ + ha = adup(la); + ha->tag |= TH; + } else + ha = areg(cpu, i->a2->len, RDX); + aw(la, l); + aw(ha, h); + if(h) + cpu->reg[RFL] |= (CF|OF); + else + cpu->reg[RFL] &= ~(CF|OF); +} + +static void +opimul(Cpu *cpu, Inst *i) +{ + ulong l, h, m, n; + vlong r; + int s; + + s = i->a2->len*8; + m = mask(s); + n = sign(s); + r = ars(i->a2) * ars(i->a3); + h = (r >> s) & m; + l = r & m; + if(i->a1->atype == AAX){ + Iarg *la, *ha; + + la = areg(cpu, i->a2->len, RAX); + if(s == 8){ + ha = adup(la); + ha->tag |= TH; + }else + ha = areg(cpu, i->a2->len, RDX); + aw(la, l); + aw(ha, h); + } else + aw(i->a1, l); + if((r > (vlong)n-1) || (r < -(vlong)n)) + cpu->reg[RFL] |= (CF|OF); + else + cpu->reg[RFL] &= ~(CF|OF); +} + +static void +opdiv(Cpu *cpu, Inst *i) +{ + Iarg *qa, *ra; + uvlong n, q; + ulong m, r, d; + int s; + + s = i->a1->len*8; + m = mask(s); + d = ar(i->a1); + if(d == 0) + trap(cpu, EDIV0); + if(s == 8){ + qa = areg(cpu, 1, RAX); + ra = adup(qa); + ra->tag |= TH; + } else { + qa = areg(cpu, i->olen, RAX); + ra = areg(cpu, i->olen, RDX); + } + n = (uvlong)ar(ra)< m) + trap(cpu, EDIV0); + r = n%d; + aw(ra, r); + aw(qa, q); +} + +static void +opidiv(Cpu *cpu, Inst *i) +{ + Iarg *qa, *ra; + vlong n, q, min, max; + long r, d; + int s; + + s = i->a1->len*8; + d = ars(i->a1); + if(d == 0) + trap(cpu, EDIV0); + if(s == 8){ + qa = areg(cpu, 1, RAX); + ra = adup(qa); + ra->tag |= TH; + } else { + qa = areg(cpu, i->olen, RAX); + ra = areg(cpu, i->olen, RDX); + } + n = (vlong)ars(ra)< max || q < min) + trap(cpu, EDIV0); + + aw(ra, r); + aw(qa, q); +} + +static int +cctrue(Cpu *cpu, Inst *i) +{ + enum { SO = 1<<16, /* pseudo-flag SF != OF */ }; + static ulong test[] = { + OF, /* JO, JNO */ + CF, /* JC, JNC */ + ZF, /* JZ, JNZ */ + CF|ZF, /* JBE,JA */ + SF, /* JS, JNS */ + PF, /* JP, JNP */ + SO, /* JL, JGE */ + SO|ZF, /* JLE,JG */ + }; + ulong f, t; + uchar c; + + c = i->code; + switch(c){ + case 0xE3: /* JCXZ */ + return ar(areg(cpu, i->alen, RCX)) == 0; + case 0xEB: /* JMP */ + case 0xE9: + case 0xEA: + case 0xFF: + return 1; + default: + f = cpu->reg[RFL]; + if(((f&SF)!=0) ^ ((f&OF)!=0)) + f |= SO; + t = test[(c>>1)&7]; + return ((t&f) != 0) ^ (c&1); + } +} + +static void +opjump(Cpu *cpu, Inst *i) +{ + if(cctrue(cpu, i)) + jump(i->a1); +} + +static void +opset(Cpu *cpu, Inst *i) +{ + aw(i->a1, cctrue(cpu, i)); +} + +static void +oploop(Cpu *cpu, Inst *i) +{ + Iarg *cx; + ulong c; + + switch(i->op){ + default: + abort(); + case OLOOPNZ: + if(cpu->reg[RFL] & ZF) + return; + break; + case OLOOPZ: + if((cpu->reg[RFL] & ZF) == 0) + return; + break; + case OLOOP: + break; + } + cx = areg(cpu, i->alen, RCX); + c = ar(cx) - 1; + aw(cx, c); + if(c) + jump(i->a1); +} + +static void +oplea(Cpu *, Inst *i) +{ + aw(i->a1, i->a2->off); +} + +static void +opmov(Cpu *, Inst *i) +{ + aw(i->a1, ar(i->a2)); +} + +static void +opcbw(Cpu *cpu, Inst *i) +{ + aw(areg(cpu, i->olen, RAX), ars(areg(cpu, i->olen>>1, RAX))); +} + +static void +opcwd(Cpu *cpu, Inst *i) +{ + aw(areg(cpu, i->olen, RDX), ars(areg(cpu, i->olen, RAX))>>(i->olen*8-1)); +} + +static void +opmovsx(Cpu *, Inst *i) +{ + aw(i->a1, ars(i->a2)); +} + +static void +opxchg(Cpu *, Inst *i) +{ + ulong x; + + x = ar(i->a1); + aw(i->a1, ar(i->a2)); + aw(i->a2, x); +} + +static void +oplfp(Cpu *, Inst *i) +{ + Iarg *p; + + p = afar(i->a3, i->olen, i->olen); + aw(i->a1, p->seg); + aw(i->a2, p->off); +} + +static void +opbound(Cpu *cpu, Inst *i) +{ + ulong p, s, e; + + p = ar(i->a1); + s = ar(i->a2); + e = ar(i->a3); + if((p < s) || (p >= e)) + trap(cpu, EBOUND); +} + +static void +opxlat(Cpu *cpu, Inst *i) +{ + aw(i->a1, ar(amem(cpu, i->a1->len, i->sreg, ar(areg(cpu, i->alen, i->a2->reg)) + ar(i->a1)))); +} + +static void +opcpuid(Cpu *cpu, Inst *) +{ + static struct { + ulong level; + + ulong ax; + ulong bx; + ulong cx; + ulong dx; + } tab[] = { + 0, + 5, + 0x756e6547, /* Genu */ + 0x6c65746e, /* ntel */ + 0x49656e69, /* ineI */ + 1, + 4<<8, + 0x00000000, + 0x00000000, + 0x00000000, + 2, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 3, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + }; + + int i; + + for(i=0; ireg[RAX]){ + cpu->reg[RAX] = tab[i].ax; + cpu->reg[RBX] = tab[i].bx; + cpu->reg[RCX] = tab[i].cx; + cpu->reg[RDX] = tab[i].dx; + return; + } + } + trap(cpu, EBADOP); +} + +static void +opmovs(Cpu *cpu, Inst *i) +{ + Iarg *cx, *d, *s; + ulong c, m; + int n; + + m = mask(i->alen*8); + d = adup(i->a1); + s = adup(i->a2); + n = s->len; + if(cpu->reg[RFL] & DF) + n = -n; + if(i->rep){ + cx = areg(cpu, i->alen, RCX); + c = ar(cx); + } else { + cx = nil; + c = 1; + } + while(c){ + aw(d, ar(s)); + d->off += n; + d->off &= m; + s->off += n; + s->off &= m; + c--; + } + aw(areg(cpu, i->alen, RDI), d->off); + aw(areg(cpu, i->alen, RSI), s->off); + if(cx) + aw(cx, 0); +} + +static void +oplods(Cpu *cpu, Inst *i) +{ + Iarg *cx, *s; + ulong c, m; + int n; + + m = mask(i->alen*8); + s = adup(i->a2); + n = s->len; + if(cpu->reg[RFL] & DF) + n = -n; + if(i->rep){ + cx = areg(cpu, i->alen, RCX); + c = ar(cx); + } else { + cx = nil; + c = 1; + } + if(c){ + s->off += n*(c-1); + s->off &= m; + aw(i->a1, ar(s)); + s->off += n; + s->off &= m; + } + aw(areg(cpu, i->alen, RSI), s->off); + if(cx) + aw(cx, 0); +} + +static void +opstos(Cpu *cpu, Inst *i) +{ + Iarg *cx, *d; + ulong c, a, m; + int n; + + m = mask(i->alen*8); + d = adup(i->a1); + n = d->len; + if(cpu->reg[RFL] & DF) + n = -n; + if(i->rep){ + cx = areg(cpu, i->alen, RCX); + c = ar(cx); + } else { + cx = nil; + c = 1; + } + a = ar(i->a2); + while(c){ + aw(d, a); + d->off += n; + d->off &= m; + c--; + } + aw(areg(cpu, i->alen, RDI), d->off); + if(cx) + aw(cx, c); +} + +static int +repcond(ulong *f, int rep) +{ + if(rep == OREPNE) + return (*f & ZF) == 0; + return (*f & ZF) != 0; +} + +static void +opscas(Cpu *cpu, Inst *i) +{ + Iarg *cx, *d; + ulong *f, c, m; + long a; + int n, z; + + m = mask(i->alen*8); + d = adup(i->a1); + n = d->len; + z = n*8; + f = cpu->reg + RFL; + if(*f & DF) + n = -n; + if(i->rep){ + cx = areg(cpu, i->alen, RCX); + c = ar(cx); + } else { + cx = nil; + c = 1; + } + a = ars(i->a2); + while(c){ + sub(f, a, ars(d), 0, z); + d->off += n; + d->off &= m; + c--; + if(!repcond(f, i->rep)) + break; + } + aw(areg(cpu, i->alen, RDI), d->off); + if(cx) + aw(cx, c); +} + +static void +opcmps(Cpu *cpu, Inst *i) +{ + Iarg *cx, *s, *d; + ulong *f, c, m; + int n, z; + + m = mask(i->alen*8); + d = adup(i->a1); + s = adup(i->a2); + n = s->len; + z = n*8; + f = cpu->reg + RFL; + if(*f & DF) + n = -n; + if(i->rep){ + cx = areg(cpu, i->alen, RCX); + c = ar(cx); + } else { + cx = nil; + c = 1; + } + while(c){ + sub(f, ars(s), ars(d), 0, z); + s->off += n; + s->off &= m; + d->off += n; + d->off &= m; + c--; + if(!repcond(f, i->rep)) + break; + } + aw(areg(cpu, i->alen, RDI), d->off); + aw(areg(cpu, i->alen, RSI), s->off); + if(cx) + aw(cx, c); +} + +static void +opin(Cpu *cpu, Inst *i) +{ + Bus *io; + + io = cpu->port; + aw(i->a1, io->r(io->aux, ar(i->a2) & 0xFFFF, i->a1->len)); +} + +static void +opout(Cpu *cpu, Inst *i) +{ + Bus *io; + + io = cpu->port; + io->w(io->aux, ar(i->a1) & 0xFFFF, ar(i->a2), i->a2->len); +} + +static void +opnop(Cpu *, Inst *) +{ +} + +static void +ophlt(Cpu *cpu, Inst *) +{ + trap(cpu, EHALT); +} + +static void (*exctab[NUMOP])(Cpu *cpu, Inst*) = { + [OINT] = opint, + [OIRET] = opiret, + + [OCALL] = opcall, + [OJUMP] = opjump, + [OSET] = opset, + + [OLOOP] = oploop, + [OLOOPZ] = oploop, + [OLOOPNZ] = oploop, + + [ORET] = opret, + [ORETF] = opretf, + + [OENTER] = openter, + [OLEAVE] = opleave, + + [OPUSH] = oppush, + [OPOP] = oppop, + + [OPUSHF] = oppushf, + [OPOPF] = oppopf, + [OLAHF] = oplahf, + [OSAHF] = opsahf, + + [OPUSHA] = oppusha, + [OPOPA] = oppopa, + + [OCLI] = opcli, + [OSTI] = opsti, + [OCLC] = opclc, + [OSTC] = opstc, + [OCMC] = opcmc, + [OCLD] = opcld, + [OSTD] = opstd, + + [OSHL] = opshl, + [OSHR] = opshr, + [OSAR] = opsar, + + [OSHLD] = opshld, + [OSHRD] = opshrd, + + [ORCL] = oprcl, + [ORCR] = oprcr, + [OROL] = oprol, + [OROR] = opror, + + [OBT] = opbittest, + [OBTS] = opbittest, + [OBTR] = opbittest, + [OBTC] = opbittest, + + [OBSF] = opbitscan, + [OBSR] = opbitscan, + + [OAND] = opand, + [OOR] = opor, + [OXOR] = opxor, + [ONOT] = opnot, + [OTEST] = optest, + + [OADD] = opadd, + [OADC] = opadc, + [OSUB] = opsub, + [OSBB] = opsbb, + [ONEG] = opneg, + [OCMP] = opcmp, + + [OINC] = opinc, + [ODEC] = opdec, + + [OMUL] = opmul, + [OIMUL] = opimul, + [ODIV] = opdiv, + [OIDIV] = opidiv, + + [OLEA] = oplea, + [OMOV] = opmov, + [OCBW] = opcbw, + [OCWD] = opcwd, + [OMOVZX] = opmov, + [OMOVSX] = opmovsx, + [OXCHG] = opxchg, + [OLFP] = oplfp, + [OBOUND] = opbound, + [OXLAT] = opxlat, + + [OCPUID] = opcpuid, + + [OMOVS] = opmovs, + [OLODS] = oplods, + [OSTOS] = opstos, + [OSCAS] = opscas, + [OCMPS] = opcmps, + + [OIN] = opin, + [OOUT] = opout, + + [ONOP] = opnop, + [OHLT] = ophlt, +}; + +void +trap(Cpu *cpu, int e) +{ + cpu->reg[RIP] = cpu->oldip; + cpu->trap = e; + longjmp(cpu->jmp, 1); +} + +int +intr(Cpu *cpu, int v) +{ + Iarg *sp, *ip, *cs, *iv; + + if(v < 0 || v > 0xff || cpu->olen != 2) + return -1; + + sp = areg(cpu, cpu->slen, RSP); + cs = areg(cpu, 2, RCS); + ip = areg(cpu, 2, RIP); + + iv = amem(cpu, 2, R0S, v * 4); + + push(sp, areg(cpu, 2, RFL)); + push(sp, cs); + push(sp, ip); + + cpu->reg[RIP] = ar(iv); + iv->off += 2; + cpu->reg[RCS] = ar(iv); + return 0; +} + +int +xec(Cpu *cpu, int n) +{ + if(setjmp(cpu->jmp)) + return cpu->trap; + while(n--){ + void (*f)(Cpu *, Inst *); + Iarg *ip; + Inst i; + + cpu->ic++; + + ip = amem(cpu, 1, RCS, cpu->oldip = cpu->reg[RIP]); + decode(ip, &i); + cpu->reg[RIP] = ip->off; + if((f = exctab[i.op]) == nil) + trap(cpu, EBADOP); + f(cpu, &i); + } + return n; +} From 26f641da68eddef9f6f8cb8dd8a284ddeb86a4a4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 093/402] bin/rc: start realemu in termrc when monitor is vesa --- rc/bin/termrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rc/bin/termrc b/rc/bin/termrc index 5de208a553..e5cb141795 100755 --- a/rc/bin/termrc +++ b/rc/bin/termrc @@ -92,8 +92,11 @@ if(test -f /dev/mousectl){ aux/mouse $mouseport # parse vgasize into fields vgasize=`{echo $vgasize} - if(! ~ $"monitor '' && ! ~ `{cat /dev/user} none) + if(! ~ $"monitor '' && ! ~ `{cat /dev/user} none){ + if(~ $monitor vesa) + aux/realemu aux/vga -l $vgasize + } if(~ $accupoint 1) pipefile -dr /bin/aux/accupoint /dev/mouse } From e51fcc3299e6eb0cab949626ad227d79d8098d13 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 1 Sep 2017 07:53:49 +0000 Subject: [PATCH 094/402] bin/rc: start ip/ipconfig in termrc --- rc/bin/termrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rc/bin/termrc b/rc/bin/termrc index e5cb141795..d7fc426b3f 100755 --- a/rc/bin/termrc +++ b/rc/bin/termrc @@ -42,8 +42,8 @@ if(test -e /cfg/$sysname/termrc) # # If your site provides DHCP service, # -#if(! test -e /net/ipifc/0/ctl) -# ip/ipconfig +if(! test -e /net/ipifc/0/ctl) + ip/ipconfig # # Otherwise, see /cfg/$sysname/termrc (/cfg/example/termrc is an example). From 1a9bb0d0ab2a1f256fccb775095cb1838f49c326 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:11:25 +0000 Subject: [PATCH 095/402] sys/src/libsec/port: add TLS 1.2 support in tlshand --- sys/src/libsec/port/tlshand.c | 175 +++++++++++++++++++++++++--------- 1 file changed, 129 insertions(+), 46 deletions(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index a7d38b6c09..3b75781734 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -51,6 +51,12 @@ typedef struct Finished{ int n; } Finished; +typedef struct HandHash{ + MD5state md5; + SHAstate sha1; + SHA2_256state sha2_256; +} HandHash; + typedef struct TlsConnection{ TlsSec *sec; // security management goo int hand, ctl; // record layer file descriptors @@ -78,8 +84,7 @@ typedef struct TlsConnection{ int nsecret; // amount of secret data to init keys // for finished messages - MD5state hsmd5; // handshake hash - SHAstate hssha1; // handshake hash + HandHash hs; // handshake hash Finished finished; } TlsConnection; @@ -128,15 +133,17 @@ typedef struct TlsSec{ int vers; // final version // byte generation and handshake checksum void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int); - void (*setFinished)(TlsSec*, MD5state, SHAstate, uchar*, int); + void (*setFinished)(TlsSec*, HandHash, uchar*, int); int nfin; } TlsSec; enum { - TLSVersion = 0x0301, - SSL3Version = 0x0300, - ProtocolVersion = 0x0301, // maximum version we speak + SSL3Version = 0x0300, + TLS10Version = 0x0301, + TLS11Version = 0x0302, + TLS12Version = 0x0303, + ProtocolVersion = TLS12Version, // maximum version we speak MinProtoVersion = 0x0300, // limits on version we accept MaxProtoVersion = 0x03ff, }; @@ -273,7 +280,7 @@ static TlsSec* tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uc static int tlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd); static TlsSec* tlsSecInitc(int cvers, uchar *crandom); static int tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd); -static int tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient); +static int tlsSecFinished(TlsSec *sec, HandHash hs, uchar *fin, int nfin, int isclient); static void tlsSecOk(TlsSec *sec); static void tlsSecKill(TlsSec *sec); static void tlsSecClose(TlsSec *sec); @@ -283,8 +290,9 @@ static void setSecrets(TlsSec *sec, uchar *kd, int nkd); static int clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm); static Bytes *pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype); static Bytes *pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm); -static void tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient); -static void sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient); +static void tlsSetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient); +static void tls12SetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient); +static void sslSetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient); static void sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1); static int setVers(TlsSec *sec, int version); @@ -556,7 +564,7 @@ tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ... msgClear(&m); /* no CertificateVerify; skip to Finished */ - if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){ + if(tlsSecFinished(c->sec, c->hs, c->finished.verify, c->finished.n, 1) < 0){ tlsError(c, EInternalError, "can't set finished: %r"); goto Err; } @@ -578,7 +586,7 @@ tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ... goto Err; } - if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){ + if(tlsSecFinished(c->sec, c->hs, c->finished.verify, c->finished.n, 0) < 0){ tlsError(c, EInternalError, "can't set finished: %r"); goto Err; } @@ -747,7 +755,7 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ... // Cipherchange must occur immediately before Finished to avoid // potential hole; see section 4.3 of Wagner Schneier 1996. - if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){ + if(tlsSecFinished(c->sec, c->hs, c->finished.verify, c->finished.n, 1) < 0){ tlsError(c, EInternalError, "can't set finished 1: %r"); goto Err; } @@ -761,7 +769,7 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ... } msgClear(&m); - if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){ + if(tlsSecFinished(c->sec, c->hs, c->finished.verify, c->finished.n, 0) < 0){ fprint(2, "tlsClient nepm=%d\n", nepm); tlsError(c, EInternalError, "can't set finished 0: %r"); goto Err; @@ -803,6 +811,17 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ... static uchar sendbuf[9000], *sendp; +static void +msgHash(TlsConnection *c, uchar *p, int n) +{ + md5(p, n, 0, &c->hs.md5); + sha1(p, n, 0, &c->hs.sha1); + if(c->version >= TLS12Version) + sha2_256(p, n, 0, &c->hs.sha2_256); + else + memset(&c->hs.sha2_256, 0, sizeof c->hs.sha2_256); +} + static int msgSend(TlsConnection *c, Msg *m, int act) { @@ -914,8 +933,7 @@ msgSend(TlsConnection *c, Msg *m, int act) // remember hash of Handshake messages if(m->tag != HHelloRequest) { - md5(sendp, n, 0, &c->hsmd5); - sha1(sendp, n, 0, &c->hssha1); + msgHash(c, sendp, n); } sendp = p; @@ -991,8 +1009,7 @@ msgRecv(TlsConnection *c, Msg *m) p = tlsReadN(c, n); if(p == nil) return 0; - md5(p, n, 0, &c->hsmd5); - sha1(p, n, 0, &c->hssha1); + msgHash(c, p, n); m->tag = HClientHello; if(n < 22) goto Short; @@ -1030,15 +1047,13 @@ msgRecv(TlsConnection *c, Msg *m) goto Ok; } - md5(p, 4, 0, &c->hsmd5); - sha1(p, 4, 0, &c->hssha1); + msgHash(c, p, 4); p = tlsReadN(c, n); if(p == nil) return 0; - md5(p, n, 0, &c->hsmd5); - sha1(p, n, 0, &c->hssha1); + msgHash(c, p, n); m->tag = type; @@ -1388,14 +1403,19 @@ setVersion(TlsConnection *c, int version) return -1; if(version > c->version) version = c->version; - if(version == SSL3Version) { - c->version = version; + switch(version) { + case SSL3Version: c->finished.n = SSL3FinishedLen; - }else if(version == TLSVersion){ - c->version = version; + break; + case TLS10Version: + case TLS11Version: + case TLS12Version: c->finished.n = TLSFinishedLen; - }else + break; + default: return -1; + } + c->version = version; c->verset = 1; return fprint(c->ctl, "version 0x%x", version); } @@ -1721,6 +1741,32 @@ tlsPsha1(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, u } } +static void +tlsPsha2_256(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed, int nseed) +{ + uchar ai[SHA2_256dlen], tmp[SHA2_256dlen]; + int n; + SHAstate *s; + + // generate a1 + s = hmac_sha2_256(label, nlabel, key, nkey, nil, nil); + hmac_sha2_256(seed, nseed, key, nkey, ai, s); + + while(nbuf > 0) { + s = hmac_sha2_256(ai, SHA2_256dlen, key, nkey, nil, nil); + s = hmac_sha2_256(label, nlabel, key, nkey, nil, s); + hmac_sha2_256(seed, nseed, key, nkey, tmp, s); + n = SHA2_256dlen; + if(n > nbuf) + n = nbuf; + memmove(buf, tmp, n); + buf += n; + nbuf -= n; + hmac_sha2_256(ai, SHA2_256dlen, key, nkey, tmp, nil); + memmove(ai, tmp, SHA2_256dlen); + } +} + // fill buf with md5(args)^sha1(args) static void tlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) @@ -1735,6 +1781,17 @@ tlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, in tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); } +void +tls12PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) +{ + uchar seed[2*RandomSize]; + int nlabel = strlen(label); + + memmove(seed, seed0, nseed0); + memmove(seed+nseed0, seed1, nseed1); + tlsPsha2_256(buf, nbuf, key, nkey, (uchar*)label, nlabel, seed, nseed0+nseed1); +} + /* * for setting server session id's */ @@ -1833,16 +1890,16 @@ tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, in } static int -tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient) +tlsSecFinished(TlsSec *sec, HandHash hs, uchar *fin, int nfin, int isclient) { if(sec->nfin != nfin){ sec->ok = -1; werrstr("invalid finished exchange"); return -1; } - md5.malloced = 0; - sha1.malloced = 0; - (*sec->setFinished)(sec, md5, sha1, fin, isclient); + hs.md5.malloced = 0; + hs.sha1.malloced = 0; + (*sec->setFinished)(sec, hs, fin, isclient); return 1; } @@ -1875,15 +1932,24 @@ tlsSecClose(TlsSec *sec) static int setVers(TlsSec *sec, int v) { - if(v == SSL3Version){ + switch(v){ + case SSL3Version: sec->setFinished = sslSetFinished; sec->nfin = SSL3FinishedLen; sec->prf = sslPRF; - }else if(v == TLSVersion){ + break; + case TLS10Version: + case TLS11Version: sec->setFinished = tlsSetFinished; sec->nfin = TLSFinishedLen; sec->prf = tlsPRF; - }else{ + break; + case TLS12Version: + sec->setFinished = tls12SetFinished; + sec->nfin = TLSFinishedLen; + sec->prf = tls12PRF; + break; + default: werrstr("invalid version"); return -1; } @@ -1973,7 +2039,7 @@ clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm) } static void -sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient) +sslSetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient) { DigestState *s; uchar h0[MD5dlen], h1[SHA1dlen], pad[48]; @@ -1984,21 +2050,21 @@ sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, in else label = "SRVR"; - md5((uchar*)label, 4, nil, &hsmd5); - md5(sec->sec, MasterSecretSize, nil, &hsmd5); + md5((uchar*)label, 4, nil, &hs.md5); + md5(sec->sec, MasterSecretSize, nil, &hs.md5); memset(pad, 0x36, 48); - md5(pad, 48, nil, &hsmd5); - md5(nil, 0, h0, &hsmd5); + md5(pad, 48, nil, &hs.md5); + md5(nil, 0, h0, &hs.md5); memset(pad, 0x5C, 48); s = md5(sec->sec, MasterSecretSize, nil, nil); s = md5(pad, 48, nil, s); md5(h0, MD5dlen, finished, s); - sha1((uchar*)label, 4, nil, &hssha1); - sha1(sec->sec, MasterSecretSize, nil, &hssha1); + sha1((uchar*)label, 4, nil, &hs.sha1); + sha1(sec->sec, MasterSecretSize, nil, &hs.sha1); memset(pad, 0x36, 40); - sha1(pad, 40, nil, &hssha1); - sha1(nil, 0, h1, &hssha1); + sha1(pad, 40, nil, &hs.sha1); + sha1(nil, 0, h1, &hs.sha1); memset(pad, 0x5C, 40); s = sha1(sec->sec, MasterSecretSize, nil, nil); s = sha1(pad, 40, nil, s); @@ -2007,20 +2073,37 @@ sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, in // fill "finished" arg with md5(args)^sha1(args) static void -tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient) +tlsSetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient) { uchar h0[MD5dlen], h1[SHA1dlen]; char *label; // get current hash value, but allow further messages to be hashed in - md5(nil, 0, h0, &hsmd5); - sha1(nil, 0, h1, &hssha1); + md5(nil, 0, h0, &hs.md5); + sha1(nil, 0, h1, &hs.sha1); + + if(isClient) + label = "client finished"; + else + label = "server finished"; + (*sec->prf)(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen); +} + +// fill "finished" arg with sha256(args) +static void +tls12SetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient) +{ + uchar h[SHA2_256dlen]; + char *label; + + // get current hash value, but allow further messages to be hashed in + sha2_256(nil, 0, h, &hs.sha2_256); if(isClient) label = "client finished"; else label = "server finished"; - tlsPRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen); + tlsPsha2_256(finished, TLSFinishedLen, sec->sec, MasterSecretSize, (uchar*)label, strlen(label), h, SHA2_256dlen); } static void From 2fd15db77e4a46dae083874cb7d4a0a1f97e1181 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:12:28 +0000 Subject: [PATCH 096/402] sys/src/libsec/port: handle sha2 X.509 signature algorithms --- sys/src/libsec/port/x509.c | 49 +++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c index 8d7dae106c..2d6ae2bb64 100644 --- a/sys/src/libsec/port/x509.c +++ b/sys/src/libsec/port/x509.c @@ -1582,20 +1582,38 @@ enum { ALG_md5WithRSAEncryption, ALG_sha1WithRSAEncryption, ALG_sha1WithRSAEncryptionOiw, + ALG_sha256WithRSAEncryption, + ALG_sha384WithRSAEncryption, + ALG_sha512WithRSAEncryption, + ALG_sha224WithRSAEncryption, ALG_md5, + ALG_sha1, + ALG_sha256, + ALG_sha384, + ALG_sha512, + ALG_sha224, NUMALGS }; -typedef struct Ints7 { +typedef struct Ints9 { int len; - int data[7]; -} Ints7; -static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 }; -static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 }; -static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 }; -static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 }; -static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 }; -static Ints7 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 }; -static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 }; + int data[9]; +} Ints9; +static Ints9 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 }; +static Ints9 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 }; +static Ints9 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 }; +static Ints9 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 }; +static Ints9 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 }; +static Ints9 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 }; +static Ints9 oid_sha256WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 11 }; +static Ints9 oid_sha384WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 12 }; +static Ints9 oid_sha512WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 13 }; +static Ints9 oid_sha224WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 14 }; +static Ints9 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 }; +static Ints9 oid_sha1 ={6, 1, 3, 14, 3, 2, 26 }; +static Ints9 oid_sha256 ={9, 2, 16, 840, 1, 101, 3, 4, 2, 1 }; +static Ints9 oid_sha384 ={9, 2, 16, 840, 1, 101, 3, 4, 2, 2 }; +static Ints9 oid_sha512 ={9, 2, 16, 840, 1, 101, 3, 4, 2, 3 }; +static Ints9 oid_sha224 ={9, 2, 16, 840, 1, 101, 3, 4, 2, 4 }; static Ints *alg_oid_tab[NUMALGS+1] = { (Ints*)&oid_rsaEncryption, (Ints*)&oid_md2WithRSAEncryption, @@ -1603,10 +1621,19 @@ static Ints *alg_oid_tab[NUMALGS+1] = { (Ints*)&oid_md5WithRSAEncryption, (Ints*)&oid_sha1WithRSAEncryption, (Ints*)&oid_sha1WithRSAEncryptionOiw, + (Ints*)&oid_sha256WithRSAEncryption, + (Ints*)&oid_sha384WithRSAEncryption, + (Ints*)&oid_sha512WithRSAEncryption, + (Ints*)&oid_sha224WithRSAEncryption, (Ints*)&oid_md5, + (Ints*)&oid_sha1, + (Ints*)&oid_sha256, + (Ints*)&oid_sha384, + (Ints*)&oid_sha512, + (Ints*)&oid_sha224, nil }; -static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, sha1, md5, nil }; +static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, sha1, sha2_256, sha2_384, sha2_512, sha2_224, md5, sha1, sha2_256, sha2_384, sha2_512, sha2_224, nil }; static void freecert(CertX509* c) From 27680967b21732e5b3ddc681ed470a05d4fae61e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:12:28 +0000 Subject: [PATCH 097/402] sys/src/libsec/port: sign certificates using SHA256withRSA signature algorithm --- sys/src/libsec/port/x509.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sys/src/libsec/port/x509.c b/sys/src/libsec/port/x509.c index 2d6ae2bb64..02a0d09e3d 100644 --- a/sys/src/libsec/port/x509.c +++ b/sys/src/libsec/port/x509.c @@ -2538,7 +2538,7 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) RSApub *pk = rsaprivtopub(priv); Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes; Elem e, certinfo, issuer, subject, pubkey, validity, sig; - uchar digest[MD5dlen], *buf; + uchar digest[SHA2_256dlen], *buf; int buflen; mpint *pkcs1; @@ -2560,7 +2560,7 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) nil))); certinfo = mkseq( mkel(mkint(serial), - mkel(mkalg(ALG_md5WithRSAEncryption), + mkel(mkalg(ALG_sha256WithRSAEncryption), mkel(issuer, mkel(validity, mkel(subject, @@ -2568,11 +2568,11 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) nil))))))); if(encode(certinfo, &certinfobytes) != ASN_OK) goto errret; - md5(certinfobytes->data, certinfobytes->len, digest, 0); + sha2_256(certinfobytes->data, certinfobytes->len, digest, 0); freebytes(certinfobytes); sig = mkseq( - mkel(mkalg(ALG_md5), - mkel(mkoctet(digest, MD5dlen), + mkel(mkalg(ALG_sha256), + mkel(mkoctet(digest, SHA2_256dlen), nil))); if(encode(sig, &sigbytes) != ASN_OK) goto errret; @@ -2583,7 +2583,7 @@ X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen) mpfree(pkcs1); e = mkseq( mkel(certinfo, - mkel(mkalg(ALG_md5WithRSAEncryption), + mkel(mkalg(ALG_sha256WithRSAEncryption), mkel(mkbits(buf, buflen), nil)))); free(buf); @@ -2606,7 +2606,7 @@ X509req(RSApriv *priv, char *subj, int *certlen) RSApub *pk = rsaprivtopub(priv); Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes; Elem e, certinfo, subject, pubkey, sig; - uchar digest[MD5dlen], *buf; + uchar digest[SHA2_256dlen], *buf; int buflen; mpint *pkcs1; @@ -2628,11 +2628,11 @@ X509req(RSApriv *priv, char *subj, int *certlen) nil)))); if(encode(certinfo, &certinfobytes) != ASN_OK) goto errret; - md5(certinfobytes->data, certinfobytes->len, digest, 0); + sha2_256(certinfobytes->data, certinfobytes->len, digest, 0); freebytes(certinfobytes); sig = mkseq( - mkel(mkalg(ALG_md5), - mkel(mkoctet(digest, MD5dlen), + mkel(mkalg(ALG_sha256), + mkel(mkoctet(digest, SHA2_256dlen), nil))); if(encode(sig, &sigbytes) != ASN_OK) goto errret; @@ -2643,7 +2643,7 @@ X509req(RSApriv *priv, char *subj, int *certlen) mpfree(pkcs1); e = mkseq( mkel(certinfo, - mkel(mkalg(ALG_md5), + mkel(mkalg(ALG_sha256), mkel(mkbits(buf, buflen), nil)))); free(buf); @@ -2773,7 +2773,7 @@ X509dump(uchar *cert, int ncert) pk = decode_rsapubkey(c->publickey); print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n); - print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest); + print("sigalg=%d digest=%.*H\n", c->signature_alg, SHA2_256dlen, digest); e = verify_signature(c->signature, pk, digest, &sigalg); if(e==nil){ e = "nil (meaning ok)"; From d329e6b3fcc7844482d7e76b7e90dcf1d4435413 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:11:51 +0000 Subject: [PATCH 098/402] sys/src/libsec/port: disable SSL 3.0 handshake (POODLE) --- sys/src/libsec/port/tlshand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 3b75781734..fc6d13b8ac 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -1406,7 +1406,7 @@ setVersion(TlsConnection *c, int version) switch(version) { case SSL3Version: c->finished.n = SSL3FinishedLen; - break; + return -1; case TLS10Version: case TLS11Version: case TLS12Version: From 2c703c5d8348e24ae37985acf3fb3436131644c7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:12:29 +0000 Subject: [PATCH 099/402] sys/src/libsec/port: disable prohibited RC4 ciphers in tlshand (RFC7465) --- sys/src/libsec/port/tlshand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index fc6d13b8ac..79920eeb2d 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -1448,8 +1448,8 @@ static int weakCipher[CipherMax] = 1, /* TLS_RSA_WITH_NULL_MD5 */ 1, /* TLS_RSA_WITH_NULL_SHA */ 1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */ - 0, /* TLS_RSA_WITH_RC4_128_MD5 */ - 0, /* TLS_RSA_WITH_RC4_128_SHA */ + 1, /* TLS_RSA_WITH_RC4_128_MD5 */ + 1, /* TLS_RSA_WITH_RC4_128_SHA */ 1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */ 0, /* TLS_RSA_WITH_IDEA_CBC_SHA */ 1, /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */ From e128e6eae0d1f9d016d1056f58e01cd578490024 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:11:36 +0000 Subject: [PATCH 100/402] sys/src/libsec/port: various fixes in tlshand (thanks Geoff Collyer) --- sys/src/libsec/port/tlshand.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 79920eeb2d..1190f6c8cf 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -73,7 +73,7 @@ typedef struct TlsConnection{ int state; // must be set using setstate // input buffer for handshake messages - uchar buf[MaxChunk+2048]; + uchar buf[MaxChunk+8*1024]; uchar *rp, *ep; uchar crandom[RandomSize]; // client random @@ -403,8 +403,11 @@ tlsClient(int fd, TLSconn *conn) } sprint(dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); - if(data < 0) + if(data < 0) { + close(hand); + close(ctl); return -1; + } fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsClient2(ctl, hand, conn->sessionID, conn->sessionIDlen, conn->trace); close(fd); @@ -1249,6 +1252,7 @@ msgClear(Msg *m) case HClientHello: freebytes(m->u.clientHello.sid); freeints(m->u.clientHello.ciphers); + m->u.clientHello.ciphers = nil; freebytes(m->u.clientHello.compressors); break; case HServerHello: @@ -1435,7 +1439,7 @@ tlsConnectionFree(TlsConnection *c) tlsSecClose(c->sec); freebytes(c->sid); freebytes(c->cert); - memset(c, 0, sizeof(c)); + memset(c, 0, sizeof *c); free(c); } @@ -1546,12 +1550,14 @@ initCiphers(void) j = open("#a/tls/encalgs", OREAD); if(j < 0){ werrstr("can't open #a/tls/encalgs: %r"); + unlock(&ciphLock); return 0; } n = read(j, s, MaxAlgF-1); close(j); if(n <= 0){ werrstr("nothing in #a/tls/encalgs: %r"); + unlock(&ciphLock); return 0; } s[n] = 0; @@ -1570,12 +1576,14 @@ initCiphers(void) j = open("#a/tls/hashalgs", OREAD); if(j < 0){ werrstr("can't open #a/tls/hashalgs: %r"); + unlock(&ciphLock); return 0; } n = read(j, s, MaxAlgF-1); close(j); if(n <= 0){ werrstr("nothing in #a/tls/hashalgs: %r"); + unlock(&ciphLock); return 0; } s[n] = 0; @@ -1899,6 +1907,11 @@ tlsSecFinished(TlsSec *sec, HandHash hs, uchar *fin, int nfin, int isclient) } hs.md5.malloced = 0; hs.sha1.malloced = 0; + if(sec->setFinished == nil ){ + sec->ok = -1; + werrstr("nil sec->setFinished in tlsSecFinished"); + return -1; + } (*sec->setFinished)(sec, hs, fin, isclient); return 1; } @@ -1951,6 +1964,8 @@ setVers(TlsSec *sec, int v) break; default: werrstr("invalid version"); + sec->setFinished = nil; + sec->prf = nil; return -1; } sec->vers = v; @@ -1967,6 +1982,10 @@ setVers(TlsSec *sec, int v) static void setSecrets(TlsSec *sec, uchar *kd, int nkd) { + if (sec->prf == nil) { + werrstr("nil sec->prf in setSecrets"); + return; + } (*sec->prf)(kd, nkd, sec->sec, MasterSecretSize, "key expansion", sec->srandom, RandomSize, sec->crandom, RandomSize); } @@ -2086,6 +2105,10 @@ tlsSetFinished(TlsSec *sec, HandHash hs, uchar *finished, int isClient) label = "client finished"; else label = "server finished"; + if (sec->prf == nil) { + werrstr("nil sec->prf in tlsSetFinished"); + return; + } (*sec->prf)(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen); } @@ -2262,7 +2285,8 @@ pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm) if(i < modlen - 1) ans = makebytes(eb->data+i+1, modlen-(i+1)); } - freebytes(eb); + if (eb != ans) /* not freed above? */ + freebytes(eb); return ans; } From 15823fb317b2f3f14e9ed2849fe9001f0bdd4d6a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 06:13:58 +0000 Subject: [PATCH 101/402] sys/src/libsec/port: implement signature algorithms extension in tlshand (thanks Richard Miller) --- sys/src/libsec/port/tlshand.c | 72 ++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 1190f6c8cf..2c3cadaadd 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -97,6 +97,7 @@ typedef struct Msg{ Bytes* sid; Ints* ciphers; Bytes* compressors; + Ints* sigAlgs; } clientHello; struct { int version; @@ -245,6 +246,19 @@ enum { CompressionMax }; +// extensions +enum { + ExtSigalgs = 0xd, +}; + +// signature algorithms +enum { + RSA_PKCS1_SHA1 = 0x0201, + RSA_PKCS1_SHA256 = 0x0401, + RSA_PKCS1_SHA384 = 0x0501, + RSA_PKCS1_SHA512 = 0x0601 +}; + static Algs cipherAlgs[] = { {"rc4_128", "md5", 2*(16+MD5dlen), TLS_RSA_WITH_RC4_128_MD5}, {"rc4_128", "sha1", 2*(16+SHA1dlen), TLS_RSA_WITH_RC4_128_SHA}, @@ -257,6 +271,11 @@ static uchar compressors[] = { CompressionNull, }; +static int sigAlgs[] = { + RSA_PKCS1_SHA256, + RSA_PKCS1_SHA1, +}; + static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...), PEMChain *chain); static TlsConnection *tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...)); @@ -644,6 +663,8 @@ tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ... m.u.clientHello.sid = makebytes(csid, ncsid); m.u.clientHello.ciphers = makeciphers(); m.u.clientHello.compressors = makebytes(compressors,sizeof(compressors)); + if(c->clientVersion >= TLS12Version) + m.u.clientHello.sigAlgs = makeints(sigAlgs, nelem(sigAlgs)); if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); @@ -874,6 +895,19 @@ msgSend(TlsConnection *c, Msg *m, int act) p[0] = n; memmove(p+1, m->u.clientHello.compressors->data, n); p += n+1; + + if(m->u.clientHello.sigAlgs != nil) { + n = m->u.clientHello.sigAlgs->len; + put16(p, 6 + 2*n); /* length of extensions */ + put16(p+2, ExtSigalgs); + put16(p+4, 2 + 2*n); /* length of extension content */ + put16(p+6, 2*n); /* length of algorithm list */ + p += 8; + for(i = 0; i < n; i++) { + put16(p, m->u.clientHello.sigAlgs->data[i]); + p += 2; + } + } break; case HServerHello: put16(p, m->u.serverHello.version); @@ -983,7 +1017,7 @@ static int msgRecv(TlsConnection *c, Msg *m) { uchar *p; - int type, n, nn, i, nsid, nrandom, nciph; + int type, n, nn, nx, i, nsid, nrandom, nciph; for(;;) { p = tlsReadN(c, 4); @@ -1101,7 +1135,40 @@ msgRecv(TlsConnection *c, Msg *m) nn = p[0]; m->u.clientHello.compressors = newbytes(nn); memmove(m->u.clientHello.compressors->data, p+1, nn); + p += nn + 1; n -= nn + 1; + + /* extensions */ + if(n == 0) + break; + if(n < 2) + goto Short; + nx = get16(p); + p += 2; + n -= 2; + while(nx > 0){ + if(n < nx || nx < 4) + goto Short; + i = get16(p); + nn = get16(p+2); + if(nx < nn+4) + goto Short; + nx -= nn+4; + p += 4; + n -= 4; + if(i == ExtSigalgs){ + if(get16(p) != nn-2) + goto Short; + p += 2; + n -= 2; + nn -= 2; + m->u.clientHello.sigAlgs = newints(nn/2); + for(i = 0; i < nn; i += 2) + m->u.clientHello.sigAlgs->data[i >> 1] = get16(&p[i]); + } + p += nn; + n -= nn; + } break; case HServerHello: if(n < 2) @@ -1254,6 +1321,7 @@ msgClear(Msg *m) freeints(m->u.clientHello.ciphers); m->u.clientHello.ciphers = nil; freebytes(m->u.clientHello.compressors); + freeints(m->u.clientHello.sigAlgs); break; case HServerHello: freebytes(m->u.clientHello.sid); @@ -1338,6 +1406,8 @@ msgPrint(char *buf, int n, Msg *m) bs = bytesPrint(bs, be, "\tsid: ", m->u.clientHello.sid, "\n"); bs = intsPrint(bs, be, "\tciphers: ", m->u.clientHello.ciphers, "\n"); bs = bytesPrint(bs, be, "\tcompressors: ", m->u.clientHello.compressors, "\n"); + if(m->u.clientHello.sigAlgs != nil) + bs = intsPrint(bs, be, "\tsigAlgs: ", m->u.clientHello.sigAlgs, "\n"); break; case HServerHello: bs = seprint(bs, be, "ServerHello\n"); From 9a91549ccb3b82ad9909b8433754402ba07158af Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 18 Feb 2016 13:38:58 +0000 Subject: [PATCH 102/402] sys/src/libsec/port: add ChaCha20 stream cipher (RFC7539) (thanks Charles Fosyth) --- sys/include/libsec.h | 36 +++++++ sys/man/2/chacha | 97 +++++++++++++++++ sys/src/libsec/port/chacha.c | 175 +++++++++++++++++++++++++++++++ sys/src/libsec/port/chachatest.c | 70 +++++++++++++ sys/src/libsec/port/mkfile | 2 +- 5 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 sys/man/2/chacha create mode 100644 sys/src/libsec/port/chacha.c create mode 100644 sys/src/libsec/port/chachatest.c diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 28d9862920..4a4f8ee9ea 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -73,6 +73,42 @@ void bfCBCdecrypt(uchar*, int, BFstate*); void bfECBencrypt(uchar*, int, BFstate*); void bfECBdecrypt(uchar*, int, BFstate*); +/* + * Chacha definitions + */ + +enum{ + ChachaBsize= 64, + ChachaKeylen= 256/8, + ChachaIVlen= 96/8 +}; + +typedef struct Chachastate Chachastate; +struct Chachastate +{ + /* + * 0-3: a constant (sigma or tau) + * 4-11: the key + * 12: block counter + * 13-15: IV + */ + union{ + u32int input[16]; + struct{ + u32int constant[4]; + u32int key[8]; + u32int counter; + u32int iv[3]; + }; + }; + int rounds; +}; + +void setupChachastate(Chachastate*, uchar*, usize, uchar*, int); +void chacha_setblock(Chachastate*, u32int); +void chacha_encrypt(uchar*, usize, Chachastate*); +void chacha_encrypt2(uchar*, uchar*, usize, Chachastate*); + /* * DES definitions */ diff --git a/sys/man/2/chacha b/sys/man/2/chacha new file mode 100644 index 0000000000..8f8f0e62d3 --- /dev/null +++ b/sys/man/2/chacha @@ -0,0 +1,97 @@ +.TH CHACHA 2 +.SH NAME +setupChachastate, chacha_setblock, chacha_encrypt, chacha_encrypt2 - chacha encryption +.SH SYNOPSIS +.B #include +.br +.B #include +.br +.B #include +.br +.B #include +.PP +.B +void setupChachastate(Chachastate *s, uchar key[], +.B + int keylen, uchar *nonce, int rounds) +.PP +.B +void chacha_encrypt(uchar *data, int len, Chachastate *s) +.PP +.B +void chacha_encrypt2(uchar *src, uchar *dst, int len, Chachastate *s) +.PP +.B +void chacha_setblock(Chachastate *s, u32int blockno) +.SH DESCRIPTION +.PP +Chacha is D J Berstein's symmetric stream cipher, as modified by RFC7539. It uses +keys of 256 bits (128 bits is supported here for special purposes). It has an underlying block size of 64 bytes +(named as constant +.BR ChachaBsize ). +It is a potential replacement for +.IR rc4 (2). +.PP +.I SetupChachastate +takes a reference to a +.B Chachastate +structure, a +.I key +of +.I keylen +bytes, which should normally be +.BR ChachaKeylen , +a +.I nonce +or initialisation vector of +.B ChachaIVlen +bytes (set to all zeros if the argument is nil), +and the number of +.I rounds +(set to the default of 20 if the argument is zero). +With a keylength of 256 bits (32 bytes) and 20 +.IR rounds , +the function implements the Chacha20 encryption function of RFC7539. +.PP +.I Chacha_encrypt +encrypts +.I len +bytes of +.I buf +in place using the +.B Chachastate +in +.IR s . +.I Len +can be any byte length. +Encryption and decryption are the same operation given the same starting state +.IR s . +.PP +.I Chacha_encrypt2 +is similar, but encrypts +.I len +bytes of +.I src +into +.I dst +without modifying +.IR src . +.PP +.I Chacha_setblock +sets the Chacha block counter for the next encryption to +.IR blockno , +allowing seeking in an encrypted stream. +.SH SOURCE +.B /sys/src/libsec +.SH SEE ALSO +.IR mp (2), +.IR aes (2), +.IR blowfish (2), +.IR des (2), +.IR dsa (2), +.IR elgamal (2), +.IR rc4 (2), +.IR rsa (2), +.IR sechash (2), +.IR prime (2), +.IR rand (2) diff --git a/sys/src/libsec/port/chacha.c b/sys/src/libsec/port/chacha.c new file mode 100644 index 0000000000..3f7b9f5f9c --- /dev/null +++ b/sys/src/libsec/port/chacha.c @@ -0,0 +1,175 @@ +/* +Adapted from chacha-merged.c version 20080118 +D. J. Bernstein +Public domain. + +modified for use in Plan 9 and Inferno (no algorithmic changes), +and including the changes to block number and nonce defined in RFC7539 +*/ + +#include +#include +#include + +enum{ + Blockwords= ChachaBsize/sizeof(u32int) +}; + +/* little-endian data order */ +#define GET4(p) ((((((p)[3]<<8) | (p)[2])<<8) | (p)[1])<<8 | (p)[0]) +#define PUT4(p, v) (((p)[0]=v), (v>>=8), ((p)[1]=v), (v>>=8), ((p)[2]=v), (v>>=8), ((p)[3]=v)) + +#define ROTATE(v,c) ((u32int)((v) << (c)) | ((v) >> (32 - (c)))) + +#define QUARTERROUND(ia,ib,ic,id) { \ + u32int a, b, c, d, t;\ + a = x[ia]; b = x[ib]; c = x[ic]; d = x[id]; \ + a += b; t = d^a; d = ROTATE(t,16); \ + c += d; t = b^c; b = ROTATE(t,12); \ + a += b; t = d^a; d = ROTATE(t, 8); \ + c += d; t = b^c; b = ROTATE(t, 7); \ + x[ia] = a; x[ib] = b; x[ic] = c; x[id] = d; \ +} + +#define ENCRYPT(s, x, y, d) {\ + u32int v; \ + uchar *sp, *dp; \ + sp = (s); \ + v = GET4(sp); \ + v ^= (x)+(y); \ + dp = (d); \ + PUT4(dp, v); \ +} + +static uchar sigma[16] = "expand 32-byte k"; +static uchar tau[16] = "expand 16-byte k"; + +static void +load(u32int *d, uchar *s, int nw) +{ + int i; + + for(i = 0; i < nw; i++, s+=4) + d[i] = GET4(s); +} + +void +setupChachastate(Chachastate *s, uchar *key, usize keylen, uchar *iv, int rounds) +{ + if(keylen != 256/8 && keylen != 128/8) + sysfatal("invalid chacha key length"); + if(rounds == 0) + rounds = 20; + s->rounds = rounds; + if(keylen == 256/8) { /* recommended */ + load(&s->input[0], sigma, 4); + load(&s->input[4], key, 8); + }else{ + load(&s->input[0], tau, 4); + load(&s->input[4], key, 4); + load(&s->input[8], key, 4); + } + s->input[12] = 0; + if(iv == nil){ + s->input[13] = 0; + s->input[14] = 0; + s->input[15] = 0; + }else + load(&s->input[13], iv, 3); +} + +void +chacha_setblock(Chachastate *s, u32int blockno) +{ + s->input[12] = blockno; +} + +static void +encryptblock(Chachastate *s, uchar *src, uchar *dst) +{ + u32int x[Blockwords]; + int i, rounds; + + rounds = s->rounds; + x[0] = s->input[0]; + x[1] = s->input[1]; + x[2] = s->input[2]; + x[3] = s->input[3]; + x[4] = s->input[4]; + x[5] = s->input[5]; + x[6] = s->input[6]; + x[7] = s->input[7]; + x[8] = s->input[8]; + x[9] = s->input[9]; + x[10] = s->input[10]; + x[11] = s->input[11]; + x[12] = s->input[12]; + x[13] = s->input[13]; + x[14] = s->input[14]; + x[15] = s->input[15]; + + for(i = rounds; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8,12) + QUARTERROUND(1, 5, 9,13) + QUARTERROUND(2, 6,10,14) + QUARTERROUND(3, 7,11,15) + + QUARTERROUND(0, 5,10,15) + QUARTERROUND(1, 6,11,12) + QUARTERROUND(2, 7, 8,13) + QUARTERROUND(3, 4, 9,14) + } + +#ifdef FULL_UNROLL + ENCRYPT(src+0*4, x[0], s->input[0], dst+0*4); + ENCRYPT(src+1*4, x[1], s->input[1], dst+1*4); + ENCRYPT(src+2*4, x[2], s->input[2], dst+2*4); + ENCRYPT(src+3*4, x[3], s->input[3], dst+3*4); + ENCRYPT(src+4*4, x[4], s->input[4], dst+4*4); + ENCRYPT(src+5*4, x[5], s->input[5], dst+5*4); + ENCRYPT(src+6*4, x[6], s->input[6], dst+6*4); + ENCRYPT(src+7*4, x[7], s->input[7], dst+7*4); + ENCRYPT(src+8*4, x[8], s->input[8], dst+8*4); + ENCRYPT(src+9*4, x[9], s->input[9], dst+9*4); + ENCRYPT(src+10*4, x[10], s->input[10], dst+10*4); + ENCRYPT(src+11*4, x[11], s->input[11], dst+11*4); + ENCRYPT(src+12*4, x[12], s->input[12], dst+12*4); + ENCRYPT(src+13*4, x[13], s->input[13], dst+13*4); + ENCRYPT(src+14*4, x[14], s->input[14], dst+14*4); + ENCRYPT(src+15*4, x[15], s->input[15], dst+15*4); +#else + for(i=0; iinput[i], dst); + ENCRYPT(src+4, x[i+1], s->input[i+1], dst+4); + ENCRYPT(src+8, x[i+2], s->input[i+2], dst+8); + ENCRYPT(src+12, x[i+3], s->input[i+3], dst+12); + src += 16; + dst += 16; + } +#endif + + s->input[12]++; +} + +void +chacha_encrypt2(uchar *src, uchar *dst, usize bytes, Chachastate *s) +{ + uchar tmp[ChachaBsize]; + + for(; bytes >= ChachaBsize; bytes -= ChachaBsize){ + encryptblock(s, src, dst); + src += ChachaBsize; + dst += ChachaBsize; + } + if(bytes > 0){ + memmove(tmp, src, bytes); + encryptblock(s, tmp, tmp); + memmove(dst, tmp, bytes); + } +} + +void +chacha_encrypt(uchar *buf, usize bytes, Chachastate *s) +{ + chacha_encrypt2(buf, buf, bytes, s); +} diff --git a/sys/src/libsec/port/chachatest.c b/sys/src/libsec/port/chachatest.c new file mode 100644 index 0000000000..7949c6f65e --- /dev/null +++ b/sys/src/libsec/port/chachatest.c @@ -0,0 +1,70 @@ +#include +#include +#include + +static void +printblock(uchar *b, usize n) +{ + int i; + + for(i=0; i+8<=n; i+=8){ + print("%#.2ux %#.2ux %#.2ux %#.2ux %#.2ux %#.2ux %#.2ux %#.2ux\n", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + b += 8; + } + if(i < n){ + print("%#.2ux", *b++); + while(++i < n) + print(" %#.2ux", *b++); + print("\n"); + } +} + +/* test vector from RFC7539 */ +uchar rfckey[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; +uchar rfcnonce[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00}; +u32int rfccount = 1; +char rfctext[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, " + "sunscreen would be it."; +uchar rfcout[3*ChachaBsize]; +uchar rfcref[3*ChachaBsize] = { + 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, + 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, + 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, + 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, + 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, + 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, + 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42, + 0x87, 0x4d +}; + +void +main(int argc, char **argv) +{ + Chachastate s; + int n; + + ARGBEGIN{ + }ARGEND + print("rfc7539:\n"); + print("key:\n"); + printblock(rfckey, sizeof(rfckey)); + n = strlen(rfctext); + setupChachastate(&s, rfckey, sizeof(rfckey), rfcnonce, 0); + chacha_setblock(&s, rfccount); + print("rfc in:\n"); + printblock((uchar*)rfctext, n); + chacha_encrypt2((uchar*)rfctext, rfcout, n, &s); + print("rfc out:\n"); + printblock(rfcout, n); + if(memcmp(rfcout, rfcref, sizeof(rfcout)) != 0){ + print("failure of vision\n"); + exits("wrong"); + } + print("passed\n"); + exits(nil); +} diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index b749e11653..16a1c8a714 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -3,7 +3,7 @@ LIB=/$objtype/lib/libsec.a CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ - aes.c blowfish.c \ + aes.c blowfish.c chacha.c \ hmac.c md5.c md5block.c md4.c sha1.c sha1block.c\ sha2_64.c sha2_128.c sha2block64.c sha2block128.c\ sha1pickle.c md5pickle.c\ From cba0bfb9d3c4c942e9b055de95f10f8cfd83bd8b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Jun 2024 20:21:17 +0000 Subject: [PATCH 103/402] sys/src/libsec/port: add Poly1305 hash (thanks Cinap Lenrek) --- sys/include/libsec.h | 3 + sys/man/2/sechash | 7 ++ sys/src/libsec/port/mkfile | 1 + sys/src/libsec/port/poly1305.c | 192 +++++++++++++++++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 sys/src/libsec/port/poly1305.c diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 4a4f8ee9ea..38cadc03a6 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -181,6 +181,7 @@ enum MD4dlen= 16, /* MD4 digest length */ MD5dlen= 16, /* MD5 digest length */ AESdlen= 16, /* TODO: see rfc */ + Poly1305dlen= 16, /* Poly1305 digest length */ Hmacblksz = 64, /* in bytes; from rfc2104 */ }; @@ -232,6 +233,8 @@ MD5state* md5unpickle(char*); char* sha1pickle(SHA1state*); SHA1state* sha1unpickle(char*); +DigestState* poly1305(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); + /* * random number generation */ diff --git a/sys/man/2/sechash b/sys/man/2/sechash index 7524881f84..f1e33af0cc 100644 --- a/sys/man/2/sechash +++ b/sys/man/2/sechash @@ -2,6 +2,7 @@ .SH NAME md4, md5, sha1, sha2_224, sha2_256, sha2_384, sha2_512, +poly1305, aes, hmac_x, hmac_md5, hmac_sha1, hmac_sha2_224, hmac_sha2_256, hmac_sha2_384, hmac_sha2_512, hmac_aes, md5pickle, md5unpickle, @@ -57,6 +58,8 @@ DS* sha2_512(uchar *data, ulong dlen, uchar *digest, DS *state) .Ti DS* aes(uchar *data, ulong dlen, uchar *digest, DS *state) .Ti +DS* poly1305(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DS *state) +.Ti DS* hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DS *s, DS*(*x)(uchar*, ulong, uchar*, DS*), int xlen) .Ti DS* hmac_md5(uchar *data, ulong dlen, uchar *key, ulong klen, uchar *digest, DS *state) @@ -93,6 +96,7 @@ The routines .IR sha2_384 , .IR sha2_512 , .IR aes , +.IR poly1305 , .IR hmac_md5 , .IR hmac_sha1 , .IR hmac_sha2_224 , @@ -151,6 +155,9 @@ These routines all call internally, but .I hmac_x is not intended for general use. +IR poly1305 , +is a one-time authenticator designed by D. J. Bernstein. It takes a 32-byte +one-time key and a message and produces a 16-byte tag. .PP The functions .I md5pickle diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index 16a1c8a714..02b6a82835 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -7,6 +7,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ hmac.c md5.c md5block.c md4.c sha1.c sha1block.c\ sha2_64.c sha2_128.c sha2block64.c sha2block128.c\ sha1pickle.c md5pickle.c\ + poly1305.c\ rc4.c\ genrandom.c prng.c fastrand.c nfastrand.c\ probably_prime.c smallprimetest.c genprime.c dsaprimes.c\ diff --git a/sys/src/libsec/port/poly1305.c b/sys/src/libsec/port/poly1305.c new file mode 100644 index 0000000000..42f9ac4de7 --- /dev/null +++ b/sys/src/libsec/port/poly1305.c @@ -0,0 +1,192 @@ +#include +#include +#include + +/* + poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition + + derived from http://github.com/floodberry/poly1305-donna +*/ + +#define U8TO32(p) ((u32int)(p)[0] | (u32int)(p)[1]<<8 | (u32int)(p)[2]<<16 | (u32int)(p)[3]<<24) +#define U32TO8(p, v) (p)[0]=(v), (p)[1]=(v)>>8, (p)[2]=(v)>>16, (p)[3]=(v)>>24 + +/* (r,s) = (key[0:15],key[16:31]), the one time key */ +DigestState* +poly1305(uchar *m, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s) +{ + u32int r0,r1,r2,r3,r4, s1,s2,s3,s4, h0,h1,h2,h3,h4, g0,g1,g2,g3,g4; + u64int d0,d1,d2,d3,d4, f; + u32int hibit, mask, c; + + if(s == nil){ + s = malloc(sizeof(*s)); + if(s == nil) + return nil; + memset(s, 0, sizeof(*s)); + s->malloced = 1; + } + + if(s->seeded == 0){ + assert(klen == 32); + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + s->state[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff; + s->state[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03; + s->state[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff; + s->state[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff; + s->state[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff; + + /* h = 0 */ + s->state[5] = 0; + s->state[6] = 0; + s->state[7] = 0; + s->state[8] = 0; + s->state[9] = 0; + + /* save pad for later */ + s->state[10] = U8TO32(&key[16]); + s->state[11] = U8TO32(&key[20]); + s->state[12] = U8TO32(&key[24]); + s->state[13] = U8TO32(&key[28]); + + s->seeded = 1; + } + + if(s->blen){ + c = 16 - s->blen; + if(c > len) + c = len; + memmove(s->buf + s->blen, m, c); + len -= c, m += c; + s->blen += c; + if(s->blen == 16){ + s->blen = 0; + poly1305(s->buf, 16, key, klen, nil, s); + } + } + + r0 = s->state[0]; + r1 = s->state[1]; + r2 = s->state[2]; + r3 = s->state[3]; + r4 = s->state[4]; + + h0 = s->state[5]; + h1 = s->state[6]; + h2 = s->state[7]; + h3 = s->state[8]; + h4 = s->state[9]; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + hibit = 1<<24; /* 1<<128 */ + + while(len >= 16){ +Block: + /* h += m[i] */ + h0 += (U8TO32(&m[0]) ) & 0x3ffffff; + h1 += (U8TO32(&m[3]) >> 2) & 0x3ffffff; + h2 += (U8TO32(&m[6]) >> 4) & 0x3ffffff; + h3 += (U8TO32(&m[9]) >> 6) & 0x3ffffff; + h4 += (U8TO32(&m[12])>> 8) | hibit; + + /* h *= r */ + d0 = ((u64int)h0 * r0) + ((u64int)h1 * s4) + ((u64int)h2 * s3) + ((u64int)h3 * s2) + ((u64int)h4 * s1); + d1 = ((u64int)h0 * r1) + ((u64int)h1 * r0) + ((u64int)h2 * s4) + ((u64int)h3 * s3) + ((u64int)h4 * s2); + d2 = ((u64int)h0 * r2) + ((u64int)h1 * r1) + ((u64int)h2 * r0) + ((u64int)h3 * s4) + ((u64int)h4 * s3); + d3 = ((u64int)h0 * r3) + ((u64int)h1 * r2) + ((u64int)h2 * r1) + ((u64int)h3 * r0) + ((u64int)h4 * s4); + d4 = ((u64int)h0 * r4) + ((u64int)h1 * r3) + ((u64int)h2 * r2) + ((u64int)h3 * r1) + ((u64int)h4 * r0); + + /* (partial) h %= p */ + c = (u32int)(d0 >> 26); h0 = (u32int)d0 & 0x3ffffff; + d1 += c; c = (u32int)(d1 >> 26); h1 = (u32int)d1 & 0x3ffffff; + d2 += c; c = (u32int)(d2 >> 26); h2 = (u32int)d2 & 0x3ffffff; + d3 += c; c = (u32int)(d3 >> 26); h3 = (u32int)d3 & 0x3ffffff; + d4 += c; c = (u32int)(d4 >> 26); h4 = (u32int)d4 & 0x3ffffff; + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; + h1 += c; + + len -= 16, m += 16; + } + + if(len){ + s->blen = len; + memmove(s->buf, m, len); + } + + if(digest == nil){ + s->state[5] = h0; + s->state[6] = h1; + s->state[7] = h2; + s->state[8] = h3; + s->state[9] = h4; + return s; + } + + if(len){ + m = s->buf; + m[len++] = 1; + while(len < 16) + m[len++] = 0; + hibit = 0; + goto Block; + } + + c = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + c - (1 << 26); + + /* select h if h < p, or h + -p if h >= p */ + mask = (g4 >> 31) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; + + /* h = h % (2^128) */ + h0 = (h0 ) | (h1 << 26); + h1 = (h1 >> 6) | (h2 << 20); + h2 = (h2 >> 12) | (h3 << 14); + h3 = (h3 >> 18) | (h4 << 8); + + /* digest = (h + pad) % (2^128) */ + f = (u64int)h0 + s->state[10] ; h0 = (u32int)f; + f = (u64int)h1 + s->state[11] + (f >> 32); h1 = (u32int)f; + f = (u64int)h2 + s->state[12] + (f >> 32); h2 = (u32int)f; + f = (u64int)h3 + s->state[13] + (f >> 32); h3 = (u32int)f; + + U32TO8(&digest[0], h0); + U32TO8(&digest[4], h1); + U32TO8(&digest[8], h2); + U32TO8(&digest[12], h3); + + if(s->malloced){ + memset(s, 0, sizeof(*s)); + free(s); + return nil; + } + + memset(s, 0, sizeof(*s)); + return nil; +} From ee282f80906cd857293a9502dd927eb12c584061 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Jun 2024 19:59:17 +0000 Subject: [PATCH 104/402] sys/src/libsec/port: add HKDF (RFC 5869) (thanks Cinap Lenrek) --- sys/include/libsec.h | 5 +++++ sys/src/libsec/port/hkdf.c | 36 ++++++++++++++++++++++++++++++++++++ sys/src/libsec/port/mkfile | 1 + 3 files changed, 42 insertions(+) create mode 100644 sys/src/libsec/port/hkdf.c diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 38cadc03a6..33e1c4a502 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -445,3 +445,8 @@ PEMChain*readcertchain(char *filename); /* password-based key derivation function 2 (rfc2898) */ void pbkdf2_x(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d, ulong dlen, DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); + +/* hmac-based key derivation function (rfc5869) */ +void hkdf_x(uchar *salt, ulong nsalt, uchar *info, ulong ninfo, uchar *key, ulong nkey, uchar *d, ulong dlen, + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); + diff --git a/sys/src/libsec/port/hkdf.c b/sys/src/libsec/port/hkdf.c new file mode 100644 index 0000000000..5e3f27b390 --- /dev/null +++ b/sys/src/libsec/port/hkdf.c @@ -0,0 +1,36 @@ +#include "os.h" +#include + +/* rfc5869 */ +void +hkdf_x(uchar *salt, ulong nsalt, uchar *info, ulong ninfo, + uchar *key, ulong nkey, uchar *d, ulong dlen, + DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen) +{ + uchar prk[256], tmp[256], cnt; + DigestState *ds; + + assert(xlen <= sizeof(tmp)); + + memset(tmp, 0, xlen); + if(nsalt == 0){ + salt = tmp; + nsalt = xlen; + } + /* note that salt and key are swapped in this case */ + (*x)(key, nkey, salt, nsalt, prk, nil); + ds = nil; + for(cnt=1;; cnt++) { + if(ninfo > 0) + ds = (*x)(info, ninfo, prk, xlen, nil, ds); + (*x)(&cnt, 1, prk, xlen, tmp, ds); + if(dlen <= xlen){ + memmove(d, tmp, dlen); + break; + } + memmove(d, tmp, xlen); + dlen -= xlen; + d += xlen; + ds = (*x)(tmp, xlen, prk, xlen, nil, nil); + } +} diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index 02b6a82835..0234aba06f 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -19,6 +19,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \ tlshand.c thumb.c readcert.c \ pbkdf2.c\ + hkdf.c\ ALLOFILES=${CFILES:%.c=%.$O} From 3de15a84f73b78998ad9368fa3626507f6fb9ec3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Jun 2024 19:54:05 +0000 Subject: [PATCH 105/402] sys/src/libsec/port: add ChaCha20-Poly1305, IV and tsmemcmp (thanks Cinap Lenrek) --- sys/include/libsec.h | 11 ++++- sys/man/2/chacha | 63 ++++++++++++++++++++---- sys/src/libsec/port/ccpoly.c | 84 ++++++++++++++++++++++++++++++++ sys/src/libsec/port/chacha.c | 22 +++++++-- sys/src/libsec/port/chachatest.c | 56 +++++++++++++++++++-- sys/src/libsec/port/mkfile | 2 + sys/src/libsec/port/tsmemcmp.c | 26 ++++++++++ 7 files changed, 244 insertions(+), 20 deletions(-) create mode 100644 sys/src/libsec/port/ccpoly.c create mode 100644 sys/src/libsec/port/tsmemcmp.c diff --git a/sys/include/libsec.h b/sys/include/libsec.h index 33e1c4a502..63fa341c59 100644 --- a/sys/include/libsec.h +++ b/sys/include/libsec.h @@ -102,13 +102,18 @@ struct Chachastate }; }; int rounds; + int ivwords; }; -void setupChachastate(Chachastate*, uchar*, usize, uchar*, int); -void chacha_setblock(Chachastate*, u32int); +void setupChachastate(Chachastate*, uchar*, usize, uchar*, ulong, int); +void chacha_setiv(Chachastate *, uchar*); +void chacha_setblock(Chachastate*, u64int); void chacha_encrypt(uchar*, usize, Chachastate*); void chacha_encrypt2(uchar*, uchar*, usize, Chachastate*); +void ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); +int ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); + /* * DES definitions */ @@ -450,3 +455,5 @@ void pbkdf2_x(uchar *p, ulong plen, uchar *s, ulong slen, ulong rounds, uchar *d void hkdf_x(uchar *salt, ulong nsalt, uchar *info, ulong ninfo, uchar *key, ulong nkey, uchar *d, ulong dlen, DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen); +/* timing safe memcmp() */ +int tsmemcmp(void*, void*, ulong); diff --git a/sys/man/2/chacha b/sys/man/2/chacha index 8f8f0e62d3..a68d0bf1b4 100644 --- a/sys/man/2/chacha +++ b/sys/man/2/chacha @@ -1,6 +1,6 @@ .TH CHACHA 2 .SH NAME -setupChachastate, chacha_setblock, chacha_encrypt, chacha_encrypt2 - chacha encryption +setupChachastate, chacha_setblock, chacha_setiv, chacha_encrypt, chacha_encrypt2, ccpoly_encrypt, ccpoly_decrypt \- chacha encryption .SH SYNOPSIS .B #include .br @@ -11,9 +11,7 @@ setupChachastate, chacha_setblock, chacha_encrypt, chacha_encrypt2 - chacha enc .B #include .PP .B -void setupChachastate(Chachastate *s, uchar key[], -.B - int keylen, uchar *nonce, int rounds) +void setupChachastate(Chachastate *s, uchar key[], usize keylen, uchar *iv, ulong ivlen, int rounds) .PP .B void chacha_encrypt(uchar *data, int len, Chachastate *s) @@ -22,7 +20,16 @@ void chacha_encrypt(uchar *data, int len, Chachastate *s) void chacha_encrypt2(uchar *src, uchar *dst, int len, Chachastate *s) .PP .B -void chacha_setblock(Chachastate *s, u32int blockno) +void chacha_setblock(Chachastate *s, u64int blockno) +.PP +.B +void chacha_setiv(Chachastate *s, uchar *iv); +.PP +.B +void ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); +.PP +.B +int ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); .SH DESCRIPTION .PP Chacha is D J Berstein's symmetric stream cipher, as modified by RFC7539. It uses @@ -42,14 +49,19 @@ of bytes, which should normally be .BR ChachaKeylen , a -.I nonce -or initialisation vector of -.B ChachaIVlen -bytes (set to all zeros if the argument is nil), +.I iv +or nonce of +.I ivlen +bytes (can be +.BR ChachaIVlen =12 +or 8, set to all zeros if the +.I iv +argument is nil), and the number of .I rounds (set to the default of 20 if the argument is zero). -With a keylength of 256 bits (32 bytes) and 20 +With a key length of 256 bits (32 bytes), a nonce of 96 bits (12 bytes) +and 20 .IR rounds , the function implements the Chacha20 encryption function of RFC7539. .PP @@ -81,6 +93,37 @@ without modifying sets the Chacha block counter for the next encryption to .IR blockno , allowing seeking in an encrypted stream. +.PP +.I Chacha_setiv +sets the the initialization vector (nonce) to +.IR iv . +.PP +.I Ccpoly_encrypt +and +.I ccpoly_decrypt +implement authenticated encryption with associated data (AEAD) +using Chacha cipher and Poly1305 message authentication code +as specified in RFC7539. +These routines require a +.I Chachastate +that has been setup with a new (per key unique) initialization +vector (nonce) on each invocation. The referenced data +.IR dat [ ndat ] +is in-place encrypted or decrypted. +.I Ccpoly_encrypt +produces a 16 byte authentication +.IR tag , +while +.I ccpoly_decrypt +verifies the +.IR tag , +returning zero on success or negative on a mismatch. +The +.IR aad [ naad ] +arguments refer to the additional authenticated data +that is included in the +.I tag +calculation, but not encrypted. .SH SOURCE .B /sys/src/libsec .SH SEE ALSO diff --git a/sys/src/libsec/port/ccpoly.c b/sys/src/libsec/port/ccpoly.c new file mode 100644 index 0000000000..14a8a9cd4f --- /dev/null +++ b/sys/src/libsec/port/ccpoly.c @@ -0,0 +1,84 @@ +#include +#include +#include + +static void +ccpolyotk(Chachastate *cs, DigestState *ds) +{ + uchar otk[ChachaBsize]; + + memset(ds, 0, sizeof(*ds)); + memset(otk, 0, 32); + chacha_setblock(cs, 0); + chacha_encrypt(otk, ChachaBsize, cs); + poly1305(nil, 0, otk, 32, nil, ds); +} + +static void +ccpolymac(uchar *buf, ulong nbuf, DigestState *ds) +{ + static uchar zeros[16] = {0}; + ulong npad; + + if(nbuf == 0) + return; + poly1305(buf, nbuf, nil, 0, nil, ds); + npad = nbuf % 16; + if(npad == 0) + return; + poly1305(zeros, 16 - npad, nil, 0, nil, ds); +} + +static void +ccpolytag(ulong ndat, ulong naad, uchar tag[16], DigestState *ds) +{ + uchar info[16]; + + info[0] = naad; + info[1] = naad>>8; + info[2] = naad>>16; + info[3] = naad>>24; + info[4] = 0; + info[5] = 0; + info[6] = 0; + info[7] = 0; + + info[8] = ndat; + info[9] = ndat>>8; + info[10] = ndat>>16; + info[11] = ndat>>24; + info[12] = 0; + info[13] = 0; + info[14] = 0; + info[15] = 0; + + poly1305(info, 16, nil, 0, tag, ds); +} + +void +ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs) +{ + DigestState ds; + + ccpolyotk(cs, &ds); + ccpolymac(aad, naad, &ds); + chacha_encrypt(dat, ndat, cs); + ccpolymac(dat, ndat, &ds); + ccpolytag(ndat, naad, tag, &ds); +} + +int +ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs) +{ + DigestState ds; + uchar tmp[16]; + + ccpolyotk(cs, &ds); + ccpolymac(aad, naad, &ds); + ccpolymac(dat, ndat, &ds); + ccpolytag(ndat, naad, tmp, &ds); + if(tsmemcmp(tag, tmp, 16) != 0) + return -1; + chacha_encrypt(dat, ndat, cs); + return 0; +} diff --git a/sys/src/libsec/port/chacha.c b/sys/src/libsec/port/chacha.c index 3f7b9f5f9c..bcf9468bd8 100644 --- a/sys/src/libsec/port/chacha.c +++ b/sys/src/libsec/port/chacha.c @@ -54,10 +54,12 @@ load(u32int *d, uchar *s, int nw) } void -setupChachastate(Chachastate *s, uchar *key, usize keylen, uchar *iv, int rounds) +setupChachastate(Chachastate *s, uchar *key, usize keylen, uchar *iv, ulong ivlen, int rounds) { if(keylen != 256/8 && keylen != 128/8) sysfatal("invalid chacha key length"); + if(ivlen != 96/8 && ivlen != 64/8) + sysfatal("invalid chacha iv length"); if(rounds == 0) rounds = 20; s->rounds = rounds; @@ -69,19 +71,28 @@ setupChachastate(Chachastate *s, uchar *key, usize keylen, uchar *iv, int rounds load(&s->input[4], key, 4); load(&s->input[8], key, 4); } + s->ivwords = ivlen/sizeof(u32int); s->input[12] = 0; + s->input[13] = 0; if(iv == nil){ - s->input[13] = 0; s->input[14] = 0; s->input[15] = 0; }else - load(&s->input[13], iv, 3); + chacha_setiv(s, iv); } void -chacha_setblock(Chachastate *s, u32int blockno) +chacha_setiv(Chachastate *s, uchar *iv) +{ + load(&s->input[16 - s->ivwords], iv, s->ivwords); +} + +void +chacha_setblock(Chachastate *s, u64int blockno) { s->input[12] = blockno; + if(s->ivwords == 2) + s->input[13] = blockno>>32; } static void @@ -148,7 +159,8 @@ encryptblock(Chachastate *s, uchar *src, uchar *dst) } #endif - s->input[12]++; + if(++s->input[12] == 0 && s->ivwords == 2) + s->input[13]++; } void diff --git a/sys/src/libsec/port/chachatest.c b/sys/src/libsec/port/chachatest.c index 7949c6f65e..e578dec170 100644 --- a/sys/src/libsec/port/chachatest.c +++ b/sys/src/libsec/port/chachatest.c @@ -31,7 +31,7 @@ u32int rfccount = 1; char rfctext[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, " "sunscreen would be it."; uchar rfcout[3*ChachaBsize]; -uchar rfcref[3*ChachaBsize] = { +uchar rfcref[] = { 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, @@ -42,10 +42,26 @@ uchar rfcref[3*ChachaBsize] = { 0x87, 0x4d }; +uchar ccpaad[] = { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, +}; +uchar ccpkey[] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, +}; +uchar ccpiv[] = { + 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, +}; +uchar ccptag[] = { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91, +}; + void main(int argc, char **argv) { Chachastate s; + uchar tag[16]; int n; ARGBEGIN{ @@ -54,17 +70,51 @@ main(int argc, char **argv) print("key:\n"); printblock(rfckey, sizeof(rfckey)); n = strlen(rfctext); - setupChachastate(&s, rfckey, sizeof(rfckey), rfcnonce, 0); + setupChachastate(&s, rfckey, sizeof(rfckey), rfcnonce, sizeof(rfcnonce), 0); chacha_setblock(&s, rfccount); print("rfc in:\n"); printblock((uchar*)rfctext, n); chacha_encrypt2((uchar*)rfctext, rfcout, n, &s); print("rfc out:\n"); printblock(rfcout, n); - if(memcmp(rfcout, rfcref, sizeof(rfcout)) != 0){ + if(memcmp(rfcout, rfcref, sizeof(rfcref)) != 0){ print("failure of vision\n"); exits("wrong"); } + print("\n"); + + print("ccpoly key:\n"); + printblock(ccpkey, sizeof(ccpkey)); + + print("ccpoly iv:\n"); + printblock(ccpiv, sizeof(ccpiv)); + + setupChachastate(&s, ccpkey, sizeof(ccpkey), ccpiv, sizeof(ccpiv), 20); + + memmove(rfcout, rfctext, sizeof(rfctext)-1); + ccpoly_encrypt(rfcout, sizeof(rfctext)-1, ccpaad, sizeof(ccpaad), tag, &s); + + print("ccpoly cipher:\n"); + printblock(rfcout, sizeof(rfctext)-1); + + print("ccpoly tag:\n"); + printblock(tag, sizeof(tag)); + + if(memcmp(tag, ccptag, sizeof(tag)) != 0){ + print("bad ccpoly tag\n"); + exits("wrong"); + } + + if(ccpoly_decrypt(rfcout, sizeof(rfctext)-1, ccpaad, sizeof(ccpaad), tag, &s) != 0){ + print("ccpoly decryption failed\n"); + exits("wrong"); + } + + if(memcmp(rfcout, rfctext, sizeof(rfctext)-1) != 0){ + print("ccpoly bad decryption\n"); + exits("wrong"); + } + print("passed\n"); exits(nil); } diff --git a/sys/src/libsec/port/mkfile b/sys/src/libsec/port/mkfile index 0234aba06f..de54b7627d 100644 --- a/sys/src/libsec/port/mkfile +++ b/sys/src/libsec/port/mkfile @@ -20,6 +20,8 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\ tlshand.c thumb.c readcert.c \ pbkdf2.c\ hkdf.c\ + ccpoly.c\ + tsmemcmp.c\ ALLOFILES=${CFILES:%.c=%.$O} diff --git a/sys/src/libsec/port/tsmemcmp.c b/sys/src/libsec/port/tsmemcmp.c new file mode 100644 index 0000000000..6cc75377dc --- /dev/null +++ b/sys/src/libsec/port/tsmemcmp.c @@ -0,0 +1,26 @@ +#include +#include +#include + +/* + * timing safe memcmp() + */ +int +tsmemcmp(void *a1, void *a2, ulong n) +{ + int lt, gt, c1, c2, r, m; + uchar *s1, *s2; + + r = m = 0; + s1 = a1; + s2 = a2; + while(n--){ + c1 = *s1++; + c2 = *s2++; + lt = (c1 - c2) >> 8; + gt = (c2 - c1) >> 8; + r |= (lt - gt) & ~m; + m |= lt | gt; + } + return r; +} From dd3ebfaace3fdd2848093634915cd0759d074c39 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Jun 2024 20:28:23 +0000 Subject: [PATCH 106/402] sys/src/libsec/port: add mpnrand function to generate uniform random number (thanks Cinap Lenrek) --- sys/include/mp.h | 2 ++ sys/man/2/mp | 13 ++++++++++++- sys/src/libmp/port/mkfile | 1 + sys/src/libmp/port/mpnrand.c | 23 +++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 sys/src/libmp/port/mpnrand.c diff --git a/sys/include/mp.h b/sys/include/mp.h index 0cfc9e211b..29f171cfde 100644 --- a/sys/include/mp.h +++ b/sys/include/mp.h @@ -38,6 +38,8 @@ void mpassign(mpint *old, mpint *new); /* random bits */ mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b); +/* return uniform random [0..n-1] */ +mpint* mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b); /* conversion */ mpint* strtomp(char*, char**, int, mpint*); /* ascii */ diff --git a/sys/man/2/mp b/sys/man/2/mp index 9db58d1066..c1a92cc0ae 100644 --- a/sys/man/2/mp +++ b/sys/man/2/mp @@ -1,6 +1,6 @@ .TH MP 2 .SH NAME -mpsetminbits, mpnew, mpfree, mpbits, mpnorm, mpcopy, mpassign, mprand, strtomp, mpfmt,mptoa, betomp, mptobe, letomp, mptole, mptoui, uitomp, mptoi, itomp, uvtomp, mptouv, vtomp, mptov, mpdigdiv, mpadd, mpsub, mpleft, mpright, mpmul, mpexp, mpmod, mpdiv, mpcmp, mpextendedgcd, mpinvert, mpsignif, mplowbits0, mpvecdigmuladd, mpvecdigmulsub, mpvecadd, mpvecsub, mpveccmp, mpvecmul, mpmagcmp, mpmagadd, mpmagsub, crtpre, crtin, crtout, crtprefree, crtresfree \- extended precision arithmetic +mpsetminbits, mpnew, mpfree, mpbits, mpnorm, mpcopy, mpassign, mprand, mpnrand, strtomp, mpfmt,mptoa, betomp, mptobe, letomp, mptole, mptoui, uitomp, mptoi, itomp, uvtomp, mptouv, vtomp, mptov, mpdigdiv, mpadd, mpsub, mpleft, mpright, mpmul, mpexp, mpmod, mpdiv, mpcmp, mpextendedgcd, mpinvert, mpsignif, mplowbits0, mpvecdigmuladd, mpvecdigmulsub, mpvecadd, mpvecsub, mpveccmp, mpvecmul, mpmagcmp, mpmagadd, mpmagsub, crtpre, crtin, crtout, crtprefree, crtresfree \- extended precision arithmetic .SH SYNOPSIS .B #include .br @@ -34,6 +34,9 @@ void mpassign(mpint *old, mpint *new) mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b) .PP .B +mpint* mnprand(mpint *n, void (*gen)(uchar*, int), mpint *b) +.PP +.B mpint* strtomp(char *buf, char **rptr, int base, mpint *b) .PP .B @@ -300,6 +303,14 @@ bit random number using the generator takes a pointer to a string of uchar's and the number to fill in. .PP +.I Mpnrand +uses +.I gen +to generate a uniform random number +.IR x , +.if t 0 ≤ \fIx\fR < \fIn\fR. +.if n 0 ≤ x < n. +.PP .I Strtomp and .I mptoa diff --git a/sys/src/libmp/port/mkfile b/sys/src/libmp/port/mkfile index 05ee9dd332..76fa25dd7d 100644 --- a/sys/src/libmp/port/mkfile +++ b/sys/src/libmp/port/mkfile @@ -27,6 +27,7 @@ FILES=\ mpextendedgcd\ mpinvert\ mprand\ + mpnrand\ crt\ mptoi\ mptoui\ diff --git a/sys/src/libmp/port/mpnrand.c b/sys/src/libmp/port/mpnrand.c new file mode 100644 index 0000000000..278547ca61 --- /dev/null +++ b/sys/src/libmp/port/mpnrand.c @@ -0,0 +1,23 @@ +#include "os.h" +#include +#include "dat.h" + +/* return uniform random [0..n-1] */ +mpint* +mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b) +{ + int bits; + + bits = mpsignif(n); + if(bits == 0) + abort(); + if(b == nil){ + b = mpnew(bits); + setmalloctag(b, getcallerpc(&n)); + } + do { + mprand(bits, gen, b); + } while(mpmagcmp(b, n) >= 0); + + return b; +} From 27c013266a1d03c6be9922f5f78720ad6f8bf21c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 107/402] sys/src/libregexp: various fixes in libregexp --- sys/src/libregexp/regcomp.c | 4 ++-- sys/src/libregexp/regerror.c | 2 +- sys/src/libregexp/regexec.c | 2 +- sys/src/libregexp/rregsub.c | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/src/libregexp/regcomp.c b/sys/src/libregexp/regcomp.c index e48ef15acb..02754ac179 100644 --- a/sys/src/libregexp/regcomp.c +++ b/sys/src/libregexp/regcomp.c @@ -113,7 +113,7 @@ regerr2(char *s, int c) while(*s) *cp++ = *s++; *cp++ = c; - *cp = '\0'; + *cp = '\0'; rcerror(buf); } @@ -121,7 +121,7 @@ static void cant(char *s) { char buf[100]; - strcpy(buf, "can't happen: "); + strncpy(buf, "can't happen: ", sizeof(buf)); strcat(buf, s); rcerror(buf); } diff --git a/sys/src/libregexp/regerror.c b/sys/src/libregexp/regerror.c index 92b73a0d91..a208d7ba9d 100644 --- a/sys/src/libregexp/regerror.c +++ b/sys/src/libregexp/regerror.c @@ -7,7 +7,7 @@ regerror(char *s) { char buf[132]; - strcpy(buf, "regerror: "); + strncpy(buf, "regerror: ", sizeof(buf)); strcat(buf, s); strcat(buf, "\n"); write(2, buf, strlen(buf)); diff --git a/sys/src/libregexp/regexec.c b/sys/src/libregexp/regexec.c index b806ba60a3..5ab833318b 100644 --- a/sys/src/libregexp/regexec.c +++ b/sys/src/libregexp/regexec.c @@ -172,7 +172,7 @@ regexec2(Reprog *progp, /* program to run */ return -1; relist1 = malloc(BIGLISTSIZE*sizeof(Relist)); if(relist1 == nil){ - free(relist1); + free(relist0); return -1; } j->relist[0] = relist0; diff --git a/sys/src/libregexp/rregsub.c b/sys/src/libregexp/rregsub.c index c395583d0f..075d204866 100644 --- a/sys/src/libregexp/rregsub.c +++ b/sys/src/libregexp/rregsub.c @@ -28,7 +28,7 @@ rregsub(Rune *sp, /* source string */ case '8': case '9': i = *sp-'0'; - if(mp[i].rsp != 0 && mp!=0 && ms>i) + if(mp!=0 && mp[i].rsp != 0 && ms>i) for(ssp = mp[i].rsp; ssp < mp[i].rep; ssp++) @@ -47,9 +47,8 @@ rregsub(Rune *sp, /* source string */ *dp++ = *sp; break; } - }else if(*sp == '&'){ + }else if(*sp == '&'){ if(mp[0].rsp != 0 && mp!=0 && ms>0) - if(mp[0].rsp != 0) for(ssp = mp[0].rsp; ssp < mp[0].rep; ssp++) if(dp < ep) From 87f190a64a3e3a051599be4f91176dff5a26702c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 30 Apr 2016 12:16:12 +0000 Subject: [PATCH 108/402] sys/include: import trace.h changes from Bell Labs --- sys/include/trace.h | 8 +++++--- sys/src/cmd/trace.c | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sys/include/trace.h b/sys/include/trace.h index 759d41ecbe..39415caf59 100644 --- a/sys/include/trace.h +++ b/sys/include/trace.h @@ -13,12 +13,14 @@ typedef enum Tevent { SInts, /* Interrupt start */ SInte, /* Interrupt end */ SUser, /* user event */ + SLock, /* blocked on a queue or lock */ Nevent, } Tevent; typedef struct Traceevent Traceevent; struct Traceevent { - ulong pid; - ulong etype; /* Event type */ - vlong time; /* time stamp */ + u32int pid; + u32int etype; /* Event type */ + u64int time; /* time stamp */ + u32int core; /* core number */ }; diff --git a/sys/src/cmd/trace.c b/sys/src/cmd/trace.c index 72262da405..88962fba7c 100644 --- a/sys/src/cmd/trace.c +++ b/sys/src/cmd/trace.c @@ -538,7 +538,7 @@ doevent(Task *t, Traceevent *ep) } break; case SDead: -print("task died %ld %t %s\n", event->pid, event->time, schedstatename[event->etype & 0xffff]); +print("task died %d %U %s\n", event->pid, event->time, schedstatename[event->etype & 0xffff]); free(t->events); free(t->name); ntasks--; @@ -695,12 +695,12 @@ drawtrace(void) nevents = n / sizeof(Traceevent); for (ep = eventbuf; ep < eventbuf + nevents; ep++){ if ((ep->etype & 0xffff) >= Nevent){ - print("%ld %t Illegal event %ld\n", + print("%d %U Illegal event %d\n", ep->pid, ep->time, ep->etype & 0xffff); continue; } if (verbose) - print("%ld %t %s\n", + print("%d %U %s\n", ep->pid, ep->time, schedstatename[ep->etype & 0xffff]); for(i = 0; i < ntasks; i++) From f8c964d9a524860b79ca1247e769230d76571a9a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:24:49 +0000 Subject: [PATCH 109/402] sys/lib: replace sprint by snprint (thanks Geoff Collyer) --- sys/lib/yaccpar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/lib/yaccpar b/sys/lib/yaccpar index 79a8d4e010..25a481ca96 100644 --- a/sys/lib/yaccpar +++ b/sys/lib/yaccpar @@ -16,7 +16,7 @@ int yynerrs = 0; /* number of errors */ int yyerrflag = 0; /* error recovery flag */ extern int fprint(int, char*, ...); -extern int sprint(char*, char*, ...); +extern int snprint(char*, int, char*, ...); char* yytokname(int yyc) @@ -26,7 +26,7 @@ yytokname(int yyc) if(yyc > 0 && yyc <= sizeof(yytoknames)/sizeof(yytoknames[0])) if(yytoknames[yyc-1]) return yytoknames[yyc-1]; - sprint(x, "<%d>", yyc); + snprint(x, sizeof x, "<%d>", yyc); return x; } @@ -38,7 +38,7 @@ yystatname(int yys) if(yys >= 0 && yys < sizeof(yystates)/sizeof(yystates[0])) if(yystates[yys]) return yystates[yys]; - sprint(x, "<%d>\n", yys); + snprint(x, sizeof x, "<%d>\n", yys); return x; } From b38d015f72d2a04ccb35f8e974360e119c972d2e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 15 Mar 2016 20:17:42 +0000 Subject: [PATCH 110/402] sys/src/libc: import leget and beget functions (thanks Francisco Ballesteros) --- sys/include/libc.h | 20 ++++++++ sys/man/2/leget | 104 ++++++++++++++++++++++++++++++++++++++ sys/src/libc/port/beget.c | 77 ++++++++++++++++++++++++++++ sys/src/libc/port/leget.c | 76 ++++++++++++++++++++++++++++ sys/src/libc/port/mkfile | 2 + 5 files changed, 279 insertions(+) create mode 100644 sys/man/2/leget create mode 100644 sys/src/libc/port/beget.c create mode 100644 sys/src/libc/port/leget.c diff --git a/sys/include/libc.h b/sys/include/libc.h index 40776e58cf..2ace55aa4a 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -335,6 +335,26 @@ extern vlong nsec(void); extern void cycles(uvlong*); /* 64-bit value of the cycle counter if there is one, 0 if there isn't */ +/* + * endian conversion + */ +extern u16int le16get(uchar *t, uchar **r); +extern u32int le24get(uchar *t, uchar **r); +extern u32int le32get(uchar *t, uchar **r); +extern u64int le64get(uchar *t, uchar **r); +extern uchar* le16put(uchar *t, u16int r); +extern uchar* le24put(uchar *t, u32int r); +extern uchar* le32put(uchar *t, u32int r); +extern uchar* le64put(uchar *t, u64int r); +extern u16int be16get(uchar *t, uchar **r); +extern u32int be24get(uchar *t, uchar **r); +extern u32int be32get(uchar *t, uchar **r); +extern u64int be64get(uchar *t, uchar **r); +extern uchar* be16put(uchar *t, u16int r); +extern uchar* be24put(uchar *t, u32int r); +extern uchar* be32put(uchar *t, u32int r); +extern uchar* be64put(uchar *t, u64int r); + /* * one-of-a-kind */ diff --git a/sys/man/2/leget b/sys/man/2/leget new file mode 100644 index 0000000000..dc8fd3a436 --- /dev/null +++ b/sys/man/2/leget @@ -0,0 +1,104 @@ +.TH LEGET 2 +le16get, le24get, le32get, le64get, le16put, le24put, le32put, le64put, be16get, be24get, be32get, be64get, be16put, be24put, be32put, be64put\- integer marshalling +.SH SYNOPSIS +.ta +\w'\fLuvlong 'u +.PP +.nf +.B +u16int le16get(uchar *t, uchar **r) +.PP +.nf +.B +u32int le24get(uchar *t, uchar **r) +.PP +.nf +.B +u32int le32get(uchar *t, uchar **r) +.PP +.nf +.B +u64int le64get(uchar *t, uchar **r) +.PP +.nf +.B +uchar* le16put(uchar *t, u16int i) +.PP +.nf +.B +uchar* le24put(uchar *t, u32int i) +.PP +.nf +.B +uchar* le32put(uchar *t, u32int i) +.PP +.nf +.B +uchar* le64put(uchar *t, u64int i) +.PP +.nf +.B +u16int be16get(uchar *t, uchar **r) +.PP +.nf +.B +u32int be24get(uchar *t, uchar **r) +.PP +.nf +.B +u32int be32get(uchar *t, uchar **r) +.PP +.nf +.B +u64int be64get(uchar *t, uchar **r) +.PP +.nf +.B +uchar* be16put(uchar *t, u16int i) +.PP +.nf +.B +uchar* be24put(uchar *t, u32int i) +.PP +.nf +.B +uchar* be32put(uchar *t, u32int i) +.PP +.nf +.B +uchar* be64put(uchar *t, u64int i) +.PP +.SH DESCRIPTION +These functions marshal a 2- to 8-byte integer to +or from little- or big-endian formats. The +.I put +functions return the +pointer to the first byte after the integer. The +.I get +functions return the value, and if +.B r +is not +.I nil +they set +.B *r +to point at the first byte after the integer. +.SH SOURCE +.B /sys/src/libc/port/beget.c +.br +.B /sys/src/libc/port/leget.c +.SH "SEE ALSO" +.IR fcall (2), +.IR ip (2) +.SH BUGS +.IR GBIT * +and +.IR PBIT * +(from +.IR fcall (2)) +provide similar functionality for little-endian integers. +The +.IR nhget * +and +.IR nhput * +functions from +.IR ip (2) +provide similar functionality for big-endian integers. diff --git a/sys/src/libc/port/beget.c b/sys/src/libc/port/beget.c new file mode 100644 index 0000000000..8fd00a681d --- /dev/null +++ b/sys/src/libc/port/beget.c @@ -0,0 +1,77 @@ +#include +#include + +u16int +be16get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+2; + return (u16int)t[0]<<8 | (u16int)t[1]; +} + +u32int +be24get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+3; + return (u32int)t[1]<<16 | (u32int)t[2]<<8 | (u32int)t[3]; +} + +u32int +be32get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+4; + return (u32int)t[0]<<24 | (u32int)t[1]<<16 | (u32int)t[2]<<8 | (u32int)t[3]; +} + +u64int +be64get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+8; + return (u64int)t[0]<<56 | (u64int)t[1]<<48 | (u64int)t[2]<<40 | (u64int)t[3]<<32 | + (u64int)t[4]<<24 | (u64int)t[5]<<16 | (u64int)t[6]<<8 | (u64int)t[7]; +} + +uchar* +be16put(uchar *t, u16int r) +{ + *t++ = r>>8; + *t++ = r; + return t; +} + +uchar* +be32put(uchar *t, u32int r) +{ + *t++ = r>>24; + *t++ = r>>16; + *t++ = r>>8; + *t++ = r; + return t; +} + +uchar* +be24put(uchar *t, u32int r) +{ + *t++ = r>>16; + *t++ = r>>8; + *t++ = r; + return t; +} + +uchar* +be64put(uchar *t, u64int r) +{ + *t++ = r>>56; + *t++ = r>>48; + *t++ = r>>40; + *t++ = r>>32; + *t++ = r>>24; + *t++ = r>>16; + *t++ = r>>8; + *t++ = r; + return t; +} + diff --git a/sys/src/libc/port/leget.c b/sys/src/libc/port/leget.c new file mode 100644 index 0000000000..8d7d574e26 --- /dev/null +++ b/sys/src/libc/port/leget.c @@ -0,0 +1,76 @@ +#include +#include + +u16int +le16get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+2; + return (u16int)t[0] | (u16int)t[1]<<8; +} + +u32int +le24get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+3; + return (u32int)t[0] | (u32int)t[1]<<8 | (u32int)t[2]<<16; +} + +u32int +le32get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+4; + return (u32int)t[0] | (u32int)t[1]<<8 | (u32int)t[2]<<16 | (u32int)t[3]<<24; +} + +u64int +le64get(uchar *t, uchar **r) +{ + if(r != nil) + *r = t+8; + return (u64int)t[0] | (u64int)t[1]<<8 | (u64int)t[2]<<16 | (u64int)t[3]<<24 | + (u64int)t[4]<<32 | (u64int)t[5]<<40 | (u64int)t[6]<<48 | (u64int)t[7]<<56; +} + +uchar* +le16put(uchar *t, u16int r) +{ + *t++ = r; + *t++ = r>>8; + return t; +} + +uchar* +le24put(uchar *t, u32int r) +{ + *t++ = r; + *t++ = r>>8; + *t++ = r>>16; + return t; +} + +uchar* +le32put(uchar *t, u32int r) +{ + *t++ = r; + *t++ = r>>8; + *t++ = r>>16; + *t++ = r>>24; + return t; +} + +uchar* +le64put(uchar *t, u64int r) +{ + *t++ = r; + *t++ = r>>8; + *t++ = r>>16; + *t++ = r>>24; + *t++ = r>>32; + *t++ = r>>40; + *t++ = r>>48; + *t++ = r>>56; + return t; +} diff --git a/sys/src/libc/port/mkfile b/sys/src/libc/port/mkfile index c838d40b58..94f80eb505 100644 --- a/sys/src/libc/port/mkfile +++ b/sys/src/libc/port/mkfile @@ -12,6 +12,7 @@ CFILES=\ atof.c\ atol.c\ atoll.c\ + beget.c\ cistrcmp.c\ cistrncmp.c\ cistrstr.c\ @@ -32,6 +33,7 @@ CFILES=\ getuser.c\ hangup.c\ hypot.c\ + leget.c\ lnrand.c\ lock.c\ log.c\ From 78153a1be1615112e23fdb251372d06fdc0230d2 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 06:26:36 +0000 Subject: [PATCH 111/402] sys/src/libc: implement procsetname (thanks Charles Forsyth) --- sys/include/libc.h | 1 + sys/src/cmd/aux/listen.c | 2 +- sys/src/libc/9sys/mkfile | 1 + sys/src/libc/9sys/procsetname.c | 27 +++++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 sys/src/libc/9sys/procsetname.c diff --git a/sys/include/libc.h b/sys/include/libc.h index 2ace55aa4a..ffacc848a6 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -403,6 +403,7 @@ extern void notejmp(void*, jmp_buf, int); extern void perror(char*); extern int postnote(int, int, char *); extern double pow10(int); +extern void procsetname(char*, ...); extern int putenv(char*, char*); extern void qsort(void*, long, long, int (*)(void*, void*)); extern int setjmp(jmp_buf); diff --git a/sys/src/cmd/aux/listen.c b/sys/src/cmd/aux/listen.c index d8b5c6c913..77d2a40daf 100644 --- a/sys/src/cmd/aux/listen.c +++ b/sys/src/cmd/aux/listen.c @@ -53,7 +53,7 @@ usage(void) * based on libthread's threadsetname, but drags in less library code. * actually just sets the arguments displayed. */ -static void +void procsetname(char *fmt, ...) { int fd; diff --git a/sys/src/libc/9sys/mkfile b/sys/src/libc/9sys/mkfile index 73e3ebd400..b43dcaac16 100644 --- a/sys/src/libc/9sys/mkfile +++ b/sys/src/libc/9sys/mkfile @@ -29,6 +29,7 @@ OFILES=\ nulldir.$O\ postnote.$O\ privalloc.$O\ + procsetname.$O\ pushssl.$O\ pushtls.$O\ putenv.$O\ diff --git a/sys/src/libc/9sys/procsetname.c b/sys/src/libc/9sys/procsetname.c new file mode 100644 index 0000000000..403a1cb51c --- /dev/null +++ b/sys/src/libc/9sys/procsetname.c @@ -0,0 +1,27 @@ +#include +#include + +/* + * based on libthread's threadsetname, but drags in less library code. + * actually just sets the arguments displayed. + */ +void +procsetname(char *fmt, ...) +{ + int fd; + char *cmdname; + char buf[128]; + va_list arg; + + va_start(arg, fmt); + cmdname = vsmprint(fmt, arg); + va_end(arg); + if (cmdname == nil) + return; + snprint(buf, sizeof buf, "#p/%d/args", getpid()); + if((fd = open(buf, OWRITE)) >= 0){ + write(fd, cmdname, strlen(cmdname)+1); + close(fd); + } + free(cmdname); +} From 557e07fe68d52e01050be9a31b563f5dcfb9b082 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 8 Mar 2016 21:11:03 +0000 Subject: [PATCH 112/402] sys/src/libc: fix privalloc and privfree (thanks Charles Forsyth) --- sys/src/libc/9sys/privalloc.c | 37 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/sys/src/libc/9sys/privalloc.c b/sys/src/libc/9sys/privalloc.c index 907485e2f9..f0d2d9bb35 100644 --- a/sys/src/libc/9sys/privalloc.c +++ b/sys/src/libc/9sys/privalloc.c @@ -3,7 +3,7 @@ static Lock privlock; static int privinit; -static void **privs; +static u32int privmap; extern void **_privates; extern int _nprivates; @@ -15,31 +15,30 @@ privalloc(void) int i; lock(&privlock); - if(!privinit){ - privinit = 1; - if(_nprivates){ - _privates[0] = 0; - for(i = 1; i < _nprivates; i++) - _privates[i] = &_privates[i - 1]; - privs = &_privates[i - 1]; + for(i = 0; i < 32 && i < _nprivates; i++){ + if((privmap & (1< _nprivates || (privmap & (1< Date: Sun, 28 Feb 2016 06:07:17 +0000 Subject: [PATCH 113/402] sys/src/libc: simplify nsec (thanks Charles Forsyth) --- sys/src/libc/9sys/nsec.c | 71 ++++------------------------------------ 1 file changed, 7 insertions(+), 64 deletions(-) diff --git a/sys/src/libc/9sys/nsec.c b/sys/src/libc/9sys/nsec.c index 531f05f547..7372c2edb6 100644 --- a/sys/src/libc/9sys/nsec.c +++ b/sys/src/libc/9sys/nsec.c @@ -1,76 +1,19 @@ #include #include -#include -static uvlong order = 0x0001020304050607ULL; - -static void -be2vlong(vlong *to, uchar *f) -{ - uchar *t, *o; - int i; - - t = (uchar*)to; - o = (uchar*)ℴ - for(i = 0; i < sizeof order; i++) - t[o[i]] = f[i]; -} - -static int fd = -1; -static struct { - int pid; - int fd; -} fds[64]; +#define U32(x) (((((((x)[0]<<8)|(x)[1])<<8)|(x)[2])<<8)|(x)[3]) vlong nsec(void) { uchar b[8]; - vlong t; - int pid, i, f, tries; - - /* - * Threaded programs may have multiple procs - * with different fd tables, so we may need to open - * /dev/bintime on a per-pid basis - */ + int f, n; - /* First, look if we've opened it for this particular pid */ - if((pid = _tos->pid) == 0) /* 9vx bug, perhaps? */ - _tos->pid = pid = getpid(); - do{ - f = -1; - for(i = 0; i < nelem(fds); i++) - if(fds[i].pid == pid){ - f = fds[i].fd; - break; - } - tries = 0; - if(f < 0){ - /* If it's not open for this pid, try the global pid */ - if(fd >= 0) - f = fd; - else{ - /* must open */ - if((f = open("/dev/bintime", OREAD|OCEXEC)) < 0) - return 0; - fd = f; - for(i = 0; i < nelem(fds); i++) - if(fds[i].pid == pid || fds[i].pid == 0){ - fds[i].pid = pid; - fds[i].fd = f; - break; - } - } - } - if(pread(f, b, sizeof b, 0) == sizeof b){ - be2vlong(&t, b); - return t; - } + if((f = open("/dev/bintime", OREAD)) >= 0){ + n = pread(f, b, sizeof(b), 0); close(f); - if(i < nelem(fds)) - fds[i].fd = -1; - }while(tries++ == 0); /* retry once */ - USED(tries); + if(n == sizeof(b)) + return (u64int)U32(b)<<32 | U32(b+4); + } return 0; } From 476f6d443c46c4bff26d66a7e06cea0959c5ef14 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 20:37:40 +0000 Subject: [PATCH 114/402] sys/src/libc: update ARM atomic operations to work correctly on multiprocessors (thanks Richard Miller) --- sys/src/9/kw/fpiarm.c | 9 +++++++++ sys/src/ape/lib/ap/arm/atom.s | 14 ++++++++++++-- sys/src/ape/lib/ap/arm/tas.s | 32 ++++++++++++++++++++++++++++---- sys/src/libc/arm/atom.s | 14 ++++++++++++-- sys/src/libc/arm/tas.s | 32 ++++++++++++++++++++++++++++---- 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/sys/src/9/kw/fpiarm.c b/sys/src/9/kw/fpiarm.c index 6647251223..d2306ebdc3 100644 --- a/sys/src/9/kw/fpiarm.c +++ b/sys/src/9/kw/fpiarm.c @@ -468,6 +468,14 @@ casemu(ulong pc, ulong op, Ureg *ur) spllo(); } +void +dmb(ulong pc, ulong op, Ureg *ur) +{ + USED(pc); + USED(op); + USED(ur); +} + int ldrexvalid; void @@ -533,6 +541,7 @@ struct { { 0x01800f90, 0x0ff00ff0, strex }, { 0xf57ff01f, 0xffffffff, clrex }, { 0x0ed00100, 0x0ef08100, casemu }, + { 0xee070fba, 0xffffffff, dmb }, { 0x00000000, 0x00000000, nil } }; diff --git a/sys/src/ape/lib/ap/arm/atom.s b/sys/src/ape/lib/ap/arm/atom.s index b59a89d906..6b7bf8ae89 100644 --- a/sys/src/ape/lib/ap/arm/atom.s +++ b/sys/src/ape/lib/ap/arm/atom.s @@ -1,3 +1,4 @@ +#define DMB MCR 15, 0, R0, C7, C10, 5 #define CLREX WORD $0xf57ff01f #define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) /* `The order of operands is from left to right in dataflow order' - asm man */ @@ -18,11 +19,14 @@ spincas: STREX(2,0,4) /* STREX 0(R0),R2,R4 */ CMP.S $0, R4 BNE spincas + MOVW $0, R0 + DMB MOVW $1, R0 RET fail: CLREX MOVW $0, R0 + DMB RET TEXT _xinc(SB), $0 /* void _xinc(long *); */ @@ -33,6 +37,8 @@ spinainc: STREX(3,0,4) /* STREX 0(R0),R3,R4 */ CMP.S $0, R4 BNE spinainc + MOVW $0, R0 + DMB MOVW R3, R0 RET @@ -44,6 +50,8 @@ spinadec: STREX(3,0,4) /* STREX 0(R0),R3,R4 */ CMP.S $0, R4 BNE spinadec + MOVW $0, R0 + DMB MOVW R3, R0 RET @@ -53,6 +61,8 @@ TEXT loadlinked(SB), $0 /* long loadlinked(long *); */ TEXT storecond(SB), $0 /* int storecond(long *, long); */ MOVW ov+4(FP), R3 - STREX(3,0,0) /* STREX 0(R0),R3,R0 */ - RSB $1, R0 + STREX(3,0,4) /* STREX 0(R0),R3,R4 */ + MOVW $0, R0 + DMB + RSB $1, R4, R0 RET diff --git a/sys/src/ape/lib/ap/arm/tas.s b/sys/src/ape/lib/ap/arm/tas.s index f1269209e1..d7422d5f6a 100644 --- a/sys/src/ape/lib/ap/arm/tas.s +++ b/sys/src/ape/lib/ap/arm/tas.s @@ -1,5 +1,29 @@ -TEXT tas(SB), $-4 - MOVW R0,R1 - MOVW $1,R0 - SWPW R0,(R1) +#define DMB MCR 15, 0, R0, C7, C10, 5 +#define STREX(f,tp,r) WORD $(0xe<<28|0x01800f90 | (tp)<<16 | (r)<<12 | (f)<<0) +#define LDREX(fp,t) WORD $(0xe<<28|0x01900f9f | (fp)<<16 | (t)<<12) +#define CLREX WORD $0xf57ff01f + +TEXT tas(SB), $-4 /* tas(ulong *) */ + /* returns old (R0) after modifying (R0) */ + MOVW R0,R5 + MOVW $0, R0 + DMB + + MOVW $1,R2 /* new value of (R0) */ +tas1: + LDREX(5,1) /* LDREX 0(R5),R1 */ + CMP.S $0, R1 /* old value non-zero (lock taken)? */ + BNE lockbusy /* we lose */ + STREX(2,5,4) /* STREX R2,(R5),R4 */ + CMP.S $0, R4 + BNE tas1 /* strex failed? try again */ + MOVW $0, R0 + DMB + MOVW R1, R0 + RET +lockbusy: + CLREX + MOVW $0, R0 + DMB + MOVW R1, R0 RET diff --git a/sys/src/libc/arm/atom.s b/sys/src/libc/arm/atom.s index b59a89d906..6b7bf8ae89 100644 --- a/sys/src/libc/arm/atom.s +++ b/sys/src/libc/arm/atom.s @@ -1,3 +1,4 @@ +#define DMB MCR 15, 0, R0, C7, C10, 5 #define CLREX WORD $0xf57ff01f #define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) /* `The order of operands is from left to right in dataflow order' - asm man */ @@ -18,11 +19,14 @@ spincas: STREX(2,0,4) /* STREX 0(R0),R2,R4 */ CMP.S $0, R4 BNE spincas + MOVW $0, R0 + DMB MOVW $1, R0 RET fail: CLREX MOVW $0, R0 + DMB RET TEXT _xinc(SB), $0 /* void _xinc(long *); */ @@ -33,6 +37,8 @@ spinainc: STREX(3,0,4) /* STREX 0(R0),R3,R4 */ CMP.S $0, R4 BNE spinainc + MOVW $0, R0 + DMB MOVW R3, R0 RET @@ -44,6 +50,8 @@ spinadec: STREX(3,0,4) /* STREX 0(R0),R3,R4 */ CMP.S $0, R4 BNE spinadec + MOVW $0, R0 + DMB MOVW R3, R0 RET @@ -53,6 +61,8 @@ TEXT loadlinked(SB), $0 /* long loadlinked(long *); */ TEXT storecond(SB), $0 /* int storecond(long *, long); */ MOVW ov+4(FP), R3 - STREX(3,0,0) /* STREX 0(R0),R3,R0 */ - RSB $1, R0 + STREX(3,0,4) /* STREX 0(R0),R3,R4 */ + MOVW $0, R0 + DMB + RSB $1, R4, R0 RET diff --git a/sys/src/libc/arm/tas.s b/sys/src/libc/arm/tas.s index 6c34f52279..8c8b98f345 100644 --- a/sys/src/libc/arm/tas.s +++ b/sys/src/libc/arm/tas.s @@ -1,5 +1,29 @@ -TEXT _tas(SB), 1, $-4 - MOVW R0,R1 - MOVW $1,R0 - SWPW R0,(R1) /* fix: deprecated in armv7 */ +#define DMB MCR 15, 0, R0, C7, C10, 5 +#define STREX(f,tp,r) WORD $(0xe<<28|0x01800f90 | (tp)<<16 | (r)<<12 | (f)<<0) +#define LDREX(fp,t) WORD $(0xe<<28|0x01900f9f | (fp)<<16 | (t)<<12) +#define CLREX WORD $0xf57ff01f + +TEXT _tas(SB), $-4 /* _tas(ulong *) */ + /* returns old (R0) after modifying (R0) */ + MOVW R0,R5 + MOVW $0, R0 + DMB + + MOVW $1,R2 /* new value of (R0) */ +tas1: + LDREX(5,1) /* LDREX 0(R5),R1 */ + CMP.S $0, R1 /* old value non-zero (lock taken)? */ + BNE lockbusy /* we lose */ + STREX(2,5,4) /* STREX R2,(R5),R4 */ + CMP.S $0, R4 + BNE tas1 /* strex failed? try again */ + MOVW $0, R0 + DMB + MOVW R1, R0 + RET +lockbusy: + CLREX + MOVW $0, R0 + DMB + MOVW R1, R0 RET From 96d356252acd441d2a6b5d0ad14591a2cde5294a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 7 Nov 2016 00:42:13 +0000 Subject: [PATCH 115/402] sys/src/libc: handle year >= 2100 in ctime (thanks Geoff Collyer) --- sys/src/ape/lib/ap/plan9/ctime.c | 2 +- sys/src/libc/9sys/ctime.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/ape/lib/ap/plan9/ctime.c b/sys/src/ape/lib/ap/plan9/ctime.c index b0ba28d40e..d1d651f121 100644 --- a/sys/src/ape/lib/ap/plan9/ctime.c +++ b/sys/src/ape/lib/ap/plan9/ctime.c @@ -195,7 +195,7 @@ asctime_r(const struct tm *t, char *buf) ct_numb(buf+17, t->tm_sec+100); if(t->tm_year >= 100) { buf[20] = '2'; - buf[21] = '0'; + buf[21] = t->tm_year >= 200? '1': '0'; } ct_numb(buf+22, t->tm_year+100); return buf; diff --git a/sys/src/libc/9sys/ctime.c b/sys/src/libc/9sys/ctime.c index d7a57c447d..0137d6fff2 100644 --- a/sys/src/libc/9sys/ctime.c +++ b/sys/src/libc/9sys/ctime.c @@ -182,7 +182,7 @@ asctime(Tm *t) cbuf[22] = *ncp; if(t->year >= 100) { cbuf[24] = '2'; - cbuf[25] = '0'; + cbuf[25] = t->year >= 200? '1': '0'; } ct_numb(cbuf+26, t->year+100); return cbuf; From a0d1f477a13e9b97cc6faf644fa38e4ed240fab0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:29:38 +0000 Subject: [PATCH 116/402] sys/src/libc: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libc/9sys/getnetconninfo.c | 2 +- sys/src/libc/9sys/postnote.c | 4 ++-- sys/src/libc/9sys/pushssl.c | 2 +- sys/src/libc/9sys/pushtls.c | 4 ++-- sys/src/libc/fmt/fltfmt.c | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/src/libc/9sys/getnetconninfo.c b/sys/src/libc/9sys/getnetconninfo.c index 8dbb95f89b..3a7387b7a4 100644 --- a/sys/src/libc/9sys/getnetconninfo.c +++ b/sys/src/libc/9sys/getnetconninfo.c @@ -77,7 +77,7 @@ getnetconninfo(char *dir, int fd) /* figure out bind spec */ d = dirstat(nci->dir); if(d != nil){ - sprint(spec, "#%C%d", d->type, d->dev); + snprint(spec, sizeof spec, "#%C%d", d->type, d->dev); nci->spec = strdup(spec); } if(nci->spec == nil) diff --git a/sys/src/libc/9sys/postnote.c b/sys/src/libc/9sys/postnote.c index 46564e9ea7..424e5ef6ac 100644 --- a/sys/src/libc/9sys/postnote.c +++ b/sys/src/libc/9sys/postnote.c @@ -9,10 +9,10 @@ postnote(int group, int pid, char *note) switch(group) { case PNPROC: - sprint(file, "/proc/%d/note", pid); + snprint(file, sizeof file, "/proc/%d/note", pid); break; case PNGROUP: - sprint(file, "/proc/%d/notepg", pid); + snprint(file, sizeof file, "/proc/%d/notepg", pid); break; default: return -1; diff --git a/sys/src/libc/9sys/pushssl.c b/sys/src/libc/9sys/pushssl.c index 8817dd1c35..124c2543cd 100644 --- a/sys/src/libc/9sys/pushssl.c +++ b/sys/src/libc/9sys/pushssl.c @@ -21,7 +21,7 @@ pushssl(int fd, char *alg, char *secin, char *secout, int *cfd) if(n < 0) goto error; buf[n] = 0; - sprint(dname, "#D/ssl/%s/data", buf); + snprint(dname, sizeof dname, "#D/ssl/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; diff --git a/sys/src/libc/9sys/pushtls.c b/sys/src/libc/9sys/pushtls.c index 345c6b030d..476c26ffaf 100644 --- a/sys/src/libc/9sys/pushtls.c +++ b/sys/src/libc/9sys/pushtls.c @@ -60,13 +60,13 @@ pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *d sprint(dir, "#a/tls/%s", buf); // get application fd - sprint(dname, "#a/tls/%s/data", buf); + snprint(dname, sizeof dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; // get handshake fd - sprint(dname, "#a/tls/%s/hand", buf); + snprint(dname, sizeof dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0) goto error; diff --git a/sys/src/libc/fmt/fltfmt.c b/sys/src/libc/fmt/fltfmt.c index ff5462910f..ac797bcd6e 100644 --- a/sys/src/libc/fmt/fltfmt.c +++ b/sys/src/libc/fmt/fltfmt.c @@ -133,13 +133,13 @@ xdtoa(Fmt *fmt, char *s2, double f) d = e; s1[NSIGNIF-2] = '0'; s1[NSIGNIF-1] = '0'; - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + snprint(s1+NSIGNIF, sizeof s1-NSIGNIF, "e%d", e-NSIGNIF+1); g = strtod(s1, nil); if(g == f) goto found; if(xadd(s1, NSIGNIF-3, 1)) { e++; - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + snprint(s1+NSIGNIF, sizeof s1-NSIGNIF, "e%d", e-NSIGNIF+1); } g = strtod(s1, nil); if(g == f) @@ -152,7 +152,7 @@ xdtoa(Fmt *fmt, char *s2, double f) * convert back so s1 gets exact answer */ for(;;) { - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + snprint(s1+NSIGNIF, sizeof s1-NSIGNIF, "e%d", e-NSIGNIF+1); g = strtod(s1, nil); if(f > g) { if(xadd(s1, NSIGNIF-1, 1)) From 938f46f3d74a4ba79e62a96973e3ed7dd9af3c3c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 19 Sep 2017 08:40:48 +0000 Subject: [PATCH 117/402] sys/src/libc: prevent infinite loop in pow function (thanks Geoff Collyer) --- sys/src/ape/lib/ap/math/pow.c | 8 ++++++++ sys/src/libc/port/pow.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/sys/src/ape/lib/ap/math/pow.c b/sys/src/ape/lib/ap/math/pow.c index 9512a649bb..178f039986 100644 --- a/sys/src/ape/lib/ap/math/pow.c +++ b/sys/src/ape/lib/ap/math/pow.c @@ -12,6 +12,14 @@ pow(double x, double y) /* return x ^ y (exponentiation) */ if(y == 0.0) return 1.0; + /* prevent infinite loop */ + if(isNaN(x) || isNaN(y)) + return NaN(); + if(isInf(x, 0)) + return x; + if(isInf(y, 0)) + return x == 0 || x == 1? x: y; + flip = 0; if(y < 0.){ y = -y; diff --git a/sys/src/libc/port/pow.c b/sys/src/libc/port/pow.c index 0a5a0b5cd0..5fa6ae2d80 100644 --- a/sys/src/libc/port/pow.c +++ b/sys/src/libc/port/pow.c @@ -11,6 +11,14 @@ pow(double x, double y) /* return x ^ y (exponentiation) */ if(y == 0.0) return 1.0; + /* prevent infinite loop */ + if(isNaN(x) || isNaN(y)) + return NaN(); + if(isInf(x, 0)) + return x; + if(isInf(y, 0)) + return x == 0 || x == 1? x: y; + flip = 0; if(y < 0.){ y = -y; From 66311f6967420c0415a8897f0de49a69ebd9f466 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 1 May 2021 16:03:30 +0000 Subject: [PATCH 118/402] sys/src/libc/fmt: use Rune instead of int in Convfmt (thanks Geoff Collyer) --- sys/src/libc/fmt/fmt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/src/libc/fmt/fmt.c b/sys/src/libc/fmt/fmt.c index 72e556ea6e..6292b58160 100644 --- a/sys/src/libc/fmt/fmt.c +++ b/sys/src/libc/fmt/fmt.c @@ -10,7 +10,7 @@ enum typedef struct Convfmt Convfmt; struct Convfmt { - int c; + Rune c; volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */ }; @@ -57,7 +57,7 @@ int (*doquote)(int); * _fmtlock() must be set */ static int -_fmtinstall(int c, Fmts f) +_fmtinstall(Rune c, Fmts f) { Convfmt *p, *ep; @@ -95,10 +95,13 @@ fmtinstall(int c, Fmts f) } static Fmts -fmtfmt(int c) +fmtfmt(Rune c) { Convfmt *p, *ep; + if (c == '\0') + return _badfmt; + ep = &fmtalloc.fmt[fmtalloc.nfmt]; for(p=fmtalloc.fmt; pc == c){ From ace6ab03e09b78f8227ec0ae6341042feb99d29f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 27 Feb 2016 23:07:32 +0000 Subject: [PATCH 119/402] sys/src/libauth: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libauth/newns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libauth/newns.c b/sys/src/libauth/newns.c index 3486a93ab8..1c021c8136 100644 --- a/sys/src/libauth/newns.c +++ b/sys/src/libauth/newns.c @@ -368,7 +368,7 @@ setenv(char *name, char *val) char ename[ANAMELEN+6]; long s; - sprint(ename, "#e/%s", name); + snprint(ename, sizeof ename, "#e/%s", name); f = create(ename, OWRITE, 0664); if(f < 0) return -1; From efabe58b95037d022d12d16e4bef5baaa8c43b51 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 7 Nov 2016 13:39:08 +0000 Subject: [PATCH 120/402] sys/src/cmd/cc: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/cmd/cc/cc.y | 4 ++-- sys/src/cmd/cc/funct.c | 6 +++--- sys/src/cmd/cc/lex.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/src/cmd/cc/cc.y b/sys/src/cmd/cc/cc.y index 8c9d09b194..221c6dad7b 100644 --- a/sys/src/cmd/cc/cc.y +++ b/sys/src/cmd/cc/cc.y @@ -1008,7 +1008,7 @@ complex: | LSTRUCT sbody { taggen++; - sprint(symb, "_%d_", taggen); + snprint(symb, sizeof symb, "_%d_", taggen); $$ = dotag(lookup(), TSTRUCT, autobn); $$->link = $2; sualign($$); @@ -1033,7 +1033,7 @@ complex: | LUNION sbody { taggen++; - sprint(symb, "_%d_", taggen); + snprint(symb, sizeof symb, "_%d_", taggen); $$ = dotag(lookup(), TUNION, autobn); $$->link = $2; sualign($$); diff --git a/sys/src/cmd/cc/funct.c b/sys/src/cmd/cc/funct.c index f794c6a622..1c2803d397 100644 --- a/sys/src/cmd/cc/funct.c +++ b/sys/src/cmd/cc/funct.c @@ -262,7 +262,7 @@ dclfunct(Type *t, Sym *s) o = ftabinit[i].op; if(o == OXXX) break; - sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name); + snprint(str, sizeof str, "%s_%s_", t->tag->name, ftabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->sym[o] = n->sym; @@ -296,7 +296,7 @@ dclfunct(Type *t, Sym *s) /* * OCAST types T1 _T2_T1_(T2) */ - sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name); + snprint(str, sizeof str, "_%s%s_", gtabinit[i].name, t->tag->name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castto[o] = n->sym; @@ -305,7 +305,7 @@ dclfunct(Type *t, Sym *s) f1->down = types[o]; dodecl(xdecl, CEXTERN, f1, n); - sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name); + snprint(str, sizeof str, "%s_%s_", t->tag->name, gtabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castfr[o] = n->sym; diff --git a/sys/src/cmd/cc/lex.c b/sys/src/cmd/cc/lex.c index e88f2b4a66..f2a625fc17 100644 --- a/sys/src/cmd/cc/lex.c +++ b/sys/src/cmd/cc/lex.c @@ -258,11 +258,11 @@ compile(char *file, char **defs, int ndef) /* 1999 ANSI C requires recognising // comments */ av[i++] = strdup("-+"); for(c = 0; c < ndef; c++) { - sprint(opt, "-D%s", defs[c]); + snprint(opt, sizeof opt, "-D%s", defs[c]); av[i++] = strdup(opt); } for(c = 0; c < ninclude; c++) { - sprint(opt, "-I%s", include[c]); + snprint(opt, sizeof opt, "-I%s", include[c]); av[i++] = strdup(opt); } if(strcmp(file, "stdin") != 0) @@ -1386,19 +1386,19 @@ Tconv(Fmt *fp) if(str[0]) strcat(str, " "); if(t->garb&~GINCOMPLETE) { - sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]); + snprint(s, sizeof s, "%s ", gnames[t->garb&~GINCOMPLETE]); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); } - sprint(s, "%s", tnames[et]); + snprint(s, sizeof s, "%s", tnames[et]); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); if(et == TFUNC && (t1 = t->down)) { - sprint(s, "(%T", t1); + snprint(s, sizeof s, "(%T", t1); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); while(t1 = t1->down) { - sprint(s, ", %T", t1); + snprint(s, sizeof s, ", %T", t1); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); } @@ -1409,12 +1409,12 @@ Tconv(Fmt *fp) n = t->width; if(t->link && t->link->width) n /= t->link->width; - sprint(s, "[%ld]", n); + snprint(s, sizeof s, "[%ld]", n); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); } if(t->nbits) { - sprint(s, " %d:%d", t->shift, t->nbits); + snprint(s, sizeof s, " %d:%d", t->shift, t->nbits); if(strlen(str) + strlen(s) < STRINGSZ) strcat(str, s); } From 34a83c545fc22ddf5759c7bbaca19aafa3a23faf Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:25:35 +0000 Subject: [PATCH 121/402] sys/src/cmd/ndb: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/cmd/ndb/cs.c | 2 +- sys/src/cmd/ndb/dblookup.c | 2 +- sys/src/cmd/ndb/dnudpserver.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/ndb/cs.c b/sys/src/cmd/ndb/cs.c index ab3de43f6a..44b6e0186c 100644 --- a/sys/src/cmd/ndb/cs.c +++ b/sys/src/cmd/ndb/cs.c @@ -970,7 +970,7 @@ readipinterfaces(void) { if(myipaddr(ipa, mntpt) != 0) ipmove(ipa, IPnoaddr); - sprint(ipaddr, "%I", ipa); + snprint(ipaddr, sizeof ipaddr, "%I", ipa); if (debug) syslog(0, "dns", "ipaddr is %s\n", ipaddr); } diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index 7bc5be2853..9d9a508278 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -1064,7 +1064,7 @@ createv4ptrs(void) net[IPv4off+1] = atoi(f[2]); net[IPv4off+2] = atoi(f[1]); net[IPv4off+3] = atoi(f[0]); - sprint(ipa, "%I", net); + snprint(ipa, sizeof ipa, "%I", net); t = ndbipinfo(db, "ip", ipa, attribs, 1); if(t == nil) /* could be a reverse with no forward */ continue; diff --git a/sys/src/cmd/ndb/dnudpserver.c b/sys/src/cmd/ndb/dnudpserver.c index 8d936b66e8..115c036204 100644 --- a/sys/src/cmd/ndb/dnudpserver.c +++ b/sys/src/cmd/ndb/dnudpserver.c @@ -281,7 +281,7 @@ udpannounce(char *mntpt) static int whined; /* get a udp port */ - sprint(datafile, "%s/udp!*!dns", mntpt); + snprint(datafile, sizeof datafile, "%s/udp!*!dns", mntpt); ctl = announce(datafile, dir); if(ctl < 0){ if(!whined++) From 21f768e7cb30b069efe447fdb76f57ff54697f2e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 5 Jun 2022 15:22:36 +0000 Subject: [PATCH 122/402] sys/src/libbio: import Bfdopen from plan9port (thanks Russ Cox) --- sys/include/bio.h | 1 + sys/man/2/bio | 20 ++++++++++++++++++-- sys/src/libbio/binit.c | 22 +++++++++++++++++++--- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sys/include/bio.h b/sys/include/bio.h index 763692b07c..3a3afbf87e 100644 --- a/sys/include/bio.h +++ b/sys/include/bio.h @@ -58,6 +58,7 @@ int Binits(Biobufhdr*, int, int, uchar*, int); int Blinelen(Biobufhdr*); vlong Boffset(Biobufhdr*); Biobuf* Bopen(char*, int); +Biobuf* Bfdopen(int, int); int Bprint(Biobufhdr*, char*, ...); int Bvprint(Biobufhdr*, char*, va_list); int Bputc(Biobufhdr*, int); diff --git a/sys/man/2/bio b/sys/man/2/bio index 695a011b8a..e231005100 100644 --- a/sys/man/2/bio +++ b/sys/man/2/bio @@ -1,6 +1,6 @@ .TH BIO 2 .SH NAME -Bopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetrune, Bgetd, Bungetc, Bungetrune, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bputrune, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output +Bopen, Bfdopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetrune, Bgetd, Bungetc, Bungetrune, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bputrune, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output .SH SYNOPSIS .ta \w'Biobuf* 'u .B #include @@ -13,6 +13,9 @@ Bopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetrune, Bgetd, Bungetc, Bungetru Biobuf* Bopen(char *file, int mode) .PP .B +Biobuf* Bfdopen(int fd, int mode) +.PP +.B int Binit(Biobuf *bp, int fd, int mode) .PP .B @@ -93,6 +96,17 @@ It calls .IR malloc (2) to allocate a buffer. .PP +.I Bfdopen +allocates a buffer for the already-open file descriptor +.I fd +for mode +.B OREAD +or +.BR OWRITE . +It calls +.IR malloc (2) +to allocate a buffer. +.PP .I Binit initializes a standard size buffer, type .IR Biobuf , @@ -138,7 +152,9 @@ and returns .IR Bflush 's return value. If the buffer was allocated by -.IR Bopen , +.I Bopen +or +.IR Bfdopen , the buffer is .I freed and the file is closed. diff --git a/sys/src/libbio/binit.c b/sys/src/libbio/binit.c index 75cee333bb..ae07b3fa90 100644 --- a/sys/src/libbio/binit.c +++ b/sys/src/libbio/binit.c @@ -93,6 +93,22 @@ Binit(Biobuf *bp, int f, int mode) return Binits(bp, f, mode, bp->b, sizeof(bp->b)); } +Biobuf* +Bfdopen(int f, int mode) +{ + Biobuf *bp; + + bp = malloc(sizeof(Biobuf)); + if(bp == 0) + return 0; + if(Binits(bp, f, mode, bp->b, sizeof(bp->b)) != 0){ + free(bp); + return 0; + } + bp->flag = Bmagic; /* mark bp open & malloced */ + return bp; +} + Biobuf* Bopen(char *name, int mode) { @@ -112,9 +128,9 @@ Bopen(char *name, int mode) } if(f < 0) return 0; - bp = malloc(sizeof(Biobuf)); - Binits(bp, f, mode, bp->b, sizeof(bp->b)); - bp->flag = Bmagic; /* mark bp open & malloced */ + bp = Bfdopen(f, mode); + if(bp == 0) + close(f); return bp; } From 13f3c174af32df6cffaf55ede1259d147c586ee8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 7 Nov 2016 13:39:42 +0000 Subject: [PATCH 123/402] sys/src/libcontrol: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libcontrol/control.c | 7 +++++-- sys/src/libcontrol/scribble.c | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sys/src/libcontrol/control.c b/sys/src/libcontrol/control.c index f30d6fe57f..c0c16ddb18 100644 --- a/sys/src/libcontrol/control.c +++ b/sys/src/libcontrol/control.c @@ -343,9 +343,12 @@ _ctlrunestr(char *s) char* _ctlstrrune(Rune *r) { + int nb; char *s; - s = ctlmalloc(runestrlen(r)*UTFmax+1); - sprint(s, "%S", r); + + nb = runestrlen(r)*UTFmax+1; + s = ctlmalloc(nb); + snprint(s, nb, "%S", r); return s; } diff --git a/sys/src/libcontrol/scribble.c b/sys/src/libcontrol/scribble.c index 4e10ab68f9..4d8c1d1344 100644 --- a/sys/src/libcontrol/scribble.c +++ b/sys/src/libcontrol/scribble.c @@ -110,9 +110,9 @@ scribchar(Scrib *b, Rune r) else if(r == ' ') strcpy(b->lastchar, "' '"); else if(r < ' ') - sprint(b->lastchar, "ctl-%c", r+'@'); + snprint(b->lastchar, sizeof b->lastchar, "ctl-%c", r+'@'); else - sprint(b->lastchar, "%C", r); + snprint(b->lastchar, sizeof b->lastchar, "%C", r); } From 093856a05df15de427611ace232a9931d6b794ee Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:30:41 +0000 Subject: [PATCH 124/402] sys/src/libdraw: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libdraw/event.c | 2 +- sys/src/libdraw/init.c | 6 +++--- sys/src/libdraw/keyboard.c | 6 ++++-- sys/src/libdraw/readcolmap.c | 2 +- sys/src/libdraw/writecolmap.c | 2 +- sys/src/libdraw/writeimage.c | 4 ++-- sys/src/libdraw/writesubfont.c | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/sys/src/libdraw/event.c b/sys/src/libdraw/event.c index 1cf223c36d..c6faf78547 100644 --- a/sys/src/libdraw/event.c +++ b/sys/src/libdraw/event.c @@ -434,7 +434,7 @@ emoveto(Point pt) char buf[2*12+2]; int n; - n = sprint(buf, "m%d %d", pt.x, pt.y); + n = snprint(buf, sizeof buf, "m%d %d", pt.x, pt.y); write(mousefd, buf, n); } diff --git a/sys/src/libdraw/init.c b/sys/src/libdraw/init.c index 0e298cd2af..0b771ad993 100644 --- a/sys/src/libdraw/init.c +++ b/sys/src/libdraw/init.c @@ -220,7 +220,7 @@ initdisplay(char *dev, char *win, void(*error)(Display*, char*)) if(t == nil) return nil; - sprint(buf, "%s/draw/new", dev); + snprint(buf, sizeof buf, "%s/draw/new", dev); ctlfd = open(buf, ORDWR|OCEXEC); if(ctlfd < 0){ if(bind("#i", dev, MAFTER) < 0){ @@ -244,11 +244,11 @@ initdisplay(char *dev, char *win, void(*error)(Display*, char*)) isnew = 0; if(n < NINFO) /* this will do for now, we need something better here */ isnew = 1; - sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12)); + snprint(buf, sizeof buf, "%s/draw/%d/data", dev, atoi(info+0*12)); datafd = open(buf, ORDWR|OCEXEC); if(datafd < 0) goto Error2; - sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12)); + snprint(buf, sizeof buf, "%s/draw/%d/refresh", dev, atoi(info+0*12)); reffd = open(buf, OREAD|OCEXEC); if(reffd < 0){ Error3: diff --git a/sys/src/libdraw/keyboard.c b/sys/src/libdraw/keyboard.c index 5ab911ab8c..06839b03ec 100644 --- a/sys/src/libdraw/keyboard.c +++ b/sys/src/libdraw/keyboard.c @@ -59,6 +59,7 @@ _ioproc(void *arg) Keyboardctl* initkeyboard(char *file) { + int nb; Keyboardctl *kc; char *t; @@ -69,13 +70,14 @@ initkeyboard(char *file) file = "/dev/cons"; kc->file = strdup(file); kc->consfd = open(file, ORDWR|OCEXEC); - t = malloc(strlen(file)+16); + nb = strlen(file)+16; + t = malloc(nb); if(kc->consfd<0 || t==nil){ Error1: free(kc); return nil; } - sprint(t, "%sctl", file); + snprint(t, nb, "%sctl", file); kc->ctlfd = open(t, OWRITE|OCEXEC); if(kc->ctlfd < 0){ fprint(2, "initkeyboard: can't open %s: %r\n", t); diff --git a/sys/src/libdraw/readcolmap.c b/sys/src/libdraw/readcolmap.c index 6eb8ee26ec..18df86d074 100644 --- a/sys/src/libdraw/readcolmap.c +++ b/sys/src/libdraw/readcolmap.c @@ -26,7 +26,7 @@ readcolmap(Display *d, RGB *colmap) USED(screen); - sprint(buf, "/dev/draw/%d/colormap", d->dirno); + snprint(buf, sizeof buf, "/dev/draw/%d/colormap", d->dirno); b = Bopen(buf, OREAD); if(b == 0) drawerror(d, "rdcolmap: can't open colormap device"); diff --git a/sys/src/libdraw/writecolmap.c b/sys/src/libdraw/writecolmap.c index 26c1f7f1f2..2a5fe094d8 100644 --- a/sys/src/libdraw/writecolmap.c +++ b/sys/src/libdraw/writecolmap.c @@ -15,7 +15,7 @@ writecolmap(Display *d, RGB *m) char buf[64], *t; ulong r, g, b; - sprint(buf, "/dev/draw/%d/colormap", d->dirno); + snprint(buf, sizeof buf, "/dev/draw/%d/colormap", d->dirno); fd = open(buf, OWRITE); if(fd < 0) drawerror(d, "writecolmap: open colormap failed"); diff --git a/sys/src/libdraw/writeimage.c b/sys/src/libdraw/writeimage.c index b4dcff061c..71f401db49 100644 --- a/sys/src/libdraw/writeimage.c +++ b/sys/src/libdraw/writeimage.c @@ -66,7 +66,7 @@ writeimage(int fd, Image *i, int dolock) if(nb != dy*bpl) goto ErrOut; } - sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ", + snprint(hdr, sizeof hdr, "compressed\n%11s %11d %11d %11d %11d ", chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y); if(write(fd, hdr, 11+5*12) != 11+5*12) goto ErrOut; @@ -172,7 +172,7 @@ writeimage(int fd, Image *i, int dolock) if(loutp == outbuf) goto ErrOut; n = loutp-outbuf; - sprint(hdr, "%11d %11ld ", r.max.y, n); + snprint(hdr, sizeof hdr, "%11d %11ld ", r.max.y, n); write(fd, hdr, 2*12); write(fd, outbuf, n); r.min.y = r.max.y; diff --git a/sys/src/libdraw/writesubfont.c b/sys/src/libdraw/writesubfont.c index 1ea985f002..1c53326d4f 100644 --- a/sys/src/libdraw/writesubfont.c +++ b/sys/src/libdraw/writesubfont.c @@ -27,7 +27,7 @@ writesubfont(int fd, Subfont *f) uchar *data; int nb; - sprint(hdr, "%11d %11d %11d ", f->n, f->height, f->ascent); + snprint(hdr, sizeof hdr, "%11d %11d %11d ", f->n, f->height, f->ascent); if(write(fd, hdr, 3*12) != 3*12){ Err: werrstr("writesubfont: bad write: %r"); From 1344ba1c69d7aa56b20e23d8399b8f2d75e0558b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:30:51 +0000 Subject: [PATCH 125/402] sys/src/libhtml: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libhtml/lex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libhtml/lex.c b/sys/src/libhtml/lex.c index ca8fc77d65..f8c7516165 100644 --- a/sys/src/libhtml/lex.c +++ b/sys/src/libhtml/lex.c @@ -1418,7 +1418,7 @@ Tconv(Fmt *f) t = va_arg(f->args, Token*); if(t == nil) - sprint(buf, ""); + snprint(buf, sizeof buf, ""); else { i = 0; if(dbglex > 1) From 2f743880e317fc36ceeac54f40019125c422b538 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:31:07 +0000 Subject: [PATCH 126/402] sys/src/libhttpd: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libhttpd/redirected.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/src/libhttpd/redirected.c b/sys/src/libhttpd/redirected.c index 96ce7038f3..a6be732a1f 100644 --- a/sys/src/libhttpd/redirected.c +++ b/sys/src/libhttpd/redirected.c @@ -9,7 +9,7 @@ hredirected(HConnect *c, char *how, char *uri) Hio *hout; char *s, *ss, *scheme, *host; char sayport[NETPATHLEN]; - int n; + int n, nb; scheme = c->scheme? c->scheme: "http"; host = c->head.host; @@ -19,8 +19,9 @@ hredirected(HConnect *c, char *how, char *uri) s = strrchr(c->req.uri, '/'); if(s != nil) *s = '\0'; - ss = halloc(c, strlen(c->req.uri) + strlen(uri) + 2 + UTFmax); - sprint(ss, "%s/%s", c->req.uri, uri); + nb = strlen(c->req.uri) + strlen(uri) + 2 + UTFmax; + ss = halloc(c, nb); + snprint(ss, nb, "%s/%s", c->req.uri, uri); uri = ss; if(s != nil) *s = '/'; From b15f1a1f8a1403960b09ef73549b2a746172b647 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:31:19 +0000 Subject: [PATCH 127/402] sys/src/libip: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libip/eipfmt.c | 6 +++--- sys/src/libip/myetheraddr.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/src/libip/eipfmt.c b/sys/src/libip/eipfmt.c index ee04c5de88..17fb351847 100644 --- a/sys/src/libip/eipfmt.c +++ b/sys/src/libip/eipfmt.c @@ -61,14 +61,14 @@ eipfmt(Fmt *f) n = 0; for(i = 0; i < 16; i += 2){ if(i == eli){ - n += sprint(buf+n, "::"); + n += snprint(buf+n, sizeof buf-n, "::"); i += eln; if(i >= 16) break; } else if(i != 0) - n += sprint(buf+n, ":"); + n += snprint(buf+n, sizeof buf-n, ":"); s = (p[i]<<8) + p[i+1]; - n += sprint(buf+n, "%ux", s); + n += snprint(buf+n, sizeof buf-n, "%ux", s); } return fmtstrcpy(f, buf); diff --git a/sys/src/libip/myetheraddr.c b/sys/src/libip/myetheraddr.c index 34506fa069..05a56a967a 100644 --- a/sys/src/libip/myetheraddr.c +++ b/sys/src/libip/myetheraddr.c @@ -9,9 +9,9 @@ myetheraddr(uchar *to, char *dev) char buf[256]; if(*dev == '/') - sprint(buf, "%s/addr", dev); + snprint(buf, sizeof buf, "%s/addr", dev); else - sprint(buf, "/net/%s/addr", dev); + snprint(buf, sizeof buf, "/net/%s/addr", dev); fd = open(buf, OREAD); if(fd < 0) From bc675f03a925bdec2f32a4382d2d767a6fc91baf Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:32:11 +0000 Subject: [PATCH 128/402] sys/src/libmach: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libmach/5db.c | 18 +++++++++--------- sys/src/libmach/kdb.c | 12 ++++++------ sys/src/libmach/map.c | 4 ++-- sys/src/libmach/qdb.c | 4 ++-- sys/src/libmach/sym.c | 4 ++-- sys/src/libmach/vcodas.c | 20 ++++++++++---------- sys/src/libmach/vdb.c | 22 +++++++++++----------- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/sys/src/libmach/5db.c b/sys/src/libmach/5db.c index cf76ace373..d2b065114e 100644 --- a/sys/src/libmach/5db.c +++ b/sys/src/libmach/5db.c @@ -636,7 +636,7 @@ armshiftval(Map *map, Rgetter rget, Instr *i) ulong v; ulong s = (i->w & BITS(7,11)) >> 7; - sprint(buf, "R%ld", i->w & 0xf); + snprint(buf, sizeof buf, "R%ld", i->w & 0xf); v = rget(map, buf); switch((i->w & BITS(4, 6)) >> 4) { @@ -644,14 +644,14 @@ armshiftval(Map *map, Rgetter rget, Instr *i) case 0: /* LSLIMM */ return v << s; case 1: /* LSLREG */ - sprint(buf, "R%lud", s >> 1); + snprint(buf, sizeof buf, "R%lud", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) return 0; return v << s; case 2: /* LSRIMM */ return LSR(v, s); case 3: /* LSRREG */ - sprint(buf, "R%ld", s >> 1); + snprint(buf, sizeof buf, "R%ld", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) return 0; return LSR(v, s); @@ -663,7 +663,7 @@ armshiftval(Map *map, Rgetter rget, Instr *i) } return ASR(v, s); case 5: /* ASRREG */ - sprint(buf, "R%ld", s >> 1); + snprint(buf, sizeof buf, "R%ld", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) { if((v & (1U<<31)) == 0) @@ -679,7 +679,7 @@ armshiftval(Map *map, Rgetter rget, Instr *i) } return ROR(v, s); case 7: /* RORREG */ - sprint(buf, "R%ld", (s>>1)&0xF); + snprint(buf, sizeof buf, "R%ld", (s>>1)&0xF); s = rget(map, buf); if(s == 0 || (s & 0xF) == 0) return v; @@ -711,7 +711,7 @@ armmaddr(Map *map, Rgetter rget, Instr *i) ulong rn; rn = (i->w >> 16) & 0xf; - sprint(buf,"R%ld", rn); + snprint(buf, sizeof buf, "R%ld", rn); v = rget(map, buf); nb = nbits(i->w & ((1 << 15) - 1)); @@ -746,7 +746,7 @@ armaddr(Map *map, Rgetter rget, Instr *i) uchar c; uchar rm; - sprint(buf, "R%ld", i->w & 0xf); + snprint(buf, sizeof buf, "R%ld", i->w & 0xf); rm = rget(map, buf); switch((i->w & BITS(5,6)) >> 5) { @@ -779,7 +779,7 @@ armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc) return pc+4; r = (i->w >> 16) & 0xf; - sprint(buf, "R%d", r); + snprint(buf, sizeof buf, "R%d", r); return rget(map, buf) + armshiftval(map, rget, i); } @@ -793,7 +793,7 @@ armfbx(Map *map, Rgetter rget, Instr *i, uvlong pc) if(!armcondpass(map, rget, (i->w>>28)&0xf)) return pc+4; r = (i->w >> 0) & 0xf; - sprint(buf, "R%d", r); + snprint(buf, sizeof buf, "R%d", r); return rget(map, buf); } diff --git a/sys/src/libmach/kdb.c b/sys/src/libmach/kdb.c index 83070d15c9..7871260434 100644 --- a/sys/src/libmach/kdb.c +++ b/sys/src/libmach/kdb.c @@ -56,9 +56,9 @@ excname(ulong tbr) if(tbr < sizeof trapname/sizeof(char*)) return trapname[tbr]; if(tbr >= 130) - sprint(buf, "trap instruction %ld", tbr-128); + snprint(buf, sizeof buf, "trap instruction %ld", tbr-128); else if(17<=tbr && tbr<=31) - sprint(buf, "interrupt level %ld", tbr-16); + snprint(buf, sizeof buf, "interrupt level %ld", tbr-16); else switch(tbr){ case 36: return "cp disabled"; @@ -69,7 +69,7 @@ excname(ulong tbr) case 129: return "breakpoint"; default: - sprint(buf, "unknown trap %ld", tbr); + snprint(buf, sizeof buf, "unknown trap %ld", tbr); } return buf; } @@ -678,7 +678,7 @@ moveinstr(int op3, char *m) s = ""; if((op3&11)==1 || (op3&11)==2) s="U"; - sprint(buf, "MOV%c%s", c, s); + snprint(buf, sizeof buf, "MOV%c%s", c, s); return buf; } return m; @@ -1035,12 +1035,12 @@ sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) } if((w&0xC1F80000) == 0x81C00000){ /* JMPL */ - sprint(buf, "R%ld", (w>>14)&0xF); + snprint(buf, sizeof buf, "R%ld", (w>>14)&0xF); r1 = (*rget)(map, buf); if(w & 0x2000) /* JMPL R1+simm13 */ r2 = i.simm13; else{ /* JMPL R1+R2 */ - sprint(buf, "R%ld", w&0xF); + snprint(buf, sizeof buf, "R%ld", w&0xF); r2 = (*rget)(map, buf); } foll[0] = r1 + r2; diff --git a/sys/src/libmach/map.c b/sys/src/libmach/map.c index 1e1f699866..7bb3e6033c 100644 --- a/sys/src/libmach/map.c +++ b/sys/src/libmach/map.c @@ -93,7 +93,7 @@ attachproc(int pid, int kflag, int corefd, Fhdr *fp) else regs = "regs"; if (mach->regsize) { - sprint(buf, "/proc/%d/%s", pid, regs); + snprint(buf, sizeof buf, "/proc/%d/%s", pid, regs); fd = open(buf, ORDWR); if(fd < 0) fd = open(buf, OREAD); @@ -104,7 +104,7 @@ attachproc(int pid, int kflag, int corefd, Fhdr *fp) setmap(map, fd, 0, mach->regsize, 0, "regs"); } if (mach->fpregsize) { - sprint(buf, "/proc/%d/fpregs", pid); + snprint(buf, sizeof buf, "/proc/%d/fpregs", pid); fd = open(buf, ORDWR); if(fd < 0) fd = open(buf, OREAD); diff --git a/sys/src/libmach/qdb.c b/sys/src/libmach/qdb.c index 257a69bd53..371245f2dd 100644 --- a/sys/src/libmach/qdb.c +++ b/sys/src/libmach/qdb.c @@ -84,7 +84,7 @@ powerexcep(Map *map, Rgetter rget) c = (*rget)(map, "CAUSE") >> 8; if(c < nelem(excname)) return excname[c]; - sprint(buf, "unknown trap #%lx", c); + snprint(buf, sizeof buf, "unknown trap #%lx", c); return buf; } @@ -357,7 +357,7 @@ branch(Opcode *o, Instr *i) if(bo==4 || bo==12 || bo==20) { /* simple forms */ if(bo != 20) { bi = i->bi&3; - sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]); + snprint(buf, sizeof buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]); format(buf, i, nil); bprint(i, "\t"); if(i->bi > 4) diff --git a/sys/src/libmach/sym.c b/sys/src/libmach/sym.c index a5fde8741b..770b0b31ad 100644 --- a/sys/src/libmach/sym.c +++ b/sys/src/libmach/sym.c @@ -1084,7 +1084,7 @@ fline(char *str, int n, long line, Hist *base, Hist **ret) else { k = fileelem(fnames, (uchar*)start->name, str, n); if(k+8 < n) - sprint(str+k, ":%ld", line); + snprint(str+k, n-k, ":%ld", line); } /**********Remove comments for complete back-trace of include sequence * if(start != base) { @@ -1095,7 +1095,7 @@ fline(char *str, int n, long line, Hist *base, Hist **ret) * } * k += fileelem(fnames, (uchar*) base->name, str+k, n-k); * if(k+10 < n) - * sprint(str+k, ":%ld}", start->line-delta); + * snprint(str+k, n-k, ":%ld}", start->line-delta); * } ********************/ return 0; diff --git a/sys/src/libmach/vcodas.c b/sys/src/libmach/vcodas.c index 8a5b2ac6d0..7fa48a9bcd 100644 --- a/sys/src/libmach/vcodas.c +++ b/sys/src/libmach/vcodas.c @@ -412,19 +412,19 @@ copz(int cop, Instr *i) switch (i->rs) { case 0: - sprint(buf, "mfc%d", cop); + snprint(buf, sizeof buf, "mfc%d", cop); break; case 2: - sprint(buf, "cfc%d", cop); + snprint(buf, sizeof buf, "cfc%d", cop); break; case 4: - sprint(buf, "mtc%d", cop); + snprint(buf, sizeof buf, "mtc%d", cop); break; case 6: - sprint(buf, "ctc%d", cop); + snprint(buf, sizeof buf, "ctc%d", cop); break; case 8: @@ -432,30 +432,30 @@ copz(int cop, Instr *i) switch (i->rt) { case 0: - sprint(buf, "bc%df", cop); + snprint(buf, sizeof buf, "bc%df", cop); break; case 1: - sprint(buf, "bc%dt", cop); + snprint(buf, sizeof buf, "bc%dt", cop); break; case 2: - sprint(buf, "bc%dfl", cop); + snprint(buf, sizeof buf, "bc%dfl", cop); break; case 3: - sprint(buf, "bc%dtl", cop); + snprint(buf, sizeof buf, "bc%dtl", cop); break; default: - sprint(buf, "cop%d", cop); + snprint(buf, sizeof buf, "cop%d", cop); f = mipscoxxx; break; } break; default: - sprint(buf, "cop%d", cop); + snprint(buf, sizeof buf, "cop%d", cop); if (i->rs & 0x10) f = "function %c"; else diff --git a/sys/src/libmach/vdb.c b/sys/src/libmach/vdb.c index f4025b50a8..f6a554831d 100644 --- a/sys/src/libmach/vdb.c +++ b/sys/src/libmach/vdb.c @@ -875,19 +875,19 @@ copz(int cop, Instr *i) switch (i->rs) { case 0: - sprint(buf, "mfc%d", cop); + snprint(buf, sizeof buf, "mfc%d", cop); break; case 2: - sprint(buf, "cfc%d", cop); + snprint(buf, sizeof buf, "cfc%d", cop); break; case 4: - sprint(buf, "mtc%d", cop); + snprint(buf, sizeof buf, "mtc%d", cop); break; case 6: - sprint(buf, "ctc%d", cop); + snprint(buf, sizeof buf, "ctc%d", cop); break; case 8: @@ -895,30 +895,30 @@ copz(int cop, Instr *i) switch (i->rt) { case 0: - sprint(buf, "bc%df", cop); + snprint(buf, sizeof buf, "bc%df", cop); break; case 1: - sprint(buf, "bc%dt", cop); + snprint(buf, sizeof buf, "bc%dt", cop); break; case 2: - sprint(buf, "bc%dfl", cop); + snprint(buf, sizeof buf, "bc%dfl", cop); break; case 3: - sprint(buf, "bc%dtl", cop); + snprint(buf, sizeof buf, "bc%dtl", cop); break; default: - sprint(buf, "cop%d", cop); + snprint(buf, sizeof buf, "cop%d", cop); f = mipscoxxx; break; } break; default: - sprint(buf, "cop%d", cop); + snprint(buf, sizeof buf, "cop%d", cop); if (i->rs & 0x10) f = "function %c"; else @@ -1148,7 +1148,7 @@ mipsfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) switch(l){ case 0: /* SPECIAL */ if((w&0x3E) == 0x08){ /* JR, JALR */ - sprint(buf, "R%ld", (w>>21)&0x1F); + snprint(buf, sizeof buf, "R%ld", (w>>21)&0x1F); foll[0] = (*rget)(map, buf); return 1; } From c68723826f7a1027e6d97c69f41362e81d000d31 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:53:45 +0000 Subject: [PATCH 129/402] sys/src/libmemdraw: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libmemdraw/write.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/libmemdraw/write.c b/sys/src/libmemdraw/write.c index a8816ed040..e97fe099f5 100644 --- a/sys/src/libmemdraw/write.c +++ b/sys/src/libmemdraw/write.c @@ -64,7 +64,7 @@ writememimage(int fd, Memimage *i) if(nb != dy*bpl) goto ErrOut; } - sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ", + snprint(hdr, sizeof hdr, "compressed\n%11s %11d %11d %11d %11d ", chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y); if(write(fd, hdr, 11+5*12) != 11+5*12) goto ErrOut; @@ -170,7 +170,7 @@ writememimage(int fd, Memimage *i) if(loutp == outbuf) goto ErrOut; n = loutp-outbuf; - sprint(hdr, "%11d %11ld ", r.max.y, n); + snprint(hdr, sizeof hdr, "%11d %11ld ", r.max.y, n); write(fd, hdr, 2*12); write(fd, outbuf, n); r.min.y = r.max.y; From e19486a7eda79d57ba9e153dae88ff6abc426dd8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:32:28 +0000 Subject: [PATCH 130/402] sys/src/libndb: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libndb/ndbhash.c | 2 +- sys/src/libndb/ndbipinfo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/libndb/ndbhash.c b/sys/src/libndb/ndbhash.c index 94dfd67c71..ef3a155670 100644 --- a/sys/src/libndb/ndbhash.c +++ b/sys/src/libndb/ndbhash.c @@ -86,7 +86,7 @@ hfopen(Ndb *db, char *attr) /* compare it to the database file */ strncpy(hf->attr, attr, sizeof(hf->attr)-1); - sprint(buf, "%s.%s", db->file, hf->attr); + snprint(buf, sizeof buf, "%s.%s", db->file, hf->attr); hf->fd = open(buf, OREAD); if(hf->fd >= 0){ hf->len = 0; diff --git a/sys/src/libndb/ndbipinfo.c b/sys/src/libndb/ndbipinfo.c index f01335543a..ad74ea6022 100644 --- a/sys/src/libndb/ndbipinfo.c +++ b/sys/src/libndb/ndbipinfo.c @@ -127,7 +127,7 @@ subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix) int masklen; t = nil; - sprint(netstr, "%I", net); + snprint(netstr, sizeof netstr, "%I", net); nt = ndbsearch(db, &s, "ip", netstr); while(nt != nil){ xt = ndbfindattr(nt, nt, "ipnet"); From e1d5121f59201c6c22f884117d4dd42ccb21904b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:32:45 +0000 Subject: [PATCH 131/402] sys/src/liboventi: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/liboventi/plan9-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/liboventi/plan9-io.c b/sys/src/liboventi/plan9-io.c index e34a8d3759..756b6f0a8c 100644 --- a/sys/src/liboventi/plan9-io.c +++ b/sys/src/liboventi/plan9-io.c @@ -94,7 +94,7 @@ vtThreadSetName(char *name) int fd; char buf[32]; - sprint(buf, "/proc/%d/args", getpid()); + snprint(buf, sizeof buf, "/proc/%d/args", getpid()); if((fd = open(buf, OWRITE)) >= 0){ write(fd, name, strlen(name)); close(fd); From a8b8ce77eff16d04e085edc96b665c67498d707e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Apr 2021 07:44:40 +0000 Subject: [PATCH 132/402] sys/src/libsec: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libsec/port/tlshand.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/src/libsec/port/tlshand.c b/sys/src/libsec/port/tlshand.c index 2c3cadaadd..2282f8d035 100644 --- a/sys/src/libsec/port/tlshand.c +++ b/sys/src/libsec/port/tlshand.c @@ -358,8 +358,8 @@ tlsServer(int fd, TLSconn *conn) return -1; } buf[n] = 0; - sprint(conn->dir, "#a/tls/%s", buf); - sprint(dname, "#a/tls/%s/hand", buf); + snprint(conn->dir, sizeof conn->dir, "#a/tls/%s", buf); + snprint(dname, sizeof dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0){ close(ctl); @@ -367,7 +367,7 @@ tlsServer(int fd, TLSconn *conn) } fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->trace, conn->chain); - sprint(dname, "#a/tls/%s/data", buf); + snprint(dname, sizeof dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); close(fd); close(hand); @@ -413,14 +413,14 @@ tlsClient(int fd, TLSconn *conn) return -1; } buf[n] = 0; - sprint(conn->dir, "#a/tls/%s", buf); - sprint(dname, "#a/tls/%s/hand", buf); + snprint(conn->dir, sizeof conn->dir, "#a/tls/%s", buf); + snprint(dname, sizeof dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0){ close(ctl); return -1; } - sprint(dname, "#a/tls/%s/data", buf); + snprint(dname, sizeof dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); if(data < 0) { close(hand); From 71e5fe271a7b964f6104eef457177ca374499246 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 22:34:24 +0000 Subject: [PATCH 133/402] sys/src/libthread: replace sprint by snprint (thanks Geoff Collyer) --- sys/src/libthread/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libthread/debug.c b/sys/src/libthread/debug.c index 183869d18e..091fa8280a 100644 --- a/sys/src/libthread/debug.c +++ b/sys/src/libthread/debug.c @@ -42,7 +42,7 @@ _threadassert(char *s) p = _threadgetproc(); if(p && p->thread) - n = sprint(buf, "%d.%d ", p->pid, p->thread->id); + n = snprint(buf, sizeof buf, "%d.%d ", p->pid, p->thread->id); else n = 0; snprint(buf+n, sizeof(buf)-n, "%s: assertion failed\n", s); From 32268cde23542ab1898bf1e521e8c809fdffc6a0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Nov 2016 23:45:49 +0000 Subject: [PATCH 134/402] sys/src/libthread: remove xinc/xdec since they were replaced by ainc/adec (thanks Geoff Collyer) --- sys/src/libthread/xinc386.s | 29 ---------------------- sys/src/libthread/xincamd64.s | 20 --------------- sys/src/libthread/xincarm.c | 1 - sys/src/libthread/xincmips.s | 46 ----------------------------------- sys/src/libthread/xincport.h | 25 ------------------- sys/src/libthread/xincpower.s | 21 ---------------- 6 files changed, 142 deletions(-) delete mode 100644 sys/src/libthread/xinc386.s delete mode 100644 sys/src/libthread/xincamd64.s delete mode 100644 sys/src/libthread/xincarm.c delete mode 100644 sys/src/libthread/xincmips.s delete mode 100644 sys/src/libthread/xincport.h delete mode 100644 sys/src/libthread/xincpower.s diff --git a/sys/src/libthread/xinc386.s b/sys/src/libthread/xinc386.s deleted file mode 100644 index 006c821c91..0000000000 --- a/sys/src/libthread/xinc386.s +++ /dev/null @@ -1,29 +0,0 @@ -/*#define XADDL(s,d) BYTE $0x0F; BYTE $0xC1; BYTE $((0<<6)|(s<<3)|(d))*/ - -/*TEXT xadd(SB),$0 /* long xadd(long *, long); */ - -/* MOVL l+0(FP),BX -/* MOVL i+4(FP),AX -/* LOCK -/* XADDL(0,3) -/* RET -*/ - -TEXT _xinc(SB),$0 /* void _xinc(long *); */ - - MOVL l+0(FP),AX - LOCK - INCL 0(AX) - RET - -TEXT _xdec(SB),$0 /* long _xdec(long *); */ - - MOVL l+0(FP),AX - LOCK - DECL 0(AX) - JZ iszero - MOVL $1, AX - RET -iszero: - MOVL $0, AX - RET diff --git a/sys/src/libthread/xincamd64.s b/sys/src/libthread/xincamd64.s deleted file mode 100644 index ed1c814190..0000000000 --- a/sys/src/libthread/xincamd64.s +++ /dev/null @@ -1,20 +0,0 @@ -/*TEXT xadd(SB),$0 /* long xadd(long *, long); */ - -/* MOVL i+8(FP),AX -/* LOCK -/* XADDL AX, (RARG) -/* RET -*/ - -TEXT _xinc(SB),$0 /* void _xinc(long *); */ - - LOCK; INCL 0(RARG) - RET - -TEXT _xdec(SB),$0 /* long _xdec(long *); */ - - MOVL $0, AX - MOVL $1, BX - LOCK; DECL 0(RARG) - CMOVLNE BX, AX - RET diff --git a/sys/src/libthread/xincarm.c b/sys/src/libthread/xincarm.c deleted file mode 100644 index a8e0929142..0000000000 --- a/sys/src/libthread/xincarm.c +++ /dev/null @@ -1 +0,0 @@ -#include "xincport.h" diff --git a/sys/src/libthread/xincmips.s b/sys/src/libthread/xincmips.s deleted file mode 100644 index 8e53c1adfa..0000000000 --- a/sys/src/libthread/xincmips.s +++ /dev/null @@ -1,46 +0,0 @@ -/* - * R4000 user level lock code - */ - -#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16)) -#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16)) -#define NOOP WORD $0x27 - -#ifdef oldstyle -TEXT xadd(SB), $0 - - MOVW R1, R2 /* address of counter */ -loop: MOVW n+4(FP), R3 /* increment */ - LL(2, 1) - NOOP - ADD R1,R3,R3 - SC(2, 3) - NOOP - BEQ R3,loop - RET -#endif - -TEXT _xinc(SB), $0 - - MOVW R1, R2 /* address of counter */ -loop: MOVW $1, R3 - LL(2, 1) - NOOP - ADD R1,R3,R3 - SC(2, 3) - NOOP - BEQ R3,loop - RET - -TEXT _xdec(SB), $0 - - MOVW R1, R2 /* address of counter */ -loop1: MOVW $-1, R3 - LL(2, 1) - NOOP - ADD R1,R3,R3 - MOVW R3, R1 - SC(2, 3) - NOOP - BEQ R3,loop1 - RET diff --git a/sys/src/libthread/xincport.h b/sys/src/libthread/xincport.h deleted file mode 100644 index d5d8fe3238..0000000000 --- a/sys/src/libthread/xincport.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -static Lock l; - -void -_xinc(long *p) -{ - - lock(&l); - (*p)++; - unlock(&l); -} - -long -_xdec(long *p) -{ - long r; - - lock(&l); - r = --(*p); - unlock(&l); - return r; -} diff --git a/sys/src/libthread/xincpower.s b/sys/src/libthread/xincpower.s deleted file mode 100644 index 66bff2e39c..0000000000 --- a/sys/src/libthread/xincpower.s +++ /dev/null @@ -1,21 +0,0 @@ -TEXT _xinc(SB),$0 /* void _xinc(long *); */ - - MOVW R3, R4 -xincloop: - LWAR (R4), R3 - ADD $1, R3 - DCBT (R4) /* fix 405 errata cpu_210 */ - STWCCC R3, (R4) - BNE xincloop - RETURN - -TEXT _xdec(SB),$0 /* long _xdec(long *); */ - - MOVW R3, R4 -xdecloop: - LWAR (R4), R3 - ADD $-1, R3 - DCBT (R4) /* fix 405 errata cpu_210 */ - STWCCC R3, (R4) - BNE xdecloop - RETURN From 42e95831a4c71d32747f57a1765d381b814f1812 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Nov 2016 23:24:06 +0000 Subject: [PATCH 135/402] sys/src/cmd/ip/snoopy: fix timestamp in PCAP format --- sys/src/cmd/ip/snoopy/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/src/cmd/ip/snoopy/main.c b/sys/src/cmd/ip/snoopy/main.c index bccda83505..aede215007 100644 --- a/sys/src/cmd/ip/snoopy/main.c +++ b/sys/src/cmd/ip/snoopy/main.c @@ -286,9 +286,10 @@ struct pcap_file_header { }; struct pcap_pkthdr { - uvlong ts; /* time stamp */ - ulong caplen; /* length of portion present */ - ulong len; /* length this packet (off wire) */ + ulong ts_sec; /* time stamp seconds */ + ulong ts_µsec; /* time stamp microseconds */ + ulong caplen; /* length of portion present */ + ulong len; /* length this packet (off wire) */ }; /* @@ -323,7 +324,8 @@ tracepkt(uchar *ps, int len) len = Mflag; if(pcap){ goo = (struct pcap_pkthdr*)(ps-16); - goo->ts = pkttime; + goo->ts_sec = (uvlong)pkttime / 1000000000; + goo->ts_µsec = ((uvlong)pkttime % 1000000000) / 1000; goo->caplen = len; goo->len = len; write(1, goo, len+16); From 6e9e081fb7f2cff7240555aeda3624c4d9cd8247 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 2 Feb 2016 12:04:37 +0000 Subject: [PATCH 136/402] sys/src/cmd/ip/ipconfig: fix comparison of IPv6 addresses in the ARP cache --- sys/src/cmd/ip/ipconfig/ipv6.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/ip/ipconfig/ipv6.c b/sys/src/cmd/ip/ipconfig/ipv6.c index 614f2b32ee..c8a0004029 100644 --- a/sys/src/cmd/ip/ipconfig/ipv6.c +++ b/sys/src/cmd/ip/ipconfig/ipv6.c @@ -385,8 +385,8 @@ dialicmp(uchar *dst, int dport, int *ctlfd) int ip6cfg(int autoconf) { - int dupfound = 0, n; - char *p; + int dupfound = 0, n, nf; + char *p, *fields[4]; char buf[256]; uchar ethaddr[6]; Biobuf *bp; @@ -433,7 +433,8 @@ ip6cfg(int autoconf) snprint(buf, sizeof buf, "%I", conf.laddr); while(p = Brdline(bp, '\n')){ p[Blinelen(bp)-1] = 0; - if(cistrstr(p, buf) != 0) { + nf = tokenize(p, fields, nelem(fields)); + if(nf >= 4 && cistrcmp(fields[2], buf) == 0) { warning("found dup entry in arp cache"); dupfound = 1; break; From ad1a519d14b1c33fd6a6315601e9bf6455f0757c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 15 Apr 2016 20:26:21 +0000 Subject: [PATCH 137/402] sys/src/cmd/ip/ipconfig: handle MTU parameter --- sys/src/cmd/ip/ipconfig/main.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/ip/ipconfig/main.c b/sys/src/cmd/ip/ipconfig/main.c index f308e4c23c..249e0622c3 100644 --- a/sys/src/cmd/ip/ipconfig/main.c +++ b/sys/src/cmd/ip/ipconfig/main.c @@ -36,6 +36,7 @@ enum Taddrs, Tstr, Tbyte, + Tushort, Tulong, Tvec, }; @@ -79,7 +80,7 @@ Option option[256] = [OBttl] { "ttl", Tulong }, [OBpathtimeout] { "pathtimeout", Taddrs }, [OBpathplateau] { "pathplateau", Taddrs }, -[OBmtu] { "mtu", Tulong }, +[OBmtu] { "mtu", Tushort }, [OBsubnetslocal] { "subnetslocal", Taddrs }, [OBbaddr] { "baddr", Taddrs }, [OBdiscovermask] { "discovermask", Taddrs }, @@ -208,6 +209,7 @@ int optgetaddr(uchar*, int, uchar*); int optgetbyte(uchar*, int); int optgetstr(uchar*, int, char*, int); uchar* optget(uchar*, int, int*); +ushort optgetushort(uchar*, int); ulong optgetulong(uchar*, int); int optgetvec(uchar*, int, uchar*, int); char* optgetx(uchar*, uchar); @@ -842,6 +844,15 @@ ip4cfg(void) return -1; } + if(!validip(conf.raddr) && conf.mtu != 0){ + n = snprint(buf, sizeof buf, " mtu %d", conf.mtu); + + if(write(conf.cfd, buf, n) < 0){ + warning("write(%s): %r", buf); + return -1; + } + } + if(beprimary==1 && validip(conf.gaddr)) adddefroute(conf.mpoint, conf.gaddr); @@ -1263,6 +1274,14 @@ dhcprecv(void) optgetstr(bp->optdata, OBdomainname, conf.domainname, sizeof conf.domainname); + /* get mtu */ + if(conf.mtu == 0){ + conf.mtu = optgetushort(bp->optdata, OBmtu); + if(conf.mtu != 0) + conf.mtu += 14; /* size of ethernet header */ + DEBUG("mtu=%d ", conf.mtu); + } + /* get anything else we asked for */ getoptions(bp->optdata); @@ -1461,6 +1480,18 @@ optgetbyte(uchar *p, int op) return *p; } +ushort +optgetushort(uchar *p, int op) +{ + int len; + + len = 2; + p = optget(p, op, &len); + if(p == nil) + return 0; + return nhgets(p); +} + ulong optgetulong(uchar *p, int op) { From 43f24d6769a64e5ab6670dba895ce8004c53719c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 18 Feb 2016 11:10:00 +0000 Subject: [PATCH 138/402] sys/src/cmd/ndb: fix leak in cs (thanks Charles Forsyth) --- sys/src/cmd/ndb/cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/ndb/cs.c b/sys/src/cmd/ndb/cs.c index 44b6e0186c..4b1cca9fda 100644 --- a/sys/src/cmd/ndb/cs.c +++ b/sys/src/cmd/ndb/cs.c @@ -1197,7 +1197,8 @@ lookup(Mfile *mf) mf->replylen[mf->nreply] = strlen(cp); mf->reply[mf->nreply++] = cp; rv++; - } + }else + free(cp); } } ndbfree(nt); From 8508ce78438990ca720cf13c401d36f90c649127 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 21 Oct 2020 09:21:38 +0000 Subject: [PATCH 139/402] sys/src/cmd/ip/ipconfig: handle DHCP Classless Static Routes option (RFC 3442) (thanks Kyohei Kadota) --- sys/src/cmd/ip/dhcp.h | 2 + sys/src/cmd/ip/ipconfig/ipconfig.h | 1 + sys/src/cmd/ip/ipconfig/main.c | 76 ++++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/sys/src/cmd/ip/dhcp.h b/sys/src/cmd/ip/dhcp.h index 3e739dade8..20978d66e2 100644 --- a/sys/src/cmd/ip/dhcp.h +++ b/sys/src/cmd/ip/dhcp.h @@ -115,6 +115,8 @@ enum ODpxeni= 94, ODpxeguid= 97, + ODcstaticroutes= 121, /* see rfc 3442 */ + /* plan9 vendor info options, v4 addresses only (deprecated) */ OP9fsv4= 128, /* plan9 file servers */ OP9authv4= 129, /* plan9 auth servers */ diff --git a/sys/src/cmd/ip/ipconfig/ipconfig.h b/sys/src/cmd/ip/ipconfig/ipconfig.h index 5eef7902a3..440e192d68 100644 --- a/sys/src/cmd/ip/ipconfig/ipconfig.h +++ b/sys/src/cmd/ip/ipconfig/ipconfig.h @@ -26,6 +26,7 @@ struct Conf uchar fs[2*IPaddrlen]; uchar auth[2*IPaddrlen]; uchar ntp[IPaddrlen]; + uchar iproutes[6*IPaddrlen]; /* mask, network, gateway */ int mtu; /* dhcp specific */ diff --git a/sys/src/cmd/ip/ipconfig/main.c b/sys/src/cmd/ip/ipconfig/main.c index 249e0622c3..da4bdf1fac 100644 --- a/sys/src/cmd/ip/ipconfig/main.c +++ b/sys/src/cmd/ip/ipconfig/main.c @@ -39,6 +39,7 @@ enum Tushort, Tulong, Tvec, + Tshortaddrs, }; typedef struct Option Option; @@ -129,6 +130,7 @@ Option option[256] = [ODclientid] { "clientid", Tvec }, [ODtftpserver] { "tftp", Taddr }, [ODbootfile] { "bootfile", Tstr }, +[ODcstaticroutes] { "staticroutes", Tshortaddrs }, }; uchar defrequested[] = { @@ -176,6 +178,7 @@ char *verbs[] = { }; void adddefroute(char*, uchar*); +void addroute(char*, char*, char*, char*); int addoption(char*); void binddevice(void); void bootprequest(void); @@ -204,6 +207,7 @@ uchar* optadd(uchar*, int, void*, int); uchar* optaddulong(uchar*, int, ulong); uchar* optaddvec(uchar*, int, uchar*, int); int optgetaddrs(uchar*, int, uchar*, int); +int optgetshortaddrs(uchar*, int, uchar*, int); int optgetp9addrs(uchar*, int, uchar*, int); int optgetaddr(uchar*, int, uchar*); int optgetbyte(uchar*, int); @@ -716,6 +720,18 @@ dounbind(void) /* set the default route */ void adddefroute(char *mpoint, uchar *gaddr) +{ + char buf[40]; + + snprint(buf, sizeof buf, "%I", gaddr); + if(isv4(gaddr)) + addroute(mpoint, "0", "0", buf); + else + addroute(mpoint, "::", "/0", buf); +} + +void +addroute(char *mpoint, char *addr, char *mask, char *gaddr) { char buf[256]; int cfd; @@ -725,10 +741,7 @@ adddefroute(char *mpoint, uchar *gaddr) if(cfd < 0) return; - if(isv4(gaddr)) - fprint(cfd, "add 0 0 %I", gaddr); - else - fprint(cfd, "add :: /0 %I", gaddr); + fprint(cfd, "add %s %s %s", addr, mask, gaddr); close(cfd); } @@ -822,6 +835,8 @@ ip4cfg(void) { char buf[256]; int n; + uchar *p, *e; + char addr[16], mask[16], gaddr[16]; if(!validip(conf.laddr)) return -1; @@ -853,6 +868,15 @@ ip4cfg(void) } } + e = conf.iproutes + sizeof conf.iproutes; + for(p = conf.iproutes; p < e; p += IPaddrlen*3){ + if(ipcmp(p, IPnoaddr) == 0) + break; + snprint(addr, sizeof addr, "%I", p+IPaddrlen); + snprint(mask, sizeof mask, "%M", p); + snprint(gaddr, sizeof gaddr, "%I", p+IPaddrlen*2); + addroute(conf.mpoint, addr, mask, gaddr); + } if(beprimary==1 && validip(conf.gaddr)) adddefroute(conf.mpoint, conf.gaddr); @@ -1285,6 +1309,11 @@ dhcprecv(void) /* get anything else we asked for */ getoptions(bp->optdata); + /* get static routes */ + n = optgetshortaddrs(bp->optdata, ODcstaticroutes, conf.iproutes, 6); + for(i = 0; i < n; i++) + DEBUG("iproutes=%I ", conf.iproutes + i*IPaddrlen); + /* get plan9-specific options */ n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1); if(n > 0 && parseoptions(vopts, n) == 0){ @@ -1535,6 +1564,39 @@ optgetaddrs(uchar *p, int op, uchar *ip, int n) return i; } +int +optgetshortaddrs(uchar *p, int op, uchar *ip, int n) +{ + int len, i, l; + uchar buf[IPv4addrlen]; + char mask[5]; + + len = 5; + p = optget(p, op, &len); + if(p == nil) + return 0; + n /= 3; + for(i = 0; i < n; i++){ + l = (*p+7) / 8; + snprint(mask, sizeof mask, "/%d", 96 + *p++); + parseipmask(ip, mask); + ip += IPaddrlen; + + memset(buf, 0, sizeof buf); + memmove(buf, p, l); + v4tov6(ip, buf); + ip += IPaddrlen; + p += l; + + v4tov6(ip, p); + ip += IPaddrlen; + p += IPv4addrlen; + } + if(i > n) + i = n; + return i * 3; +} + /* expect at most n addresses; ip[] only has room for that many */ int optgetp9addrs(uchar *ap, int op, uchar *ip, int n) @@ -1930,7 +1992,11 @@ optgetx(uchar *p, uchar opt) s = smprint("%s=%I", o->name, ip); break; case Taddrs: - n = optgetaddrs(p, opt, ips, 16); + case Tshortaddrs: + if(o->type == Taddrs) + n = optgetaddrs(p, opt, ips, 16); + else + n = optgetshortaddrs(p, opt, ips, 16); if(n > 0) s = smprint("%s=%I", o->name, ips); for(i = 1; i < n; i++){ From 224c4cf3bb3d84eae6f0726c1c9350631a19c5bb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 19:36:03 +0000 Subject: [PATCH 140/402] sys/src/cmd: various fixes for ramfs (thanks Richard Miller) --- sys/src/cmd/ramfs.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/sys/src/cmd/ramfs.c b/sys/src/cmd/ramfs.c index 1a7dde4b3a..f021c4f9ef 100644 --- a/sys/src/cmd/ramfs.c +++ b/sys/src/cmd/ramfs.c @@ -13,7 +13,7 @@ enum { OPERM = 0x3, /* mask of all permission types in open mode */ - Nram = 4096, + Nram = 1024, Maxsize = 768*1024*1024, Maxfdata = 8192, Maxulong= (1ULL << 32) - 1, @@ -62,7 +62,8 @@ enum ulong path; /* incremented for each new file */ Fid *fids; -Ram ram[Nram]; +Ram *ram; +int maxnram = Nram; int nram; int mfd[2]; char *user; @@ -82,6 +83,7 @@ void *emalloc(ulong); char *estrdup(char*); void usage(void); int perm(Fid*, Ram*, int); +Ram *ramexpand(Ram*); char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*), *rattach(Fid*), *rwalk(Fid*), @@ -209,6 +211,7 @@ main(int argc, char *argv[]) user = getuser(); notify(notifyf); + ram = emalloc(maxnram*sizeof(Ram)); nram = 1; r = &ram[0]; r->busy = 1; @@ -459,7 +462,7 @@ rcreate(Fid *f) if(strcmp((char*)name, r->name)==0) return Einuse; for(r=ram; r->busy; r++) - if(r == &ram[Nram-1]) + if(r == &ram[maxnram-1] && (r = ramexpand(r)) == nil) return "no free ram resources"; r->busy = 1; r->qid.path = ++path; @@ -637,6 +640,8 @@ rremove(Fid *f) f->open = 0; r = f->ram; f->ram = 0; + if(r->busy == 0) + return Enotexist; if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite)) return Eperm; ram[r->parent].mtime = time(0); @@ -686,10 +691,11 @@ rwstat(Fid *f) } /* - * To change mode, must be owner or group leader. + * To change mode or mtime, must be owner or group leader. * Because of lack of users file, leader=>group itself. */ - if(dir.mode!=~0 && r->perm!=dir.mode){ + if(dir.mode!=~0 && r->perm!=dir.mode || + dir.mtime!=~0 && dir.mtime!=r->mtime){ if(strcmp(f->user, r->user) != 0) if(strcmp(f->user, r->group) != 0) return Enotowner; @@ -717,6 +723,8 @@ rwstat(Fid *f) dir.mode |= r->perm&DMDIR; r->perm = dir.mode; } + if(dir.mtime != ~0) + r->mtime = dir.mtime; if(dir.name[0] != '\0'){ free(r->name); r->name = estrdup(dir.name); @@ -857,6 +865,26 @@ perm(Fid *f, Ram *r, int p) return 0; } +Ram* +ramexpand(Ram *r) +{ + Ram *newram; + Fid *f; + uintptr offs; + + newram = (Ram*)realloc(ram, (maxnram+Nram)*sizeof(Ram)); + if(newram == nil) + return nil; + memset(newram + maxnram, 0, Nram*sizeof(Ram)); + offs = (uintptr)newram - (uintptr)ram; + for(f = fids; f; f = f->next) + if(f->busy && f->ram != nil) + f->ram = (Ram*)((uintptr)f->ram + offs); + maxnram += Nram; + ram = newram; + return (Ram*)((uintptr)r + offs); +} + void error(char *s) { @@ -880,7 +908,7 @@ void * erealloc(void *p, ulong n) { p = realloc(p, n); - if(!p) + if(n != 0 && !p) error("out of memory"); return p; } From d542aa2b155bafceb064d53675db0adf2c661223 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 12 Nov 2016 00:12:29 +0000 Subject: [PATCH 141/402] sys/src/cmd: update qid.vers on wstat in ramfs --- sys/src/cmd/ramfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/src/cmd/ramfs.c b/sys/src/cmd/ramfs.c index f021c4f9ef..da167ea331 100644 --- a/sys/src/cmd/ramfs.c +++ b/sys/src/cmd/ramfs.c @@ -736,6 +736,7 @@ rwstat(Fid *f) if(r->ndata < dir.length) memset(r->data+r->ndata, 0, dir.length-r->ndata); r->ndata = dir.length; + r->qid.vers++; } ram[r->parent].mtime = time(0); return 0; From 81cd647ab6f364b3f472326c845b6b671dada5bb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 30 Nov 2018 18:29:24 +0000 Subject: [PATCH 142/402] sys/src/cmd: fix initial value of open fds during create in ramfs --- sys/src/cmd/ramfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/ramfs.c b/sys/src/cmd/ramfs.c index da167ea331..2aaf72cacc 100644 --- a/sys/src/cmd/ramfs.c +++ b/sys/src/cmd/ramfs.c @@ -492,7 +492,7 @@ rcreate(Fid *f) f->open = 1; if(thdr.mode & ORCLOSE) f->rclose = 1; - r->open++; + r->open = 1; return 0; } From 1fa245b8a58b437c627e4a1470976cdb98758e24 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 8 Aug 2022 14:09:45 +0000 Subject: [PATCH 143/402] sys/src/cmd: add reference counting to the Ram structure in ramfs (thanks Richard Miller) --- sys/src/cmd/ramfs.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sys/src/cmd/ramfs.c b/sys/src/cmd/ramfs.c index 2aaf72cacc..2fc96ca03d 100644 --- a/sys/src/cmd/ramfs.c +++ b/sys/src/cmd/ramfs.c @@ -35,6 +35,7 @@ struct Fid struct Ram { + long ref; short busy; short open; long parent; /* index in Ram array */ @@ -287,6 +288,7 @@ rattach(Fid *f) f->busy = 1; f->rclose = 0; f->ram = &ram[0]; + f->ram->ref++; rhdr.qid = f->ram->qid; if(thdr.uname[0]) f->user = estrdup(thdr.uname); @@ -379,8 +381,12 @@ rwalk(Fid *f) } if(rhdr.nwqid > 0) err = nil; /* didn't get everything in 9P2000 right! */ - if(rhdr.nwqid == thdr.nwname) /* update the fid after a successful walk */ + if(rhdr.nwqid == thdr.nwname){ /* update the fid after a successful walk */ + if(nf == nil) + f->ram->ref--; f->ram = fram; + f->ram->ref++; + } return err; } @@ -461,10 +467,11 @@ rcreate(Fid *f) if(r->busy && parent==r->parent) if(strcmp((char*)name, r->name)==0) return Einuse; - for(r=ram; r->busy; r++) + for(r=ram; r->busy || r->ref; r++) if(r == &ram[maxnram-1] && (r = ramexpand(r)) == nil) return "no free ram resources"; r->busy = 1; + r->ref = 1; r->qid.path = ++path; r->qid.vers = 0; if(prm & DMDIR) @@ -625,6 +632,7 @@ rclunk(Fid *f) e = realremove(f->ram); f->busy = 0; f->open = 0; + f->ram->ref--; f->ram = 0; return e; } @@ -639,6 +647,7 @@ rremove(Fid *f) f->busy = 0; f->open = 0; r = f->ram; + f->ram->ref--; f->ram = 0; if(r->busy == 0) return Enotexist; From 2539e9d9011e04fb96a4602e70670d625f141c10 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 06:09:45 +0000 Subject: [PATCH 144/402] sys/src/cmd/cpu.c: ensure secrets are at least 8 bytes (thanks Charles Forsyth) --- sys/src/cmd/cpu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index 0d256c4078..f120d133fb 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -592,7 +592,11 @@ p9auth(int fd) ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec); if(ai == nil) return -1; - memmove(key+4, ai->secret, ai->nsecret); + if(ai->nsecret < 8){ + werrstr("negotiated secret too short"); + return -1; + } + memmove(key+4, ai->secret, 8); if(ealgs == nil) return fd; @@ -663,7 +667,11 @@ srvp9auth(int fd, char *user) if(auth_chuid(ai, nil) < 0) return -1; strecpy(user, user+MaxStr, ai->cuid); - memmove(key+4, ai->secret, ai->nsecret); + if(ai->nsecret < 8){ + werrstr("negotiated secret too short"); + return -1; + } + memmove(key+4, ai->secret, 8); if(ealgs == nil) return fd; From 4a18143c6834247e4c4df85903bf98aa18f00040 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 06:10:47 +0000 Subject: [PATCH 145/402] sys/src/cmd/cpu.c: remove support for the pre-9P2000 version of the cpu protocol (thanks Charles Forsyth) --- sys/man/1/cpu | 8 ------- sys/src/cmd/cpu.c | 53 +++-------------------------------------------- 2 files changed, 3 insertions(+), 58 deletions(-) diff --git a/sys/man/1/cpu b/sys/man/1/cpu index e408683bcb..7c154b25a0 100644 --- a/sys/man/1/cpu +++ b/sys/man/1/cpu @@ -29,8 +29,6 @@ cpu \- connection to CPU server .B cpu [ .B -R -| -.B -O ] .SH DESCRIPTION .I Cpu @@ -170,12 +168,6 @@ flag causes to run the server (remote) side of the protocol. It is run from service files such as .BR /bin/service/tcp17010 . -The -.B -O -flag is similar but simulates the pre-9P2000 version -of the -.I cpu -protocol. .SH FILES The name space of the terminal side of the .I cpu diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index f120d133fb..bc834f68fa 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -15,7 +15,7 @@ #define Maxfdata 8192 #define MaxStr 128 -void remoteside(int); +void remoteside(void); void fatal(int, char*, ...); void lclnoteproc(int); void rmtnoteproc(void); @@ -171,12 +171,8 @@ main(int argc, char **argv) case 'f': /* ignored but accepted for compatibility */ break; - case 'O': - p9authproto = "p9sk2"; - remoteside(1); /* From listen */ - break; case 'R': /* From listen */ - remoteside(0); + remoteside(); break; case 'h': system = EARGF(usage()); @@ -285,49 +281,9 @@ fatal(int syserr, char *fmt, ...) char *negstr = "negotiating authentication method"; -char bug[256]; - -int -old9p(int fd) -{ - int p[2]; - - if(pipe(p) < 0) - fatal(1, "pipe"); - - switch(rfork(RFPROC|RFFDG|RFNAMEG)) { - case -1: - fatal(1, "rfork srvold9p"); - case 0: - if(fd != 1){ - dup(fd, 1); - close(fd); - } - if(p[0] != 0){ - dup(p[0], 0); - close(p[0]); - } - close(p[1]); - if(0){ - fd = open("/sys/log/cpu", OWRITE); - if(fd != 2){ - dup(fd, 2); - close(fd); - } - execl("/bin/srvold9p", "srvold9p", "-ds", nil); - } else - execl("/bin/srvold9p", "srvold9p", "-s", nil); - fatal(1, "exec srvold9p"); - default: - close(fd); - close(p[0]); - } - return p[1]; -} - /* Invoked with stdin, stdout and stderr connected to the network connection */ void -remoteside(int old) +remoteside(void) { char user[MaxStr], home[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr]; int i, n, fd, badchdir, gotcmd; @@ -384,9 +340,6 @@ remoteside(int old) if(n != 2 || buf[0] != 'O' || buf[1] != 'K') exits("remote tree"); - if(old) - fd = old9p(fd); - /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */ strcpy(buf, VERSION9P); if(fversion(fd, 64*1024, buf, sizeof buf) < 0) From 5194e28a66b1dfae7e76eb21d960aee91a21d0ef Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 28 Feb 2016 06:15:18 +0000 Subject: [PATCH 146/402] sys/src/cmd/exportfs: import improvements to exportfs (thanks Charles Forsyth) --- sys/src/cmd/exportfs/exportfs.c | 433 ++++++++++++++++--------------- sys/src/cmd/exportfs/exportfs.h | 18 +- sys/src/cmd/exportfs/exportsrv.c | 351 +++++++++++++------------ sys/src/cmd/exportfs/pattern.c | 14 +- 4 files changed, 416 insertions(+), 400 deletions(-) diff --git a/sys/src/cmd/exportfs/exportfs.c b/sys/src/cmd/exportfs/exportfs.c index 7f337d8ed3..8190f64b3e 100644 --- a/sys/src/cmd/exportfs/exportfs.c +++ b/sys/src/cmd/exportfs/exportfs.c @@ -42,7 +42,6 @@ int qidcnt; int qfreecnt; int ncollision; -int netfd; /* initially stdin */ int srvfd = -1; int nonone = 1; char *filterp; @@ -51,13 +50,13 @@ char *aanfilter = "/bin/aan"; int encproto = Encnone; int readonly; -static void mksecret(char *, uchar *); -static int localread9pmsg(int, void *, uint, ulong *); +static void mksecret(char *, uchar *); +static int localread9pmsg(int, void *, uint, void *); static char *anstring = "tcp!*!0"; char *netdir = "", *local = "", *remote = ""; -int filter(int, char *); +void filter(int, char *, char *); void usage(void) @@ -74,23 +73,22 @@ noteconn(int fd) NetConnInfo *nci; nci = getnetconninfo(nil, fd); - if (nci == nil) + if(nci == nil) return; - netdir = strdup(nci->dir); - local = strdup(nci->lsys); - remote = strdup(nci->rsys); + netdir = estrdup(nci->dir); + local = estrdup(nci->lsys); + remote = estrdup(nci->rsys); freenetconninfo(nci); } void main(int argc, char **argv) { - char buf[ERRMAX], ebuf[ERRMAX], *srvfdfile; - Fsrpc *r; - int doauth, n, fd; + char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; char *dbfile, *srv, *na, *nsfile, *keyspec; + int doauth, n, fd; AuthInfo *ai; - ulong initial; + Fsrpc *r; dbfile = "/tmp/exportdb"; srv = nil; @@ -166,7 +164,7 @@ main(int argc, char **argv) break; case 'S': - if(srvfdfile) + if(srvfdfile != nil) usage(); srvfdfile = EARGF(usage()); break; @@ -176,7 +174,7 @@ main(int argc, char **argv) }ARGEND USED(argc, argv); - if(doauth){ + if(na == nil && doauth){ /* * We use p9any so we don't have to visit this code again, with the * cost that this code is incompatible with the old world, which @@ -193,23 +191,23 @@ main(int argc, char **argv) putenv("service", "exportfs"); } - if(srvfdfile){ + if(srvfdfile != nil){ if((srvfd = open(srvfdfile, ORDWR)) < 0) - sysfatal("open '%s': %r", srvfdfile); + fatal("open %s: %r", srvfdfile); } - if(na){ + if(na != nil){ if(srv == nil) - sysfatal("-B requires -s"); + fatal("-B requires -s"); local = "me"; remote = na; if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) - sysfatal("can't dial %s: %r", na); + fatal("can't dial %s: %r", na); ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); if(ai == nil) - sysfatal("%r: %s", na); + fatal("%r: %s", na); dup(fd, 0); dup(fd, 1); @@ -224,24 +222,20 @@ main(int argc, char **argv) close(n); } - if(srvfd >= 0 && srv){ + if(srvfd >= 0 && srv != nil){ fprint(2, "exportfs: -S cannot be used with -r or -s\n"); usage(); } DEBUG(DFD, "exportfs: started\n"); - rfork(RFNOTEG); + rfork(RFNOTEG|RFREND); if(messagesize == 0){ - messagesize = iounit(netfd); + messagesize = iounit(0); if(messagesize == 0) messagesize = 8192+IOHDRSZ; } - - Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); -// for(i=0; i= buf + sizeof(buf)) + fatal("import parameters too long"); } - if (tokenize(buf, args, nelem(args)) != 2) - fatal("impo arguments invalid: impo%s...\n", buf); + if(tokenize(buf, args, nelem(args)) != 2) + fatal("impo arguments invalid: impo%s...", buf); - if (strcmp(args[0], "aan") == 0) + if(strcmp(args[0], "aan") == 0) filterp = aanfilter; - else if (strcmp(args[0], "nofilter") != 0) - fatal("import filter argument unsupported: %s\n", args[0]); + else if(strcmp(args[0], "nofilter") != 0) + fatal("import filter argument unsupported: %s", args[0]); - if (strcmp(args[1], "ssl") == 0) + if(strcmp(args[1], "ssl") == 0) encproto = Encssl; - else if (strcmp(args[1], "tls") == 0) + else if(strcmp(args[1], "tls") == 0) encproto = Enctls; - else if (strcmp(args[1], "clear") != 0) - fatal("import encryption proto unsupported: %s\n", args[1]); + else if(strcmp(args[1], "clear") != 0) + fatal("import encryption proto unsupported: %s", args[1]); - if (encproto == Enctls) - sysfatal("%s: tls has not yet been implemented", argv[0]); + if(encproto == Enctls) + fatal("%s: tls has not yet been implemented", argv[0]); } - if (encproto != Encnone && ealgs && ai) { - uchar key[16]; - uchar digest[SHA1dlen]; + if(encproto != Encnone && ealgs != nil && ai != nil) { + uchar key[16], digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; - memmove(key+4, ai->secret, ai->nsecret); + if(ai->nsecret < 8) + fatal("secret too small for ssl"); + memmove(key+4, ai->secret, 8); /* exchange random numbers */ srand(truerand()); for(i = 0; i < 4; i++) key[i+12] = rand(); - if (initial) - fatal("Protocol botch: old import\n"); - if(readn(netfd, key, 4) != 4) - fatal("can't read key part; %r\n"); + if(ini != nil) + fatal("Protocol botch: old import"); + if(readn(0, key, 4) != 4) + fatal("can't read key part; %r"); - if(write(netfd, key+12, 4) != 4) - fatal("can't write key part; %r\n"); + if(write(0, key+12, 4) != 4) + fatal("can't write key part; %r"); /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); - if (filterp) - netfd = filter(netfd, filterp); + if(filterp != nil) + filter(0, filterp, na); - switch (encproto) { + switch(encproto) { case Encssl: - netfd = pushssl(netfd, ealgs, fromserversecret, - fromclientsecret, nil); + fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); + if(fd < 0) + fatal("can't establish ssl connection: %r"); + if(fd != 0){ + dup(fd, 0); + close(fd); + } break; case Enctls: default: - fatal("Unsupported encryption protocol\n"); + fatal("Unsupported encryption protocol"); } - - if(netfd < 0) - fatal("can't establish ssl connection: %r"); } - else if (filterp) { - if (initial) - fatal("Protocol botch: don't know how to deal with this\n"); - netfd = filter(netfd, filterp); + else if(filterp != nil) { + if(ini != nil) + fatal("Protocol botch: don't know how to deal with this"); + filter(0, filterp, na); } + dup(0, 1); + + if(ai != nil) + auth_freeAI(ai); /* * Start serving file requests from the network */ for(;;) { r = getsbuf(); - if(r == 0) - fatal("Out of service buffers"); - - n = localread9pmsg(netfd, r->buf, messagesize, &initial); - if(n <= 0) + while((n = localread9pmsg(0, r->buf, messagesize, ini)) == 0) + ; + if(n < 0) fatal(nil); - if(convM2S(r->buf, n, &r->work) == 0) fatal("convM2S format error"); DEBUG(DFD, "%F\n", &r->work); (fcalls[r->work.type])(r); + ini = nil; } } @@ -407,7 +408,7 @@ main(int argc, char **argv) * cpu relies on this (which needs to be fixed!) -- pb. */ static int -localread9pmsg(int fd, void *abuf, uint n, ulong *initial) +localread9pmsg(int fd, void *abuf, uint n, void *ini) { int m, len; uchar *buf; @@ -415,11 +416,8 @@ localread9pmsg(int fd, void *abuf, uint n, ulong *initial) buf = abuf; /* read count */ - assert(BIT32SZ == sizeof(ulong)); - if (*initial) { - memcpy(buf, initial, BIT32SZ); - *initial = 0; - } + if(ini != nil) + memcpy(buf, ini, BIT32SZ); else { m = readn(fd, buf, BIT32SZ); if(m != BIT32SZ){ @@ -448,7 +446,7 @@ reply(Fcall *r, Fcall *t, char *err) t->tag = r->tag; t->fid = r->fid; - if(err) { + if(err != nil) { t->type = Rerror; t->ename = err; } @@ -461,10 +459,10 @@ reply(Fcall *r, Fcall *t, char *err) if(data == nil) fatal(Enomem); n = convS2M(t, data, messagesize); - if(write(netfd, data, n)!=n) -{syslog(0, "exportfs", "short write: %r"); - fatal("mount write"); -} + if(write(0, data, n) != n){ + /* not fatal, might have got a note due to flush */ + fprint(2, "exportfs: short write in reply: %r\n"); + } free(data); } @@ -473,11 +471,11 @@ getfid(int nr) { Fid *f; - for(f = fidhash(nr); f; f = f->next) + for(f = fidhash(nr); f != nil; f = f->next) if(f->nr == nr) return f; - return 0; + return nil; } int @@ -487,18 +485,18 @@ freefid(int nr) char buf[128]; l = &fidhash(nr); - for(f = *l; f; f = f->next) { + for(f = *l; f != nil; f = f->next) { if(f->nr == nr) { if(f->mid) { - sprint(buf, "/mnt/exportfs/%d", f->mid); + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); unmount(0, buf); psmap[f->mid] = 0; } - if(f->f) { + if(f->f != nil) { freefile(f->f); f->f = nil; } - if(f->dir){ + if(f->dir != nil){ free(f->dir); f->dir = nil; } @@ -520,17 +518,17 @@ newfid(int nr) int i; l = &fidhash(nr); - for(new = *l; new; new = new->next) + for(new = *l; new != nil; new = new->next) if(new->nr == nr) - return 0; + return nil; - if(fidfree == 0) { + if(fidfree == nil) { fidfree = emallocz(sizeof(Fid) * Fidchunk); for(i = 0; i < Fidchunk-1; i++) fidfree[i].next = &fidfree[i+1]; - fidfree[Fidchunk-1].next = 0; + fidfree[Fidchunk-1].next = nil; } new = fidfree; @@ -546,41 +544,45 @@ newfid(int nr) return new; } +static struct { + Lock; + Fsrpc *free; + + /* statistics */ + int nalloc; + int nfree; +} sbufalloc; + Fsrpc * getsbuf(void) { - static int ap; - int look, rounds; - Fsrpc *wb; - int small_instead_of_fast = 1; - - if(small_instead_of_fast) - ap = 0; /* so we always start looking at the beginning and reuse buffers */ - - for(rounds = 0; rounds < 10; rounds++) { - for(look = 0; look < Nr_workbufs; look++) { - if(++ap == Nr_workbufs) - ap = 0; - if(Workq[ap].busy == 0) - break; - } - - if(look == Nr_workbufs){ - sleep(10 * rounds); - continue; - } - - wb = &Workq[ap]; - wb->pid = 0; - wb->canint = 0; - wb->flushtag = NOTAG; - wb->busy = 1; - if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ - wb->buf = emallocz(messagesize); - return wb; + Fsrpc *w; + + lock(&sbufalloc); + w = sbufalloc.free; + if(w != nil){ + sbufalloc.free = w->next; + w->next = nil; + sbufalloc.nfree--; + unlock(&sbufalloc); + } else { + sbufalloc.nalloc++; + unlock(&sbufalloc); + w = emallocz(sizeof(*w) + messagesize); } - fatal("No more work buffers"); - return nil; + w->flushtag = NOTAG; + return w; +} + +void +putsbuf(Fsrpc *w) +{ + w->flushtag = NOTAG; + lock(&sbufalloc); + w->next = sbufalloc.free; + sbufalloc.free = w; + sbufalloc.nfree++; + unlock(&sbufalloc); } void @@ -588,30 +590,25 @@ freefile(File *f) { File *parent, *child; -Loop: - f->ref--; - if(f->ref > 0) - return; - freecnt++; - if(f->ref < 0) abort(); - DEBUG(DFD, "free %s\n", f->name); - /* delete from parent */ - parent = f->parent; - if(parent->child == f) - parent->child = f->childlist; - else{ - for(child=parent->child; child->childlist!=f; child=child->childlist) - if(child->childlist == nil) - fatal("bad child list"); - child->childlist = f->childlist; - } - freeqid(f->qidt); - free(f->name); - f->name = nil; - free(f); - f = parent; - if(f != nil) - goto Loop; + while(--f->ref == 0){ + freecnt++; + DEBUG(DFD, "free %s\n", f->name); + /* delete from parent */ + parent = f->parent; + if(parent->child == f) + parent->child = f->childlist; + else{ + for(child = parent->child; child->childlist != f; child = child->childlist) { + if(child->childlist == nil) + fatal("bad child list"); + } + child->childlist = f->childlist; + } + freeqid(f->qidt); + free(f->name); + free(f); + f = parent; + } } File * @@ -633,7 +630,7 @@ file(File *parent, char *name) if(dir == nil) return nil; - for(f = parent->child; f; f = f->childlist) + for(f = parent->child; f != nil; f = f->childlist) if(strcmp(name, f->name) == 0) break; @@ -694,7 +691,7 @@ initroot(void) free(dir); psmpt = file(psmpt, "mnt"); - if(psmpt == 0) + if(psmpt == nil) return; psmpt = file(psmpt, "exportfs"); } @@ -711,9 +708,7 @@ makepath(File *p, char *name) seg[i] = p->name; n += strlen(p->name)+1; } - path = malloc(n); - if(path == nil) - fatal("out of memory"); + path = emallocz(n); s = path; while(i--) { @@ -747,8 +742,7 @@ freeqid(Qidtab *q) ulong h; Qidtab *l; - q->ref--; - if(q->ref > 0) + if(--q->ref) return; qfreecnt++; h = qidhash(q->path); @@ -815,10 +809,8 @@ uniqueqid(Dir *d) path |= newqid<<48; DEBUG(DFD, "assign qid %.16llux\n", path); } - q = mallocz(sizeof(Qidtab), 1); - if(q == nil) - fatal("no memory for qid table"); qidcnt++; + q = emallocz(sizeof(Qidtab)); q->ref = 1; q->type = d->type; q->dev = d->dev; @@ -837,20 +829,20 @@ fatal(char *s, ...) va_list arg; Proc *m; - if (s) { + if(s != nil) { va_start(arg, s); vsnprint(buf, ERRMAX, s, arg); va_end(arg); } /* Clear away the slave children */ - for(m = Proclist; m; m = m->next) + for(m = Proclist; m != nil; m = m->next) postnote(PNPROC, m->pid, "kill"); - DEBUG(DFD, "%s\n", buf); - if (s) + if(s != nil) { + DEBUG(DFD, "%s\n", buf); sysfatal("%s", buf); /* caution: buf could contain '%' */ - else + } else exits(nil); } @@ -862,6 +854,7 @@ emallocz(uint n) p = mallocz(n, 1); if(p == nil) fatal(Enomem); + setmalloctag(p, getcallerpc(&n)); return p; } @@ -873,65 +866,81 @@ estrdup(char *s) t = strdup(s); if(t == nil) fatal(Enomem); + setmalloctag(t, getcallerpc(&s)); return t; } -/* Network on fd1, mount driver on fd0 */ -int -filter(int fd, char *cmd) +void +filter(int fd, char *cmd, char *host) { - int p[2], lfd, len, nb, argc; - char newport[128], buf[128], devdir[40], *s, *file, *argv[16]; - - /* Get a free port and post it to the client. */ - if (announce(anstring, devdir) < 0) - sysfatal("filter: Cannot announce %s: %r", anstring); - - snprint(buf, sizeof(buf), "%s/local", devdir); - buf[sizeof buf - 1] = '\0'; - if ((lfd = open(buf, OREAD)) < 0) - sysfatal("filter: Cannot open %s: %r", buf); - if ((len = read(lfd, newport, sizeof newport - 1)) < 0) - sysfatal("filter: Cannot read %s: %r", buf); - close(lfd); - newport[len] = '\0'; - - if ((s = strchr(newport, '\n')) != nil) - *s = '\0'; - - if ((nb = write(fd, newport, len)) < 0) - sysfatal("getport; cannot write port; %r"); - assert(nb == len); - - argc = tokenize(cmd, argv, nelem(argv)-2); + char addr[128], buf[256], *s, *file, *argv[16]; + int lfd, p[2], len, argc; + + if(host == nil){ + /* Get a free port and post it to the client. */ + if (announce(anstring, addr) < 0) + fatal("filter: Cannot announce %s: %r", anstring); + + snprint(buf, sizeof(buf), "%s/local", addr); + if ((lfd = open(buf, OREAD)) < 0) + fatal("filter: Cannot open %s: %r", buf); + if ((len = read(lfd, buf, sizeof buf - 1)) < 0) + fatal("filter: Cannot read %s: %r", buf); + close(lfd); + buf[len] = '\0'; + if ((s = strchr(buf, '\n')) != nil) + len = s - buf; + if (write(fd, buf, len) != len) + fatal("filter: cannot write port; %r"); + } else { + /* Read address string from connection */ + if ((len = read(fd, buf, sizeof buf - 1)) < 0) + sysfatal("filter: cannot write port; %r"); + buf[len] = '\0'; + + if ((s = strrchr(buf, '!')) == nil) + sysfatal("filter: illegally formatted port %s", buf); + strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); + strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); + } + + DEBUG(DFD, "filter: %s\n", addr); + + snprint(buf, sizeof(buf), "%s", cmd); + argc = tokenize(buf, argv, nelem(argv)-3); if (argc == 0) sysfatal("filter: empty command"); - argv[argc++] = buf; + + if(host != nil) + argv[argc++] = "-c"; + argv[argc++] = addr; argv[argc] = nil; + file = argv[0]; - if (s = strrchr(argv[0], '/')) + if((s = strrchr(argv[0], '/')) != nil) argv[0] = s+1; if(pipe(p) < 0) - fatal("pipe"); + sysfatal("pipe: %r"); - switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { + switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { case -1: - fatal("rfork record module"); + fatal("filter: rfork; %r\n"); case 0: + close(fd); if (dup(p[0], 1) < 0) - fatal("filter: Cannot dup to 1; %r\n"); + fatal("filter: Cannot dup to 1; %r"); if (dup(p[0], 0) < 0) - fatal("filter: Cannot dup to 0; %r\n"); + fatal("filter: Cannot dup to 0; %r"); close(p[0]); close(p[1]); exec(file, argv); - fatal("exec record module"); + fatal("filter: exec; %r"); default: - close(fd); + dup(p[1], fd); close(p[0]); + close(p[1]); } - return p[1]; } static void diff --git a/sys/src/cmd/exportfs/exportfs.h b/sys/src/cmd/exportfs/exportfs.h index 0f7ba3e71e..7397951660 100644 --- a/sys/src/cmd/exportfs/exportfs.h +++ b/sys/src/cmd/exportfs/exportfs.h @@ -14,12 +14,10 @@ typedef struct Qidtab Qidtab; struct Fsrpc { - int busy; /* Work buffer has pending rpc to service */ - uintptr pid; /* Pid of slave process executing the rpc */ - int canint; /* Interrupt gate */ + Fsrpc *next; /* freelist */ int flushtag; /* Tag on which to reply to flush */ Fcall work; /* Plan 9 incoming Fcall */ - uchar *buf; /* Data buffer */ + uchar buf[]; /* Data buffer */ }; struct Fid @@ -53,9 +51,10 @@ struct File struct Proc { - uintptr pid; - int busy; + Lock; + Fsrpc *busy; Proc *next; + int pid; }; struct Qidtab @@ -70,9 +69,7 @@ struct Qidtab enum { - MAXPROC = 50, FHASHSIZE = 64, - Nr_workbufs = 50, Fidchunk = 1000, Npsmpt = 32, Nqidbits = 5, @@ -83,12 +80,10 @@ char Ebadfid[]; char Enotdir[]; char Edupfid[]; char Eopen[]; -char Exmnt[]; char Enomem[]; char Emip[]; char Enopsmt[]; -Extern Fsrpc *Workq; Extern int dbg; Extern File *root; Extern File *psmpt; @@ -121,6 +116,7 @@ Fid *getfid(int); int freefid(int); Fid *newfid(int); Fsrpc *getsbuf(void); +void putsbuf(Fsrpc*); void initroot(void); void fatal(char*, ...); char* makepath(File*, char*); @@ -129,7 +125,7 @@ void freefile(File*); void slaveopen(Fsrpc*); void slaveread(Fsrpc*); void slavewrite(Fsrpc*); -void blockingslave(void); +void blockingslave(Proc*); void reopen(Fid *f); void noteproc(int, char*); void flushaction(void*, char*); diff --git a/sys/src/cmd/exportfs/exportsrv.c b/sys/src/cmd/exportfs/exportsrv.c index 842880529a..05cba593c9 100644 --- a/sys/src/cmd/exportfs/exportsrv.c +++ b/sys/src/cmd/exportfs/exportsrv.c @@ -7,16 +7,16 @@ extern char *netdir, *local, *remote; -char Ebadfid[] = "Bad fid"; -char Enotdir[] = "Not a directory"; -char Edupfid[] = "Fid already in use"; -char Eopen[] = "Fid already opened"; -char Exmnt[] = "Cannot .. past mount point"; -char Emip[] = "Mount in progress"; -char Enopsmt[] = "Out of pseudo mount points"; -char Enomem[] = "No memory"; -char Eversion[] = "Bad 9P2000 version"; -char Ereadonly[] = "File system read only"; +char Ebadfid[] = "bad fid"; +char Enotdir[] = "not a directory"; +char Edupfid[] = "fid already in use"; +char Eopen[] = "fid already opened"; +char Emip[] = "mount in progress"; +char Enopsmt[] = "out of pseudo mount points"; +char Enomem[] = "no memory"; +char Eversion[] = "bad 9P2000 version"; +char Ereadonly[] = "file system read only"; +char Enoprocs[] = "out of processes"; ulong messagesize; int readonly; @@ -26,17 +26,23 @@ Xversion(Fsrpc *t) { Fcall rhdr; + if(t->work.msize < 256){ + reply(&t->work, &rhdr, "version: message size too small"); + putsbuf(t); + return; + } if(t->work.msize > messagesize) t->work.msize = messagesize; messagesize = t->work.msize; if(strncmp(t->work.version, "9P2000", 6) != 0){ reply(&t->work, &rhdr, Eversion); + putsbuf(t); return; } rhdr.version = "9P2000"; rhdr.msize = t->work.msize; reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -45,34 +51,37 @@ Xauth(Fsrpc *t) Fcall rhdr; reply(&t->work, &rhdr, "exportfs: authentication not required"); - t->busy = 0; + putsbuf(t); } void Xflush(Fsrpc *t) { - Fsrpc *w, *e; Fcall rhdr; + Fsrpc *w; + Proc *m; - e = &Workq[Nr_workbufs]; - - for(w = Workq; w < e; w++) { - if(w->work.tag == t->work.oldtag) { - DEBUG(DFD, "\tQ busy %d pid %p can %d\n", w->busy, w->pid, w->canint); - if(w->busy && w->pid) { - w->flushtag = t->work.tag; - DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); - if(w->canint) - postnote(PNPROC, w->pid, "flush"); - t->busy = 0; - return; - } + for(m = Proclist; m != nil; m = m->next){ + w = m->busy; + if(w == nil || w->work.tag != t->work.oldtag) + continue; + + lock(m); + w = m->busy; + if(w != nil && w->work.tag == t->work.oldtag) { + w->flushtag = t->work.tag; + DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); + postnote(PNPROC, m->pid, "flush"); + unlock(m); + putsbuf(t); + return; } + unlock(m); } reply(&t->work, &rhdr, 0); DEBUG(DFD, "\tflush reply\n"); - t->busy = 0; + putsbuf(t); } void @@ -84,36 +93,31 @@ Xattach(Fsrpc *t) char buf[128]; f = newfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } if(srvfd >= 0){ - if(psmpt == 0){ - Nomount: - reply(&t->work, &rhdr, Enopsmt); - t->busy = 0; - freefid(t->work.fid); - return; - } + if(psmpt == nil) + goto Nomount; for(i=0; i= Npsmpt) goto Nomount; - sprint(buf, "%d", i); + snprint(buf, sizeof(buf), "%d", i); f->f = file(psmpt, buf); if(f->f == nil) goto Nomount; - sprint(buf, "/mnt/exportfs/%d", i); + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", i); nfd = dup(srvfd, -1); if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){ errstr(buf, sizeof buf); reply(&t->work, &rhdr, buf); - t->busy = 0; freefid(t->work.fid); + putsbuf(t); close(nfd); return; } @@ -126,7 +130,13 @@ Xattach(Fsrpc *t) rhdr.qid = f->f->qid; reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); + return; + +Nomount: + reply(&t->work, &rhdr, Enopsmt); + freefid(t->work.fid); + putsbuf(t); } Fid* @@ -135,15 +145,15 @@ clonefid(Fid *f, int new) Fid *n; n = newfid(new); - if(n == 0) { + if(n == nil) { n = getfid(new); - if(n == 0) + if(n == nil) fatal("inconsistent fids"); if(n->fid >= 0) close(n->fid); freefid(new); n = newfid(new); - if(n == 0) + if(n == nil) fatal("inconsistent fids2"); } n->f = f->f; @@ -161,9 +171,9 @@ Xwalk(Fsrpc *t) int i; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -176,28 +186,22 @@ Xwalk(Fsrpc *t) rhdr.nwqid = 0; e = nil; for(i=0; iwork.nwname; i++){ - if(i == MAXWELEM){ - e = "Too many path elements"; - break; - } if(strcmp(t->work.wname[i], "..") == 0) { - if(f->f->parent == nil) { - e = Exmnt; + if(f->f->parent != nil) + wf = f->f->parent; + else + wf = f->f; + wf->ref++; + }else{ + wf = file(f->f, t->work.wname[i]); + if(wf == nil){ + errstr(err, sizeof err); + e = err; break; } - wf = f->f->parent; - wf->ref++; - goto Accept; - } - - wf = file(f->f, t->work.wname[i]); - if(wf == 0){ - errstr(err, sizeof err); - e = err; - break; } - Accept: + freefile(f->f); rhdr.wqid[rhdr.nwqid++] = wf->qid; f->f = wf; @@ -209,7 +213,7 @@ Xwalk(Fsrpc *t) if(rhdr.nwqid > 0) e = nil; reply(&t->work, &rhdr, e); - t->busy = 0; + putsbuf(t); } void @@ -219,9 +223,9 @@ Xclunk(Fsrpc *t) Fid *f; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -230,7 +234,7 @@ Xclunk(Fsrpc *t) freefid(t->work.fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -244,9 +248,9 @@ Xstat(Fsrpc *t) uchar *statbuf; f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } if(f->fid >= 0) @@ -260,7 +264,7 @@ Xstat(Fsrpc *t) if(d == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } @@ -273,7 +277,7 @@ Xstat(Fsrpc *t) rhdr.stat = statbuf; reply(&t->work, &rhdr, 0); free(statbuf); - t->busy = 0; + putsbuf(t); } static int @@ -297,13 +301,13 @@ Xcreate(Fsrpc *t) if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -314,15 +318,15 @@ Xcreate(Fsrpc *t) if(f->fid < 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } nf = file(f->f, t->work.name); - if(nf == 0) { + if(nf == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } @@ -332,7 +336,7 @@ Xcreate(Fsrpc *t) rhdr.qid = f->f->qid; rhdr.iounit = getiounit(f->fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -344,13 +348,13 @@ Xremove(Fsrpc *t) if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } @@ -360,7 +364,7 @@ Xremove(Fsrpc *t) free(path); errstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); return; } free(path); @@ -371,7 +375,7 @@ Xremove(Fsrpc *t) freefid(t->work.fid); reply(&t->work, &rhdr, 0); - t->busy = 0; + putsbuf(t); } void @@ -386,20 +390,20 @@ Xwstat(Fsrpc *t) if(readonly) { reply(&t->work, &rhdr, Ereadonly); - t->busy = 0; + putsbuf(t); return; } f = getfid(t->work.fid); - if(f == 0) { + if(f == nil) { reply(&t->work, &rhdr, Ebadfid); - t->busy = 0; + putsbuf(t); return; } strings = emallocz(t->work.nstat); /* ample */ if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){ rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); - t->busy = 0; + putsbuf(t); free(strings); return; } @@ -417,14 +421,14 @@ Xwstat(Fsrpc *t) } else { /* wstat may really be rename */ - if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){ + if(strcmp(d.name, f->f->name)!=0 && d.name[0]!=0){ free(f->f->name); f->f->name = estrdup(d.name); } reply(&t->work, &rhdr, 0); } free(strings); - t->busy = 0; + putsbuf(t); } /* @@ -455,90 +459,99 @@ procsetname(char *fmt, ...) void slave(Fsrpc *f) { - Proc *p; - uintptr pid; - Fcall rhdr; static int nproc; + Proc *m, **l; + Fcall rhdr; + int omode; + int pid; if(readonly){ switch(f->work.type){ case Twrite: reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; + putsbuf(f); return; case Topen: - if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){ + omode = f->work.mode & 3; + if(omode != OREAD && omode != OEXEC || (f->work.mode&(OTRUNC|ORCLOSE)) != 0){ reply(&f->work, &rhdr, Ereadonly); - f->busy = 0; + putsbuf(f); return; } } } for(;;) { - for(p = Proclist; p; p = p->next) { - if(p->busy == 0) { - f->pid = p->pid; - p->busy = 1; - pid = (uintptr)rendezvous((void*)p->pid, f); - if(pid != p->pid) - fatal("rendezvous sync fail"); - return; - } - } + for(l = &Proclist; (m = *l) != nil; l = &m->next) { + if(m->busy != nil) + continue; + + m->busy = f; + while(rendezvous(m, f) == (void*)~0) + ; + + /* swept a slave proc */ + if(f == nil){ + *l = m->next; + free(m); + nproc--; + break; + } + f = nil; - if(++nproc > MAXPROC) - fatal("too many procs"); + /* + * as long as the number of slave procs + * is small, dont bother sweeping. + */ + if(nproc < 16) + break; + } + if(f == nil) + return; - pid = rfork(RFPROC|RFMEM); + m = emallocz(sizeof(Proc)); + pid = rfork(RFPROC|RFMEM|RFNOWAIT); switch(pid) { case -1: - fatal("rfork"); + reply(&f->work, &rhdr, Enoprocs); + putsbuf(f); + free(m); + return; case 0: - if (local[0] != '\0') - if (netdir[0] != '\0') - procsetname("%s: %s -> %s", netdir, - local, remote); + if(local[0] != '\0'){ + if(netdir[0] != '\0') + procsetname("%s: %s -> %s", netdir, local, remote); else procsetname("%s -> %s", local, remote); - blockingslave(); - fatal("slave"); + } + blockingslave(m); + _exits(0); default: - p = malloc(sizeof(Proc)); - if(p == 0) - fatal("out of memory"); - - p->busy = 0; - p->pid = pid; - p->next = Proclist; - Proclist = p; - - rendezvous((void*)pid, p); + m->pid = pid; + m->next = Proclist; + Proclist = m; + nproc++; } } } void -blockingslave(void) +blockingslave(Proc *m) { Fsrpc *p; Fcall rhdr; - Proc *m; - uintptr pid; notify(flushaction); - pid = getpid(); - - m = rendezvous((void*)pid, 0); - for(;;) { - p = rendezvous((void*)pid, (void*)pid); - if(p == (void*)~0) /* Interrupted */ + p = rendezvous(m, nil); + if(p == (void*)~0) /* Interrupted */ continue; + if(p == nil) /* Swept */ + break; - DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid); + DEBUG(DFD, "\tslave: %d %F\n", m->pid, &p->work); if(p->flushtag != NOTAG) goto flushme; @@ -558,28 +571,35 @@ blockingslave(void) default: reply(&p->work, &rhdr, "exportfs: slave type error"); } - if(p->flushtag != NOTAG) { flushme: + lock(m); + m->busy = nil; + unlock(m); + + /* no more flushes can come in now */ + if(p->flushtag != NOTAG) { p->work.type = Tflush; p->work.tag = p->flushtag; reply(&p->work, &rhdr, 0); } - p->busy = 0; - m->busy = 0; + putsbuf(p); } } int openmount(int sfd) { - int p[2]; + int p[2], fd, i, n; char *arg[10], fdbuf[20], mbuf[20]; + Dir *dir; if(pipe(p) < 0) return -1; - switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){ + switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG|RFREND)){ case -1: + close(p[0]); + close(p[1]); return -1; default: @@ -591,20 +611,30 @@ openmount(int sfd) break; } - close(p[1]); + dup(p[0], 0); + dup(p[0], 1); - arg[0] = "exportfs"; + /* close all remaining file descriptors except sfd */ + if((fd = open("/fd", OREAD)) < 0) + _exits("open /fd failed"); + n = dirreadall(fd, &dir); + for(i=0; i 2 && fd != sfd) + close(fd); + } + free(dir); + + arg[0] = argv0; /* "/bin/exportfs" */ snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd); arg[1] = fdbuf; snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ); arg[2] = mbuf; arg[3] = nil; - close(0); - close(1); - dup(p[0], 0); - dup(p[0], 1); - exec("/bin/exportfs", arg); + exec(arg[0], arg); _exits("whoops: exec failed"); return -1; } @@ -620,7 +650,7 @@ slaveopen(Fsrpc *p) work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } @@ -631,16 +661,8 @@ slaveopen(Fsrpc *p) path = makepath(f->f, ""); DEBUG(DFD, "\topen: %s %d\n", path, work->mode); - - p->canint = 1; - if(p->flushtag != NOTAG){ - free(path); - return; - } - /* There is a race here I ignore because there are no locks */ f->fid = open(path, work->mode); free(path); - p->canint = 0; if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) { Error: errstr(err, sizeof err); @@ -674,32 +696,29 @@ slaveread(Fsrpc *p) work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; - p->canint = 1; - if(p->flushtag != NOTAG) - return; data = malloc(n); - if(data == nil) - fatal(Enomem); + if(data == nil) { + reply(work, &rhdr, Enomem); + return; + } /* can't just call pread, since directories must update the offset */ if(patternfile != nil && (f->f->qid.type&QTDIR)) r = preaddir(f, (uchar*)data, n, work->offset); else r = pread(f->fid, data, n, work->offset); - p->canint = 0; if(r < 0) { free(data); errstr(err, sizeof err); reply(work, &rhdr, err); return; } - DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r); rhdr.data = data; @@ -719,17 +738,13 @@ slavewrite(Fsrpc *p) work = &p->work; f = getfid(work->fid); - if(f == 0) { + if(f == nil) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; - p->canint = 1; - if(p->flushtag != NOTAG) - return; n = pwrite(f->fid, work->data, n, work->offset); - p->canint = 0; if(n < 0) { errstr(err, sizeof err); reply(work, &rhdr, err); diff --git a/sys/src/cmd/exportfs/pattern.c b/sys/src/cmd/exportfs/pattern.c index 0dcbc9380a..4dfed5bca6 100644 --- a/sys/src/cmd/exportfs/pattern.c +++ b/sys/src/cmd/exportfs/pattern.c @@ -24,15 +24,11 @@ exclusions(void) fatal("cannot open patternfile"); ni = 0; nmaxi = 100; - include = malloc(nmaxi*sizeof(*include)); - if(include == nil) - fatal("out of memory"); + include = emallocz(nmaxi*sizeof(*include)); include[0] = nil; ne = 0; nmaxe = 100; - exclude = malloc(nmaxe*sizeof(*exclude)); - if(exclude == nil) - fatal("out of memory"); + exclude = emallocz(nmaxe*sizeof(*exclude)); exclude[0] = nil; while(line = Brdline(f, '\n')){ line[Blinelen(f) - 1] = 0; @@ -80,16 +76,16 @@ excludefile(char *path) else p = path+1; - DEBUG(DFD, "checking %s\n", path); + DEBUG(DFD, "checking %s\n", p); for(re = include; *re != nil; re++){ if(regexec(*re, p, nil, 0) != 1){ - DEBUG(DFD, "excluded+ %s\n", path); + DEBUG(DFD, "excluded+ %s\n", p); return -1; } } for(re = exclude; *re != nil; re++){ if(regexec(*re, p, nil, 0) == 1){ - DEBUG(DFD, "excluded- %s\n", path); + DEBUG(DFD, "excluded- %s\n", p); return -1; } } From adaa796a98e51e76ddb626f9700e4db847ac863f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:37 +0000 Subject: [PATCH 147/402] sys/src/cmd/aux/flashfs: fix to work with port/devflash.c instead of bitsy/devflash.c --- sys/src/cmd/aux/flashfs/devfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/aux/flashfs/devfs.c b/sys/src/cmd/aux/flashfs/devfs.c index 5b0576e36f..5d2cff34b8 100644 --- a/sys/src/cmd/aux/flashfs/devfs.c +++ b/sys/src/cmd/aux/flashfs/devfs.c @@ -61,8 +61,8 @@ initdata(char *f, int) n = tokenize(buf, fld, nelem(fld)); if(n < 7) sysfatal("bad flash geometry"); - nsects = atoi(fld[5]); sectsize = atoi(fld[6]); + nsects = (atoi(fld[5])-atoi(fld[4]))/sectsize; if(nsects < 8) sysfatal("unreasonable value for nsects: %lud", nsects); if(sectsize < 512) From 7a556073071010f24cbc4a46b988149f28e4b2d5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 10 Mar 2016 12:24:59 +0000 Subject: [PATCH 148/402] sys/src/cmd: delete 2-space code in fmt (thanks Russ Cox) --- sys/src/cmd/fmt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sys/src/cmd/fmt.c b/sys/src/cmd/fmt.c index a072c8ba2c..a5be5aa92c 100644 --- a/sys/src/cmd/fmt.c +++ b/sys/src/cmd/fmt.c @@ -166,22 +166,6 @@ printindent(int w) } } -/* give extra space if word ends with period, etc. */ -int -nspaceafter(char *s) -{ - int n; - - n = strlen(s); - if(n < 2) - return 1; - if(isupper(s[0]) && n < 4) - return 1; - if(strchr(".!?", s[n-1]) != nil) - return 2; - return 1; -} - void printwords(Word **w, int nw) @@ -207,7 +191,7 @@ printwords(Word **w, int nw) break; /* out of words */ if(w[i]->indent != w[i-1]->indent) break; /* indent change */ - nsp = nspaceafter(w[i-1]->text); + nsp = 1; if(col+nsp+utflen(w[i]->text) > extraindent+length) break; /* fold line */ if(!join && w[i]->bol) From bb823596e9ad581ca0217b139d00c80b850b2273 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 21 Feb 2021 21:10:10 +0000 Subject: [PATCH 149/402] sys/src/cmd/usb/ether: support more usb cdc-ecm devices (thanks Richard Miller) --- sys/src/cmd/usb/ether/cdc.c | 20 +++++++++++++-- sys/src/cmd/usb/lib/dev.c | 50 ++++++++++++++++++++++--------------- sys/src/cmd/usb/usbd/usbdb | 1 + 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/sys/src/cmd/usb/ether/cdc.c b/sys/src/cmd/usb/ether/cdc.c index aea54e7077..c88f4e278e 100644 --- a/sys/src/cmd/usb/ether/cdc.c +++ b/sys/src/cmd/usb/ether/cdc.c @@ -48,13 +48,29 @@ getmac(Ether *ether) int cdcreset(Ether *ether) { + Usbdev *ud; + Ep *ep; + int i; + /* * Assume that all communication devices are going to * be std. ethernet communication devices. Specific controllers * must have been probed first. - * NB: This ignores unions. */ - if(ether->dev->usb->class == Clcomms) + ud = ether->dev->usb; + if(ud->class == Clcomms) return getmac(ether); + if(getmac(ether) == 0){ + for(i = 0; i < Nep; i++){ + ep = ud->ep[i]; + if(ep == nil) + continue; + if(ep->iface == nil || !okclass(ep->iface)) + continue; + if(ep->conf->cval != 1) + usbcmd(ether->dev, Rh2d|Rstd|Rdev, Rsetconf, ep->conf->cval, 0, nil, 0); + return 0; + } + } return -1; } diff --git a/sys/src/cmd/usb/lib/dev.c b/sys/src/cmd/usb/lib/dev.c index 675cc69084..4ff488a44b 100644 --- a/sys/src/cmd/usb/lib/dev.c +++ b/sys/src/cmd/usb/lib/dev.c @@ -148,7 +148,7 @@ int loaddevconf(Dev *d, int n) { uchar *buf; - int nr; + int l, nr; int type; if(n >= nelem(d->usb->conf)){ @@ -158,11 +158,22 @@ loaddevconf(Dev *d, int n) } buf = emallocz(Maxdevconf, 0); type = Rd2h|Rstd|Rdev; - nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Maxdevconf); + nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Dconflen); if(nr < Dconflen){ free(buf); return -1; } + l = GET2(((DConf*)buf)->wTotalLength); + if(l > Maxdevconf){ + free(buf); + return -1; + } + nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, l); + if(nr < l){ + free(buf); + return -1; + } + if(d->usb->conf[n] == nil) d->usb->conf[n] = emallocz(sizeof(Conf), 1); nr = parseconf(d->usb, d->usb->conf[n], buf, nr); @@ -188,6 +199,8 @@ mkstr(uchar *b, int n) char *s; char *e; + if(n > b[0]) + n = b[0]; if(n <= 2 || (n & 1) != 0) return strdup("none"); n = (n - 2)/2; @@ -204,42 +217,37 @@ mkstr(uchar *b, int n) char* loaddevstr(Dev *d, int sid) { - uchar buf[128]; - int type; - int nr; + uchar buf[256]; + int type, langid, nr; if(sid == 0) return estrdup("none"); type = Rd2h|Rstd|Rdev; - nr=usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf)); + nr = usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf)); + if(nr < 4) + langid = 0x0409; /* english */ + else + langid = buf[3]<<8 | buf[2]; + nr = usbcmd(d, type, Rgetdesc, Dstr<<8|sid, langid, buf, sizeof(buf)); + return mkstr(buf, nr); } int loaddevdesc(Dev *d) { - uchar buf[Ddevlen+255]; + uchar buf[Ddevlen]; int nr; int type; Ep *ep0; type = Rd2h|Rstd|Rdev; - nr = sizeof(buf); memset(buf, 0, Ddevlen); - if((nr=usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, nr)) < 0) + if((nr = usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, Ddevlen)) < 0) return -1; - /* - * Several hubs are returning descriptors of 17 bytes, not 18. - * We accept them and leave number of configurations as zero. - * (a get configuration descriptor also fails for them!) - */ if(nr < Ddevlen){ - print("%s: %s: warning: device with short descriptor\n", - argv0, d->dir); - if(nr < Ddevlen-1){ - werrstr("short device descriptor (%d bytes)", nr); - return -1; - } + werrstr("short device descriptor (%d bytes)", nr); + return -1; } d->usb = emallocz(sizeof(Usbdev), 1); ep0 = mkep(d->usb, 0); @@ -254,6 +262,8 @@ loaddevdesc(Dev *d) d->usb->serial = loaddevstr(d, d->usb->ssid); } } + else + print("usbd: desc error: %r"); return nr; } diff --git a/sys/src/cmd/usb/usbd/usbdb b/sys/src/cmd/usb/usbd/usbdb index d0e5b0d794..73c63ff536 100644 --- a/sys/src/cmd/usb/usbd/usbdb +++ b/sys/src/cmd/usb/usbd/usbdb @@ -5,6 +5,7 @@ embed disk class=storage args= ether class=255 csp=0x00ffff vid=0x0b95 args= ether class=255 csp=0xff00ff vid=0x0424 did=0xec00 args= + ether class=255 csp=0x000602 vid=0x0bda did=0x8152 args= serial class=255 csp=0xffffff vid=0x9e88 did=0x9e8f args= serial class=255 csp=0xffffff vid=0x0403 args= serial class=255 csp=0x0000ff vid=0x10c4 args= From d7d9ecde849fce0b3032361bc40aefa5b1687bcc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 19:34:26 +0000 Subject: [PATCH 150/402] sys/src/cmd/usb/ether: various fixes for Raspberry Pi (thanks Richard Miller) --- sys/src/cmd/usb/ether/ether.c | 51 ++++++++++++++++++++++------------- sys/src/cmd/usb/ether/smsc.c | 32 ++++++++++------------ 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/sys/src/cmd/usb/ether/ether.c b/sys/src/cmd/usb/ether/ether.c index 50d3295678..93c87c1467 100644 --- a/sys/src/cmd/usb/ether/ether.c +++ b/sys/src/cmd/usb/ether/ether.c @@ -1145,29 +1145,34 @@ etherinit(Ether *e, int *ei, int *eo) static int kernelproxy(Ether *e) { - int ctlfd, n; + int ctlfd, n, i; + char ename[20]; char eaddr[13]; - ctlfd = open("#l0/ether0/clone", ORDWR); - if(ctlfd < 0){ - deprint(2, "%s: etherusb bind #l0: %r\n", argv0); - return -1; - } close(e->epin->dfd); close(e->epout->dfd); - seprintaddr(eaddr, eaddr+sizeof(eaddr), e->addr); - n = fprint(ctlfd, "bind %s #u/usb/ep%d.%d/data #u/usb/ep%d.%d/data %s %d %d", - e->name, e->dev->id, e->epin->id, e->dev->id, e->epout->id, - eaddr, e->bufsize, e->epout->maxpkt); - if(n < 0){ - deprint(2, "%s: etherusb bind #l0: %r\n", argv0); - opendevdata(e->epin, OREAD); - opendevdata(e->epout, OWRITE); + for(i = 0; i < 10; i++){ + sprint(ename, "#l%d/ether%d/clone", i, i); + ctlfd = open(ename, ORDWR); + if(ctlfd < 0){ + deprint(2, "%s: etherusb bind %.3s: %r\n", argv0, ename); + break; + } + seprintaddr(eaddr, eaddr+sizeof(eaddr), e->addr); + n = fprint(ctlfd, "bind %s #u/usb/ep%d.%d/data #u/usb/ep%d.%d/data %s %d %d", + e->name, e->dev->id, e->epin->id, e->dev->id, e->epout->id, + eaddr, e->bufsize, e->epout->maxpkt); + if(n < 0){ + deprint(2, "%s: etherusb bind %.3s: %r\n", argv0, ename); + close(ctlfd); + continue; + } close(ctlfd); - return -1; + return 0; } - close(ctlfd); - return 0; + opendevdata(e->epin, OREAD); + opendevdata(e->epout, OWRITE); + return -1; } int @@ -1222,8 +1227,18 @@ ethermain(Dev *dev, int argc, char **argv) if(openeps(e, epin, epout) < 0) return -1; - if(kernelproxy(e) == 0) + if(kernelproxy(e) == 0){ + if(e->multicast != nil){ + /* + * Until there is an interface for the kernel etherusb driver + * to write to usb/ether ctl file, multicast needs to be on + * by default so ipv6 will work. + */ + e->nmcasts++; + e->multicast(e, nil, 1); + } return 0; + } e->fs = etherfs; snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", devid); e->fs.dev = dev; diff --git a/sys/src/cmd/usb/ether/smsc.c b/sys/src/cmd/usb/ether/smsc.c index 9a01514a59..784dc793a0 100644 --- a/sys/src/cmd/usb/ether/smsc.c +++ b/sys/src/cmd/usb/ether/smsc.c @@ -323,38 +323,34 @@ smscbwrite(Ether *e, Buf *bp) static int smscpromiscuous(Ether *e, int on) { - USED(on, e); -#ifdef TODO /* copied from asix */ + Dev *d; int rxctl; - deprint(2, "%s: smscpromiscuous %d\n", argv0, on); - rxctl = getrxctl(e->dev); - if(on != 0) - rxctl |= Rxctlprom; + d = e->dev; + rxctl = rr(d, Maccr); + if(on) + rxctl |= Prms; else - rxctl &= ~Rxctlprom; - return wr(e->dev, Cwrxctl, rxctl); -#endif - return -1; + rxctl &= ~Prms; + return wr(d, Maccr, rxctl); } static int smscmulticast(Ether *e, uchar *addr, int on) { - USED(addr, on, e); -#ifdef TODO /* needed for ipv6; copied from asix */ int rxctl; + Dev *d; + USED(addr, on); /* BUG: should write multicast filter */ - rxctl = getrxctl(e->dev); + d = e->dev; + rxctl = rr(d, Maccr); if(e->nmcasts != 0) - rxctl |= Rxctlamall; + rxctl |= Mcpas; else - rxctl &= ~Rxctlamall; + rxctl &= ~Mcpas; deprint(2, "%s: smscmulticast %d\n", argv0, e->nmcasts); - return wr(e->dev, Cwrxctl, rxctl); -#endif - return -1; + return wr(d, Maccr, rxctl); } static void From 50032773a89e72646974a75146133790196cdf63 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 19:42:12 +0000 Subject: [PATCH 151/402] sys/src/cmd/usb/ether: add support for Microchip LAN78xx usb ethernet (thanks Richard Miller) --- sys/src/cmd/usb/ether/ether.c | 4 + sys/src/cmd/usb/ether/ether.h | 2 + sys/src/cmd/usb/ether/lan78xx.c | 452 ++++++++++++++++++++++++++++++++ sys/src/cmd/usb/ether/mkfile | 1 + sys/src/cmd/usb/ether/smsc.c | 26 +- sys/src/cmd/usb/usbd/usbdb | 1 + 6 files changed, 476 insertions(+), 10 deletions(-) create mode 100644 sys/src/cmd/usb/ether/lan78xx.c diff --git a/sys/src/cmd/usb/ether/ether.c b/sys/src/cmd/usb/ether/ether.c index 93c87c1467..8f14c2be12 100644 --- a/sys/src/cmd/usb/ether/ether.c +++ b/sys/src/cmd/usb/ether/ether.c @@ -82,6 +82,9 @@ Cinfo cinfo[] = {0x0424, 0x9505, S95xx}, {0x0424, 0x9E00, S95xx}, {0x0424, 0x9E01, S95xx}, + /* LAN78xx family - gigabit ethernet + */ + {0x0424, 0x7800, S78xx}, /* raspberry pi 3 B+ */ {0, 0, 0}, }; @@ -121,6 +124,7 @@ Resetf ethers[] = { asixreset, smscreset, + lan78xxreset, cdcreset, /* keep last */ }; diff --git a/sys/src/cmd/usb/ether/ether.h b/sys/src/cmd/usb/ether/ether.h index dfb0148453..52c20f3882 100644 --- a/sys/src/cmd/usb/ether/ether.h +++ b/sys/src/cmd/usb/ether/ether.h @@ -14,6 +14,7 @@ enum A88179, A88772, S95xx, /* SMSC */ + S78xx, Eaddrlen = 6, Epktlen = 1514, @@ -114,6 +115,7 @@ struct Etherpkt int ethermain(Dev *dev, int argc, char **argv); int asixreset(Ether*); int smscreset(Ether*); +int lan78xxreset(Ether*); int cdcreset(Ether*); int parseaddr(uchar *m, char *s); void dumpframe(char *tag, void *p, int n); diff --git a/sys/src/cmd/usb/ether/lan78xx.c b/sys/src/cmd/usb/ether/lan78xx.c new file mode 100644 index 0000000000..483701862e --- /dev/null +++ b/sys/src/cmd/usb/ether/lan78xx.c @@ -0,0 +1,452 @@ +/* + * Microchip (ex SMSC) LAN78XX + * Also used as ethernet core in LAN7515 usb hub + ethernet + */ + +#include +#include +#include +#include +#include "usb.h" +#include "usbfs.h" +#include "ether.h" + +enum { + Doburst = 1, + Resettime = 1000, + E2pbusytime = 1000, + Hsburst = 32, + Defbulkdly = 1000, + Rxfifosize = (12*1024), + Txfifosize = (12*1024), + + MACoffset = 1, + PHYinternal = 1, + Rxerror = 0x00400000, + Txfcs = 1<<22, + + /* USB vendor requests */ + Writereg = 0xA0, + Readreg = 0xA1, + + /* device registers */ + Idrev = 0x00, + Intsts = 0x0C, + Hwcfg = 0x10, + Led0en = 1<<20, + Led1en = 1<<21, + Mef = 1<<4, + Lrst = 1<<1, + Pmctrl = 0x14, + Ready = 1<<7, + Phyrst = 1<<4, + Gpiocfg0 = 0x18, + Gpiocfg1 = 0x1C, + E2pcmd = 0x40, + Busy = 1<<31, + Timeout = 1<<10, + Loaded = 1<<9, + Read = 0, + E2pdata = 0x44, + Burstcap = 0x90, + Intepctl = 0x98, + Phyint = 1<<17, + Bulkdelay = 0x94, + Rfectl = 0xB0, + Rxcoe = 0xF<<11, + Ab = 1<<10, + Am = 1<<9, + Au = 1<<8, + Dpf = 1<<1, + Usbcfg0 = 0x80, + Bir = 1<<6, + Bce = 1<<5, + Usbcfg1 = 0x84, + Rxfifoctl = 0xC0, + Rxen = 1<<31, + Txfifoctl = 0xC4, + Txen = 1<<31, + Rxfifo = 0xC8, + Txfifo = 0xCc, + Fctflow = 0xD0, + Maccr = 0x100, + Add = 1<<12, + Asd = 1<<11, + Macrx = 0x104, + Macfcs = 1<<4, + Macrxen = 1<<0, + Mactx = 0x108, + Mactxen = 1<<0, + Addrh = 0x118, + Addrl = 0x11C, + MIIaddr = 0x120, + MIIwrite= 1<<1, + MIIread = 0<<1, + MIIbusy = 1<<0, + MIIdata = 0x124, + Flow = 0x10C, + Addrfilth = 0x400, + Afvalid = 1<<31, + Addrfiltl = 0x404, + + /* MII registers */ + Bmcr = 0, + Bmcrreset= 1<<15, + Speed100= 1<<13, + Anenable= 1<<12, + Anrestart= 1<<9, + Fulldpx = 1<<8, + Speed1000= 1<<6, + Bmsr = 1, + Advertise = 4, + Adcsma = 0x0001, + Ad10h = 0x0020, + Ad10f = 0x0040, + Ad100h = 0x0080, + Ad100f = 0x0100, + Adpause = 0x0400, + Adpauseasym= 0x0800, + Adall = Ad10h|Ad10f|Ad100h|Ad100f, + Lpa = 5, + Ctrl1000 = 9, + Ad1000h = 0x0400, + Ad1000f = 0x0200, + Ledmodes = 29, + Led0shift = 0, + Led1shift = 4, + Linkact = 0x0, + Link1000 = 0x1, + Phyintmask = 25, + Anegcomp= 1<<10, + Linkchg = 1<<13, +}; + +static int burstcap = Hsburst, bulkdelay = Defbulkdly; + +static int +wr(Dev *d, int reg, int val) +{ + int ret; + + ret = usbcmd(d, Rh2d|Rvendor|Rdev, Writereg, 0, reg, + (uchar*)&val, sizeof(val)); + if(ret < 0) + deprint(2, "%s: wr(%x, %x): %r", argv0, reg, val); + return ret; +} + +static int +rr(Dev *d, int reg) +{ + int ret, rval; + + ret = usbcmd(d, Rd2h|Rvendor|Rdev, Readreg, 0, reg, + (uchar*)&rval, sizeof(rval)); + if(ret < 0){ + fprint(2, "%s: rr(%x): %r", argv0, reg); + return 0; + } + return rval; +} + +static int +miird(Dev *d, int idx) +{ + while(rr(d, MIIaddr) & MIIbusy) + ; + wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIread | MIIbusy); + while(rr(d, MIIaddr) & MIIbusy) + ; + return rr(d, MIIdata); +} + +static void +miiwr(Dev *d, int idx, int val) +{ + while(rr(d, MIIaddr) & MIIbusy) + ; + wr(d, MIIdata, val); + wr(d, MIIaddr, PHYinternal<<11 | idx<<6 | MIIwrite | MIIbusy); + while(rr(d, MIIaddr) & MIIbusy) + ; +} + +static int +eepromr(Dev *d, int off, uchar *buf, int len) +{ + int i, v; + + for(i = 0; i < E2pbusytime; i++) + if((rr(d, E2pcmd) & Busy) == 0) + break; + if(i == E2pbusytime) + return -1; + for(i = 0; i < len; i++){ + wr(d, E2pcmd, Busy|Read|(i+off)); + while((v = rr(d, E2pcmd) & (Busy|Timeout)) == Busy) + ; + if(v & Timeout) + return -1; + buf[i] = rr(d, E2pdata); + } + return 0; +} + +static void +phyinit(Dev *d) +{ + int i; + + miiwr(d, Bmcr, Bmcrreset|Anenable); + for(i = 0; i < Resettime/10; i++){ + if((miird(d, Bmcr) & Bmcrreset) == 0) + break; + sleep(10); + } + miiwr(d, Advertise, Adcsma|Adall|Adpause|Adpauseasym); + miiwr(d, Ctrl1000, Ad1000f); + miiwr(d, Phyintmask, 0); + miiwr(d, Ledmodes, (Linkact<cid != S78xx) + return -1; + d = ether->dev; + deprint(2, "%s: setting up LAN78XX\n", argv0); + deprint(2, "chip id/rev = %8.8ux\n", rr(d, Idrev)); + if(!doreset(d, Hwcfg, Lrst) || !doreset(d, Pmctrl, Phyrst)) + return -1; + for(i = 0; i < Resettime/10; i++){ + if(rr(d, Pmctrl) & Ready) + break; + sleep(10); + } + if((rr(d, Pmctrl) & Ready) == 0){ + deprint(2, "%s: device not ready after reset\n", argv0); + return -1; + } + if(getmac(d, ether->addr) < 0) + deprint(2, "%s: can't read etheraddr from EEPROM\n", argv0); + a = GET4(ether->addr); + wr(d, Addrl, a); + wr(d, Addrfiltl, a); + a = GET2(ether->addr+4); + wr(d, Addrh, a); + wr(d, Addrfilth, a|Afvalid); + deprint(2, "Address filter %8.8ux %8.8ux\n", rr(d, Addrfilth), rr(d, Addrfiltl)); + + wr(d, Usbcfg0, rr(d, Usbcfg0) | Bir); + if(Doburst){ + wr(d, Hwcfg, rr(d, Hwcfg)|Mef); + wr(d, Usbcfg0, rr(d, Usbcfg0)|Bce); + wr(d, Burstcap, burstcap); + wr(d, Bulkdelay, bulkdelay); + }else{ + wr(d, Hwcfg, rr(d, Hwcfg)&~Mef); + wr(d, Usbcfg0, rr(d, Usbcfg0)&~Bce); + wr(d, Burstcap, 0); + wr(d, Bulkdelay, 0); + } + wr(d, Rxfifo, (Rxfifosize-512)/512); + wr(d, Txfifo, (Txfifosize-512)/512); + wr(d, Intsts, ~0); + wr(d, Hwcfg, rr(d, Hwcfg) | Led0en|Led1en); + wr(d, Flow, 0); + wr(d, Fctflow, 0); + wr(d, Rfectl, (rr(d, Rfectl) & ~Rxcoe) | Ab|Dpf); /* TODO could offload checksums? */ + + phyinit(d); + + wr(d, Maccr, rr(d,Maccr)|Add|Asd); + + wr(d, Intepctl, rr(d, Intepctl)|Phyint); + wr(d, Mactx, Mactxen); + wr(d, Macrx, rr(d, Macrx) | Macfcs|Macrxen); + wr(d, Txfifoctl, Txen); + wr(d, Rxfifoctl, Rxen); + + return 0; +} + +static long +lan78xxbread(Ether *e, Buf *bp) +{ + uint hd; + int n, m; + Buf *rbp; + + rbp = e->aux; + if(rbp->ndata < 10){ + rbp->rp = rbp->data; + rbp->ndata = read(e->epin->dfd, rbp->rp, Doburst? burstcap*512: + Maxpkt); + if(rbp->ndata < 0) + return -1; + } + if(rbp->ndata < 10){ + werrstr("short frame"); + fprint(2, "lan78xx short frame %d bytes\n", rbp->ndata); + sleep(1000); + return 0; + } + hd = GET4(rbp->rp); + n = hd & 0x3FFF; + rbp->rp += 10; + rbp->ndata -= 10; + if(n < 6 || n > rbp->ndata){ + werrstr("frame length"); + fprint(2, "lan78xx length error packet %d buf %d\n", n, rbp->ndata); + rbp->ndata = 0; + return 0; + } + if(hd & Rxerror){ + fprint(2, "lan78xx rx error %8.8ux\n", hd); + n = 0; + }else{ + bp->rp = bp->data + Hdrsize; + memmove(bp->rp, rbp->rp, n); + } + bp->ndata = n; + rbp->rp += n; + rbp->ndata -= n; + if(rbp->ndata > 0){ + m = rbp->rp - rbp->data; + if(m&3){ + m = 4 - (m&3); + rbp->rp += m; + rbp->ndata -= m; + } + } + return n; +} + +static long +lan78xxbwrite(Ether *e, Buf *bp) +{ + int n; + + n = bp->ndata & 0xFFFFF; + bp->rp -= 8; + bp->ndata += 8; + PUT4(bp->rp, n | Txfcs); + PUT4(bp->rp+4, 0); + n = write(e->epout->dfd, bp->rp, bp->ndata); + if(n != bp->ndata) + deprint(2, "bwrite %d: %r\n", n); + return n; +} + +static int +lan78xxpromiscuous(Ether *e, int on) +{ + Dev *d; + int rxctl; + + d = e->dev; + rxctl = rr(d, Rfectl); + if(on) + rxctl |= Am|Au; + else + rxctl &= ~(Am|Au); + return wr(d, Rfectl, rxctl); +} + +static int +lan78xxmulticast(Ether *e, uchar *addr, int on) +{ + int rxctl; + Dev *d; + + USED(addr, on); + /* BUG: should write multicast filter */ + d = e->dev; + rxctl = rr(d, Rfectl); + if(e->nmcasts != 0) + rxctl |= Am; + else + rxctl &= ~Am; + deprint(2, "%s: lan78xxmulticast %d\n", argv0, e->nmcasts); + return wr(d, Rfectl, rxctl); +} + +static void +lan78xxfree(Ether *ether) +{ + free(ether->aux); + ether->aux = nil; +} + +int +lan78xxreset(Ether *ether) +{ + Cinfo *ip; + Dev *dev; + + dev = ether->dev; + for(ip = cinfo; ip->vid != 0; ip++) + if(ip->vid == dev->usb->vid && ip->did == dev->usb->did){ + ether->cid = ip->cid; + if(lan78xxinit(ether) < 0){ + deprint(2, "%s: lan78xx init failed: %r\n", argv0); + return -1; + } + deprint(2, "%s: lan78xx reset done\n", argv0); + ether->name = "lan78xx"; + if(Doburst){ + ether->bufsize = burstcap*512; + ether->aux = emallocz(sizeof(Buf) + + ether->bufsize - Maxpkt, 1); + }else{ + ether->bufsize = Maxpkt; + ether->aux = emallocz(sizeof(Buf), 1); + } + ether->free = lan78xxfree; + ether->bread = lan78xxbread; + ether->bwrite = lan78xxbwrite; + ether->promiscuous = lan78xxpromiscuous; + ether->multicast = lan78xxmulticast; + ether->mbps = 100; /* BUG */ + return 0; + } + return -1; +} diff --git a/sys/src/cmd/usb/ether/mkfile b/sys/src/cmd/usb/ether/mkfile index 27571957d5..977f85f1be 100644 --- a/sys/src/cmd/usb/ether/mkfile +++ b/sys/src/cmd/usb/ether/mkfile @@ -8,6 +8,7 @@ LIBDOFILES=\ ether.$O\ asix.$O\ smsc.$O\ + lan78xx.$O\ cdc.$O\ HFILES=\ diff --git a/sys/src/cmd/usb/ether/smsc.c b/sys/src/cmd/usb/ether/smsc.c index 784dc793a0..296360cec3 100644 --- a/sys/src/cmd/usb/ether/smsc.c +++ b/sys/src/cmd/usb/ether/smsc.c @@ -15,10 +15,9 @@ enum { Resettime = 1000, E2pbusytime = 1000, Afcdefault = 0xF830A1, -// Hsburst = 37, /* from original linux driver */ - Hsburst = 8, + Hsburst = 24, Fsburst = 129, - Defbulkdly = 0x2000, + Defbulkdly = 1000, Ethp8021q = 0x8100, MACoffset = 1, @@ -102,6 +101,8 @@ enum { Linkdown= 1<<4, }; +static int burstcap = Hsburst, bulkdelay = Defbulkdly; + static int wr(Dev *d, int reg, int val) { @@ -238,12 +239,13 @@ smscinit(Ether *ether) wr(d, Addrh, GET2(ether->addr+4)); if(Doburst){ wr(d, Hwcfg, (rr(d,Hwcfg)&~Rxdoff)|Bir|Mef|Bce); - wr(d, Burstcap, Hsburst); + wr(d, Burstcap, burstcap); + wr(d, Bulkdelay, bulkdelay); }else{ wr(d, Hwcfg, (rr(d,Hwcfg)&~(Rxdoff|Mef|Bce))|Bir); wr(d, Burstcap, 0); + wr(d, Bulkdelay, 0); } - wr(d, Bulkdelay, Defbulkdly); wr(d, Intsts, ~0); wr(d, Ledgpio, Ledspd|Ledlnk|Ledfdx); wr(d, Flow, 0); @@ -274,7 +276,7 @@ smscbread(Ether *e, Buf *bp) rbp = e->aux; if(rbp->ndata < 4){ rbp->rp = rbp->data; - rbp->ndata = read(e->epin->dfd, rbp->rp, Doburst? Hsburst*512: + rbp->ndata = read(e->epin->dfd, rbp->rp, Doburst? burstcap*512: Maxpkt); if(rbp->ndata < 0) return -1; @@ -285,20 +287,24 @@ smscbread(Ether *e, Buf *bp) return 0; } hd = GET4(rbp->rp); + rbp->rp += 4; + rbp->ndata -= 4; n = hd >> 16; - m = (n + 4 + 3) & ~3; - if(n < 6 || m > rbp->ndata){ + if(n < 6 || n > rbp->ndata){ werrstr("frame length"); fprint(2, "smsc length error packet %d buf %d\n", n, rbp->ndata); rbp->ndata = 0; return 0; } + m = n; + if(rbp->ndata - m < 4) + m = rbp->ndata; if(hd & Rxerror){ fprint(2, "smsc rx error %8.8ux\n", hd); n = 0; }else{ bp->rp = bp->data + Hdrsize; - memmove(bp->rp, rbp->rp+4, n); + memmove(bp->rp, rbp->rp, n); } bp->ndata = n; rbp->rp += m; @@ -377,7 +383,7 @@ smscreset(Ether *ether) deprint(2, "%s: smsc reset done\n", argv0); ether->name = "smsc"; if(Doburst){ - ether->bufsize = Hsburst*512; + ether->bufsize = burstcap*512; ether->aux = emallocz(sizeof(Buf) + ether->bufsize - Maxpkt, 1); }else{ diff --git a/sys/src/cmd/usb/usbd/usbdb b/sys/src/cmd/usb/usbd/usbdb index 73c63ff536..10e6bef1de 100644 --- a/sys/src/cmd/usb/usbd/usbdb +++ b/sys/src/cmd/usb/usbd/usbdb @@ -5,6 +5,7 @@ embed disk class=storage args= ether class=255 csp=0x00ffff vid=0x0b95 args= ether class=255 csp=0xff00ff vid=0x0424 did=0xec00 args= + ether class=255 csp=0xff00ff vid=0x0424 did=0x7800 args= ether class=255 csp=0x000602 vid=0x0bda did=0x8152 args= serial class=255 csp=0xffffff vid=0x9e88 did=0x9e8f args= serial class=255 csp=0xffffff vid=0x0403 args= From 58ad3b98cca30b682285487e4464766f30722f2e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 31 May 2016 19:31:34 +0000 Subject: [PATCH 152/402] sys/src/cmd/usb/serial: break up long writes to fit the 63-byte limit imposed by FTDI serial protocol (thanks Richard Miller) --- sys/src/cmd/usb/serial/ftdi.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sys/src/cmd/usb/serial/ftdi.c b/sys/src/cmd/usb/serial/ftdi.c index d1997ef250..f4530b1dec 100644 --- a/sys/src/cmd/usb/serial/ftdi.c +++ b/sys/src/cmd/usb/serial/ftdi.c @@ -622,22 +622,28 @@ wait4data(Serialport *p, uchar *data, int count) static int wait4write(Serialport *p, uchar *data, int count) { - int off, fd; + int off, fd, nleft, n; uchar *b; Serial *ser; ser = p->s; - b = emallocz(count+ser->outhdrsz, 1); - off = ftsetouthdr(p, b, count); - memmove(b+off, data, count); - + b = emallocz(ser->maxwtrans, 1); fd = p->epout->dfd; qunlock(ser); - count = write(fd, b, count+off); + for(nleft = count; nleft > 0; data += n, nleft -= n){ + n = ser->maxwtrans - ser->outhdrsz; + if(n > nleft) + n = nleft; + off = ftsetouthdr(p, b, n); + memmove(b+off, data, n); + n = write(fd, b, n+off); + if(n <= 0) + break; + } qlock(ser); free(b); - return count; + return count - nleft; } typedef struct Packser Packser; From 3d84a60848cb88329a33a41c55afb673a95cf039 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 29 Sep 2019 16:59:14 +0000 Subject: [PATCH 153/402] sys/src/cmd/usb/usbd: implement USB 3.0 support (thanks Richard Miller) --- sys/src/cmd/usb/lib/usb.h | 6 ++ sys/src/cmd/usb/usbd/usbd.c | 179 ++++++++++++++++++++++++++---------- sys/src/cmd/usb/usbd/usbd.h | 17 ++++ 3 files changed, 151 insertions(+), 51 deletions(-) diff --git a/sys/src/cmd/usb/lib/usb.h b/sys/src/cmd/usb/lib/usb.h index e52dddae1f..b0fb281b50 100644 --- a/sys/src/cmd/usb/lib/usb.h +++ b/sys/src/cmd/usb/lib/usb.h @@ -49,6 +49,10 @@ enum { Rsetiface = 11, Rsynchframe = 12, + /* standard requests (USB3.0) */ + Rsethubdepth = 12, + Rgetporterrcnt = 13, + Rgetcur = 0x81, Rgetmin = 0x82, Rgetmax = 0x83, @@ -169,6 +173,8 @@ struct Dev int id; /* usb id for device or ep. number */ int dfd; /* descriptor for the data file */ int cfd; /* descriptor for the control file */ + int isusb3; /* this is a usb3 device */ + int depth; /* hub depth for usb3 hubs */ int maxpkt; /* cached from usb description */ Ref nerrs; /* number of errors in requests */ Usbdev* usb; /* USB description */ diff --git a/sys/src/cmd/usb/usbd/usbd.c b/sys/src/cmd/usb/usbd/usbd.c index 6b318ac1b1..f1f31a0478 100644 --- a/sys/src/cmd/usb/usbd/usbd.c +++ b/sys/src/cmd/usb/usbd/usbd.c @@ -54,7 +54,7 @@ confighub(Hub *h) { int type; uchar buf[128]; /* room for extra descriptors */ - int i; + int i, dt, dl; Usbdev *d; DHub *dd; Port *pp; @@ -65,22 +65,62 @@ confighub(Hub *h) int mask; d = h->dev->usb; + if(h->dev->isusb3){ + dt = Dsshub; + dl = Dsshublen; + } else { + dt = Dhub; + dl = Dhublen; + } for(i = 0; i < nelem(d->ddesc); i++) if(d->ddesc[i] == nil) break; - else if(d->ddesc[i]->data.bDescriptorType == Dhub){ + else if(d->ddesc[i]->data.bDescriptorType == dt){ dd = (DHub*)&d->ddesc[i]->data; - nr = Dhublen; + nr = d->ddesc[i]->data.bLength; goto Config; } type = Rd2h|Rclass|Rdev; - nr = usbcmd(h->dev, type, Rgetdesc, Dhub<<8|0, 0, buf, sizeof buf); - if(nr < Dhublen){ + nr = usbcmd(h->dev, type, Rgetdesc, dt<<8|0, 0, buf, sizeof buf); + if(nr < 0){ dprint(2, "%s: %s: getdesc hub: %r\n", argv0, h->dev->dir); return -1; } dd = (DHub*)buf; Config: + if(nr < dl){ + fprint(2, "%s: %s: hub descriptor too small (%d < %d)\n", argv0, h->dev->dir, nr, dl); + return -1; + } + if(h->dev->isusb3){ + DSSHub *ds; + ds = (DSSHub*)dd; + h->nport = ds->bNbrPorts; + nmap = 1 + h->nport/8; + if(nr < 10 + nmap){ + fprint(2, "%s: %s: descr. too small\n", argv0, h->dev->dir); + return -1; + } + h->port = emallocz((h->nport+1)*sizeof(Port), 1); + h->pwrms = ds->bPwrOn2PwrGood*2; + if(h->pwrms < Powerdelay) + h->pwrms = Powerdelay; + h->maxcurrent = ds->bHubContrCurrent; + h->pwrmode = ds->wHubCharacteristics[0] & 3; + h->compound = (ds->wHubCharacteristics[0] & (1<<2))!=0; + h->leds = (ds->wHubCharacteristics[0] & (1<<7)) != 0; + for(i = 1; i <= h->nport; i++){ + pp = &h->port[i]; + offset = i/8; + mask = 1<<(i%8); + pp->removable = (ds->DeviceRemovable[offset] & mask) != 0; + } + if(usbcmd(h->dev, Rh2d|Rclass|Rdev, Rsethubdepth, h->dev->depth, 0, nil, 0) < 0){ + fprint(2, "%s: %s: sethubdepth: %r\n", argv0, h->dev->dir); + return -1; + } + return 0; + } h->nport = dd->bNbrPorts; nmap = 1 + h->nport/8; if(nr < 7 + 2*nmap){ @@ -110,7 +150,7 @@ static void configroothub(Hub *h) { Dev *d; - char buf[128]; + char buf[1024]; char *p; int nr; @@ -123,6 +163,7 @@ configroothub(Hub *h) goto Done; buf[nr] = 0; + d->isusb3 = strstr(buf, "speed super") != nil; p = strstr(buf, "ports "); if(p == nil) fprint(2, "%s: %s: no port information\n", argv0, d->dir); @@ -144,6 +185,9 @@ newhub(char *fn, Dev *d) Hub *h; int i; Usbdev *ud; + int usbpower; + static int firsttime; + char *p; h = emallocz(sizeof(Hub), 1); h->isroot = (d == nil); @@ -157,6 +201,7 @@ newhub(char *fn, Dev *d) fprint(2, "%s: opendevdata: %s: %r\n", argv0, fn); goto Fail; } + h->dev->depth = -1; configroothub(h); /* never fails */ }else{ h->dev = d; @@ -177,6 +222,13 @@ newhub(char *fn, Dev *d) else{ devctl(h->dev, "info hub csp %#08ulx ports %d %q %q", ud->csp, h->nport, ud->vendor, ud->product); + if(!firsttime++ && (p = getenv("usbpower")) != nil){ + usbpower = atoi(p); + for(i = 1; i <= h->nport; i++) + if(hubfeature(h, i, Fportpower, 0) < 0) + fprint(2, "%s: %s: power: %r\n", argv0, fn); + sleep(usbpower); + } for(i = 1; i <= h->nport; i++) if(hubfeature(h, i, Fportpower, 1) < 0) fprint(2, "%s: %s: power: %r\n", argv0, fn); @@ -267,26 +319,28 @@ portstatus(Hub *h, int p) } static char* -stsstr(int sts) +stsstr(int sts, int isusb3) { static char s[80]; char *e; e = s; - if(sts&PSsuspend) - *e++ = 'z'; + if(!isusb3){ + if(sts&PSsuspend) + *e++ = 'z'; + if(sts&PSslow) + *e++ = 'l'; + if(sts&PShigh) + *e++ = 'h'; + if(sts&PSchange) + *e++ = 'c'; + if(sts&PSstatuschg) + *e++ = 's'; + } if(sts&PSreset) *e++ = 'r'; - if(sts&PSslow) - *e++ = 'l'; - if(sts&PShigh) - *e++ = 'h'; - if(sts&PSchange) - *e++ = 'c'; if(sts&PSenable) *e++ = 'e'; - if(sts&PSstatuschg) - *e++ = 's'; if(sts&PSpresent) *e++ = 'p'; if(e == s) @@ -332,30 +386,40 @@ portattach(Hub *h, int p, int sts) pp->state = Pattached; dprint(2, "%s: %s: port %d attach sts %#ux\n", argv0, d->dir, p, sts); sleep(Connectdelay); - if(hubfeature(h, p, Fportenable, 1) < 0) - dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p); - sleep(Enabledelay); - if(hubfeature(h, p, Fportreset, 1) < 0){ - dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p); - goto Fail; - } - sleep(Resetdelay); - sts = portstatus(h, p); - if(sts < 0) - goto Fail; - if((sts & PSenable) == 0){ - dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); - hubfeature(h, p, Fportenable, 1); + if(h->dev->isusb3){ + sleep(Enabledelay); sts = portstatus(h, p); - if((sts & PSenable) == 0) + if(sts == -1) + goto Fail; + if((sts & PSenable) == 0){ + dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); + goto Fail; + } + sp = "super"; + } else { + sleep(Enabledelay); + if(hubfeature(h, p, Fportreset, 1) < 0){ + dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p); goto Fail; + } + sleep(Resetdelay); + sts = portstatus(h, p); + if(sts < 0) + goto Fail; + if((sts & PSenable) == 0){ + dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); + hubfeature(h, p, Fportenable, 1); + sts = portstatus(h, p); + if((sts & PSenable) == 0) + goto Fail; + } + sp = "full"; + if(sts & PSslow) + sp = "low"; + if(sts & PShigh) + sp = "high"; + dprint(2, "%s: %s: port %d: attached status %#ux\n", argv0, d->dir, p, sts); } - sp = "full"; - if(sts & PSslow) - sp = "low"; - if(sts & PShigh) - sp = "high"; - dprint(2, "%s: %s: port %d: attached status %#ux\n", argv0, d->dir, p, sts); if(devctl(d, "newdev %s %d", sp, p) < 0){ fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p); @@ -378,6 +442,8 @@ portattach(Hub *h, int p, int sts) fprint(2, "%s: %s: port %d: opendev: %r\n", argv0, d->dir, p); goto Fail; } + nd->depth = h->dev->depth+1; + nd->isusb3 = h->dev->isusb3; if(usbdebug > 2) devctl(nd, "debug 1"); if(opendevdata(nd, ORDWR) < 0){ @@ -401,7 +467,7 @@ portattach(Hub *h, int p, int sts) dprint(2, "%s; %s: port %d: maxpkt %d\n", argv0, d->dir, p, mp); devctl(nd, "maxpkt %d", mp); } - if((sts & PSslow) != 0 && strcmp(sp, "full") == 0) + if(!h->dev->isusb3 && (sts & PSslow) != 0 && strcmp(sp, "full") == 0) dprint(2, "%s: %s: port %d: %s is full speed when port is low\n", argv0, d->dir, p, nd->dir); if(configdev(nd) < 0){ @@ -427,7 +493,8 @@ portattach(Hub *h, int p, int sts) pp->sts = 0; if(pp->hub != nil) pp->hub = nil; /* hub closed by enumhub */ - hubfeature(h, p, Fportenable, 0); + if(!h->dev->isusb3) + hubfeature(h, p, Fportenable, 0); if(nd != nil) devctl(nd, "detach"); closedev(nd); @@ -504,7 +571,7 @@ portresetwanted(Hub *h, int p) static void portreset(Hub *h, int p) { - int sts; + int i, sts; Dev *d, *nd; Port *pp; @@ -516,10 +583,16 @@ portreset(Hub *h, int p) dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p); goto Fail; } - sleep(Resetdelay); - sts = portstatus(h, p); - if(sts < 0) - goto Fail; + sts = 0; + for(i = 0; i < 10; i++){ + sleep(Resetdelay); + sts = portstatus(h, p); + if(sts < 0) + goto Fail; + if((sts & PSreset) == 0) + break; + } + dprint(2, "%s: %s: port %d sts %x after %d ms\n", argv0, d->dir, p, sts, (i+1)*Resetdelay); if((sts & PSenable) == 0){ dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); hubfeature(h, p, Fportenable, 1); @@ -528,7 +601,10 @@ portreset(Hub *h, int p) goto Fail; } nd = pp->dev; - opendevdata(nd, ORDWR); + if(opendevdata(nd, ORDWR) < 0){ + fprint(2, "%s: %s: opendevdata: %r\n", argv0, nd->dir); + goto Fail; + } if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p); goto Fail; @@ -574,7 +650,7 @@ portgone(Port *pp, int sts) static int enumhub(Hub *h, int p) { - int sts; + int sts, sts0; Dev *d; Port *pp; int onhubs; @@ -592,12 +668,13 @@ enumhub(Hub *h, int p) } pp = &h->port[p]; onhubs = nhubs; - if((sts & PSsuspend) != 0){ + if(!h->dev->isusb3 && (sts & PSsuspend) != 0){ if(hubfeature(h, p, Fportenable, 1) < 0) dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p); sleep(Enabledelay); + sts0 = sts; sts = portstatus(h, p); - fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts); + fprint(2, "%s: %s: port %d: resumed (sts %#ux -> %#ux)\n", argv0, d->dir, p, sts0, sts); } if((pp->sts & PSpresent) == 0 && (sts & PSpresent) != 0){ if(portattach(h, p, sts) != nil) @@ -609,8 +686,8 @@ enumhub(Hub *h, int p) portreset(h, p); else if(pp->sts != sts){ dprint(2, "%s: %s port %d: sts %s %#x ->", - argv0, d->dir, p, stsstr(pp->sts), pp->sts); - dprint(2, " %s %#x\n",stsstr(sts), sts); + argv0, d->dir, p, stsstr(pp->sts, h->dev->isusb3), pp->sts); + dprint(2, " %s %#x\n",stsstr(sts, h->dev->isusb3), sts); } pp->sts = sts; if(onhubs != nhubs) diff --git a/sys/src/cmd/usb/usbd/usbd.h b/sys/src/cmd/usb/usbd/usbd.h index 792db8d312..76dabf52b3 100644 --- a/sys/src/cmd/usb/usbd/usbd.h +++ b/sys/src/cmd/usb/usbd/usbd.h @@ -1,6 +1,7 @@ typedef struct Hub Hub; typedef struct Port Port; typedef struct DHub DHub; +typedef struct DSSHub DSSHub; typedef struct Devtab Devtab; typedef struct Usbfs Usbfs; @@ -10,6 +11,8 @@ enum Dhub = 0x29, /* hub descriptor type */ Dhublen = 9, /* hub descriptor length */ + Dsshub = 0x2A, /* superspeed hub descriptor type */ + Dsshublen = 12, /* superspeed hub descriptor length */ /* hub class feature selectors */ Fhublocalpower = 0, @@ -111,6 +114,20 @@ struct DHub uchar DeviceRemovable[1]; /* variable length */ }; +/* Superspeed HUB descriptor */ +struct DSSHub +{ + uchar bLength; + uchar bDescriptorType; + uchar bNbrPorts; + uchar wHubCharacteristics[2]; + uchar bPwrOn2PwrGood; + uchar bHubContrCurrent; + uchar bHubHdrDecLat; + uchar wHubDelay[2]; + uchar DeviceRemovable[1]; /* variable length */ +}; + struct Devtab { char *name; From 012e7fb31a8d7c3b3a0e9f17666c183d0f8167cc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 24 Nov 2021 15:17:22 +0000 Subject: [PATCH 154/402] sys/src/cmd/usb: allows USB 3.0 disks to be used in a USB 3.0 port on Raspberry Pi 4 (thanks Richard Miller) --- sys/src/cmd/usb/lib/parse.c | 11 ++++++++++- sys/src/cmd/usb/usbd/usbd.c | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/usb/lib/parse.c b/sys/src/cmd/usb/lib/parse.c index 642c427a23..e9dc7e076f 100644 --- a/sys/src/cmd/usb/lib/parse.c +++ b/sys/src/cmd/usb/lib/parse.c @@ -66,6 +66,11 @@ parseiface(Usbdev *d, Conf *c, uchar *b, int n, Iface **ipp, Altc **app) } if(c->iface[ifid] == nil) c->iface[ifid] = emallocz(sizeof(Iface), 1); + else{ + /* hack to avoid unsupported uasp disk interface */ + if(dip->bInterfaceClass == Clstorage && dip->bInterfaceProtocol != 0x50) + return 0; + } ip = c->iface[ifid]; class = dip->bInterfaceClass; subclass = dip->bInterfaceSubClass; @@ -164,6 +169,7 @@ parsedesc(Usbdev *d, Conf *c, uchar *b, int n) Ep *ep; Altc *altc; char *hd; + int ok; assert(d != nil && c != nil); tot = 0; @@ -174,6 +180,7 @@ parsedesc(Usbdev *d, Conf *c, uchar *b, int n) if(d->ddesc[nd] == nil) break; + ok = 1; while(n > 2 && b[0] != 0 && b[0] <= n){ len = b[0]; if(usbdebug>1){ @@ -189,7 +196,7 @@ parsedesc(Usbdev *d, Conf *c, uchar *b, int n) ddprint(2, "%s\tparsedesc: %r", argv0); break; case Diface: - if(parseiface(d, c, b, n, &ip, &altc) < 0){ + if((ok = parseiface(d, c, b, n, &ip, &altc)) < 0){ ddprint(2, "%s\tparsedesc: %r\n", argv0); return -1; } @@ -199,6 +206,8 @@ parsedesc(Usbdev *d, Conf *c, uchar *b, int n) werrstr("unexpected endpoint descriptor"); break; } + if(!ok) + break; if(parseendpt(d, c, ip, altc, b, n, &ep) < 0){ ddprint(2, "%s\tparsedesc: %r\n", argv0); return -1; diff --git a/sys/src/cmd/usb/usbd/usbd.c b/sys/src/cmd/usb/usbd/usbd.c index f1f31a0478..ffbbc1f617 100644 --- a/sys/src/cmd/usb/usbd/usbd.c +++ b/sys/src/cmd/usb/usbd/usbd.c @@ -362,6 +362,8 @@ getmaxpkt(Dev *d, int islow) dd->bMaxPacketSize0 = 64; if(usbcmd(d, Rd2h|Rstd|Rdev, Rgetdesc, Ddev<<8|0, 0, buf, sizeof(buf)) < 0) return -1; + if((dd->bcdUSB[1] & 0xF) == 3) + return 1 << dd->bMaxPacketSize0; return dd->bMaxPacketSize0; } From e0c4b1ba6d2e53df6837621f20143fff80b842f9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 31 Jul 2016 23:42:57 +0000 Subject: [PATCH 155/402] sys/src/cmd: various fixes and cleanup in xd (thanks Geoff Collyer) --- sys/src/cmd/xd.c | 110 ++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/sys/src/cmd/xd.c b/sys/src/cmd/xd.c index b3c0a998ae..2d91f62ad8 100644 --- a/sys/src/cmd/xd.c +++ b/sys/src/cmd/xd.c @@ -2,8 +2,12 @@ #include #include -uchar odata[16]; -uchar data[32]; +enum { + Nsee = 4*4, /* process this many bytes at a time; see swizz */ +}; + +uchar odata[Nsee]; +uchar data[2*Nsee]; int ndata; int nread; ulong addr; @@ -11,9 +15,11 @@ int repeats; int swizzle; int flush; int abase=2; + int xd(char *, int); void xprint(char *, ...); void initarg(void), swizz(void); + enum{ Narg=10, @@ -25,7 +31,7 @@ typedef struct Arg Arg; typedef void fmtfn(char *); struct Arg { - int chartype; /* TNone, TAscii, TRunes */ + int chartype; /* TNone, TAscii, TRunes */ int loglen; /* 0==1, 1==2, 2==4, 3==8 */ int base; /* 0==8, 1==10, 2==16 */ fmtfn *fn; /* function to call with data */ @@ -203,12 +209,35 @@ initarg(void) ap->afmt = afmt[narg>1][abase]; } +/* + * format the first ndata bytes in data[] (at most Nsee bytes). + * increment addr to account for them. + */ +void +fmtdata(void) +{ + Arg *ap; + + for(ap=arg; ap<&arg[narg]; ap++){ + xprint(ap->afmt, addr); + (*ap->fn)(ap->fmt); + xprint("\n", 0); + if(flush) + Bflush(&bout); + } + addr += ndata; + if(ndata= 0){ + /* read 2*Nsee but see only Nsee so that runes are happy */ + while((ndata=Bread(bp, data + nleft, 2*Nsee - nleft)) >= 0){ ndata += nleft; nleft = 0; nread = ndata; - if(ndata>nsee) - ndata = nsee; - else if(ndataNsee) + ndata = Nsee; + else if(ndata0 && data[0]==odata[0]){ - for(i=1; i0 && memcmp(odata, data, Nsee) == 0){ + doprint = 0; + if(star == 0){ + star++; + xprint("*\n", 0); } + } else { /* not a repetition */ + memmove(odata, data, Nsee); + star = 0; } - for(i=0; iafmt, addr); - (*ap->fn)(ap->fmt); - xprint("\n", 0); - if(flush) - Bflush(&bout); - } - addr += ndata; - if(ndatansee){ - nleft = nread - nsee; - memmove(data, data + nsee, nleft); + if(nread>Nsee){ + nleft = nread - Nsee; + memmove(data, data + Nsee, nleft); } } Bterm(bp); @@ -287,11 +299,11 @@ swizz(void) { uchar *p, *q; int i; - uchar swdata[16]; + uchar swdata[Nsee]; p = data; q = swdata; - for(i=0; i<16; i++) + for(i=0; i Date: Wed, 17 Aug 2016 19:30:25 +0000 Subject: [PATCH 156/402] sys/src/cmd/vac: increase buffer size and fix read in vacfs (thanks Geoff Collyer) --- sys/src/cmd/vac/file.c | 1 - sys/src/cmd/vac/vac.c | 3 +-- sys/src/cmd/vac/vacfs.c | 40 ++++++++++++++++++++++++++++------------ 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/sys/src/cmd/vac/file.c b/sys/src/cmd/vac/file.c index 119e07cdea..15defab972 100644 --- a/sys/src/cmd/vac/file.c +++ b/sys/src/cmd/vac/file.c @@ -2101,4 +2101,3 @@ sha1matches(VacFile *f, ulong b, uchar *buf, int n) return 1; return 0; } - diff --git a/sys/src/cmd/vac/vac.c b/sys/src/cmd/vac/vac.c index 5a8bae7d7f..ec939b7c73 100644 --- a/sys/src/cmd/vac/vac.c +++ b/sys/src/cmd/vac/vac.c @@ -558,7 +558,7 @@ vacstdin(VacFile *fp, char *name) { vlong off; VacFile *f; - static char buf[8192]; + static char buf[16*1024]; int n; if((f = vacfilecreate(fp, name, 0666)) == nil){ @@ -712,4 +712,3 @@ warn(char *fmt, ...) fprint(2, "\n"); va_end(arg); } - diff --git a/sys/src/cmd/vac/vacfs.c b/sys/src/cmd/vac/vacfs.c index 164bf8060d..dd17c3df36 100644 --- a/sys/src/cmd/vac/vacfs.c +++ b/sys/src/cmd/vac/vacfs.c @@ -17,12 +17,12 @@ enum struct Fid { - short busy; - short open; - int fid; - char *user; - Qid qid; - VacFile *file; + char busy; + char open; + int fid; + char *user; + Qid qid; + VacFile *file; VacDirEnum *vde; Fid *next; }; @@ -42,7 +42,7 @@ uchar *data; int mfd[2]; int srvfd = -1; char *user; -uchar mdata[8192+IOHDRSZ]; +uchar mdata[16*1024+IOHDRSZ]; int messagesize = sizeof mdata; Fcall rhdr; Fcall thdr; @@ -492,10 +492,9 @@ rread(Fid *f) { char *buf; vlong off; - int cnt; + int n, tot, cnt, zrds; VacFile *vf; char err[80]; - int n; if(!f->busy) return vtstrdup(Enotexist); @@ -512,8 +511,26 @@ rread(Fid *f) return vtstrdup("symbolic link"); else if(vacfilegetmode(f->file)&ModeNamedPipe) return vtstrdup("named pipe"); - else - n = vacfileread(vf, buf, cnt, off); + else { + /* + * Empirically, we can get a short read if it attempts to + * cross a venti block boundary, so keep trying, so that + * our clients get expected behaviour. We might get a + * zero-length read before actual end of file; stop after a few. + */ + tot = n = zrds = 0; + while (tot < cnt && zrds < 10 && + (n = vacfileread(vf, buf + tot, cnt - tot, off + tot)) >= 0){ + tot += n; /* read some bytes, if not cnt-tot */ + if (n == 0) + zrds++; + else + zrds = 0; + } + if (tot > 0) /* read something? */ + n = tot; /* return that much */ + /* else first (& last) read was eof | error, so leave n alone */ + } if(n < 0) { rerrstr(err, sizeof err); return vtstrdup(err); @@ -785,4 +802,3 @@ vacshutdown(void) vacfsclose(fs); vthangup(conn); } - From 8f1a58837aa8378b193f6f66397342334e3af5e8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 17 Aug 2016 20:26:29 +0000 Subject: [PATCH 157/402] sys/src/cmd/rc: handle bad runes in rc (thanks Geoff Collyer) --- sys/src/cmd/rc/code.c | 2 +- sys/src/cmd/rc/exec.c | 159 +++++++++++++++------- sys/src/cmd/rc/fns.h | 9 +- sys/src/cmd/rc/getflags.c | 233 -------------------------------- sys/src/cmd/rc/getflags.h | 7 - sys/src/cmd/rc/glob.c | 61 +++------ sys/src/cmd/rc/havefork.c | 21 ++- sys/src/cmd/rc/haventfork.c | 3 +- sys/src/cmd/rc/io.c | 70 ++++++---- sys/src/cmd/rc/io.h | 2 + sys/src/cmd/rc/lex.c | 109 ++++++++------- sys/src/cmd/rc/mkfile | 2 - sys/src/cmd/rc/pfnc.c | 4 +- sys/src/cmd/rc/plan9.c | 255 ++++++++++++++++++++---------------- sys/src/cmd/rc/rc.h | 50 +++---- sys/src/cmd/rc/rune.c | 165 +++++++++++++++++++++++ sys/src/cmd/rc/simple.c | 18 +-- sys/src/cmd/rc/syn.y | 4 +- sys/src/cmd/rc/tree.c | 2 +- sys/src/cmd/rc/unix.c | 21 ++- sys/src/cmd/rc/unix.h | 73 ++++++++++- sys/src/cmd/rc/utfrune.c | 28 ++++ sys/src/cmd/rc/utfutf.c | 24 ++++ sys/src/cmd/rc/var.c | 13 +- sys/src/cmd/rc/win32.c | 7 - 25 files changed, 723 insertions(+), 619 deletions(-) delete mode 100644 sys/src/cmd/rc/getflags.c delete mode 100644 sys/src/cmd/rc/getflags.h create mode 100644 sys/src/cmd/rc/rune.c create mode 100644 sys/src/cmd/rc/utfrune.c create mode 100644 sys/src/cmd/rc/utfutf.c diff --git a/sys/src/cmd/rc/code.c b/sys/src/cmd/rc/code.c index 7aad38bc12..cddab625e1 100644 --- a/sys/src/cmd/rc/code.c +++ b/sys/src/cmd/rc/code.c @@ -2,7 +2,7 @@ #include "io.h" #include "exec.h" #include "fns.h" -#include "getflags.h" + #define c0 t->child[0] #define c1 t->child[1] #define c2 t->child[2] diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c index 03141739ca..9c4c9beb5b 100644 --- a/sys/src/cmd/rc/exec.c +++ b/sys/src/cmd/rc/exec.c @@ -1,12 +1,15 @@ #include "rc.h" -#include "getflags.h" #include "exec.h" #include "io.h" #include "fns.h" + +char flagset[] = ""; /* anything non-nil will do */ +char *flag[NFLAG]; + /* * Start executing the given code at the given pc with the given redirection */ -char *argv0="rc"; +char *argv0; void start(code *c, int pc, var *local) @@ -113,6 +116,8 @@ var* newvar(char *name, var *next) { var *v = new(var); + + assert(name != nil); v->name = name; v->val = 0; v->fn = 0; @@ -121,62 +126,99 @@ newvar(char *name, var *next) v->next = next; return v; } + +/* fabricate bootstrap code (*=(argv);. /rc/lib/rcmain $*; exit) */ +static void +loadboot(code *base, int nel, char *rcmain) +{ + code *bs; + + bs = base; + bs++->i = 1; /* reference count */ + bs++->f = Xmark; /* "* = $*" */ + bs++->f = Xword; + bs++->s="*"; + bs++->f = Xassign; + bs++->f = Xmark; + bs++->f = Xmark; + bs++->f = Xword; + bs++->s="*"; + bs++->f = Xdol; + bs++->f = Xword; + bs++->s = rcmain; /* ". /rc/lib/rcmain $*" */ + bs++->f = Xword; + bs++->s="."; + bs++->f = Xsimple; + bs++->f = Xexit; /* exit */ + bs++->i = 0; /* not reached */ + if (bs > base + nel) + panic("bootstrap array too small", 0); +} + +void +usage(void) +{ + pfmt(err, "Usage: rc [-srdiIlxepvV] [-c arg] [-m command] " + "[file [arg ...]]\n"); + Exit("bad flags"); +} + /* * get command line flags, initialize keywords & traps. * get values from environment. * set $pid, $cflag, $* - * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) + * fabricate bootstrap code and start it * start interpreting code */ - void main(int argc, char *argv[]) { code bootstrap[17]; - char num[12], *rcmain; + char num[12]; int i; - argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1); - if(argc==-1) - usage("[file [arg ...]]"); - if(argv[0][0]=='-') + + err = openfd(2); + ARGBEGIN { + case 'd': case 'e': case 'i': case 'l': + case 'p': case 'r': case 's': case 'v': + case 'x': case 'I': case 'V': + flag[ARGC()] = flagset; + break; + case 'c': + case 'm': + if (flag[ARGC()]) + usage(); + flag[ARGC()] = EARGF(usage()); + break; + default: + usage(); + break; + } ARGEND + if(argc < 0) + usage(); + if(argv0 == nil) + argv0 = "rc"; + if(argv0[0]=='-') /* login shell? */ flag['l'] = flagset; if(flag['I']) flag['i'] = 0; - else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset; - rcmain = flag['m']?flag['m'][0]:Rcmain; - err = openfd(2); + else if(flag['i']==0 && argc==0 && Isatty(0)) + flag['i'] = flagset; /* force interactive */ + kinit(); Trapinit(); Vinit(); inttoascii(num, mypid = getpid()); setvar("pid", newword(num, (word *)0)); - setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) - :(word *)0); - setvar("rcname", newword(argv[0], (word *)0)); - i = 0; - memset(bootstrap, 0, sizeof bootstrap); - bootstrap[i++].i = 1; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xassign; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xdol; - bootstrap[i++].f = Xword; - bootstrap[i++].s = rcmain; - bootstrap[i++].f = Xword; - bootstrap[i++].s="."; - bootstrap[i++].f = Xsimple; - bootstrap[i++].f = Xexit; - bootstrap[i].i = 0; + setvar("cflag", flag['c']? newword(flag['c'], (word *)0): (word *)0); + setvar("rcname", newword(argv0, (word *)0)); + + loadboot(bootstrap, nelem(bootstrap), (flag['m']? flag['m']: Rcmain)); start(bootstrap, 1, (var *)0); /* prime bootstrap argv */ pushlist(); - argv0 = strdup(argv[0]); - for(i = argc-1;i!=0;--i) pushword(argv[i]); + for(i = argc-1; i >= 0; --i) + pushword(argv[i]); for(;;){ if(flag['r']) pfnc(err, runq); @@ -186,6 +228,7 @@ main(int argc, char *argv[]) dotrap(); } } + /* * Opcode routines * Arguments on stack (...) @@ -226,13 +269,14 @@ main(int argc, char *argv[]) * Xpipewait * Xpopm(value) pop value from stack * Xpopredir + * Xqdol(name) concatenate variable components * Xrdcmds * Xrdfn * Xrdwr(file)[fd] open file for reading and writing * Xread(file)[fd] open file to read - * Xqdol(name) concatenate variable components * Xreturn kill thread * Xsimple(args) run command and wait + * Xsettrue * Xsub * Xsubshell{... Xexit} execute {} in a subshell and wait * Xtrue{...} execute {} if true @@ -263,7 +307,7 @@ Xappend(void) Xerror("can't open"); return; } - Seek(f, 0L, 2); + seek(f, 0, 2); pushredir(ROPEN, f, runq->code[runq->pc].i); runq->pc++; poplist(); @@ -692,7 +736,7 @@ word* copynwords(word *a, word *tail, int n) { word *v, **end; - + v = 0; end = &v; while(n-- > 0){ @@ -930,24 +974,45 @@ Xrdcmds(void) } void -Xerror(char *s) +pargv0(io *f) { if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s: %r\n", s); + pfmt(f, "rc: "); else - pfmt(err, "rc (%s): %s: %r\n", argv0, s); + pfmt(f, "rc (%s): ", argv0); +} + +void +hisfault(io *f) +{ + thread *t; + + for(t = runq; !t->cmdfile && t->ret != 0; t = t->ret) + ; + if(t->cmdfile && !t->iflag) + pfmt(f, "%s:%d ", t->cmdfile, t->lineno); +} + +void +Xerror(char *s) +{ + io *msg = openstr(); + + pargv0(msg); + hisfault(msg); /* capture errstr before another sys call */ + pfmt(err, "%s%s: %r\n", (char *)msg->strp, s); + closeio(msg); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); } void -Xerror1(char *s) +Xerror1(char *s) /* omit errstr */ { - if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s\n", s); - else - pfmt(err, "rc (%s): %s\n", argv0, s); + pargv0(err); + hisfault(err); + pfmt(err, "%s\n", s); flush(err); setstatus("error"); while(!runq->iflag) Xreturn(); diff --git a/sys/src/cmd/rc/fns.h b/sys/src/cmd/rc/fns.h index 1559d91765..d0519d6cfd 100644 --- a/sys/src/cmd/rc/fns.h +++ b/sys/src/cmd/rc/fns.h @@ -15,7 +15,6 @@ void Noerror(void); int Opendir(char*); long Read(int, void*, long); int Readdir(int, void*, int); -long Seek(int, long, long); void Trapinit(void); void Unlink(char*); void Updenv(void); @@ -23,7 +22,7 @@ void Vinit(void); int Waitfor(int, int); long Write(int, void*, long); void addwaitpid(int); -int advance(void); +Rune advance(void); int back(int); void cleanhere(char*); void codefree(code*); @@ -37,7 +36,7 @@ void freenodes(void); void freewords(word*); void globlist(void); int havewaitpid(int); -int idchr(int); +int idchr(Rune); void inttoascii(char*, long); void kinit(void); int mapfd(int); @@ -60,8 +59,8 @@ void setvar(char*, word*); void skipnl(void); void start(code*, int, var*); int truestatus(void); -void usage(char*); -int wordchr(int); +void usage(void); +int wordchr(Rune); void yyerror(char*); int yylex(void); int yyparse(void); diff --git a/sys/src/cmd/rc/getflags.c b/sys/src/cmd/rc/getflags.c deleted file mode 100644 index 3c2f9adeb8..0000000000 --- a/sys/src/cmd/rc/getflags.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "rc.h" -#include "getflags.h" -#include "fns.h" -char *flagset[] = {""}; -char **flag[NFLAG]; -char *cmdname; -static char *flagarg=""; -static void reverse(char**, char**); -static int scanflag(int, char*); -static void errn(char*, int); -static void errs(char*); -static void errc(int); -static int reason; -#define RESET 1 -#define FEWARGS 2 -#define FLAGSYN 3 -#define BADFLAG 4 -static int badflag; - -int -getflags(int argc, char *argv[], char *flags, int stop) -{ - char *s; - int i, j, c, count; - flagarg = flags; - if(cmdname==0) - cmdname = argv[0]; - - i = 1; - while(i!=argc){ - if(argv[i][0] != '-' || argv[i][1] == '\0'){ - if(stop) /* always true in rc */ - return argc; - i++; - continue; - } - s = argv[i]+1; - while(*s){ - c=*s++; - count = scanflag(c, flags); - if(count==-1) - return -1; - if(flag[c]){ reason = RESET; badflag = c; return -1; } - if(count==0){ - flag[c] = flagset; - if(*s=='\0'){ - for(j = i+1;j<=argc;j++) - argv[j-1] = argv[j]; - --argc; - } - } - else{ - if(*s=='\0'){ - for(j = i+1;j<=argc;j++) - argv[j-1] = argv[j]; - --argc; - s = argv[i]; - } - if(argc-i int havefork = 1; @@ -83,11 +81,10 @@ Xbackq(void) int pfd[2]; char *stop; char utf[UTFmax+1]; - struct io *f; + io *f, *wd; var *ifs = vlook("ifs"); word *v, *nextv; Rune r; - String *word; stop = ifs->val? ifs->val->word: ""; if(pipe(pfd)<0){ @@ -110,26 +107,26 @@ Xbackq(void) addwaitpid(pid); close(pfd[PWR]); f = openfd(pfd[PRD]); - word = s_new(); + wd = openstr(); v = nil; /* rutf requires at least UTFmax+1 bytes in utf */ while((n = rutf(f, utf, &r)) != EOF){ utf[n] = '\0'; if(utfutf(stop, utf) == nil) - s_nappend(word, utf, n); + pstr(wd, utf); /* append utf to word */ else /* * utf/r is an ifs rune (e.g., \t, \n), thus * ends the current word, if any. */ - if(s_len(word) > 0){ - v = newword(s_to_c(word), v); - s_reset(word); + if(*(char *)wd->strp != '\0'){ + v = newword((char *)wd->strp, v); + rewind(wd); } } - if(s_len(word) > 0) - v = newword(s_to_c(word), v); - s_free(word); + if(*(char *)wd->strp != '\0') + v = newword((char *)wd->strp, v); + closeio(wd); closeio(f); Waitfor(pid, 0); /* v points to reversed arglist -- reverse it onto argv */ diff --git a/sys/src/cmd/rc/haventfork.c b/sys/src/cmd/rc/haventfork.c index 654e033ce0..94ea0fe31d 100644 --- a/sys/src/cmd/rc/haventfork.c +++ b/sys/src/cmd/rc/haventfork.c @@ -1,5 +1,4 @@ #include "rc.h" -#include "getflags.h" #include "exec.h" #include "io.h" #include "fns.h" @@ -47,7 +46,7 @@ Xasync(void) } runq->pc++; - sprint(buf, "%d", pid); + snprint(buf, sizeof buf, "%d", pid); setvar("apid", newword(buf, (word *)0)); } diff --git a/sys/src/cmd/rc/io.c b/sys/src/cmd/rc/io.c index d1d22a6911..e2db21d2f5 100644 --- a/sys/src/cmd/rc/io.c +++ b/sys/src/cmd/rc/io.c @@ -23,7 +23,7 @@ pfmt(io *f, char *fmt, ...) if(*++fmt == '\0') /* "blah%"? */ break; switch(*fmt){ - case 'c': + case 'c': /* char, not Rune */ pchr(f, va_arg(ap, int)); break; case 'd': @@ -64,7 +64,7 @@ pfmt(io *f, char *fmt, ...) } void -pchr(io *b, int c) +pchr(io *b, int c) /* print a char, not a Rune */ { if(b->bufp==b->ebuf) fullbuf(b, c); @@ -79,31 +79,39 @@ rchr(io *b) return *b->bufp++; } +/* + * read next utf sequence from b into buf, and convert it to Rune *r. + * return EOF or number of bytes consumed. + */ int rutf(io *b, char *buf, Rune *r) { - int n, i, c; + int i, c; c = rchr(b); - if(c == EOF) + if(c == EOF) { + buf[0] = 0; + *r = EOF; return EOF; + } *buf = c; - if(c < Runesync){ + if(c < Runeself){ /* ascii? */ + buf[1] = 0; *r = c; return 1; } - for(i = 1; (c = rchr(b)) != EOF; ){ + + /* multi-byte utf sequence */ + for(i = 1; i <= UTFmax && (c = rchr(b)) != EOF && c >= Runeself; ){ buf[i++] = c; buf[i] = 0; - if(fullrune(buf, i)){ - n = chartorune(r, buf); - b->bufp -= i - n; /* push back unconsumed bytes */ - assert(b->fd == -1 || b->bufp > b->buf); - return n; - } + if(fullrune(buf, i)) + return chartorune(r, buf); } - /* at eof */ - b->bufp -= i - 1; /* consume 1 byte */ + + /* bad utf sequence: too long, or unexpected ascii or EOF */ + if (c != EOF && c < Runeself && b->bufp > b->buf) + b->bufp--; /* push back ascii */ *r = Runeerror; return runetochar(buf, r); } @@ -123,10 +131,14 @@ void pwrd(io *f, char *s) { char *t; - for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break; - if(t==s || *t) + + for (t = s; *t; t++) + if (*(uchar *)t < Runeself && needsrcquote(*t)) + break; + if (t == s || *t) pquo(f, s); - else pstr(f, s); + else + pstr(f, s); } void @@ -134,12 +146,14 @@ pptr(io *f, void *v) { int n; uintptr p; + static char uphex[] = "0123456789ABCDEF"; p = (uintptr)v; - if(sizeof(uintptr) == sizeof(uvlong) && p>>32) - for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); - - for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); + if (sizeof(uintptr) == sizeof(uvlong) && p >> 32) + for (n = 60; n >= 32; n -= 4) + pchr(f, uphex[(p>>n)&0xF]); + for (n = 28; n >= 0; n -= 4) + pchr(f, uphex[(p>>n)&0xF]); } void @@ -244,6 +258,7 @@ openstr(void) f->fd = -1; f->bufp = f->strp = emalloc(Stralloc+1); f->ebuf = f->bufp + Stralloc; + f->output = 1; memset(f->bufp, '\0', Stralloc+1); return f; } @@ -261,6 +276,7 @@ opencore(char *s, int len) f->fd = -1 /*open("/dev/null", 0)*/; f->bufp = f->strp = buf; f->ebuf = buf+len; + f->output = 0; Memcpy(buf, s, len); return f; } @@ -268,11 +284,13 @@ opencore(char *s, int len) void rewind(io *io) { - if(io->fd==-1) + if(io->fd==-1) { io->bufp = io->strp; - else{ + if (io->output) + memset(io->strp, 0, io->ebuf - io->strp); + }else{ io->bufp = io->ebuf = io->buf; - Seek(io->fd, 0L, 0); + seek(io->fd, 0, 0); } } @@ -290,7 +308,9 @@ int emptybuf(io *f) { int n; - if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF; + + if(f->fd == -1 || (n = Read(f->fd, f->buf, NBUF))<=0) + return EOF; f->bufp = f->buf; f->ebuf = f->buf + n; return *f->bufp++; diff --git a/sys/src/cmd/rc/io.h b/sys/src/cmd/rc/io.h index 5d33fd2777..62b463b7af 100644 --- a/sys/src/cmd/rc/io.h +++ b/sys/src/cmd/rc/io.h @@ -5,6 +5,7 @@ struct io{ int fd; uchar *bufp, *ebuf, *strp; uchar buf[NBUF]; + uchar output; /* flag */ }; io *err; @@ -13,6 +14,7 @@ int emptybuf(io*); void pchr(io*, int); int rchr(io*); int rutf(io*, char*, Rune*); +void rewind(io*); void closeio(io*); void flush(io*); int fullbuf(io*, int); diff --git a/sys/src/cmd/rc/lex.c b/sys/src/cmd/rc/lex.c index bccc0118ec..74e56ad9ad 100644 --- a/sys/src/cmd/rc/lex.c +++ b/sys/src/cmd/rc/lex.c @@ -1,35 +1,43 @@ #include "rc.h" #include "exec.h" #include "io.h" -#include "getflags.h" #include "fns.h" -int getnext(void); + +Rune getnext(void); int -wordchr(int c) +wordchr(Rune c) /* is c in the alphabet of words (non-delimiters)? */ { - return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF; + return c != EOF && + (c >= Runeself || strchr("\n \t#;&|^$=`'{}()<>", c) == nil); } +/* + * is c in the alphabet of identifiers? as in the c compiler, treat + * non-ascii as alphabetic. + */ int -idchr(int c) +idchr(Rune c) { /* * Formerly: * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9' * || c=='_' || c=='*'; */ - return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c); + return c != EOF && (c >= Runeself || + c > ' ' && + strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c) == nil); } -int future = EOF; + +Rune future = EOF; int doprompt = 1; -int inquote; -int incomm; +int inquote; /* are we processing a quoted word ('...')? */ +int incomm; /* are we ignoring input in a comment (#...\n)? */ /* * Look ahead in the input stream */ -int +Rune nextc(void) { if(future==EOF) @@ -40,23 +48,26 @@ nextc(void) * Consume the lookahead character. */ -int +Rune advance(void) { - int c = nextc(); + Rune c = nextc(); + lastc = future; future = EOF; return c; } /* * read a character from the input stream - */ + */ -int +Rune getnext(void) { - int c; - static int peekc = EOF; + Rune c; + char buf[UTFmax+1]; + static Rune peekc = EOF; + if(peekc!=EOF){ c = peekc; peekc = EOF; @@ -66,9 +77,9 @@ getnext(void) return EOF; if(doprompt) pprompt(); - c = rchr(runq->cmdfd); + rutf(runq->cmdfd, buf, &c); if(!inquote && c=='\\'){ - c = rchr(runq->cmdfd); + rutf(runq->cmdfd, buf, &c); if(c=='\n' && !incomm){ /* don't continue a comment */ doprompt = 1; c=' '; @@ -105,7 +116,8 @@ pprompt(void) void skipwhite(void) { - int c; + Rune c; + for(;;){ c = nextc(); /* Why did this used to be if(!inquote && c=='#') ?? */ @@ -129,18 +141,22 @@ skipwhite(void) void skipnl(void) { - int c; - for(;;){ + Rune c, c0; + + for(c0 = nextc(); ; c0 = c){ skipwhite(); c = nextc(); + if(c != c0) + lastword = 0; /* change of whitespace or c is not ws */ if(c!='\n') return; + lastword = 0; /* new line; continue */ advance(); } } int -nextis(int c) +nextis(Rune c) { if(nextc()==c){ advance(); @@ -150,38 +166,16 @@ nextis(int c) } char* -addtok(char *p, int val) +addutf(char *p, Rune c) { if(p==0) return 0; - if(p >= &tok[NTOK]){ + if(p >= &tok[NTOK-1-UTFmax*2]){ *p = 0; yyerror("token buffer too short"); return 0; } - *p++=val; - return p; -} - -char* -addutf(char *p, int c) -{ - uchar b, m; - int i; - - p = addtok(p, c); /* 1-byte UTF runes are special */ - if(c < Runeself) - return p; - - m = 0xc0; - b = 0x80; - for(i=1; i < UTFmax; i++){ - if((c&m) == b) - break; - p = addtok(p, advance()); - b = m; - m = (m >> 1)|0x80; - } + p += runetochar(p, &c); return p; } @@ -191,16 +185,17 @@ int lastword; /* was the last token read a word or compound word terminator? */ int yylex(void) { - int c, d = nextc(); + Rune c, d = nextc(); char *w = tok; struct tree *t; + yylval.tree = 0; /* - * Embarassing sneakiness: if the last token read was a quoted or unquoted - * WORD then we alter the meaning of what follows. If the next character - * is `(', we return SUB (a subscript paren) and consume the `('. Otherwise, - * if the next character is the first character of a simple or compound word, - * we insert a `^' before it. + * Embarrassing sneakiness: if the last token read was a quoted or + * unquoted WORD then we alter the meaning of what follows. If the + * next character is `(', we return SUB (a subscript paren) and + * consume the `('. Otherwise, if the next character is the first + * character of a simple or compound word, we insert a `^' before it. */ if(lastword){ lastword = 0; @@ -214,7 +209,6 @@ yylex(void) return '^'; } } - inquote = 0; skipwhite(); switch(c = advance()){ case EOF: @@ -357,23 +351,22 @@ yylex(void) t = token(tok, WORD); t->quoted = 1; yylval.tree = t; + inquote = 0; return t->type; } if(!wordchr(c)){ lastdol = 0; - tok[0] = c; - tok[1]='\0'; + addutf(tok, c); return c; } for(;;){ if(c=='*' || c=='[' || c=='?' || c==GLOB) - w = addtok(w, GLOB); + w = addutf(w, GLOB); w = addutf(w, c); c = nextc(); if(lastdol?!idchr(c):!wordchr(c)) break; advance(); } - lastword = 1; lastdol = 0; if(w!=0) diff --git a/sys/src/cmd/rc/mkfile b/sys/src/cmd/rc/mkfile index b2ea3c5eb9..2bdfa2fa17 100644 --- a/sys/src/cmd/rc/mkfile +++ b/sys/src/cmd/rc/mkfile @@ -4,7 +4,6 @@ TARG=rc COMMONOFILES=\ code.$O\ exec.$O\ - getflags.$O\ glob.$O\ here.$O\ io.$O\ @@ -29,7 +28,6 @@ HFILES=rc.h\ io.h\ exec.h\ fns.h\ - getflags.h\ YFILES=syn.y diff --git a/sys/src/cmd/rc/pfnc.c b/sys/src/cmd/rc/pfnc.c index 4c99a03795..1d0a12bad9 100644 --- a/sys/src/cmd/rc/pfnc.c +++ b/sys/src/cmd/rc/pfnc.c @@ -63,14 +63,14 @@ pfnc(io *fd, thread *t) list *a; pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc); - for (i = 0; fname[i].f; i++) + for (i = 0; fname[i].f; i++) if (fname[i].f == fn) { pstr(fd, fname[i].name); break; } if (!fname[i].f) pfmt(fd, "%p", fn); - for (a = t->argv; a; a = a->next) + for (a = t->argv; a; a = a->next) pfmt(fd, " (%v)", a->words); pchr(fd, '\n'); flush(fd); diff --git a/sys/src/cmd/rc/plan9.c b/sys/src/cmd/rc/plan9.c index 4d7ad0edf0..294a93f11e 100644 --- a/sys/src/cmd/rc/plan9.c +++ b/sys/src/cmd/rc/plan9.c @@ -7,11 +7,6 @@ #include "exec.h" #include "io.h" #include "fns.h" -#include "getflags.h" - -enum { - Maxenvname = 256, /* undocumented limit */ -}; char *Signame[] = { "sigexit", "sighup", "sigint", "sigquit", @@ -63,27 +58,28 @@ execnewpgrp(void) break; case 2: arg = 0; - for(s = runq->argv->words->next->word;*s;s++) switch(*s){ - default: - goto Usage; - case 'n': - arg|=RFNAMEG; break; - case 'N': - arg|=RFCNAMEG; - break; - case 'm': - arg|=RFNOMNT; break; - case 'e': - arg|=RFENVG; break; - case 'E': - arg|=RFCENVG; break; - case 's': - arg|=RFNOTEG; break; - case 'f': - arg|=RFFDG; break; - case 'F': - arg|=RFCFDG; break; - } + for(s = runq->argv->words->next->word;*s;s++) + switch(*s){ + default: + goto Usage; + case 'n': + arg|=RFNAMEG; break; + case 'N': + arg|=RFCNAMEG; + break; + case 'm': + arg|=RFNOMNT; break; + case 'e': + arg|=RFENVG; break; + case 'E': + arg|=RFCENVG; break; + case 's': + arg|=RFNOTEG; break; + case 'f': + arg|=RFFDG; break; + case 'F': + arg|=RFCFDG; break; + } break; default: Usage: @@ -101,12 +97,40 @@ execnewpgrp(void) poplist(); } +int +openenv(char *shortname) +{ + int f; + io *envname; + + envname = openstr(); + pfmt(envname, "/env/%s", shortname); + f = open((char *)envname->strp, OREAD); + closeio(envname); + return f; +} + +int +createenv(char *pfx, char *shortname) +{ + int f; + io *envname; + + envname = openstr(); + pfmt(envname, "/env/%s%s", pfx, shortname); + f = Creat((char *)envname->strp); + if (f < 0) + pfmt(err, "rc: can't create %s: %r\n", (char *)envname->strp); + closeio(envname); + return f; +} + void Vinit(void) { int dir, f, len, i, n, nent; - char *buf, *s; - char envname[Maxenvname]; + char *buf, *s, *name; + var *namevar; word *val; Dir *ent; @@ -116,52 +140,52 @@ Vinit(void) return; } ent = nil; - for(;;){ - nent = dirread(dir, &ent); - if(nent <= 0) - break; + while ((nent = dirread(dir, &ent)) > 0) { for(i = 0; i=0){ - buf = emalloc(len+1); - n = readn(f, buf, len); - if (n <= 0) - buf[0] = '\0'; - else - buf[n] = '\0'; - val = 0; - /* Charitably add a 0 at the end if need be */ - if(buf[len-1]) - buf[len++]='\0'; - s = buf+len-1; - for(;;){ - while(s!=buf && s[-1]!='\0') --s; - val = newword(s, val); - if(s==buf) - break; - --s; - } - setvar(ent[i].name, val); - vlook(ent[i].name)->changed = 0; - close(f); - efree(buf); - } + name = ent[i].name; + if(len <= 0 || strncmp(name, "fn#", 3) == 0) + continue; + if((f = openenv(name)) < 0) + continue; + buf = emalloc(len+1); + n = readn(f, buf, len); + if (n <= 0) + buf[0] = '\0'; + else + buf[n] = '\0'; + val = 0; + /* Charitably add a 0 at the end if need be */ + if(buf[len-1]) + buf[len++]='\0'; + s = buf+len-1; + for(;;){ + while(s!=buf && s[-1]!='\0') + --s; + val = newword(s, val); + if(s==buf) + break; + --s; } + setvar(name, val); + namevar = vlook(name); + assert(namevar != nil); + namevar->changed = 0; + close(f); + efree(buf); } free(ent); } close(dir); } + int envdir; void Xrdfn(void) { - int f, len; + int f; Dir *e; - char envname[Maxenvname]; static Dir *ent, *allocent; static int nent; @@ -176,10 +200,8 @@ Xrdfn(void) while(nent){ e = ent++; nent--; - len = e->length; - if(len && strncmp(e->name, "fn#", 3)==0){ - snprint(envname, sizeof envname, "/env/%s", e->name); - if((f = open(envname, 0))>=0){ + if(e->length && strncmp(e->name, "fn#", 3)==0){ + if((f = openenv(e->name)) >= 0){ execcmds(openfd(f)); return; } @@ -189,6 +211,7 @@ Xrdfn(void) close(envdir); Xreturn(); } + union code rdfns[4]; void @@ -222,6 +245,9 @@ Waitfor(int pid, int) return 0; while((w = wait()) != nil){ + /* this would otherwise go unreported by rc */ + if(strstr(w->msg, "error in demand load") != nil) + pfmt(err, "rc: %s\n", w->msg); delwaitpid(w->pid); if(w->pid==pid){ setstatus(w->msg); @@ -254,27 +280,20 @@ mkargv(word *a) void addenv(var *v) { - char envname[Maxenvname]; word *w; int f; io *fd; if(v->changed){ v->changed = 0; - snprint(envname, sizeof envname, "/env/%s", v->name); - if((f = Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ + if((f = createenv("", v->name)) >= 0) { for(w = v->val;w;w = w->next) - write(f, w->word, strlen(w->word)+1L); + write(f, w->word, strlen(w->word)+1); close(f); } } if(v->fnchanged){ v->fnchanged = 0; - snprint(envname, sizeof envname, "/env/fn#%s", v->name); - if((f = Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ + if((f = createenv("fn#", v->name)) >= 0) { if(v->fn){ fd = openfd(f); pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s); @@ -339,43 +358,48 @@ void Execute(word *args, word *path) { char **argv = mkargv(args); - char file[1024], errstr[1024]; + char file[1024], errstr[ERRMAX+1]; int nc; Updenv(); errstr[0] = '\0'; for(;path;path = path->next){ nc = strlen(path->word); - if(nc < sizeof file - 1){ /* 1 for / */ - strcpy(file, path->word); - if(file[0]){ - strcat(file, "/"); - nc++; - } - if(nc + strlen(argv[1]) < sizeof file){ - strcat(file, argv[1]); - exec(file, argv+1); - rerrstr(errstr, sizeof errstr); - /* - * if file exists and is executable, exec should - * have worked, unless it's a directory or an - * executable for another architecture. in - * particular, if it failed due to lack of - * swap/vm (e.g., arg. list too long) or other - * allocation failure, stop searching and print - * the reason for failure. - */ - if (strstr(errstr, " allocat") != nil || - strstr(errstr, " full") != nil) - break; - } - else werrstr("command name too long"); + if(nc >= sizeof file - 1){ /* 1 for / */ + werrstr("path component too long"); + continue; + } + strcpy(file, path->word); + if(file[0]){ + strcat(file, "/"); + nc++; + } + if(nc + strlen(argv[1]) >= sizeof file){ + werrstr("command name too long"); + continue; } + strcat(file, argv[1]); + exec(file, argv+1); + /* + * if file exists and is executable, exec should have worked, + * unless it's a directory or an executable for another + * architecture. in particular, if it failed due to lack of + * swap/vm (e.g., arg. list too long) or other allocation or + * i/o failure, stop searching and print the reason for failure. + */ + rerrstr(errstr, sizeof errstr); + if (strstr(errstr, " allocat") != nil || + strstr(errstr, " full") != nil || + strstr(errstr, "i/o error") != nil) + break; } + if(errstr[0] == '\0') /* pick up any werrstr "too long"s */ + rerrstr(errstr, sizeof errstr); pfmt(err, "%s: %s\n", argv[1], errstr); efree((char *)argv); } -#define NDIR 256 /* shoud be a better way */ + +#define NDIR 256 /* should be a better way */ int Globsize(char *p) @@ -438,7 +462,7 @@ trimdirs(Dir *d, int nd) * onlydirs is advisory -- it means you only * need to return the directories. it's okay to * return files too (e.g., on unix where you can't - * tell during the readdir), but that just makes + * tell during the readdir), but that just makes * the globber work harder. */ int @@ -458,7 +482,7 @@ Readdir(int f, void *p, int onlydirs) n = trimdirs(dir[f].dbuf, n); if(n == 0) goto Again; - } + } dir[f].n = n; }else dir[f].n = 0; @@ -482,24 +506,29 @@ Closedir(int f) } close(f); } + int interrupted = 0; + void notifyf(void*, char *s) { int i; - for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){ - if(strncmp(s, "sys: ", 5)!=0) interrupted = 1; - goto Out; - } + + for (i = 0; syssigname[i]; i++) + if (strncmp(s, syssigname[i], strlen(syssigname[i])) == 0) { + if (strncmp(s, "sys: ", 5) != 0) + interrupted = 1; + goto Out; + } pfmt(err, "rc: note: %s\n", s); noted(NDFLT); return; Out: - if(strcmp(s, "interrupt")!=0 || trap[i]==0){ + if (strcmp(s, "interrupt") != 0 || trap[i] == 0) { trap[i]++; ntrap++; } - if(ntrap>=32){ /* rc is probably in a trap loop */ + if (ntrap >= 32) { /* rc is probably in a trap loop */ pfmt(err, "rc: Too many traps (trap %s), aborting\n", s); abort(); } @@ -530,12 +559,6 @@ Read(int fd, void *buf, long cnt) return read(fd, buf, cnt); } -long -Seek(int fd, long cnt, long whence) -{ - return seek(fd, cnt, whence); -} - int Executable(char *file) { @@ -553,7 +576,7 @@ Executable(char *file) int Creat(char *file) { - return create(file, 1, 0666L); + return create(file, 1, 0666); } int @@ -640,7 +663,7 @@ void delwaitpid(int pid) { int r, w; - + for(r=w=0; r= '0' && (c) <= '9') /* NB: unsafe macro */ + #ifndef Unix /* plan 9 */ #include #include +#pragma incomplete word +#pragma incomplete io + +/* unix compatibility */ +#define unixclsexec(wdirfd) + #define NSIG 32 #define SIGINT 2 #define SIGQUIT 3 - -#define fcntl(fd, op, arg) /* unix compatibility */ -#define F_SETFD -#define FD_CLOEXEC #else #include "unix.h" #endif -#ifndef ERRMAX -#define ERRMAX 128 -#endif - #define YYMAXDEPTH 500 #ifndef YYPREFIX #ifndef PAREN @@ -30,21 +40,6 @@ #endif #endif -typedef struct tree tree; -typedef struct word word; -typedef struct io io; -typedef union code code; -typedef struct var var; -typedef struct list list; -typedef struct redir redir; -typedef struct thread thread; -typedef struct builtin builtin; - -#ifndef Unix -#pragma incomplete word -#pragma incomplete io -#endif - struct tree{ int type; int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ @@ -147,5 +142,10 @@ char *Rcmain, *Fdprefix; */ int ndot; char *getstatus(void); -int lastc; +Rune lastc; int lastword; + +#define NFLAG 128 /* limited to ascii */ + +extern char *flag[NFLAG]; +extern char flagset[]; diff --git a/sys/src/cmd/rc/rune.c b/sys/src/cmd/rc/rune.c new file mode 100644 index 0000000000..cb1ea87a94 --- /dev/null +++ b/sys/src/cmd/rc/rune.c @@ -0,0 +1,165 @@ +#include "rc.h" + +#define Bit(i) (7-(i)) +/* N 0's preceded by i 1's, T(Bit(2)) is 1100 0000 */ +#define T(i) (((1 << (Bit(i)+1))-1) ^ 0xFF) +/* 0000 0000 0000 0111 1111 1111 */ +#define RuneX(i) ((1 << (Bit(i) + ((i)-1)*Bitx))-1) + +enum +{ + Bitx = Bit(1), + + Tx = T(1), /* 1000 0000 */ + Rune1 = (1<<(Bit(0)+0*Bitx))-1, /* 0000 0000 0000 0000 0111 1111 */ + + Maskx = (1< T1 + * 00080-007FF => T2 Tx + * 00800-0FFFF => T3 Tx Tx + * 10000-10FFFF => T4 Tx Tx Tx + */ + + c[0] = *(uchar*)(str); + if(c[0] < Tx){ + *rune = c[0]; + return 1; + } + l = c[0]; + + for(i = 1; i < UTFmax; i++) { + c[i] = *(uchar*)(str+i); + c[i] ^= Tx; + if(c[i] & Testx) + goto bad; + l = (l << Bitx) | c[i]; + if(c[0] < T(i + 2)) { + l &= RuneX(i + 1); + if(i == 1) { + if(c[0] < T(2) || l <= Rune1) + goto bad; + } else if(l <= RuneX(i) || l > Runemax) + goto bad; + if (i == 2 && SurrogateMin <= l && l <= SurrogateMax) + goto bad; + *rune = l; + return i + 1; + } + } + + /* + * bad decoding + */ +bad: + *rune = Bad; + return 1; +} + +int +runetochar(char *str, Rune *rune) +{ + int i, j; + Rune c; + + c = *rune; + if(c <= Rune1) { + str[0] = c; + return 1; + } + + /* + * one character sequence + * 00000-0007F => 00-7F + * two character sequence + * 0080-07FF => T2 Tx + * three character sequence + * 0800-FFFF => T3 Tx Tx + * four character sequence (21-bit value) + * 10000-1FFFFF => T4 Tx Tx Tx + * If the Rune is out of range or a surrogate half, + * convert it to the error rune. + * Do this test when i==3 because the error rune encodes to three bytes. + * Doing it earlier would duplicate work, since an out of range + * Rune wouldn't have fit in one or two bytes. + */ + for(i = 2; i < UTFmax + 1; i++){ + if(i == 3){ + if(c > Runemax) + c = Runeerror; + if(SurrogateMin <= c && c <= SurrogateMax) + c = Runeerror; + } + if (c <= RuneX(i) || i == UTFmax ) { + str[0] = T(i) | (c >> (i - 1)*Bitx); + for(j = 1; j < i; j++) + str[j] = Tx | ((c >> (i - j - 1)*Bitx) & Maskx); + return i; + } + } + return UTFmax; +} + +int +runelen(long c) +{ + Rune rune; + char str[10]; + + rune = c; + return runetochar(str, &rune); +} + +int +runenlen(Rune *r, int nrune) +{ + int nb, i; + Rune c; + + nb = 0; + while(nrune--) { + c = *r++; + if(c <= Rune1){ + nb++; + } else { + for(i = 2; i < UTFmax + 1; i++) + if(c <= RuneX(i) || i == UTFmax){ + nb += i; + break; + } + } + } + return nb; +} + +int +fullrune(char *str, int n) +{ + int i; + Rune c; + + if(n <= 0) + return 0; + c = *(uchar*)str; + if(c < Tx) + return 1; + for(i = 3; i < UTFmax + 1; i++) + if(c < T(i)) + return n >= i - 1; + return n >= UTFmax; +} diff --git a/sys/src/cmd/rc/simple.c b/sys/src/cmd/rc/simple.c index 2dbf51fe48..3d7ec48d7b 100644 --- a/sys/src/cmd/rc/simple.c +++ b/sys/src/cmd/rc/simple.c @@ -2,7 +2,6 @@ * Maybe `simple' is a misnomer. */ #include "rc.h" -#include "getflags.h" #include "exec.h" #include "io.h" #include "fns.h" @@ -10,7 +9,8 @@ * Search through the following code to see if we're just going to exit. */ int -exitnext(void){ +exitnext(void) +{ union code *c=&runq->code[runq->pc]; while(c->f==Xpopredir) c++; return c->f==Xexit; @@ -146,7 +146,7 @@ dochdir(char *word) if(wdirfd==-2) /* try only once */ wdirfd = open("/dev/wdir", OWRITE|OCEXEC); if(wdirfd>=0) { - fcntl(wdirfd, F_SETFD, FD_CLOEXEC); + unixclsexec(wdirfd); write(wdirfd, word, strlen(word)); } } @@ -263,15 +263,6 @@ execshift(void) poplist(); } -int -octal(char *s) -{ - int n = 0; - while(*s==' ' || *s=='\t' || *s=='\n') s++; - while('0'<=*s && *s<='7') n = n*8+*s++-'0'; - return n; -} - int mapfd(int fd) { @@ -447,7 +438,8 @@ execflag(void) } void -execwhatis(void){ /* mildly wrong -- should fork before writing */ +execwhatis(void) /* mildly wrong -- should fork before writing */ +{ word *a, *b, *path; var *v; struct builtin *bp; diff --git a/sys/src/cmd/rc/syn.y b/sys/src/cmd/rc/syn.y index c7de353138..e64a36dd0c 100644 --- a/sys/src/cmd/rc/syn.y +++ b/sys/src/cmd/rc/syn.y @@ -45,7 +45,7 @@ cmd: {$$=0;} | IF NOT {skipnl();} cmd {$$=mung1($2, $4);} | FOR '(' word IN words ')' {skipnl();} cmd /* - * if ``words'' is nil, we need a tree element to distinguish between + * if ``words'' is nil, we need a tree element to distinguish between * for(i in ) and for(i), the former being a loop over the empty set * and the latter being the implicit argument loop. so if $5 is nil * (the empty set), we represent it as "()". don't parenthesize non-nil @@ -73,7 +73,7 @@ cmd: {$$=0;} simple: first | simple word {$$=tree2(ARGLIST, $1, $2);} | simple redir {$$=tree2(ARGLIST, $1, $2);} -first: comword +first: comword | first '^' word {$$=tree2('^', $1, $3);} word: keyword {lastword=1; $1->type=WORD;} | comword diff --git a/sys/src/cmd/rc/tree.c b/sys/src/cmd/rc/tree.c index a2cd1af697..338cf5bd90 100644 --- a/sys/src/cmd/rc/tree.c +++ b/sys/src/cmd/rc/tree.c @@ -138,7 +138,7 @@ void freetree(tree *p) { if(p==0) - return; + return; freetree(p->child[0]); freetree(p->child[1]); freetree(p->child[2]); diff --git a/sys/src/cmd/rc/unix.c b/sys/src/cmd/rc/unix.c index 7c5bac8960..f1d8b1863c 100644 --- a/sys/src/cmd/rc/unix.c +++ b/sys/src/cmd/rc/unix.c @@ -6,7 +6,6 @@ #include "rc.h" #include "io.h" #include "exec.h" -#include "getflags.h" #include char *Rcmain = "/usr/lib/rcmain"; @@ -431,11 +430,6 @@ char *buf; { return read(fd, buf, cnt); } -Seek(fd, cnt, whence) -long cnt; -{ - return lseek(fd, cnt, whence); -} Executable(file) char *file; { @@ -489,6 +483,15 @@ Abort() abort(); } +int +octal(char *s) +{ + int n = 0; + while(*s==' ' || *s=='\t' || *s=='\n') s++; + while('0'<=*s && *s<='7') n = n*8+*s++-'0'; + return n; +} + void execumask(void) /* wrong -- should fork before writing */ { @@ -551,6 +554,12 @@ rfork(int bits) return fork(); } +void +unixclsexec(int fd) +{ + fcntl(fd, F_SETFD, FD_CLOEXEC); +} + int *waitpids; int nwaitpids; diff --git a/sys/src/cmd/rc/unix.h b/sys/src/cmd/rc/unix.h index 86b125871d..2fbf2f6270 100644 --- a/sys/src/cmd/rc/unix.h +++ b/sys/src/cmd/rc/unix.h @@ -1,3 +1,5 @@ +/* mostly plan 9 compatibility */ + #undef _BSD_EXTENSION /* avoid multiple def'n if predefined */ #undef _PLAN9_SOURCE #undef _POSIX_SOURCE @@ -22,17 +24,29 @@ #define NSIG 32 #endif -/* plan 9 compatibility */ #define RFPROC 1 #define RFFDG 1 #define RFNOTEG 1 -#define uintptr uintptr_t +#define OREAD O_RDONLY +#define OWRITE O_WRONLY +#define ORDWR O_RDWR +#define OCEXEC 0 -char *strdup(const char *); +#define ERRMAX 128 +#define uintptr uintptr_t #define nil ((void*)0) +#define assert(cond) +#define seek lseek +#define print printf +#define fprint fprintf +#define snprint snprintf + +char *strdup(const char *); +void unixclsexec(int); + /* in case uchar, etc. are built-in types */ #define uchar _fmtuchar #define ushort _fmtushort @@ -47,7 +61,52 @@ typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned long long uvlong; -#define OREAD O_RDONLY -#define OWRITE O_WRONLY -#define ORDWR O_RDWR -#define OCEXEC 0 +typedef ulong Rune; + +enum +{ + UTFmax = 4, /* maximum bytes per rune */ + Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ + Runeself = 0x80, /* rune and UTF sequences are the same (<) */ + Runeerror = 0xFFFD, /* decoding error in UTF */ + Runemax = 0x10FFFF, /* 21-bit rune */ + Runemask = 0x1FFFFF, /* bits used by runes (see grep) */ +}; + +/* + * rune routines + */ +extern int runetochar(char*, Rune*); +extern int chartorune(Rune*, char*); +extern int runelen(long); +extern int runenlen(Rune*, int); +extern int fullrune(char*, int); +extern int utflen(char*); +extern int utfnlen(char*, long); +extern char* utfrune(char*, long); +extern char* utfrrune(char*, long); +extern char* utfutf(char*, char*); +extern char* utfecpy(char*, char*, char*); + +extern char *argv0; +#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ + argv[0] && argv[0][0]=='-' && argv[0][1];\ + argc--, argv++) {\ + char *_args, *_argt;\ + Rune _argc;\ + _args = &argv[0][1];\ + if(_args[0]=='-' && _args[1]==0){\ + argc--; argv++; break;\ + }\ + _argc = 0;\ + while(*_args && (_args += chartorune(&_argc, _args)))\ + switch(_argc) +#define ARGEND SET(_argt);USED(_argt,_argc,_args);}USED(argv, argc); +#define ARGF() (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) +#define EARGF(x) (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) + +#define ARGC() _argc + +#define nelem(x) (sizeof(x)/sizeof((x)[0])) diff --git a/sys/src/cmd/rc/utfrune.c b/sys/src/cmd/rc/utfrune.c new file mode 100644 index 0000000000..2d2858f0ae --- /dev/null +++ b/sys/src/cmd/rc/utfrune.c @@ -0,0 +1,28 @@ +#include "rc.h" + +char* +utfrune(char *s, long c) +{ + long c1; + Rune r; + int n; + + if(c < Runesync) /* not part of utf sequence */ + return strchr(s, c); + + for(;;) { + c1 = *(uchar*)s; + if(c1 < Runeself) { /* one byte rune */ + if(c1 == 0) + return 0; + if(c1 == c) + return s; + s++; + continue; + } + n = chartorune(&r, s); + if(r == c) + return s; + s += n; + } +} diff --git a/sys/src/cmd/rc/utfutf.c b/sys/src/cmd/rc/utfutf.c new file mode 100644 index 0000000000..5573677a02 --- /dev/null +++ b/sys/src/cmd/rc/utfutf.c @@ -0,0 +1,24 @@ +#include "rc.h" + +/* + * Return pointer to first occurrence of s2 in s1, + * 0 if none + */ +char* +utfutf(char *s1, char *s2) +{ + char *p; + long f, n1, n2; + Rune r; + + n1 = chartorune(&r, s2); + f = r; + if(f <= Runesync) /* represents self */ + return strstr(s1, s2); + + n2 = strlen(s2); + for(p=s1; p=utfrune(p, f); p+=n1) + if(strncmp(p, s2, n2) == 0) + return p; + return 0; +} diff --git a/sys/src/cmd/rc/var.c b/sys/src/cmd/rc/var.c index cf650f891f..101ac74b52 100644 --- a/sys/src/cmd/rc/var.c +++ b/sys/src/cmd/rc/var.c @@ -67,7 +67,10 @@ gvlook(char *name) { int h = hash(name, NVAR); var *v; - for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v; + + for (v = gvar[h]; v; v = v->next) + if (strcmp(v->name, name) == 0) + return v; return gvar[h] = newvar(strdup(name), gvar[h]); } @@ -75,9 +78,11 @@ var* vlook(char *name) { var *v; - if(runq) - for(v = runq->local;v;v = v->next) - if(strcmp(v->name, name)==0) return v; + + if (runq) + for (v = runq->local; v; v = v->next) + if (strcmp(v->name, name) == 0) + return v; return gvlook(name); } diff --git a/sys/src/cmd/rc/win32.c b/sys/src/cmd/rc/win32.c index b368d6bda5..d782c56215 100644 --- a/sys/src/cmd/rc/win32.c +++ b/sys/src/cmd/rc/win32.c @@ -7,7 +7,6 @@ #include "exec.h" #include "io.h" #include "fns.h" -#include "getflags.h" char *Signame[] = { "sigexit", "sighup", "sigint", "sigquit", "sigalrm", "sigkill", "sigfpe", "sigterm", @@ -458,12 +457,6 @@ Read(int fd, void *buf, long cnt) return read(fd, buf, cnt); } -long -Seek(int fd, long cnt, long whence) -{ - return seek(fd, cnt, whence); -} - int Executable(char *file) { From 0ba02c4439410a870aecd0d1ee94883843e09b84 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 22 Feb 2021 02:52:29 +0000 Subject: [PATCH 158/402] sys/src/cmd/rc: import rc syntax `delim{cmd} for splitting commands from 9atom (thanks Ori Bernstein) --- sys/man/1/rc | 4 ++++ sys/src/cmd/rc/code.c | 16 +++++++++++++++- sys/src/cmd/rc/exec.c | 2 +- sys/src/cmd/rc/havefork.c | 6 ++++-- sys/src/cmd/rc/pcmd.c | 2 +- sys/src/cmd/rc/syn.y | 3 ++- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/sys/man/1/rc b/sys/man/1/rc index 2dd2a1dd30..32f88753d9 100644 --- a/sys/man/1/rc +++ b/sys/man/1/rc @@ -233,6 +233,8 @@ The value is a single string containing the components of the named variable separated by spaces. A variable with zero elements yields the empty string. .HP .BI `{ command } +.HP +.BI ` "split " { command } .br .I rc executes the @@ -245,6 +247,8 @@ If .B $ifs is not otherwise set, its value is .BR "'\ \et\en'" . +In the second form of the command, split is used instead of +.BR $ifs . .HP .BI <{ command } .HP diff --git a/sys/src/cmd/rc/code.c b/sys/src/cmd/rc/code.c index cddab625e1..d428bb40b5 100644 --- a/sys/src/cmd/rc/code.c +++ b/sys/src/cmd/rc/code.c @@ -84,6 +84,8 @@ outcode(tree *t, int eflag) { int p, q; tree *tt; + char *ifs; + if(t==0) return; if(t->type!=NOT && t->type!=';') @@ -131,10 +133,22 @@ outcode(tree *t, int eflag) emitf(Xconc); break; case '`': + emitf(Xmark); + if(c0){ + outcode(c0, 0); + emitf(Xglob); + } else { + if((ifs = strdup("ifs")) == nil) + sysfatal("strdup: %r"); + emitf(Xmark); + emitf(Xword); + emits(ifs); + emitf(Xdol); + } emitf(Xbackq); if(havefork){ p = emiti(0); - outcode(c0, 0); + outcode(c1, 0); emitf(Xexit); stuffdot(p); } else diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c index 9c4c9beb5b..f73d72643d 100644 --- a/sys/src/cmd/rc/exec.c +++ b/sys/src/cmd/rc/exec.c @@ -238,7 +238,7 @@ main(int argc, char *argv[]) * Xappend(file)[fd] open file to append * Xassign(name, val) assign val to name * Xasync{... Xexit} make thread for {}, no wait - * Xbackq{... Xreturn} make thread for {}, push stdout + * Xbackq(split){... Xreturn} make thread for {}, push stdout * Xbang complement condition * Xcase(pat, value){...} exec code on match, leave (value) on * stack diff --git a/sys/src/cmd/rc/havefork.c b/sys/src/cmd/rc/havefork.c index d72fb7d35c..6985d6e25a 100644 --- a/sys/src/cmd/rc/havefork.c +++ b/sys/src/cmd/rc/havefork.c @@ -82,11 +82,12 @@ Xbackq(void) char *stop; char utf[UTFmax+1]; io *f, *wd; - var *ifs = vlook("ifs"); word *v, *nextv; Rune r; - stop = ifs->val? ifs->val->word: ""; + stop = ""; + if(runq->argv && runq->argv->words) + stop = runq->argv->words->word; if(pipe(pfd)<0){ Xerror("can't make pipe"); return; @@ -129,6 +130,7 @@ Xbackq(void) closeio(wd); closeio(f); Waitfor(pid, 0); + poplist(); /* ditch split in "stop" */ /* v points to reversed arglist -- reverse it onto argv */ while(v){ nextv = v->next; diff --git a/sys/src/cmd/rc/pcmd.c b/sys/src/cmd/rc/pcmd.c index 384c888eee..e50d92eba3 100644 --- a/sys/src/cmd/rc/pcmd.c +++ b/sys/src/cmd/rc/pcmd.c @@ -33,7 +33,7 @@ pcmd(io *f, tree *t) break; case '^': pfmt(f, "%t^%t", c0, c1); break; - case '`': pfmt(f, "`%t", c0); + case '`': pfmt(f, "`%t%t", c0, c1); break; case ANDAND: pfmt(f, "%t && %t", c0, c1); break; diff --git a/sys/src/cmd/rc/syn.y b/sys/src/cmd/rc/syn.y index e64a36dd0c..264cf4c10f 100644 --- a/sys/src/cmd/rc/syn.y +++ b/sys/src/cmd/rc/syn.y @@ -83,7 +83,8 @@ comword: '$' word {$$=tree1('$', $2);} | '"' word {$$=tree1('"', $2);} | COUNT word {$$=tree1(COUNT, $2);} | WORD -| '`' brace {$$=tree1('`', $2);} +| '`' brace {$$=tree2('`', (struct tree*)0, $2);} +| '`' word brace {$$=tree2('`', $2, $3);} | '(' words ')' {$$=tree1(PAREN, $2);} | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;} keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN From 5c4db26b0535bdad2417fe93d62ee8f892c2fc44 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Jun 2021 14:17:35 +0000 Subject: [PATCH 159/402] sys/src/cmd/rc: fix Xpipefd unbalancing the redir stack (thanks Cinap Lenrek) --- sys/src/cmd/rc/exec.c | 15 +++++++++++++++ sys/src/cmd/rc/fns.h | 1 + sys/src/cmd/rc/havefork.c | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c index f73d72643d..c0860a6100 100644 --- a/sys/src/cmd/rc/exec.c +++ b/sys/src/cmd/rc/exec.c @@ -112,6 +112,21 @@ pushredir(int type, int from, int to) runq->redir = rp; } +void +shuffleredir(void) +{ + redir **rr, *rp; + + rp = runq->redir; + if(rp==0) + return; + runq->redir = rp->next; + rp->next = runq->startredir; + for(rr = &runq->redir; *rr != rp->next; rr = &((*rr)->next)) + ; + *rr = rp; +} + var* newvar(char *name, var *next) { diff --git a/sys/src/cmd/rc/fns.h b/sys/src/cmd/rc/fns.h index d0519d6cfd..6c1c34f873 100644 --- a/sys/src/cmd/rc/fns.h +++ b/sys/src/cmd/rc/fns.h @@ -56,6 +56,7 @@ void readhere(void); word* searchpath(char*); void setstatus(char*); void setvar(char*, word*); +void shuffleredir(void); void skipnl(void); void start(code*, int, var*); int truestatus(void); diff --git a/sys/src/cmd/rc/havefork.c b/sys/src/cmd/rc/havefork.c index 6985d6e25a..09d6203325 100644 --- a/sys/src/cmd/rc/havefork.c +++ b/sys/src/cmd/rc/havefork.c @@ -177,7 +177,8 @@ Xpipefd(void) default: addwaitpid(pid); close(sidefd); - pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ + pushredir(ROPEN, mainfd, mainfd); + shuffleredir(); /* shuffle redir to bottom of stack for turfredir() */ strcpy(name, Fdprefix); inttoascii(name+strlen(name), mainfd); pushword(name); From 1f705653efc89aafcb4f2aa415d3369fd1121af1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Nov 2016 23:49:40 +0000 Subject: [PATCH 160/402] sys/src/libstdio: various fixes in stdio (thanks Geoff Collyer) --- sys/include/ape/stdio.h | 186 +++++++++++++++------------- sys/include/stdio.h | 170 +++++++++++++------------ sys/src/ape/lib/ap/stdio/_IO_getc.c | 10 +- sys/src/ape/lib/ap/stdio/_IO_putc.c | 8 +- sys/src/ape/lib/ap/stdio/_dtoa.c | 4 +- sys/src/ape/lib/ap/stdio/_fconv.c | 2 + sys/src/ape/lib/ap/stdio/fdopen.c | 2 +- sys/src/ape/lib/ap/stdio/freopen.c | 2 +- sys/src/ape/lib/ap/stdio/ftell.c | 2 +- sys/src/ape/lib/ap/stdio/ftello.c | 2 +- sys/src/ape/lib/ap/stdio/ftoa.c | 2 +- sys/src/ape/lib/ap/stdio/fwrite.c | 4 +- sys/src/ape/lib/ap/stdio/iolib.h | 5 + sys/src/ape/lib/ap/stdio/mkfile | 3 +- sys/src/ape/lib/ap/stdio/rdline.c | 8 +- sys/src/ape/lib/ap/stdio/rewind.c | 2 +- sys/src/ape/lib/ap/stdio/sclose.c | 3 +- sys/src/ape/lib/ap/stdio/setbuf.c | 4 +- sys/src/ape/lib/ap/stdio/setvbuf.c | 5 +- sys/src/ape/lib/ap/stdio/sopenr.c | 2 +- sys/src/ape/lib/ap/stdio/stdio.c | 7 +- sys/src/ape/lib/ap/stdio/strtod.c | 2 + sys/src/ape/lib/ap/stdio/ungetc.c | 7 +- sys/src/ape/lib/ap/stdio/vfprintf.c | 22 ++-- sys/src/ape/lib/ap/stdio/vfscanf.c | 15 ++- sys/src/libstdio/Stdio.h | 109 ---------------- sys/src/libstdio/_IO_getc.c | 2 +- sys/src/libstdio/_IO_putc.c | 8 +- sys/src/libstdio/dtoa.c | 42 +++---- sys/src/libstdio/fdopen.c | 4 +- sys/src/libstdio/fflush.c | 7 +- sys/src/libstdio/freopen.c | 2 +- sys/src/libstdio/ftell.c | 2 +- sys/src/libstdio/ftello.c | 2 +- sys/src/libstdio/fwrite.c | 4 +- sys/src/libstdio/iolib.h | 6 +- sys/src/libstdio/mkfile | 3 +- sys/src/libstdio/rewind.c | 2 +- sys/src/libstdio/sclose.c | 2 +- sys/src/libstdio/setbuf.c | 2 +- sys/src/libstdio/setvbuf.c | 2 +- sys/src/libstdio/sopenr.c | 2 +- sys/src/libstdio/vfprintf.c | 20 +-- sys/src/libstdio/vfscanf.c | 12 +- 44 files changed, 316 insertions(+), 396 deletions(-) delete mode 100644 sys/src/libstdio/Stdio.h diff --git a/sys/include/ape/stdio.h b/sys/include/ape/stdio.h index c1be325ac6..a5b727ba1d 100644 --- a/sys/include/ape/stdio.h +++ b/sys/include/ape/stdio.h @@ -11,35 +11,37 @@ /* * According to X3J11, there is only one i/o buffer * and it must not be occupied by both input and output data. - * If rpwp>=(f)->rp || (f)->flags&LINEBUF && _IO_ctmp=='\n'\ - * ?_IO_putc(_IO_ctmp, f)\ - * :*(f)->wp++=_IO_ctmp) - * + * + * If rpwp>=(f)->rp || (f)->flags&LINEBUF && _IO_ctmp=='\n'?\ + * _IO_putc(_IO_ctmp, f): *(f)->wp++=_IO_ctmp) */ typedef struct{ int fd; /* UNIX file pointer */ char flags; /* bits for must free buffer on close, line-buffered */ char state; /* last operation was read, write, position, error, eof */ - char *buf; /* pointer to i/o buffer */ - char *rp; /* read pointer (or write end-of-buffer) */ - char *wp; /* write pointer (or read end-of-buffer) */ - char *lp; /* actual write pointer used when line-buffering */ + unsigned char *buf; /* pointer to i/o buffer */ + unsigned char *rp; /* read pointer (or write end-of-buffer) */ + unsigned char *wp; /* write pointer (or read end-of-buffer) */ + unsigned char *lp; /* actual write pointer used when line-buffering */ size_t bufl; /* actual length of buffer */ - char unbuf[1]; /* tiny buffer for unbuffered io (used for ungetc?) */ + unsigned char unbuf[1]; /* tiny buffer for unbuffered io (used for ungetc?) */ + int junk; }FILE; -typedef long long fpos_t; + +typedef off_t fpos_t; + #ifndef NULL #ifdef __cplusplus #define NULL 0 @@ -47,107 +49,115 @@ typedef long long fpos_t; #define NULL ((void*)0) #endif #endif + /* * Third arg of setvbuf */ #define _IOFBF 1 /* block-buffered */ #define _IOLBF 2 /* line-buffered */ #define _IONBF 3 /* unbuffered */ -#define BUFSIZ 4096 /* size of setbuf buffer */ + +#define BUFSIZ 8192 /* size of setbuf buffer */ #define EOF (-1) /* returned on end of file */ -#define FOPEN_MAX 90 /* max files open */ +#define FOPEN_MAX 128 /* max files open */ #define FILENAME_MAX BUFSIZ /* silly filename length */ #define L_tmpnam 20 /* sizeof "/tmp/abcdefghij9999 */ #define L_cuserid 32 /* maximum size user name */ #define L_ctermid 32 /* size of name of controlling tty */ + +#ifndef SEEK_SET /* also defined in unistd.h */ #define SEEK_CUR 1 #define SEEK_END 2 #define SEEK_SET 0 +#endif #define TMP_MAX 64 /* very hard to set correctly */ + #define stderr (&_IO_stream[2]) #define stdin (&_IO_stream[0]) #define stdout (&_IO_stream[1]) -#define _IO_CHMASK 0377 /* mask for 8 bit characters */ + +extern FILE _IO_stream[FOPEN_MAX]; #ifdef __cplusplus extern "C" { #endif -extern int remove(const char *); -extern int rename(const char *, const char *); -extern FILE *tmpfile(void); -extern char *tmpnam(char *); -extern int fclose(FILE *); -extern int fflush(FILE *); -extern FILE *fopen(const char *, const char *); -extern FILE *freopen(const char *, const char *, FILE *); -extern void setbuf(FILE *, char *); -extern int setvbuf(FILE *, char *, int, size_t); -extern int fprintf(FILE *, const char *, ...); -extern int fscanf(FILE *, const char *, ...); -extern int printf(const char *, ...); -extern int scanf(const char *, ...); -extern int sprintf(char *, const char *, ...); - +int _IO_getc(FILE *f); +int _IO_putc(int, FILE *); +void clearerr(FILE *); +int fclose(FILE *); +FILE *fdopen(const int, const char *); +int feof(FILE *); +int ferror(FILE *); +int fflush(FILE *); +int fgetc(FILE *); +int fgetpos(FILE *, fpos_t *); +char *fgets(char *, int, FILE *); +int fileno(FILE *); +FILE *fopen(const char *, const char *); +int fprintf(FILE *, const char *, ...); +int fputc(int, FILE *); +int fputs(const char *, FILE *); +size_t fread(void *, size_t, size_t, FILE *); +FILE *freopen(const char *, const char *, FILE *); +int fscanf(FILE *, const char *, ...); +int fseek(FILE *, long, int); +int fseeko(FILE *, off_t, int); +int fsetpos(FILE *, const fpos_t *); +long ftell(FILE *); +off_t ftello(FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); +int getc(FILE *); +#define getc(f) ((f)->rp>=(f)->wp? _IO_getc(f): *(f)->rp++) +int getchar(void); +#define getchar() getc(stdin) +char *gets(char *); +void perror(const char *); +int printf(const char *, ...); +int putc(int, FILE *); +/* assignment to f->junk eliminates warnings about unused result of operation */ +#define putc(c, f) ((f)->junk = ((f)->wp>=(f)->rp? \ + _IO_putc(c, f): (*(f)->wp++ = (c)))) +int putchar(int); +#define putchar(c) putc(c, stdout) +int puts(const char *); +int remove(const char *); +int rename(const char *, const char *); +void rewind(FILE *); +int scanf(const char *, ...); +void setbuf(FILE *, char *); +int setvbuf(FILE *, char *, int, size_t); /* - * NB: C99 now *requires *snprintf to return the number of characters + * NB: C99 now requires *snprintf to return the number of characters * that would have been written, had there been room. */ -extern int snprintf(char *, size_t, const char *, ...); -extern int vsnprintf(char *, size_t, const char *, va_list); - -extern int sscanf(const char *, const char *, ...); -extern int vfprintf(FILE *, const char *, va_list); -extern int vprintf(const char *, va_list); -extern int vsprintf(char *, const char *, va_list); -extern int vfscanf(FILE *, const char *, va_list); -extern int fgetc(FILE *); -extern char *fgets(char *, int, FILE *); -extern int fputc(int, FILE *); -extern int fputs(const char *, FILE *); -extern int getc(FILE *); -#define getc(f) ((f)->rp>=(f)->wp?_IO_getc(f):*(f)->rp++&_IO_CHMASK) -extern int _IO_getc(FILE *f); -extern int getchar(void); -#define getchar() getc(stdin) -extern char *gets(char *); -extern int putc(int, FILE *); -#define putc(c, f) ((f)->wp>=(f)->rp?_IO_putc(c, f):(*(f)->wp++=c)&_IO_CHMASK) -extern int _IO_putc(int, FILE *); -extern int putchar(int); -#define putchar(c) putc(c, stdout) -extern int puts(const char *); -extern int ungetc(int, FILE *); -extern size_t fread(void *, size_t, size_t, FILE *); -extern size_t fwrite(const void *, size_t, size_t, FILE *); -extern int fgetpos(FILE *, fpos_t *); -extern int fseek(FILE *, long, int); -extern int fseeko(FILE *, off_t, int); -extern int fsetpos(FILE *, const fpos_t *); -extern long ftell(FILE *); -extern off_t ftello(FILE *); -extern void rewind(FILE *); -extern void clearerr(FILE *); -extern int feof(FILE *); -extern int ferror(FILE *); -extern void perror(const char *); -extern FILE _IO_stream[FOPEN_MAX]; +int snprintf(char *, size_t, const char *, ...); +int sprintf(char *, const char *, ...); +int sscanf(const char *, const char *, ...); +FILE *tmpfile(void); +char *tmpnam(char *); +int ungetc(int, FILE *); +int vfprintf(FILE *, const char *, va_list); +int vfscanf(FILE *, const char *, va_list); +int vprintf(const char *, va_list); +int vsnprintf(char *, size_t, const char *, va_list); +int vsprintf(char *, const char *, va_list); #ifdef _POSIX_SOURCE -extern int fileno(FILE *); -extern FILE* fdopen(int, const char*); -extern char *ctermid(char *); +int fileno(FILE *); +FILE* fdopen(int, const char*); +char *ctermid(char *); #endif #ifdef _REENTRANT_SOURCE -extern char *tmpnam_r(char *); -extern char *ctermid_r(char *); +char *tmpnam_r(char *); +char *ctermid_r(char *); #endif #ifdef _BSD_EXTENSION #pragma lib "/$M/lib/ape/libbsd.a" -extern FILE *popen(char *, char *); -extern int pclose(FILE *); +FILE *popen(char *, char *); +int pclose(FILE *); #endif #ifdef __cplusplus diff --git a/sys/include/stdio.h b/sys/include/stdio.h index 834bfb4ab9..1f9605dc34 100644 --- a/sys/include/stdio.h +++ b/sys/include/stdio.h @@ -2,117 +2,123 @@ #pragma lib "libstdio.a" /* - * pANS astdio.h + * pANS stdio.h */ /* * According to X3J11, there is only one i/o buffer * and it must not be occupied by both input and output data. - * If rpwp>=(f)->rp || (f)->flags&LINEBUF && _IO_ctmp=='\n'\ - * ?_IO_putc(_IO_ctmp, f)\ - * :*(f)->wp++=_IO_ctmp) - * + * + * If rpwp>=(f)->rp || (f)->flags&LINEBUF && _IO_ctmp=='\n'?\ + * _IO_putc(_IO_ctmp, f): *(f)->wp++=_IO_ctmp) */ typedef struct{ int fd; /* UNIX file pointer */ char flags; /* bits for must free buffer on close, line-buffered */ char state; /* last operation was read, write, position, error, eof */ - char *buf; /* pointer to i/o buffer */ - char *rp; /* read pointer (or write end-of-buffer) */ - char *wp; /* write pointer (or read end-of-buffer) */ - char *lp; /* actual write pointer used when line-buffering */ + unsigned char *buf; /* pointer to i/o buffer */ + unsigned char *rp; /* read pointer (or write end-of-buffer) */ + unsigned char *wp; /* write pointer (or read end-of-buffer) */ + unsigned char *lp; /* actual write pointer used when line-buffering */ long bufl; /* actual length of buffer */ - char unbuf[1]; /* tiny buffer for unbuffered io (used for ungetc?) */ + unsigned char unbuf[1]; /* tiny buffer for unbuffered io (used for ungetc?) */ + int junk; }FILE; -typedef long fpos_t; + +typedef long long fpos_t; + #ifndef NULL #define NULL ((void*)0) #endif + /* * Third arg of setvbuf */ #define _IOFBF 1 /* block-buffered */ #define _IOLBF 2 /* line-buffered */ #define _IONBF 3 /* unbuffered */ -#define BUFSIZ 4096 /* size of setbuf buffer */ + +#define BUFSIZ 8192 /* size of setbuf buffer */ #define EOF (-1) /* returned on end of file */ -#define FOPEN_MAX 100 /* max files open */ +#define FOPEN_MAX 128 /* max files open */ #define FILENAME_MAX BUFSIZ /* silly filename length */ #define L_tmpnam 20 /* sizeof "/tmp/abcdefghij9999 */ -#ifndef SEEK_SET /* also defined in unistd.h */ #define SEEK_CUR 1 #define SEEK_END 2 #define SEEK_SET 0 -#endif #define TMP_MAX 64 /* very hard to set correctly */ + #define stderr (&_IO_stream[2]) #define stdin (&_IO_stream[0]) #define stdout (&_IO_stream[1]) -#define _IO_CHMASK 0377 /* mask for 8 bit characters */ -FILE *tmpfile(void); -char *tmpnam(char *); -int fclose(FILE *); -int fflush(FILE *); -FILE *fopen(const char *, const char *); -FILE *fdopen(const int, const char *); -FILE *freopen(const char *, const char *, FILE *); -void setbuf(FILE *, char *); -int setvbuf(FILE *, char *, int, long); -int fprintf(FILE *, const char *, ...); -int fscanf(FILE *, const char *, ...); -int printf(const char *, ...); -int scanf(const char *, ...); -int sprintf(char *, const char *, ...); -int snprintf(char *, int, const char *, ...); -int sscanf(const char *, const char *, ...); -int vfprintf(FILE *, const char *, va_list); -int vprintf(const char *, va_list); -int vsprintf(char *, const char *, va_list); -int vsnprintf(char *, int, const char *, va_list); -int vfscanf(FILE *, const char *, va_list); -int fgetc(FILE *); -char *fgets(char *, int, FILE *); -int fputc(int, FILE *); -int fputs(const char *, FILE *); -int getc(FILE *); -#define getc(f) ((f)->rp>=(f)->wp?_IO_getc(f):*(f)->rp++&_IO_CHMASK) -int _IO_getc(FILE *f); -int getchar(void); + +extern FILE _IO_stream[FOPEN_MAX]; + +int _IO_getc(FILE *f); +int _IO_putc(int, FILE *); +void clearerr(FILE *); +int fclose(FILE *); +FILE *fdopen(const int, const char *); +int feof(FILE *); +int ferror(FILE *); +int fflush(FILE *); +int fgetc(FILE *); +int fgetpos(FILE *, fpos_t *); +char *fgets(char *, int, FILE *); +int fileno(FILE *); +FILE *fopen(const char *, const char *); +int fprintf(FILE *, const char *, ...); +int fputc(int, FILE *); +int fputs(const char *, FILE *); +long fread(void *, long, long, FILE *); +FILE *freopen(const char *, const char *, FILE *); +int fscanf(FILE *, const char *, ...); +int fseek(FILE *, long, int); +int fseeko(FILE *, long long, int); +int fsetpos(FILE *, const fpos_t *); +long ftell(FILE *); +long long ftello(FILE *); +long fwrite(const void *, long, long, FILE *); +int getc(FILE *); +#define getc(f) ((f)->rp>=(f)->wp?_IO_getc(f):*(f)->rp++) +int getchar(void); #define getchar() getc(stdin) -char *gets(char *); -int putc(int, FILE *); -#define putc(c, f) ((f)->wp>=(f)->rp?_IO_putc(c, f):(*(f)->wp++=c)&_IO_CHMASK) -int _IO_putc(int, FILE *); -int putchar(int); +char *gets(char *); +void perror(const char *); +int printf(const char *, ...); +int putc(int, FILE *); +/* assignment to f->junk eliminates warnings about unused result of operation */ +#define putc(c, f) ((f)->junk = ((f)->wp>=(f)->rp? \ + _IO_putc(c, f): (*(f)->wp++ = (c)))) +int putchar(int); #define putchar(c) putc(c, stdout) -int puts(const char *); -int ungetc(int, FILE *); -long fread(void *, long, long, FILE *); -long fwrite(const void *, long, long, FILE *); -int fgetpos(FILE *, fpos_t *); -int fseek(FILE *, long, int); -int fseeko(FILE *, long long, int); -int fsetpos(FILE *, const fpos_t *); -long ftell(FILE *); -long long ftello(FILE *); -void rewind(FILE *); -void clearerr(FILE *); -int feof(FILE *); -int ferror(FILE *); -void perror(const char *); -extern FILE _IO_stream[FOPEN_MAX]; -FILE *sopenr(const char *); -FILE *sopenw(void); -char *sclose(FILE *); -int fileno(FILE *); +int puts(const char *); +void rewind(FILE *); +int scanf(const char *, ...); +char *sclose(FILE *); +void setbuf(FILE *, void *); +int setvbuf(FILE *, void *, int, long); +int snprintf(char *, int, const char *, ...); +FILE *sopenr(const char *); +FILE *sopenw(void); +int sprintf(char *, const char *, ...); +int sscanf(const char *, const char *, ...); +FILE *tmpfile(void); +char *tmpnam(char *); +int ungetc(int, FILE *); +int vfprintf(FILE *, const char *, va_list); +int vfscanf(FILE *, const char *, va_list); +int vprintf(const char *, va_list); +int vsnprintf(char *, int, const char *, va_list); +int vsprintf(char *, const char *, va_list); diff --git a/sys/src/ape/lib/ap/stdio/_IO_getc.c b/sys/src/ape/lib/ap/stdio/_IO_getc.c index 3f99922c29..1c053fd85f 100644 --- a/sys/src/ape/lib/ap/stdio/_IO_getc.c +++ b/sys/src/ape/lib/ap/stdio/_IO_getc.c @@ -3,7 +3,7 @@ */ #include "iolib.h" int _IO_getc(FILE *f){ - int cnt, n; + int cnt; switch(f->state){ default: /* CLOSED, WR, ERR, EOF */ return EOF; @@ -12,11 +12,7 @@ int _IO_getc(FILE *f){ case RDWR: case RD: if(f->flags&STRING) return EOF; - if(f->buf == f->unbuf) - n = 1; - else - n = f->bufl; - cnt=read(f->fd, f->buf, n); + cnt=read(f->fd, f->buf, f->buf==f->unbuf?1:f->bufl); switch(cnt){ case -1: f->state=ERR; return EOF; case 0: f->state=END; return EOF; @@ -24,7 +20,7 @@ int _IO_getc(FILE *f){ f->state=RD; f->rp=f->buf; f->wp=f->buf+cnt; - return (*f->rp++)&_IO_CHMASK; + return *f->rp++; } } } diff --git a/sys/src/ape/lib/ap/stdio/_IO_putc.c b/sys/src/ape/lib/ap/stdio/_IO_putc.c index 8cef77fd3d..9f43417d6c 100644 --- a/sys/src/ape/lib/ap/stdio/_IO_putc.c +++ b/sys/src/ape/lib/ap/stdio/_IO_putc.c @@ -57,7 +57,7 @@ int _IO_putc(int c, FILE *f){ else if(f->flags&LINEBUF){ if(f->lp==f->rp){ cnt=f->lp-f->buf; - if(f->flags&APPEND) lseek(f->fd, 0L, SEEK_END); + if(f->flags&APPEND) lseek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; @@ -67,7 +67,7 @@ int _IO_putc(int c, FILE *f){ *f->lp++=c; if(c=='\n'){ cnt=f->lp-f->buf; - if(f->flags&APPEND) lseek(f->fd, 0L, SEEK_END); + if(f->flags&APPEND) lseek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; @@ -77,7 +77,7 @@ int _IO_putc(int c, FILE *f){ } else if(f->buf==f->unbuf){ f->unbuf[0]=c; - if(f->flags&APPEND) lseek(f->fd, 0L, SEEK_END); + if(f->flags&APPEND) lseek(f->fd, 0, SEEK_END); if(write(f->fd, f->buf, 1)!=1){ f->state=ERR; return EOF; @@ -86,7 +86,7 @@ int _IO_putc(int c, FILE *f){ else{ if(f->wp==f->rp){ cnt=f->wp-f->buf; - if(f->flags&APPEND) lseek(f->fd, 0L, SEEK_END); + if(f->flags&APPEND) lseek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; diff --git a/sys/src/ape/lib/ap/stdio/_dtoa.c b/sys/src/ape/lib/ap/stdio/_dtoa.c index fe147789bc..2ea49c7736 100644 --- a/sys/src/ape/lib/ap/stdio/_dtoa.c +++ b/sys/src/ape/lib/ap/stdio/_dtoa.c @@ -89,6 +89,7 @@ _dtoa(double darg, int mode, int ndigits, int *decpt, int *sign, char **rve) static int result_k; Dul d; + mlo = 0; d.d = darg; if (result) { result->k = result_k; @@ -230,6 +231,7 @@ _dtoa(double darg, int mode, int ndigits, int *decpt, int *sign, char **rve) try_quick = 0; } leftright = 1; + ilim = ilim1 = -1; switch(mode) { case 0: case 1: @@ -463,7 +465,7 @@ _dtoa(double darg, int mode, int ndigits, int *decpt, int *sign, char **rve) S = pow5mult(S, s5); /* Check for special case that d is a normalized power of 2. */ - + spec_case = 0; if (mode < 2) { if (!word1(d) && !(word0(d) & Bndry_mask) #ifndef Sudden_Underflow diff --git a/sys/src/ape/lib/ap/stdio/_fconv.c b/sys/src/ape/lib/ap/stdio/_fconv.c index fc72d4731a..678a447c1d 100644 --- a/sys/src/ape/lib/ap/stdio/_fconv.c +++ b/sys/src/ape/lib/ap/stdio/_fconv.c @@ -510,6 +510,7 @@ _d2b(double darg, int *e, int *bits) else x[0] = y; i = b->wds = (x[1] = z) ? 2 : 1; + USED(i); } else { #ifdef DEBUG @@ -519,6 +520,7 @@ _d2b(double darg, int *e, int *bits) k = lo0bits(&z); x[0] = z; i = b->wds = 1; + USED(i); k += 32; } #else diff --git a/sys/src/ape/lib/ap/stdio/fdopen.c b/sys/src/ape/lib/ap/stdio/fdopen.c index 0c585b9659..db7b8926e7 100644 --- a/sys/src/ape/lib/ap/stdio/fdopen.c +++ b/sys/src/ape/lib/ap/stdio/fdopen.c @@ -21,7 +21,7 @@ FILE *fdopen(const int fd, const char *mode){ return NULL; f->fd=fd; if(mode[0]=='a') - lseek(f->fd, 0L, 2); + lseek(f->fd, 0, SEEK_END); if(f->fd==-1) return NULL; f->flags=0; f->state=OPEN; diff --git a/sys/src/ape/lib/ap/stdio/freopen.c b/sys/src/ape/lib/ap/stdio/freopen.c index ba586bbfc5..222790f3a5 100644 --- a/sys/src/ape/lib/ap/stdio/freopen.c +++ b/sys/src/ape/lib/ap/stdio/freopen.c @@ -50,7 +50,7 @@ FILE *freopen(const char *name, const char *mode, FILE *f){ f->fd=open(name, O_RDWR); } } - lseek(f->fd, 0L, 2); + lseek(f->fd, 0, SEEK_END); break; } diff --git a/sys/src/ape/lib/ap/stdio/ftell.c b/sys/src/ape/lib/ap/stdio/ftell.c index 3693589ea0..e0b24beca9 100644 --- a/sys/src/ape/lib/ap/stdio/ftell.c +++ b/sys/src/ape/lib/ap/stdio/ftell.c @@ -3,7 +3,7 @@ */ #include "iolib.h" long ftell(FILE *f){ - long seekp=lseek(f->fd, 0L, 1); + long seekp=lseek(f->fd, 0, SEEK_CUR); if(seekp<0) return -1; /* enter error state? */ switch(f->state){ default: diff --git a/sys/src/ape/lib/ap/stdio/ftello.c b/sys/src/ape/lib/ap/stdio/ftello.c index 4ebb7b138d..50b5cadc71 100644 --- a/sys/src/ape/lib/ap/stdio/ftello.c +++ b/sys/src/ape/lib/ap/stdio/ftello.c @@ -3,7 +3,7 @@ */ #include "iolib.h" off_t ftello(FILE *f){ - off_t seekp=lseek(f->fd, 0L, 1); + off_t seekp=lseek(f->fd, 0, SEEK_CUR); if(seekp<0) return -1; /* enter error state? */ switch(f->state){ default: diff --git a/sys/src/ape/lib/ap/stdio/ftoa.c b/sys/src/ape/lib/ap/stdio/ftoa.c index b241d2d43f..f67e4b62f2 100644 --- a/sys/src/ape/lib/ap/stdio/ftoa.c +++ b/sys/src/ape/lib/ap/stdio/ftoa.c @@ -27,7 +27,7 @@ int ftoa(double f, char *bp){ e1=e/2; e2=e-e1; p=f*pow10(e2); - while((g=p*pow10(e1))<1.) e1++; + while(p*pow10(e1)<1.) e1++; while((g=p*pow10(e1))>=10.) --e1; e=e1+e2; f=g; diff --git a/sys/src/ape/lib/ap/stdio/fwrite.c b/sys/src/ape/lib/ap/stdio/fwrite.c index 5e871c0692..54f5959d3d 100644 --- a/sys/src/ape/lib/ap/stdio/fwrite.c +++ b/sys/src/ape/lib/ap/stdio/fwrite.c @@ -24,7 +24,7 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){ d=f->wp-f->buf; if(d>0){ if(f->flags&APPEND) - lseek(f->fd, 0L, SEEK_END); + lseek(f->fd, 0, SEEK_END); if(write(f->fd, f->buf, d)!=d){ f->state=ERR; goto ret; @@ -32,7 +32,7 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){ f->wp=f->rp=f->buf; } if(f->flags&APPEND) - lseek(f->fd, 0L, SEEK_END); + lseek(f->fd, 0, SEEK_END); d=write(f->fd, s, n); if(d<=0){ f->state=ERR; diff --git a/sys/src/ape/lib/ap/stdio/iolib.h b/sys/src/ape/lib/ap/stdio/iolib.h index 3a5bd63a0c..19b27dfeb6 100644 --- a/sys/src/ape/lib/ap/stdio/iolib.h +++ b/sys/src/ape/lib/ap/stdio/iolib.h @@ -14,7 +14,12 @@ * fseek fsetpos ftell rewind clearerr * feof ferror perror */ +#ifndef _SUSV2_SOURCE +#define _SUSV2_SOURCE /* for *intptr_t types */ +#endif + #include +#include #include #include #include diff --git a/sys/src/ape/lib/ap/stdio/mkfile b/sys/src/ape/lib/ap/stdio/mkfile index 033bd7df37..dc7cea7c60 100644 --- a/sys/src/ape/lib/ap/stdio/mkfile +++ b/sys/src/ape/lib/ap/stdio/mkfile @@ -65,5 +65,4 @@ OFILES=\ -char *rdline(FILE *f, char **ep){ +char *rdline(FILE *f, char **aep){ int cnt; - char *nlp, *vp; + void *vp; + unsigned char *nlp; + unsigned char **ep; + + ep = (unsigned char **)aep; switch(f->state){ default: /* CLOSED, WR, ERR, EOF */ return NULL; diff --git a/sys/src/ape/lib/ap/stdio/rewind.c b/sys/src/ape/lib/ap/stdio/rewind.c index 0cfdb957c5..51ae3cdf04 100644 --- a/sys/src/ape/lib/ap/stdio/rewind.c +++ b/sys/src/ape/lib/ap/stdio/rewind.c @@ -3,5 +3,5 @@ */ #include "iolib.h" void rewind(FILE *f){ - fseek(f, 0L, SEEK_SET); + fseek(f, 0, SEEK_SET); } diff --git a/sys/src/ape/lib/ap/stdio/sclose.c b/sys/src/ape/lib/ap/stdio/sclose.c index d55396a3a3..357b0285de 100644 --- a/sys/src/ape/lib/ap/stdio/sclose.c +++ b/sys/src/ape/lib/ap/stdio/sclose.c @@ -2,7 +2,6 @@ * pANS stdio -- sclose */ #include "iolib.h" -#include char *_IO_sclose(FILE *f){ switch(f->state){ @@ -33,5 +32,5 @@ char *_IO_sclose(FILE *f){ } f->state=CLOSED; f->flags=0; - return f->buf; + return (char *)f->buf; } diff --git a/sys/src/ape/lib/ap/stdio/setbuf.c b/sys/src/ape/lib/ap/stdio/setbuf.c index 31c5d3e1e8..da1b47e212 100644 --- a/sys/src/ape/lib/ap/stdio/setbuf.c +++ b/sys/src/ape/lib/ap/stdio/setbuf.c @@ -7,10 +7,10 @@ void setbuf(FILE *f, char *buf){ if(buf) f->bufl=BUFSIZ; else{ - buf=f->unbuf; + buf=(char *)f->unbuf; f->bufl=0; } - f->rp=f->wp=f->lp=f->buf=buf; + f->rp=f->wp=f->lp=f->buf=(unsigned char *)buf; f->state=RDWR; } /* else error, but there's no way to report it */ diff --git a/sys/src/ape/lib/ap/stdio/setvbuf.c b/sys/src/ape/lib/ap/stdio/setvbuf.c index 58bea00986..7091cdb41f 100644 --- a/sys/src/ape/lib/ap/stdio/setvbuf.c +++ b/sys/src/ape/lib/ap/stdio/setvbuf.c @@ -2,7 +2,6 @@ * pANS stdio -- setvbuf */ #include "iolib.h" -#include int setvbuf(FILE *f, char *buf, int mode, size_t size){ if(f->state!=OPEN){ f->state=ERR; @@ -24,11 +23,11 @@ int setvbuf(FILE *f, char *buf, int mode, size_t size){ f->bufl=size; break; case _IONBF: - buf=f->unbuf; + buf=(char *)f->unbuf; f->bufl=0; break; } - f->rp=f->wp=f->lp=f->buf=buf; + f->rp=f->wp=f->lp=f->buf=(unsigned char *)buf; f->state=RDWR; return 0; } diff --git a/sys/src/ape/lib/ap/stdio/sopenr.c b/sys/src/ape/lib/ap/stdio/sopenr.c index 279ec726b3..1f1d269e14 100644 --- a/sys/src/ape/lib/ap/stdio/sopenr.c +++ b/sys/src/ape/lib/ap/stdio/sopenr.c @@ -8,7 +8,7 @@ FILE *_IO_sopenr(const char *s){ FILE *f; for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break; if(f==&_IO_stream[FOPEN_MAX]) return NULL; - f->buf=f->rp=(char *)s; /* what an annoyance const is */ + f->buf=f->rp=(unsigned char *)s; /* what an annoyance const is */ f->bufl=strlen(s); f->wp=f->buf+f->bufl; f->state=RD; diff --git a/sys/src/ape/lib/ap/stdio/stdio.c b/sys/src/ape/lib/ap/stdio/stdio.c index 854efe42bf..e6bf0733f7 100644 --- a/sys/src/ape/lib/ap/stdio/stdio.c +++ b/sys/src/ape/lib/ap/stdio/stdio.c @@ -3,8 +3,7 @@ */ #include "iolib.h" FILE _IO_stream[]={ -/* fd flags state buf rp wp lp bufl unbuf */ - 0, 0, OPEN, 0, 0, 0, 0, 0, 0, - 1, 0, OPEN, 0, 0, 0, 0, 0, 0, - 2, 0, OPEN, 0, 0, 0, 0, 0, 0, + { .fd 0, .state OPEN, }, + { .fd 1, .state OPEN, }, + { .fd 2, .state OPEN, }, }; diff --git a/sys/src/ape/lib/ap/stdio/strtod.c b/sys/src/ape/lib/ap/stdio/strtod.c index ff820ef624..1aad598922 100644 --- a/sys/src/ape/lib/ap/stdio/strtod.c +++ b/sys/src/ape/lib/ap/stdio/strtod.c @@ -219,6 +219,8 @@ strtod(CONST char *s00, char **se) long L; unsigned long y, z; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; + + bb = bd = bs = delta = 0; sign = nz0 = nz = 0; rv.d = 0.; for(s = s00;;s++) switch(*s) { diff --git a/sys/src/ape/lib/ap/stdio/ungetc.c b/sys/src/ape/lib/ap/stdio/ungetc.c index 3c071690bd..4c12c5869e 100644 --- a/sys/src/ape/lib/ap/stdio/ungetc.c +++ b/sys/src/ape/lib/ap/stdio/ungetc.c @@ -15,12 +15,7 @@ int ungetc(int c, FILE *f){ _IO_setvbuf(f); case RDWR: case END: - f->wp=f->buf; - if(f->bufl==0) - f->wp += 1; - else - f->wp += f->bufl; - f->rp = f->wp; + f->rp=f->wp=f->buf+(f->bufl==0?1:f->bufl); f->state=RD; case RD: if(f->rp==f->buf) return EOF; diff --git a/sys/src/ape/lib/ap/stdio/vfprintf.c b/sys/src/ape/lib/ap/stdio/vfprintf.c index dc8c406ff2..4345f327da 100644 --- a/sys/src/ape/lib/ap/stdio/vfprintf.c +++ b/sys/src/ape/lib/ap/stdio/vfprintf.c @@ -4,7 +4,6 @@ #include "iolib.h" #include #include -#include #include /* * Leading flags @@ -149,11 +148,13 @@ ocvt_x, 0, 0, 0, 0, 0, 0, 0, /* x y z { | } ~ ^? */ static int nprint; int -vfprintf(FILE *f, const char *s, va_list args) +vfprintf(FILE *f, const char *as, va_list args) { int tfl, flags, width, precision; + unsigned char *s; nprint = 0; + s = (unsigned char *)as; while(*s){ if(*s != '%'){ putc(*s++, f); @@ -162,7 +163,7 @@ vfprintf(FILE *f, const char *s, va_list args) } s++; flags = 0; - while(lflag[*s&_IO_CHMASK]) flags |= lflag[*s++&_IO_CHMASK]; + while(lflag[*s]) flags |= lflag[*s++]; if(*s == '*'){ width = va_arg(args, int); s++; @@ -188,7 +189,7 @@ vfprintf(FILE *f, const char *s, va_list args) } else precision = -1; - while(tfl = tflag[*s&_IO_CHMASK]){ + while(tfl = tflag[*s]){ if(tfl == LONG && (flags & LONG)){ flags &= ~LONG; tfl = VLONG; @@ -208,9 +209,9 @@ vfprintf(FILE *f, const char *s, va_list args) static int ocvt_c(FILE *f, va_list *args, int flags, int width, int precision) { -#pragma ref precision int i; + USED(precision); if(!(flags&LEFT)) for(i=1; i #include -#include #include static int icvt_f(FILE *f, va_list *args, int store, int width, int type); static int icvt_x(FILE *f, va_list *args, int store, int width, int type); @@ -106,8 +105,7 @@ int vfscanf(FILE *f, const char *s, va_list args){ return ncvt; } static int icvt_n(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref f -#pragma ref width + USED(f, width); if(store){ --ncvt; /* this assignment doesn't count! */ switch(type){ @@ -279,9 +277,11 @@ static int icvt_f(FILE *f, va_list *args, int store, int width, int type){ return 1; } static int icvt_s(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type int c, nn; register char *s; + + USED(type); + s = 0; if(store) s=va_arg(*args, char *); do c=ngetc(f); @@ -307,9 +307,11 @@ static int icvt_s(FILE *f, va_list *args, int store, int width, int type){ return 1; } static int icvt_c(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type int c; register char *s; + + USED(type); + s = 0; if(store) s=va_arg(*args, char *); if(width<0) width=1; for(;;){ @@ -339,10 +341,11 @@ static int match(int c, const char *pat){ return !ok; } static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type int c, nn; register char *s; register const char *pat; + USED(type); + s = 0; pat=++fmtp; if(*fmtp=='^') fmtp++; if(*fmtp!='\0') fmtp++; diff --git a/sys/src/libstdio/Stdio.h b/sys/src/libstdio/Stdio.h deleted file mode 100644 index 909c90705b..0000000000 --- a/sys/src/libstdio/Stdio.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * pANS stdio.h - */ -/* - * According to X3J11, there is only one i/o buffer - * and it must not be occupied by both input and output data. - * If rpwp>=(f)->rp || (f)->flags&LINEBUF && _IO_ctmp=='\n'\ - * ?_IO_putc(_IO_ctmp, f)\ - * :*(f)->wp++=_IO_ctmp) - * - */ -typedef struct{ - int fd; /* UNIX file pointer */ - char flags; /* bits for must free buffer on close, line-buffered */ - char state; /* last operation was read, write, position, error, eof */ - char *buf; /* pointer to i/o buffer */ - char *rp; /* read pointer (or write end-of-buffer) */ - char *wp; /* write pointer (or read end-of-buffer) */ - char *lp; /* actual write pointer used when line-buffering */ - long bufl; /* actual length of buffer */ - char unbuf[1]; /* tiny buffer for unbuffered io (used for ungetc?) */ -}FILE; -typedef long fpos_t; -#ifndef NULL -#define NULL 0 -#endif -/* - * Third arg of setvbuf - */ -#define _IOFBF 1 /* block-buffered */ -#define _IOLBF 2 /* line-buffered */ -#define _IONBF 3 /* unbuffered */ -#define BUFSIZ 4096 /* size of setbuf buffer */ -#define EOF (-1) /* returned on end of file */ -#define FOPEN_MAX 128 /* max files open */ -#define FILENAME_MAX BUFSIZ /* silly filename length */ -#define L_tmpnam 20 /* sizeof "/tmp/abcdefghij9999 */ -#define SEEK_CUR 1 -#define SEEK_END 2 -#define SEEK_SET 0 -#define TMP_MAX 64 /* very hard to set correctly */ -#define stderr (&_IO_stream[2]) -#define stdin (&_IO_stream[0]) -#define stdout (&_IO_stream[1]) -#define _IO_CHMASK 0377 /* mask for 8 bit characters */ -FILE *tmpfile(void); -char *tmpnam(char *); -int fclose(FILE *); -int fflush(FILE *); -FILE *fopen(const char *, const char *); -FILE *freopen(const char *, const char *, FILE *); -void setbuf(FILE *, char *); -int setvbuf(FILE *, char *, int, long); -int fprintf(FILE *, const char *, ...); -int fscanf(FILE *, const char *, ...); -int printf(const char *, ...); -int scanf(const char *, ...); -int sprintf(char *, const char *, ...); -int sscanf(const char *, const char *, ...); -int vfprintf(FILE *, const char *, va_list); -int vprintf(const char *, va_list); -int vsprintf(char *, const char *, va_list); -int vfscanf(FILE *, const char *, va_list); -int fgetc(FILE *); -char *fgets(char *, int, FILE *); -int fputc(int, FILE *); -int fputs(const char *, FILE *); -int getc(FILE *); -#define getc(f) ((f)->rp>=(f)->wp?_IO_getc(f):*(f)->rp++&_IO_CHMASK) -int _IO_getc(FILE *f); -int getchar(void); -#define getchar() getc(stdin) -char *gets(char *); -int putc(int, FILE *); -#define putc(c, f) ((f)->wp>=(f)->rp?_IO_putc(c, f):(*(f)->wp++=c)&_IO_CHMASK) -int _IO_putc(int, FILE *); -int putchar(int); -#define putchar(c) putc(c, stdout) -int puts(const char *); -int ungetc(int, FILE *); -long fread(void *, long, long, FILE *); -long fwrite(const void *, long, long, FILE *); -int fgetpos(FILE *, fpos_t *); -int fseek(FILE *, long int, int); -int fsetpos(FILE *, const fpos_t *); -long int ftell(FILE *); -void rewind(FILE *); -void clearerr(FILE *); -int feof(FILE *); -int ferror(FILE *); -void perror(const char *); -extern FILE _IO_stream[FOPEN_MAX]; -FILE *sopenr(const char *); -FILE *sopenw(void); -char *sclose(FILE *); -char *dtoa(double, int, int, int*, int*, char**); -void freedtoa(char*); diff --git a/sys/src/libstdio/_IO_getc.c b/sys/src/libstdio/_IO_getc.c index b6ab110c06..1c053fd85f 100644 --- a/sys/src/libstdio/_IO_getc.c +++ b/sys/src/libstdio/_IO_getc.c @@ -20,7 +20,7 @@ int _IO_getc(FILE *f){ f->state=RD; f->rp=f->buf; f->wp=f->buf+cnt; - return (*f->rp++)&_IO_CHMASK; + return *f->rp++; } } } diff --git a/sys/src/libstdio/_IO_putc.c b/sys/src/libstdio/_IO_putc.c index 4c3a742386..8825c3675e 100644 --- a/sys/src/libstdio/_IO_putc.c +++ b/sys/src/libstdio/_IO_putc.c @@ -56,7 +56,7 @@ int _IO_putc(int c, FILE *f){ else if(f->flags&LINEBUF){ if(f->lp==f->rp){ cnt=f->lp-f->buf; - if(f->flags&APPEND) seek(f->fd, 0L, 2); + if(f->flags&APPEND) seek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; @@ -66,7 +66,7 @@ int _IO_putc(int c, FILE *f){ *f->lp++=c; if(c=='\n'){ cnt=f->lp-f->buf; - if(f->flags&APPEND) seek(f->fd, 0L, 2); + if(f->flags&APPEND) seek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; @@ -76,7 +76,7 @@ int _IO_putc(int c, FILE *f){ } else if(f->buf==f->unbuf){ f->unbuf[0]=c; - if(f->flags&APPEND) seek(f->fd, 0L, 2); + if(f->flags&APPEND) seek(f->fd, 0, SEEK_END); if(write(f->fd, f->buf, 1)!=1){ f->state=ERR; return EOF; @@ -85,7 +85,7 @@ int _IO_putc(int c, FILE *f){ else{ if(f->wp==f->rp){ cnt=f->wp-f->buf; - if(f->flags&APPEND) seek(f->fd, 0L, 2); + if(f->flags&APPEND) seek(f->fd, 0, SEEK_END); if(cnt!=0 && write(f->fd, f->buf, cnt)!=cnt){ f->state=ERR; return EOF; diff --git a/sys/src/libstdio/dtoa.c b/sys/src/libstdio/dtoa.c index 22a3616664..66d1e1b727 100644 --- a/sys/src/libstdio/dtoa.c +++ b/sys/src/libstdio/dtoa.c @@ -130,7 +130,7 @@ Balloc(int k) return rv; } -static void +static void Bfree(Bigint *v) { if (v) { @@ -184,7 +184,7 @@ s2b(const char *s, int nd0, int nd, unsigned int y9) int x, y; x = (nd + 8) / 9; - for (k = 0, y = 1; x > y; y <<= 1, k++) + for (k = 0, y = 1; x > y; y <<= 1, k++) ; b = Balloc(k); b->x[0] = y9; @@ -193,7 +193,7 @@ s2b(const char *s, int nd0, int nd, unsigned int y9) i = 9; if (9 < nd0) { s += 9; - do + do b = multadd(b, 10, *s++ - '0'); while (++i < nd0); s++; @@ -204,7 +204,7 @@ s2b(const char *s, int nd0, int nd, unsigned int y9) return b; } -static int +static int hi0bits(register unsigned int x) { register int k = 0; @@ -233,7 +233,7 @@ hi0bits(register unsigned int x) return k; } -static int +static int lo0bits(unsigned int *y) { register int k; @@ -345,7 +345,7 @@ mult(Bigint *a, Bigint *b) *xc = z2; } } - for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) + for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; c->wds = wc; return c; @@ -358,7 +358,7 @@ pow5mult(Bigint *b, int k) { Bigint * b1, *p5, *p51; int i; - static int p05[3] = { + static int p05[3] = { 5, 25, 125 }; if (i = k & 3) @@ -423,7 +423,7 @@ lshift(Bigint *b, int k) } while (x < xe); if (*x1 = z) ++n1; - } else + } else do *x1++ = *x++; while (x < xe); @@ -432,7 +432,7 @@ lshift(Bigint *b, int k) return b1; } -static int +static int cmp(Bigint *a, Bigint *b) { unsigned int * xa, *xa0, *xb, *xb0; @@ -508,7 +508,7 @@ diff(Bigint *a, Bigint *b) return c; } -static double +static double ulp(double x) { ulong L; @@ -519,7 +519,7 @@ ulp(double x) return ulongs2double((Ulongs){L, 0}); } -static double +static double b2d(Bigint *a, int *e) { unsigned *xa, *xa0, w, y, z; @@ -583,7 +583,7 @@ d2b(double d, int *e, int *bits) return b; } -static double +static double ratio(Bigint *a, Bigint *b) { double da, db; @@ -614,10 +614,10 @@ tens[] = { }; static const double -bigtens[] = { +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static const double tinytens[] = { +static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 9007199254740992.e-256 }; @@ -631,7 +631,7 @@ static const double tinytens[] = { #define NAN_WORD1 0 -static int +static int match(const char **sp, char *t) { int c, d; @@ -647,7 +647,7 @@ match(const char **sp, char *t) return 1; } -static void +static void gethex(double *rvp, const char **sp) { unsigned int c, x[2]; @@ -690,7 +690,7 @@ gethex(double *rvp, const char **sp) *rvp = ulongs2double((Ulongs){Exp_mask | x[0], x[1]}); } -static int +static int quorem(Bigint *b, Bigint *S) { int n; @@ -761,8 +761,8 @@ rv_alloc(int i) int j, k, *r; j = sizeof(unsigned int); - for (k = 0; - sizeof(Bigint) - sizeof(unsigned int) - sizeof(int) + j <= i; + for (k = 0; + sizeof(Bigint) - sizeof(unsigned int) - sizeof(int) + j <= i; j <<= 1) k++; r = (int * )Balloc(k); @@ -777,7 +777,7 @@ nrv_alloc(char *s, char **rve, int n) char *rv, *t; t = rv = rv_alloc(n); - while (*t = *s++) + while (*t = *s++) t++; if (rve) *rve = t; @@ -1114,7 +1114,7 @@ dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) mhi = mlo = 0; if (leftright) { if (mode < 2) { - i = + i = 1 + P - bbits; } else { j = ilim - 1; diff --git a/sys/src/libstdio/fdopen.c b/sys/src/libstdio/fdopen.c index c2b5034fea..2353e15ed4 100644 --- a/sys/src/libstdio/fdopen.c +++ b/sys/src/libstdio/fdopen.c @@ -13,7 +13,7 @@ * a+ a+b ab+ open to read and write, positioned at eof, creating if non-existant. */ FILE *fdopen(const int fd, const char *mode){ - FILE *f; + FILE *f; qlock(&_stdiolk); for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) @@ -24,7 +24,7 @@ FILE *fdopen(const int fd, const char *mode){ } f->fd=fd; if(mode[0]=='a') - seek(f->fd, 0L, 2); + seek(f->fd, 0, SEEK_END); if(f->fd==-1) return NULL; f->flags=0; f->state=OPEN; diff --git a/sys/src/libstdio/fflush.c b/sys/src/libstdio/fflush.c index a5a5f0b3c7..13470b3408 100644 --- a/sys/src/libstdio/fflush.c +++ b/sys/src/libstdio/fflush.c @@ -6,10 +6,9 @@ * pANS stdio -- data (put here, since loader won't load a separate file) */ FILE _IO_stream[]={ -/* fd flags state buf rp wp lp bufl unbuf */ - 0, 0, OPEN, 0, 0, 0, 0, 0, 0, - 1, 0, OPEN, 0, 0, 0, 0, 0, 0, - 2, 0, OPEN, 0, 0, 0, 0, 0, 0, + { .fd 0, .state OPEN, }, + { .fd 1, .state OPEN, }, + { .fd 2, .state OPEN, }, }; int _fflush(FILE *f){ diff --git a/sys/src/libstdio/freopen.c b/sys/src/libstdio/freopen.c index a5ac259933..d498d17266 100644 --- a/sys/src/libstdio/freopen.c +++ b/sys/src/libstdio/freopen.c @@ -40,7 +40,7 @@ FILE *freopen(const char *name, const char *mode, FILE *f){ f->fd=open(name, m); if(f->fd<0) f->fd=create(name, m, 0666); - seek(f->fd, 0LL, 2); + seek(f->fd, 0, SEEK_END); break; } diff --git a/sys/src/libstdio/ftell.c b/sys/src/libstdio/ftell.c index d5acbb3739..3a06133a04 100644 --- a/sys/src/libstdio/ftell.c +++ b/sys/src/libstdio/ftell.c @@ -3,7 +3,7 @@ */ #include "iolib.h" long ftell(FILE *f){ - long seekp=seek(f->fd, 0L, 1); + long seekp=seek(f->fd, 0, SEEK_CUR); if(seekp<0) return -1; /* enter error state? */ switch(f->state){ default: diff --git a/sys/src/libstdio/ftello.c b/sys/src/libstdio/ftello.c index 2480856b98..1b2b9b38f5 100644 --- a/sys/src/libstdio/ftello.c +++ b/sys/src/libstdio/ftello.c @@ -3,7 +3,7 @@ */ #include "iolib.h" long long ftello(FILE *f){ - long long seekp=seek(f->fd, 0L, 1); + long long seekp=seek(f->fd, 0, SEEK_CUR); if(seekp<0) return -1; /* enter error state? */ switch(f->state){ default: diff --git a/sys/src/libstdio/fwrite.c b/sys/src/libstdio/fwrite.c index d77679b22d..d3483a985e 100644 --- a/sys/src/libstdio/fwrite.c +++ b/sys/src/libstdio/fwrite.c @@ -23,7 +23,7 @@ long fwrite(const void *p, long recl, long nrec, FILE *f){ d=f->wp-f->buf; if(d>0){ if(f->flags&APPEND) - seek(f->fd, 0L, 2); + seek(f->fd, 0, SEEK_END); if(write(f->fd, f->buf, d)!=d){ f->state=ERR; goto ret; @@ -31,7 +31,7 @@ long fwrite(const void *p, long recl, long nrec, FILE *f){ f->wp=f->rp=f->buf; } if(f->flags&APPEND) - seek(f->fd, 0L, 2); + seek(f->fd, 0, SEEK_END); d=write(f->fd, s, n); if(d<=0){ f->state=ERR; diff --git a/sys/src/libstdio/iolib.h b/sys/src/libstdio/iolib.h index 8748b55180..4c3cd3fd33 100644 --- a/sys/src/libstdio/iolib.h +++ b/sys/src/libstdio/iolib.h @@ -19,7 +19,7 @@ #include #include #undef END -#include "Stdio.h" +#include /* * Flag bits */ @@ -42,3 +42,7 @@ int _IO_setvbuf(FILE *); /* half hearted attempt to make multi threaded */ extern QLock _stdiolk; + +/* internal functions */ +char *dtoa(double, int, int, int*, int*, char**); +void freedtoa(char*); diff --git a/sys/src/libstdio/mkfile b/sys/src/libstdio/mkfile index 9fa7060d7c..692cf37cfe 100644 --- a/sys/src/libstdio/mkfile +++ b/sys/src/libstdio/mkfile @@ -62,8 +62,7 @@ UPDATE=\ ${LIB:/$objtype/%=/386/%}\ state=CLOSED; f->flags=0; - return f->buf; + return (char *)f->buf; } diff --git a/sys/src/libstdio/setbuf.c b/sys/src/libstdio/setbuf.c index 31c5d3e1e8..0264208000 100644 --- a/sys/src/libstdio/setbuf.c +++ b/sys/src/libstdio/setbuf.c @@ -2,7 +2,7 @@ * pANS stdio -- setbuf */ #include "iolib.h" -void setbuf(FILE *f, char *buf){ +void setbuf(FILE *f, void *buf){ if(f->state==OPEN){ if(buf) f->bufl=BUFSIZ; diff --git a/sys/src/libstdio/setvbuf.c b/sys/src/libstdio/setvbuf.c index 34c3bf7c8b..fd4afad1ac 100644 --- a/sys/src/libstdio/setvbuf.c +++ b/sys/src/libstdio/setvbuf.c @@ -2,7 +2,7 @@ * pANS stdio -- setvbuf */ #include "iolib.h" -int setvbuf(FILE *f, char *buf, int mode, long size){ +int setvbuf(FILE *f, void *buf, int mode, long size){ if(f->state!=OPEN){ f->state=ERR; return -1; diff --git a/sys/src/libstdio/sopenr.c b/sys/src/libstdio/sopenr.c index bbd3776027..7264bbaa21 100644 --- a/sys/src/libstdio/sopenr.c +++ b/sys/src/libstdio/sopenr.c @@ -11,7 +11,7 @@ FILE *sopenr(const char *s){ qunlock(&_stdiolk); return NULL; } - f->buf=f->rp=(char *)s; /* what an annoyance const is */ + f->buf=f->rp=(uchar *)s; /* what an annoyance const is */ f->bufl=strlen(s); f->wp=f->buf+f->bufl; f->state=RD; diff --git a/sys/src/libstdio/vfprintf.c b/sys/src/libstdio/vfprintf.c index 4600caff63..5114656e53 100644 --- a/sys/src/libstdio/vfprintf.c +++ b/sys/src/libstdio/vfprintf.c @@ -146,12 +146,14 @@ static int nprint; QLock _stdiolk; int -vfprintf(FILE *f, const char *s, va_list args) +vfprintf(FILE *f, const char *as, va_list args) { int flags, width, precision; + uchar *s; qlock(&_stdiolk); + s = (uchar *)as; nprint = 0; while(*s){ if(*s != '%'){ @@ -161,7 +163,7 @@ vfprintf(FILE *f, const char *s, va_list args) } s++; flags = 0; - while(lflag[*s&_IO_CHMASK]) flags |= lflag[*s++&_IO_CHMASK]; + while(lflag[*s]) flags |= lflag[*s++]; if(*s == '*'){ width = va_arg(args, int); s++; @@ -187,7 +189,7 @@ vfprintf(FILE *f, const char *s, va_list args) } else precision = -1; - while(tflag[*s&_IO_CHMASK]) flags |= tflag[*s++&_IO_CHMASK]; + while(tflag[*s]) flags |= tflag[*s++]; if(ocvt[*s]) nprint += (*ocvt[*s++])(f, &args, flags, width, precision); else if(*s){ putc(*s++, f); @@ -210,9 +212,9 @@ vfprintf(FILE *f, const char *s, va_list args) static int ocvt_c(FILE *f, va_list *args, int flags, int width, int precision) { -#pragma ref precision int i; + USED(precision); if(!(flags&LEFT)) for(i=1; i0) nout += exponent; /* digits before decimal point */ else nout++; /* there's always at least one */ if(sign || flags&(SPACE|SIGN)) nout++; /* sign */ + eptr = nil; /* silence used and not set */ if(fmt != 'f'){ /* exponent */ eptr = ebuf; for(i=exponent<=0?1-exponent:exponent-1; i; i/=10) diff --git a/sys/src/libstdio/vfscanf.c b/sys/src/libstdio/vfscanf.c index d17dcf2c4a..10caf27896 100644 --- a/sys/src/libstdio/vfscanf.c +++ b/sys/src/libstdio/vfscanf.c @@ -103,8 +103,7 @@ int vfscanf(FILE *f, const char *s, va_list args){ return ncvt; } static int icvt_n(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref f -#pragma ref width + USED(f, width); if(store){ --ncvt; /* this assignment doesn't count! */ switch(type){ @@ -276,9 +275,10 @@ static int icvt_f(FILE *f, va_list *args, int store, int width, int type){ return 1; } static int icvt_s(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type + USED(type); int c, nn; register char *s; + s = nil; /* silence used and not set */ if(store) s=va_arg(*args, char *); do c=ngetc(f); @@ -304,9 +304,10 @@ static int icvt_s(FILE *f, va_list *args, int store, int width, int type){ return 1; } static int icvt_c(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type + USED(type); int c; register char *s; + s = nil; /* silence used and not set */ if(store) s=va_arg(*args, char *); if(width<0) width=1; for(;;){ @@ -336,7 +337,7 @@ static int match(int c, const char *pat){ return !ok; } static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){ -#pragma ref type + USED(type); int c, nn; register char *s; register const char *pat; @@ -344,6 +345,7 @@ static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){ if(*fmtp=='^') fmtp++; if(*fmtp!='\0') fmtp++; while(*fmtp!='\0' && *fmtp!=']') fmtp++; + s = nil; /* silence used and not set */ if(store) s=va_arg(*args, char *); nn=0; for(;;){ From c86cf2abf86a7b2b6e6c4c64ffba85552a3ab60d Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 20 Oct 2016 01:58:57 +0000 Subject: [PATCH 161/402] sys/src/cmd/ip/ftpfs: fix size of 9P buffers (thanks Geoff Collyer) --- sys/src/cmd/ip/ftpfs/ftpfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/ip/ftpfs/ftpfs.c b/sys/src/cmd/ip/ftpfs/ftpfs.c index 17e0df7b42..cbdaae509d 100644 --- a/sys/src/cmd/ip/ftpfs/ftpfs.c +++ b/sys/src/cmd/ip/ftpfs/ftpfs.c @@ -19,9 +19,9 @@ struct Fid Fid *fids; /* linked list of fids */ char errstring[128]; /* error to return */ int mfd; /* fd for 9fs */ -int messagesize = 4*1024*IOHDRSZ; -uchar mdata[8*1024*IOHDRSZ]; -uchar mbuf[8*1024*IOHDRSZ]; +int messagesize = 4*1024+IOHDRSZ; +uchar mdata[8*1024+IOHDRSZ]; +uchar mbuf[8*1024+IOHDRSZ]; Fcall rhdr; Fcall thdr; int debug; From bde2bf191b3b950640a19f69a23780261f3a9fff Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 19 Nov 2016 00:07:08 +0000 Subject: [PATCH 162/402] sys/src: times are unsigned (thanks Geoff Collyer) --- sys/man/2/ctime | 10 ++++++++-- sys/src/cmd/ar.c | 10 +++++----- sys/src/cmd/mk/archive.c | 2 +- sys/src/cmd/upas/smtp/greylist.c | 4 ++-- sys/src/libc/9sys/ctime.c | 24 ++++++++++++++---------- sys/src/libc/9sys/tm2sec.c | 20 ++++++++++---------- 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/sys/man/2/ctime b/sys/man/2/ctime index a4e074343e..814dc76318 100644 --- a/sys/man/2/ctime +++ b/sys/man/2/ctime @@ -121,9 +121,15 @@ GMT 0 .SH BUGS The return values point to static data whose content is overwritten by each call. -.br +.PP Daylight Savings Time is ``normal'' in the Southern hemisphere. -.br +.PP These routines are not equipped to handle non-\c .SM ASCII text, and are provincial anyway. +.PP +These interfaces are fixed, but all occurrences of +.B long +in the above should be manipulated as +.BR ulong ; +this extends the range of valid times into the year 2106. diff --git a/sys/src/cmd/ar.c b/sys/src/cmd/ar.c index 006a54a839..0d066adea5 100644 --- a/sys/src/cmd/ar.c +++ b/sys/src/cmd/ar.c @@ -731,11 +731,11 @@ armove(Biobuf *b, Arfile *ap, Armember *bp) for (cp = strchr(bp->hdr.name, 0); /* blank pad on right */ cp < bp->hdr.name+sizeof(bp->hdr.name); cp++) *cp = ' '; - sprint(bp->hdr.date, "%-12ld", d->mtime); + sprint(bp->hdr.date, "%-12lud", d->mtime); sprint(bp->hdr.uid, "%-6d", 0); sprint(bp->hdr.gid, "%-6d", 0); sprint(bp->hdr.mode, "%-8lo", d->mode); - sprint(bp->hdr.size, "%-10lld", d->length); + sprint(bp->hdr.size, "%-10llud", d->length); strncpy(bp->hdr.fmag, ARFMAG, 2); bp->size = d->length; arread(b, bp, bp->size); @@ -829,11 +829,11 @@ rl(int fd) len = symdefsize; if(len&01) len++; - sprint(a.date, "%-12ld", time(0)); + sprint(a.date, "%-12lud", time(0)); sprint(a.uid, "%-6d", 0); sprint(a.gid, "%-6d", 0); sprint(a.mode, "%-8lo", 0644L); - sprint(a.size, "%-10ld", len); + sprint(a.size, "%-10lud", len); strncpy(a.fmag, ARFMAG, 2); strcpy(a.name, symdef); for (cp = strchr(a.name, 0); /* blank pad on right */ @@ -988,7 +988,7 @@ longt(Armember *bp) pmode(strtoul(bp->hdr.mode, 0, 8)); Bprint(&bout, "%3ld/%1ld", strtol(bp->hdr.uid, 0, 0), strtol(bp->hdr.gid, 0, 0)); - Bprint(&bout, "%7ld", bp->size); + Bprint(&bout, "%7lud", bp->size); cp = ctime(bp->date); Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24); } diff --git a/sys/src/cmd/mk/archive.c b/sys/src/cmd/mk/archive.c index 8c4c0c81e2..8d73ca7af3 100644 --- a/sys/src/cmd/mk/archive.c +++ b/sys/src/cmd/mk/archive.c @@ -67,7 +67,7 @@ atouch(char *name) if(strcmp(member, h.name) == 0){ t = SARNAME-sizeof(h); /* ughgghh */ LSEEK(fd, t, 1); - fprint(fd, "%-12ld", time(0)); + fprint(fd, "%-12lud", time(0)); break; } t = atol(h.size); diff --git a/sys/src/cmd/upas/smtp/greylist.c b/sys/src/cmd/upas/smtp/greylist.c index b5cee5a6ee..460423a575 100644 --- a/sys/src/cmd/upas/smtp/greylist.c +++ b/sys/src/cmd/upas/smtp/greylist.c @@ -30,7 +30,7 @@ typedef struct { int existed; /* these two are distinct to cope with errors */ int created; int noperm; - long mtime; /* mod time, iff it already existed */ + ulong mtime; /* mod time, iff it already existed */ } Greysts; static char whitelist[] = "/mail/grey/whitelist"; @@ -218,7 +218,7 @@ addgreylist(char *file, Greysts *gsp) static int recentcall(Greysts *gsp) { - long delay = time(0) - gsp->mtime; + ulong delay = (ulong)time(0) - gsp->mtime; if (!gsp->existed) return 0; diff --git a/sys/src/libc/9sys/ctime.c b/sys/src/libc/9sys/ctime.c index 0137d6fff2..f072ad8439 100644 --- a/sys/src/libc/9sys/ctime.c +++ b/sys/src/libc/9sys/ctime.c @@ -47,7 +47,8 @@ static char dmsize[12] = static int dysize(int); static void ct_numb(char*, int); -#define TZSIZE 150 +#define TZSIZE ((136*2)+10) /* 1970-2106; match tm2sec.c */ + static void readtimezone(void); static int rd_name(char**, char*); static int rd_long(char**, long*); @@ -58,7 +59,7 @@ struct char dlname[4]; long stdiff; long dldiff; - long dlpairs[TZSIZE]; + ulong dlpairs[TZSIZE]; } timezone; char* @@ -68,12 +69,13 @@ ctime(long t) } Tm* -localtime(long tim) +localtime(long atim) /* should be ulong, but it's too late */ { Tm *ct; - long t, *p; + ulong tim, t, *p; int dlflag; + tim = atim; if(timezone.stname[0] == 0) readtimezone(); t = tim + timezone.stdiff; @@ -97,17 +99,19 @@ localtime(long tim) } Tm* -gmtime(long tim) +gmtime(long atim) /* should be ulong, but it's too late */ { int d0, d1; long hms, day; + ulong tim; static Tm xtime; /* * break initial number into days */ - hms = (ulong)tim % 86400L; - day = (ulong)tim / 86400L; + tim = atim; + hms = tim % 86400L; + day = tim / 86400L; if(hms < 0) { hms += 86400L; day -= 1; @@ -182,7 +186,7 @@ asctime(Tm *t) cbuf[22] = *ncp; if(t->year >= 100) { cbuf[24] = '2'; - cbuf[25] = t->year >= 200? '1': '0'; + cbuf[25] = '0'; } ct_numb(cbuf+26, t->year+100); return cbuf; @@ -234,12 +238,12 @@ readtimezone(void) if(rd_long(&p, &timezone.dldiff)) goto error; for(i=0; i #include -#define TZSIZE 150 +#define TZSIZE ((136*2)+10) /* 1970-2106; match tm2sec.c */ + static void readtimezone(void); static int rd_name(char**, char*); static int rd_long(char**, long*); + static struct { @@ -12,12 +14,12 @@ struct char dlname[4]; long stdiff; long dldiff; - long dlpairs[TZSIZE]; + ulong dlpairs[TZSIZE]; } timezone; -#define SEC2MIN 60L -#define SEC2HOUR (60L*SEC2MIN) -#define SEC2DAY (24L*SEC2HOUR) +#define SEC2MIN 60UL +#define SEC2HOUR (60UL*SEC2MIN) +#define SEC2DAY (24UL*SEC2HOUR) /* * days per month plus days/year @@ -50,7 +52,7 @@ yrsize(int y) long tm2sec(Tm *tm) { - long secs; + ulong secs; int i, yday, year, *d2m; if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0) @@ -95,8 +97,6 @@ tm2sec(Tm *tm) secs -= timezone.stdiff; else if(strcmp(tm->zone, timezone.dlname) == 0) secs -= timezone.dldiff; - if(secs < 0) - secs = 0; return secs; } @@ -124,12 +124,12 @@ readtimezone(void) if(rd_long(&p, &timezone.dldiff)) goto error; for(i=0; i Date: Wed, 29 Mar 2017 16:00:04 +0000 Subject: [PATCH 163/402] sys/src/cmd: fix kprof on Trim-Slice (thanks Geoff Collyer) --- sys/src/cmd/kprof.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sys/src/cmd/kprof.c b/sys/src/cmd/kprof.c index 4dab86dc14..0e0755611b 100644 --- a/sys/src/cmd/kprof.c +++ b/sys/src/cmd/kprof.c @@ -40,17 +40,16 @@ void main(int argc, char *argv[]) { int fd; - long i, j, k, n; - char *name; + long delta, i, j, k, n; + ulong sum; ulong *data; vlong tbase; - ulong sum; - long delta; - Symbol s; + char *name; Biobuf outbuf; + struct COUNTER *cp; Fhdr f; Dir *d; - struct COUNTER *cp; + Symbol s; if(argc != 3) error(0, "usage: kprof text data"); @@ -87,18 +86,22 @@ main(int argc, char *argv[]) close(fd); for(i=0; ikbase; - if(tbase != s.value & ~0xFFF) + if(tbase != (s.value & ~0xFFF)) { print("warning: kbase %.8llux != tbase %.8llux\n", tbase, s.value&~0xFFF); + tbase = s.value; + } print("KTZERO %.8llux PGSIZE %dKb\n", tbase, mach->pgsize/1024); /* * Accumulate counts for each function From 4be05b6bfea243e627947d1f36ae3f9c49482c79 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 22 Aug 2017 14:21:39 +0000 Subject: [PATCH 164/402] sys/src/libauthsrv: fix findnvram on amd64 (thanks Kyohei Kadota) --- sys/src/libauthsrv/readnvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libauthsrv/readnvram.c b/sys/src/libauthsrv/readnvram.c index e991599277..883f23791e 100644 --- a/sys/src/libauthsrv/readnvram.c +++ b/sys/src/libauthsrv/readnvram.c @@ -152,7 +152,7 @@ findnvram(Nvrwhere *locp) cputype = getenv("cputype"); if(cputype == nil) cputype = strdup("mips"); - if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) { + if(strcmp(cputype, "386")==0 || strcmp(cputype, "amd64")==0 || strcmp(cputype, "alpha")==0) { free(cputype); cputype = strdup("pc"); } From 9bfd1132e8b82b18b6c25a53c5b8f01cd3600ae9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 9 Dec 2022 15:25:06 +0000 Subject: [PATCH 165/402] sys/src/libauthsrv: add openrd function to open nvram (thanks Geoff Collyer) --- sys/src/libauthsrv/readnvram.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sys/src/libauthsrv/readnvram.c b/sys/src/libauthsrv/readnvram.c index 883f23791e..cf8aab8bc8 100644 --- a/sys/src/libauthsrv/readnvram.c +++ b/sys/src/libauthsrv/readnvram.c @@ -135,6 +135,21 @@ typedef struct { static char *nvrfile = nil, *cputype = nil; +static int +openrd(char *file) +{ + int fd; + + if(nvramdebug) + fprint(2, "nvram at %s?...", file); + fd = open(file, ORDWR); + if (fd < 0) + fd = open(file, OREAD); + if(nvramdebug) + fprint(2, "%s\n", fd >= 0? "yes": "no"); + return fd; +} + /* returns with *locp filled in and locp->fd open, if possible */ static void findnvram(Nvrwhere *locp) @@ -169,11 +184,7 @@ findnvram(Nvrwhere *locp) v[0] = ""; v[1] = nil; } - if(nvramdebug) - fprint(2, "nvram at %s?...", v[0]); - fd = open(v[0], ORDWR); - if (fd < 0) - fd = open(v[0], OREAD); + fd = openrd(v[0]); safelen = sizeof(Nvrsafe); if(strstr(v[0], "/9fat") == nil) safeoff = 0; @@ -201,10 +212,7 @@ findnvram(Nvrwhere *locp) for(i=0; i Date: Sun, 24 Sep 2017 16:18:40 +0000 Subject: [PATCH 166/402] sys/src/libflate: fix typo (thanks Geoff Collyer) --- sys/src/libflate/deflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/libflate/deflate.c b/sys/src/libflate/deflate.c index 3a55af3f10..d4f604f259 100644 --- a/sys/src/libflate/deflate.c +++ b/sys/src/libflate/deflate.c @@ -56,7 +56,7 @@ enum * assumes 8 bits for len, 5+10 for offset * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS */ - HistSlop = 512, /* must be at lead MaxMatch */ + HistSlop = 512, /* must be at least MaxMatch */ HistBlock = 64*1024, HistSize = HistBlock + HistSlop, From b3e00cef8e1f7ba937b0ec8eafc388dd5a819332 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 24 Sep 2017 16:45:09 +0000 Subject: [PATCH 167/402] sys/src/cmd/troff: replace goto rtn with return (thanks Geoff Collyer) --- sys/src/cmd/troff/n4.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sys/src/cmd/troff/n4.c b/sys/src/cmd/troff/n4.c index 3b3698e4c3..c574d716ea 100644 --- a/sys/src/cmd/troff/n4.c +++ b/sys/src/cmd/troff/n4.c @@ -713,21 +713,19 @@ void casenr(void) lgf++; skip(); if ((i = findr(getrq())) == -1) - goto rtn; + return; skip(); j = inumb(&numtabp[i].val); if (nonumb) - goto rtn; + return; numtabp[i].val = j; skip(); trace = 0; j = atoi0(); /* BUG??? */ trace = savtr; if (nonumb) - goto rtn; + return; numtabp[i].inc = j; -rtn: - return; } void caseaf(void) From dca488f55ce829c751fc74a5ba0396dd35db1051 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 13 Dec 2019 05:23:48 +0000 Subject: [PATCH 168/402] sys/src/cmd/kfs: default to sdE0 for kfs file systems (thanks Steven Stallion) --- sys/man/4/kfs | 6 +++--- sys/src/cmd/disk/kfs/main.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/man/4/kfs b/sys/man/4/kfs index 15a9514d1f..3ceb976086 100644 --- a/sys/man/4/kfs +++ b/sys/man/4/kfs @@ -70,7 +70,7 @@ Use .I file as the disk. The default is -.BR /dev/sdC0/fs . +.BR /dev/sdE0/fs . .TP .BI "n " name Use @@ -113,9 +113,9 @@ and mount it on .EE .PP .SH FILES -.TF /dev/sdC0/fs +.TF /dev/sdE0/fs .TP -.B /dev/sdC0/fs +.B /dev/sdE0/fs Default file holding blocks. .SH SOURCE .B /sys/src/cmd/disk/kfs diff --git a/sys/src/cmd/disk/kfs/main.c b/sys/src/cmd/disk/kfs/main.c index 3ca31615b8..d670121818 100644 --- a/sys/src/cmd/disk/kfs/main.c +++ b/sys/src/cmd/disk/kfs/main.c @@ -42,7 +42,7 @@ main(int argc, char *argv[]) ream = 0; newbufsize = 0; nocheck = 0; - wrenfile = "/dev/sdC0/fs"; + wrenfile = "/dev/sdE0/fs"; pid = getpid(); snprint(buf, sizeof buf, "/proc/%d/ctl", pid); From 8cff8a28d4f7567fc06dfac95b0510ab0bc2f6d4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 11 Mar 2021 12:00:15 +0000 Subject: [PATCH 169/402] sys/src/cmd/disk/9660: add -n parameter to mk9660 to specify volume date and time --- sys/man/8/mk9660 | 4 ++++ sys/src/cmd/disk/9660/dump9660.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/man/8/mk9660 b/sys/man/8/mk9660 index d41582dde0..d9290d9798 100644 --- a/sys/man/8/mk9660 +++ b/sys/man/8/mk9660 @@ -33,6 +33,10 @@ dump9660, mk9660 \- create an ISO-9660 CD image .B -v .I volume ] +[ +.B -n +.I now +] .I image .PP .B disk/dump9660 diff --git a/sys/src/cmd/disk/9660/dump9660.c b/sys/src/cmd/disk/9660/dump9660.c index f3e593a496..8605ff36bc 100644 --- a/sys/src/cmd/disk/9660/dump9660.c +++ b/sys/src/cmd/disk/9660/dump9660.c @@ -24,7 +24,7 @@ usage(void) { if(mk9660) fprint(2, "usage: disk/mk9660 [-D:] [-9cjr] " - "[-[bB] bootfile] [-o offset blocksize] " + "[-[bB] bootfile] [-o offset blocksize] [-n now] " "[-p proto] [-s src] cdimage\n"); else fprint(2, "usage: disk/dump9660 [-D:] [-9cjr] " @@ -135,7 +135,7 @@ main(int argc, char **argv) if(info.flags & CDpbs && !(info.flags & CDbootnoemu)) usage(); - if(mk9660 && (fix || now || maxsize)) + if(mk9660 && (fix || maxsize)) usage(); if(argc != 1) From d255f20db95b88fed4a8e19a01c30a78b3cccc16 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 31 Mar 2021 11:31:51 +0000 Subject: [PATCH 170/402] sys/src/cmd: fix setting of uid/gid in tar -T (thanks Geoff Collyer) --- sys/src/cmd/tar.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sys/src/cmd/tar.c b/sys/src/cmd/tar.c index 675d3d11d1..9d65cf1375 100644 --- a/sys/src/cmd/tar.c +++ b/sys/src/cmd/tar.c @@ -1133,8 +1133,9 @@ copyfromar(int ar, int fd, char *fname, ulong blksleft, Off bytes) "%s not fully extracted\n", argv0, bytes, arname, fname); } +/* update fd's metadata. called after writing all data to it. */ static void -wrmeta(int fd, Hdr *hp, long mtime, int mode) /* update metadata */ +wrmeta(int fd, int ustar, char *user, char *group, long mtime, int mode) { Dir nd; @@ -1142,12 +1143,15 @@ wrmeta(int fd, Hdr *hp, long mtime, int mode) /* update metadata */ nd.mtime = mtime; nd.mode = mode; dirfwstat(fd, &nd); - if (isustar(hp)) { + if (ustar) { nulldir(&nd); - nd.gid = hp->gname; + nd.gid = group; + /* needs extracting user to be in gname, often fails */ dirfwstat(fd, &nd); + nulldir(&nd); - nd.uid = hp->uname; + nd.uid = user; + /* needs permissions off, very often fails */ dirfwstat(fd, &nd); } } @@ -1159,11 +1163,12 @@ wrmeta(int fd, Hdr *hp, long mtime, int mode) /* update metadata */ static void extract1(int ar, Hdr *hp, char *fname) { - int fd = -1, dir = 0; + int fd = -1, dir = 0, ustar; long mtime = strtol(hp->mtime, nil, 8); ulong mode = strtoul(hp->mode, nil, 8) & 0777; Off bytes = hdrsize(hp); /* for printing */ ulong blksleft = BYTES2TBLKS(arsize(hp)); + char *user, *group; /* fiddle name, figure out mode and blocks */ if (isdir(hp)) { @@ -1196,6 +1201,16 @@ extract1(int ar, Hdr *hp, char *fname) } else print("%s\n", fname); + /* + * copyfromar may read into tpblks, so save user & group from Hdr first, + * iff settime and this is a US-tar archive. + */ + ustar = isustar(hp); + user = group = nil; + if (ustar && settime) { + user = hp->uname? strdup(hp->uname): nil; + group = hp->gname? strdup(hp->gname): nil; + } copyfromar(ar, fd, fname, blksleft, bytes); /* touch up meta data and close */ @@ -1205,9 +1220,11 @@ extract1(int ar, Hdr *hp, char *fname) * creating files in them, but we don't do that. */ if (settime) - wrmeta(fd, hp, mtime, mode); + wrmeta(fd, ustar, user, group, mtime, mode); close(fd); } + free(user); + free(group); } static char * From e39e92d024a4886217a51dd11269b11498229b9f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 10:24:47 +0000 Subject: [PATCH 171/402] sys/src/libsec: fix implementation of AES-CTR (thanks Richard Miller) --- sys/src/libsec/port/aes.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sys/src/libsec/port/aes.c b/sys/src/libsec/port/aes.c index 3999c230c9..b38b93d006 100644 --- a/sys/src/libsec/port/aes.c +++ b/sys/src/libsec/port/aes.c @@ -77,6 +77,7 @@ setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec) keybytes = AESmaxkey; memmove(s->key, key, keybytes); s->keybytes = keybytes; + s->ctrsz = 4; /* default counter size from rfc3686 */ s->rounds = aes_setup(s->ekey, s->dkey, s->key, keybytes * 8); if(ivec != nil) memmove(s->ivec, ivec, AESbsize); @@ -230,12 +231,23 @@ static void incrementCTR(uchar *p, uint ctrsz) { int len; + ulong c; uchar *ctr; mpint *mpctr, *mpctrsz; ctr = p + AESbsize - ctrsz; + if(ctrsz == 4){ + /* + * If counter is 32 bits (as in rfc3686 and ssh2) there's + * no need to use extended precision. + */ + c = 1 + (ctr[0]<<24 | ctr[1]<<16 | ctr[2]<<8 | ctr[3]); + ctr[0] = c>>24; ctr[1] = c>>16; ctr[2] = c>>8; ctr[3] = c; + return; + } mpctr = betomp(ctr, ctrsz, nil); - mpctrsz = itomp(1 << (ctrsz*8), nil); + mpctrsz = mpnew(ctrsz*8 + 1); + mpleft(mpone, ctrsz*8, mpctrsz); mpadd(mpctr, mpone, mpctr); mpmod(mpctr, mpctrsz, mpctr); len = mptobe(mpctr, ctr, ctrsz, nil); From d9851416c612e828ce890d55403930a0d35e7950 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 10:25:02 +0000 Subject: [PATCH 172/402] sys/src/cmd/ssh2: add support for AES-CTR (thanks Richard Miller) --- sys/src/cmd/ssh2/cipheraes.c | 44 ++++++++++++++++++++++++++++++++++++ sys/src/cmd/ssh2/netssh.c | 3 +++ sys/src/cmd/ssh2/netssh.h | 1 + 3 files changed, 48 insertions(+) diff --git a/sys/src/cmd/ssh2/cipheraes.c b/sys/src/cmd/ssh2/cipheraes.c index eb48ccd87d..68de018b4a 100644 --- a/sys/src/cmd/ssh2/cipheraes.c +++ b/sys/src/cmd/ssh2/cipheraes.c @@ -56,6 +56,16 @@ encryptaes(CipherState *cs, uchar *buf, int nbuf) qunlock(&aeslock); } +static void +encryptaesctr(CipherState *cs, uchar *buf, int nbuf) +{ + if(cs->state.setup != 0xcafebabe || cs->state.rounds > AESmaxrounds) + return; + qlock(&aeslock); + aesCTRencrypt(buf, nbuf, &cs->state); + qunlock(&aeslock); +} + static void decryptaes(CipherState *cs, uchar *buf, int nbuf) { @@ -66,6 +76,16 @@ decryptaes(CipherState *cs, uchar *buf, int nbuf) qunlock(&aeslock); } +static void +decryptaesctr(CipherState *cs, uchar *buf, int nbuf) +{ + if(cs->state.setup != 0xcafebabe || cs->state.rounds > AESmaxrounds) + return; + qlock(&aeslock); + aesCTRdecrypt(buf, nbuf, &cs->state); + qunlock(&aeslock); +} + Cipher cipheraes128 = { "aes128-cbc", AESbsize, @@ -74,6 +94,14 @@ Cipher cipheraes128 = { decryptaes, }; +Cipher cipheraes128ctr = { + "aes128-ctr", + AESbsize, + initaes128, + encryptaesctr, + decryptaesctr, +}; + Cipher cipheraes192 = { "aes192-cbc", AESbsize, @@ -82,6 +110,14 @@ Cipher cipheraes192 = { decryptaes, }; +Cipher cipheraes192ctr = { + "aes192-ctr", + AESbsize, + initaes192, + encryptaesctr, + decryptaesctr, +}; + Cipher cipheraes256 = { "aes256-cbc", AESbsize, @@ -89,3 +125,11 @@ Cipher cipheraes256 = { encryptaes, decryptaes, }; + +Cipher cipheraes256ctr = { + "aes256-ctr", + AESbsize, + initaes256, + encryptaesctr, + decryptaesctr, +}; diff --git a/sys/src/cmd/ssh2/netssh.c b/sys/src/cmd/ssh2/netssh.c index 81b4491c34..4b1d978667 100644 --- a/sys/src/cmd/ssh2/netssh.c +++ b/sys/src/cmd/ssh2/netssh.c @@ -35,6 +35,9 @@ Cipher *cryptos[] = { &cipheraes128, &cipheraes192, &cipheraes256, + &cipheraes128ctr, + &cipheraes192ctr, + &cipheraes256ctr, // &cipherblowfish, &cipher3des, &cipherrc4, diff --git a/sys/src/cmd/ssh2/netssh.h b/sys/src/cmd/ssh2/netssh.h index 7956019e2a..05650d985f 100644 --- a/sys/src/cmd/ssh2/netssh.h +++ b/sys/src/cmd/ssh2/netssh.h @@ -318,6 +318,7 @@ struct MBox { }; extern Cipher cipheraes128, cipheraes192, cipheraes256; +extern Cipher cipheraes128ctr, cipheraes192ctr, cipheraes256ctr; extern Cipher cipherblowfish, cipher3des, cipherrc4; extern int debug; extern int sshkeychan[]; From 343ba8fa29ad0c67910b2376932183fbc4e9dfa7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 8 Apr 2021 10:25:09 +0000 Subject: [PATCH 173/402] sys/src/cmd/ssh2: completes the implementation of DH group 14 (thanks Richard Miller) --- sys/src/cmd/ssh2/dh.c | 64 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/sys/src/cmd/ssh2/dh.c b/sys/src/cmd/ssh2/dh.c index f45a7ccfb7..8b6a87a713 100644 --- a/sys/src/cmd/ssh2/dh.c +++ b/sys/src/cmd/ssh2/dh.c @@ -20,6 +20,8 @@ enum { }; static int dh_server(Conn *, Packet *, mpint *, int); +static int dh_client1(Conn *, mpint *, int, int); +static int dh_client2(Conn *, Packet *, mpint *, int); static void genkeys(Conn *, uchar [], mpint *); /* @@ -561,19 +563,31 @@ dh_server(Conn *c, Packet *pack1, mpint *grp, int nbit) static int dh_client11(Conn *c, Packet *) +{ + return dh_client1(c, p1, 128, 1024); +} + +static int +dh_client141(Conn *c, Packet *) +{ + return dh_client1(c, p14, 256, 2014); +} + +static int +dh_client1(Conn *c, mpint *grp, int nrand, int nbit) { Packet *p; int n; if (c->e) mpfree(c->e); - c->e = mpnew(1024); + c->e = mpnew(nbit); /* Compute e: RFC4253 */ if (c->x) mpfree(c->x); - c->x = mprand(128, genrandom, nil); - mpexp(two, c->x, p1, c->e); + c->x = mprand(nrand, genrandom, nil); + mpexp(two, c->x, grp, c->e); p = new_packet(c); add_byte(p, SSH_MSG_KEXDH_INIT); @@ -682,6 +696,18 @@ verifyhostkey(Conn *c, RSApub *srvkey, Packet *sig) static int dh_client12(Conn *c, Packet *p) +{ + return dh_client2(c, p, p1, 1024); +} + +static int +dh_client142(Conn *c, Packet *p) +{ + return dh_client2(c, p, p14, 2048); +} + +static int +dh_client2(Conn *c, Packet *p, mpint *grp, int nbits) { int n, retval; #ifdef VERIFYKEYS @@ -704,8 +730,8 @@ dh_client12(Conn *c, Packet *p) q += nhgetl(q) + 4; get_string(p, q, (char *)sig->payload, Maxpktpay, &n); sig->rlength = n; - k = mpnew(1024); - mpexp(f, c->x, p1, k); + k = mpnew(nbits); + mpexp(f, c->x, grp, k); /* Compute H: RFC 4253 */ init_packet(pack2); @@ -785,34 +811,6 @@ dh_client12(Conn *c, Packet *p) return retval; } -static int -dh_client141(Conn *c, Packet *) -{ - Packet *p; - mpint *e, *x; - int n; - - /* Compute e: RFC4253 */ - e = mpnew(2048); - x = mprand(256, genrandom, nil); - mpexp(two, x, p14, e); - p = new_packet(c); - add_byte(p, SSH_MSG_KEXDH_INIT); - add_mp(p, e); - n = finish_packet(p); - iowrite(c->dio, c->datafd, p->nlength, n); - free(p); - mpfree(e); - mpfree(x); - return 0; -} - -static int -dh_client142(Conn *, Packet *) -{ - return 0; -} - static void initsha1pkt(Packet *pack2, mpint *k, uchar *h) { From 3753dfa374ffdfefa201d41a10f52c061657e084 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 9 Dec 2022 15:21:17 +0000 Subject: [PATCH 174/402] sys/src/cmd/ssh2: fix non-host owner filesystem permissions in sshsession (thanks Steven Stallion) --- sys/src/cmd/ssh2/sshsession.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sys/src/cmd/ssh2/sshsession.c b/sys/src/cmd/ssh2/sshsession.c index 6589d71780..b43ab83159 100644 --- a/sys/src/cmd/ssh2/sshsession.c +++ b/sys/src/cmd/ssh2/sshsession.c @@ -88,6 +88,27 @@ auth(char *buf, int n, int ctlfd) close(fd); } +/* + * mount factotum after auth + */ +static void +mountfactotum(int ctlfd) +{ + int fd; + + fd = open("/srv/factotum", ORDWR); + if (fd < 0) { + syslog(0, "ssh", "can't open /srv/factotum: %r"); + hangup(ctlfd); + exits("open"); + } + if (mount(fd, -1, "/mnt", MREPL, "") < 0) { + syslog(0, "ssh", "can't mount /srv/factotum in /mnt: %r"); + hangup(ctlfd); + exits("can't mount"); + } +} + /* * mount tunnel if there isn't one visible. */ @@ -135,6 +156,7 @@ authnewns(int ctlfd, char *buf, int size, int n) return 0; auth(buf, n, ctlfd); + mountfactotum(ctlfd); p = strchr(buf, '@'); if (p == nil) From df05924975f7dda8f70099500fb9f0159bf127fb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 2024 16:26:43 +0000 Subject: [PATCH 175/402] sys/src/cmd/ssh2: fix public key authentication (thanks Richard Miller) --- sys/src/cmd/ssh2/netssh.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/src/cmd/ssh2/netssh.c b/sys/src/cmd/ssh2/netssh.c index 4b1d978667..9a8ccea584 100644 --- a/sys/src/cmd/ssh2/netssh.c +++ b/sys/src/cmd/ssh2/netssh.c @@ -2875,7 +2875,6 @@ authreqpk(Packet *p, Packet *p2, Conn *c, char *user, uchar *q, char *alg, char *blob, char *sig, char *service, char *me) { int n, thisway, nblob, nsig; - char method[32]; sshdebug(c, "auth_req publickey for user %s", user); thisway = *q == '\0'; @@ -2912,12 +2911,12 @@ authreqpk(Packet *p, Packet *p2, Conn *c, char *user, uchar *q, add_byte(p2, SSH_MSG_USERAUTH_REQUEST); add_string(p2, user); add_string(p2, service); - add_string(p2, method); + add_string(p2, "publickey"); add_byte(p2, 1); add_string(p2, alg); add_block(p2, blob, nblob); if (pkas[n]->verify(c, p2->payload, p2->rlength - 1, user, sig, nsig) - == 0) { + != 1) { init_packet(p2); p2->c = c; sshlog(c, "public key login failed"); From aaf428333c09b228d944afa37be254eaad085c88 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 2024 16:28:21 +0000 Subject: [PATCH 176/402] sys/src/cmd/ssh2: return status (thanks Richard Miller) --- sys/src/cmd/ssh2/netssh.c | 9 +++++++++ sys/src/cmd/ssh2/sshsession.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/sys/src/cmd/ssh2/netssh.c b/sys/src/cmd/ssh2/netssh.c index 9a8ccea584..852782945d 100644 --- a/sys/src/cmd/ssh2/netssh.c +++ b/sys/src/cmd/ssh2/netssh.c @@ -1364,6 +1364,15 @@ writereqremproc(void *a) } add_string(p, cmd); free(cmd); + } else if (strcmp(toks[0], "exit-status") == 0) { + add_byte(p, SSH_MSG_CHANNEL_REQUEST); + add_uint32(p, ch->otherid); + add_string(p, toks[0]); + add_byte(p, 0); + if(ntok > 1) + add_uint32(p, strtol(toks[1], nil, 10)); + else + add_uint32(p, 0); } else respexit(c, r, buf, "bad request command"); n = finish_packet(p); diff --git a/sys/src/cmd/ssh2/sshsession.c b/sys/src/cmd/ssh2/sshsession.c index b43ab83159..ecbe793e1f 100644 --- a/sys/src/cmd/ssh2/sshsession.c +++ b/sys/src/cmd/ssh2/sshsession.c @@ -466,11 +466,30 @@ confine(char *q, char *s) return q; } +static long +exitstatus(char *s) +{ + long n; + char *p; + + if(s == nil || *s == '\0') + return 0; + s = strchr(s, ':'); + if(s == nil) + return 1; + n = strtol(s+1, &p, 10); + if(p == s+1) + return 1; + return n; +} + void runcmd(int reqfd, int datafd, char *svc, char *cmd, char *arg1, char *arg2) { char *p; - int fd, cmdpid, child; + Waitmsg *w; + int fd, cmdpid; + ulong status; cmdpid = rfork(RFPROC|RFMEM|RFNOTEG|RFFDG|RFENVG); switch (cmdpid) { @@ -505,10 +524,18 @@ runcmd(int reqfd, int datafd, char *svc, char *cmd, char *arg1, char *arg2) default: close(datafd); fprint(errfd, "waiting for child %d\n", cmdpid); - while ((child = waitpid()) != cmdpid && child != -1) - fprint(errfd, "child %d passed\n", child); - if (child == -1) + while ((w = wait()) != nil && w->pid != cmdpid){ + fprint(errfd, "child %d passed\n", w->pid); + free(w); + } + if (w == nil) fprint(errfd, "wait failed: %r\n"); + else { + status = exitstatus(w->msg); + fprint(errfd, "child %d exits(%s) status %lud\n", w->pid, w->msg, status); + fprint(reqfd, "exit-status %lud", status); + free(w); + } syslog(0, "ssh", "server closing ssh session for %s", uname); fprint(errfd, "closing connection\n"); From 3eaa113e74c304b88f90849fa03ae72561d4d973 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 8 Jun 2024 18:08:47 +0000 Subject: [PATCH 177/402] sys/src/cmd/ssh2: fix output of sshsession -d (thanks Richard Miller) --- sys/src/cmd/ssh2/sshsession.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/ssh2/sshsession.c b/sys/src/cmd/ssh2/sshsession.c index ecbe793e1f..9610239c9e 100644 --- a/sys/src/cmd/ssh2/sshsession.c +++ b/sys/src/cmd/ssh2/sshsession.c @@ -511,12 +511,12 @@ runcmd(int reqfd, int datafd, char *svc, char *cmd, char *arg1, char *arg2) else p = cmd; + fprint(errfd, "starting %s\n", cmd); dup(datafd, 0); dup(datafd, 1); dup(datafd, 2); close(datafd); putenv("service", svc); - fprint(errfd, "starting %s\n", cmd); execl(cmd, p, arg1, arg2, nil); syslog(0, "ssh", "cannot exec %s: %r", cmd); From c4eff5582dc2abd2a169f9e5b09358b17203df2f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Oct 2021 14:19:28 +0000 Subject: [PATCH 178/402] sys/src/cmd/upas/smtp: rename "autistic" to "avoidant" (thanks Anthony Sorace) --- sys/man/8/smtp | 2 +- sys/src/cmd/upas/smtp/smtp.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/man/8/smtp b/sys/man/8/smtp index 76e41f3e99..7a46a85bda 100644 --- a/sys/man/8/smtp +++ b/sys/man/8/smtp @@ -70,7 +70,7 @@ This option implies .BR -s . .TP .B -A -autistic server: don't wait for an SMTP greeting banner +avoidant server: don't wait for an SMTP greeting banner but immediately send a .L NOOP command to provoke the server into responding. diff --git a/sys/src/cmd/upas/smtp/smtp.c b/sys/src/cmd/upas/smtp/smtp.c index 0219d01320..901c3a8278 100644 --- a/sys/src/cmd/upas/smtp/smtp.c +++ b/sys/src/cmd/upas/smtp/smtp.c @@ -35,7 +35,7 @@ String *reply; /* last reply */ String *toline; int alarmscale; -int autistic; +int avoidant; int debug; /* true if we're debugging */ int filter; int insecure; @@ -122,8 +122,8 @@ main(int argc, char **argv) tryauth = 1; trysecure = 1; break; - case 'A': /* autistic: won't talk to us until we talk (Verizon) */ - autistic = 1; + case 'A': /* avoidant: won't talk to us until we talk (Verizon) */ + avoidant = 1; break; case 'b': if (bustedmx >= Maxbustedmx) @@ -477,7 +477,7 @@ hello(char *me, int encrypted) * answers a call. Send a no-op in the hope of making it * talk. */ - if (autistic) { + if (avoidant) { dBprint("NOOP\r\n"); getreply(); /* consume the smtp greeting */ /* next reply will be response to noop */ From 998fa9444d33f9936c47939d190a8de0d2810c5c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 7 Jun 2022 00:51:49 +0000 Subject: [PATCH 179/402] sys/src/cmd/aux: implement named flags in aux/getflags (thanks Ori Bernstein) --- sys/src/cmd/aux/getflags.c | 80 ++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/sys/src/cmd/aux/getflags.c b/sys/src/cmd/aux/getflags.c index 407b73781a..400c68c137 100644 --- a/sys/src/cmd/aux/getflags.c +++ b/sys/src/cmd/aux/getflags.c @@ -1,5 +1,6 @@ #include #include +#include void usage(void) @@ -8,18 +9,54 @@ usage(void) exits(0); } +char* +skipspace(char *p) +{ + while(isspace(*p)) + p++; + return p; +} + +char* +nextarg(char *p) +{ + char *s; + + s = strchr(p, ','); + if(s == nil) + return p+strlen(p); /* to \0 */ + while(*s == ',' || isspace(*s)) + s++; + return s; +} + char* findarg(char *flags, Rune r) { char *p; Rune rr; - - for(p=flags; p!=(char*)1; p=strchr(p, ',')+1){ + + for(p=skipspace(flags); *p; p=nextarg(p)){ chartorune(&rr, p); if(rr == r) return p; } - return nil; + return nil; +} + +char* +argname(char *p) +{ + Rune r; + int n; + + while(1){ + n = chartorune(&r, p); + if(!isalpharune(r) && !isdigitrune(r)) + break; + p += n; + } + return p; } int @@ -28,10 +65,8 @@ countargs(char *p) int n; n = 1; - while(*p == ' ') - p++; - for(; *p && *p != ','; p++) - if(*p == ' ' && *(p-1) != ' ') + for(p=skipspace(p); *p && *p != ','; p++) + if(isspace(*p) && !isspace(*(p-1))) n++; return n; } @@ -39,8 +74,9 @@ countargs(char *p) void main(int argc, char *argv[]) { - char *flags, *p, buf[512]; + char *flags, *p, *s, *e, buf[512]; int i, n; + Rune r; Fmt fmt; doquote = needsrcquote; @@ -55,19 +91,39 @@ main(int argc, char *argv[]) } fmtfdinit(&fmt, 1, buf, sizeof buf); - for(p=flags; p!=(char*)1; p=strchr(p, ',')+1) - fmtprint(&fmt, "flag%.1s=()\n", p); + for(p=skipspace(flags); *p; p=nextarg(p)){ + s = e = nil; + n = chartorune(&r, p); + if(p[n] == ':'){ + s = p + n + 1; + e = argname(s); + } + if(s != e) + fmtprint(&fmt, "%.*s=()\n", (int)(e - s), s); + else + fmtprint(&fmt, "flag%C=()\n", r); + } ARGBEGIN{ default: if((p = findarg(flags, ARGC())) == nil) usage(); p += runelen(ARGC()); + s = p + 1; + e = p + 1; + if(*p == ':' && (e = argname(s)) != s) + p = e; if(*p == ',' || *p == 0){ - fmtprint(&fmt, "flag%C=1\n", ARGC()); + if(s != e) + fmtprint(&fmt, "%.*s=1\n", (int)(e - s), s); + else + fmtprint(&fmt, "flag%C=1\n", ARGC()); break; } n = countargs(p); - fmtprint(&fmt, "flag%C=(", ARGC()); + if(s != e) + fmtprint(&fmt, "%.*s=(", (int)(e - s), s); + else + fmtprint(&fmt, "flag%C=(", ARGC()); for(i=0; i Date: Fri, 9 Dec 2022 15:32:44 +0000 Subject: [PATCH 180/402] sys/src/libauthsrv: add dos and nvram partitions to readnvram on arm (thanks Steven Stallion) --- sys/src/libauthsrv/readnvram.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/libauthsrv/readnvram.c b/sys/src/libauthsrv/readnvram.c index cf8aab8bc8..4c48216369 100644 --- a/sys/src/libauthsrv/readnvram.c +++ b/sys/src/libauthsrv/readnvram.c @@ -52,6 +52,8 @@ static struct { "power", "/nvram", 0, sizeof(Nvrsafe), /* OK for Ucu */ "arm", "#F/flash/flash0", 0x100000, sizeof(Nvrsafe), "arm", "#F/flash/flash", 0x100000, sizeof(Nvrsafe), + "arm", "#S/sdM0/nvram", 0, sizeof(Nvrsafe), + "arm", "#S/sdM0/dos", -1, sizeof(Nvrsafe), /* OK for Raspberry Pi */ "debug", "/tmp/nvram", 0, sizeof(Nvrsafe), }; From 679a2621c09b09a2b896e039d72e91619193b21e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 2024 17:24:57 +0000 Subject: [PATCH 181/402] sys/src/cmd/unix/u9fs: fix build on Unix --- sys/src/cmd/unix/u9fs/authrhosts.c | 1 + sys/src/cmd/unix/u9fs/fcall.h | 2 +- sys/src/cmd/unix/u9fs/plan9.h | 4 ++++ sys/src/cmd/unix/u9fs/rune.c | 2 ++ sys/src/cmd/unix/u9fs/safecpy.c | 2 ++ sys/src/cmd/unix/u9fs/u9fs.c | 1 - sys/src/cmd/unix/u9fs/u9fs.h | 1 + 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sys/src/cmd/unix/u9fs/authrhosts.c b/sys/src/cmd/unix/u9fs/authrhosts.c index de150850e6..2430e6f160 100644 --- a/sys/src/cmd/unix/u9fs/authrhosts.c +++ b/sys/src/cmd/unix/u9fs/authrhosts.c @@ -1,6 +1,7 @@ #include #include #include +#include /* * return whether the user is authenticated. diff --git a/sys/src/cmd/unix/u9fs/fcall.h b/sys/src/cmd/unix/u9fs/fcall.h index 4a0d6f2cca..d8ca20eaab 100644 --- a/sys/src/cmd/unix/u9fs/fcall.h +++ b/sys/src/cmd/unix/u9fs/fcall.h @@ -48,7 +48,7 @@ struct Fcall #define GBIT8(p) ((p)[0]) #define GBIT16(p) ((p)[0]|((p)[1]<<8)) #define GBIT32(p) ((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) -#define GBIT64(p) ((ulong)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ +#define GBIT64(p) ((u32int)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ ((vlong)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32)) #define PBIT8(p,v) (p)[0]=(v) diff --git a/sys/src/cmd/unix/u9fs/plan9.h b/sys/src/cmd/unix/u9fs/plan9.h index f7b7ae7e0a..2d28065b73 100644 --- a/sys/src/cmd/unix/u9fs/plan9.h +++ b/sys/src/cmd/unix/u9fs/plan9.h @@ -5,6 +5,8 @@ /* magic to get 64-bit stat on Linux, maybe others */ #define _FILE_OFFSET_BITS 64 +#define _DEFAULT_SOURCE 1 /* also for ruserok */ + #ifdef sgi #define _BSD_TYPES 1 /* for struct timeval */ #include @@ -106,6 +108,7 @@ extern int runetochar(char*, Rune*); extern int chartorune(Rune*, char*); extern int runelen(long); extern int utflen(char*); +extern char* utfrune(char*, long); extern char* strecpy(char*, char*, char*); extern int tokenize(char*, char**, int); extern int getfields(char*, char**, int, int, char*); @@ -188,6 +191,7 @@ struct Dir { long readn(int, void*, long); void remotehost(char*, int); +void sysfatal(char*, ...); enum { NAMELEN = 28, diff --git a/sys/src/cmd/unix/u9fs/rune.c b/sys/src/cmd/unix/u9fs/rune.c index 9becff119d..5c179013e9 100644 --- a/sys/src/cmd/unix/u9fs/rune.c +++ b/sys/src/cmd/unix/u9fs/rune.c @@ -8,6 +8,7 @@ enum Bit2 = 5, Bit3 = 4, Bit4 = 3, + Bit5 = 2, T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ @@ -28,6 +29,7 @@ enum SurrogateMin = 0xD800, SurrogateMax = 0xDFFF, + Runemax = 0x10FFFF, /* 21-bit rune */ Bad = Runeerror }; diff --git a/sys/src/cmd/unix/u9fs/safecpy.c b/sys/src/cmd/unix/u9fs/safecpy.c index a7513494dc..0f1f4d5269 100644 --- a/sys/src/cmd/unix/u9fs/safecpy.c +++ b/sys/src/cmd/unix/u9fs/safecpy.c @@ -1,3 +1,5 @@ +#include +#include #include void diff --git a/sys/src/cmd/unix/u9fs/u9fs.c b/sys/src/cmd/unix/u9fs/u9fs.c index d751b2b363..72238d5b8a 100644 --- a/sys/src/cmd/unix/u9fs/u9fs.c +++ b/sys/src/cmd/unix/u9fs/u9fs.c @@ -71,7 +71,6 @@ void* emalloc(size_t); void* erealloc(void*, size_t); char* estrdup(char*); char* estrpath(char*, char*, int); -void sysfatal(char*, ...); int okuser(char*); void rversion(Fcall*, Fcall*); diff --git a/sys/src/cmd/unix/u9fs/u9fs.h b/sys/src/cmd/unix/u9fs/u9fs.h index f553a3a435..30df200a33 100644 --- a/sys/src/cmd/unix/u9fs/u9fs.h +++ b/sys/src/cmd/unix/u9fs/u9fs.h @@ -28,3 +28,4 @@ Fid *newauthfid(int fid, void *magic, char **ep); Fid *oldauthfid(int fid, void **magic, char **ep); void safecpy(char *to, char *from, int len); +void getremotehostname(char*, int); From 2c0d41aa75acd930067b37e7ae28642b2baa23eb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 2024 16:39:09 +0000 Subject: [PATCH 182/402] sys/src/cmd/unix/u9fs: don't depend on chroot anymore (thanks Charles Forsyth) --- sys/src/cmd/unix/u9fs/u9fs.c | 99 ++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/sys/src/cmd/unix/u9fs/u9fs.c b/sys/src/cmd/unix/u9fs/u9fs.c index 72238d5b8a..8574f39e81 100644 --- a/sys/src/cmd/unix/u9fs/u9fs.c +++ b/sys/src/cmd/unix/u9fs/u9fs.c @@ -72,6 +72,7 @@ void* erealloc(void*, size_t); char* estrdup(char*); char* estrpath(char*, char*, int); int okuser(char*); +int groupchange(User*, User*, char**); void rversion(Fcall*, Fcall*); void rauth(Fcall*, Fcall*); @@ -146,6 +147,7 @@ int chatty9p = 0; int network = 1; int old9p = -1; int authed; +char* root; User* none; Auth *authmethods[] = { /* first is default */ @@ -170,6 +172,17 @@ char isfrog[256]={ [0x7f] 1, }; +char* +rootpath(char *path) +{ + static char buf[PATH_MAX]; + + if(root == nil) + return path; + snprint(buf, sizeof buf, "%s%s", root, path); + return buf; +} + void getfcallnew(int fd, Fcall *fc, int have) { @@ -703,7 +716,7 @@ stat2dir(char *path, struct stat *st, Dir *d) void rread(Fcall *rx, Fcall *tx) { - char *e, *path; + char *e, *path, *rpath; uchar *p, *ep; int n; Fid *fid; @@ -763,7 +776,8 @@ rread(Fcall *rx, Fcall *tx) fid->dirent = nil; continue; } - path = estrpath(fid->path, fid->dirent->d_name, 0); + rpath = rootpath(fid->path); + path = estrpath(rpath, fid->dirent->d_name, 0); memset(&st, 0, sizeof st); if(stat(path, &st) < 0){ fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno)); @@ -829,7 +843,7 @@ rwrite(Fcall *rx, Fcall *tx) void rclunk(Fcall *rx, Fcall *tx) { - char *e; + char *e, *rpath; Fid *fid; if((fid = oldfidex(rx->fid, -1, &e)) == nil){ @@ -845,8 +859,10 @@ rclunk(Fcall *rx, Fcall *tx) } } } - else if(fid->omode != -1 && fid->omode&ORCLOSE) - remove(fid->path); + else if(fid->omode != -1 && fid->omode&ORCLOSE){ + rpath = rootpath(fid->path); + remove(rpath); + } freefid(fid); } @@ -890,7 +906,7 @@ rstat(Fcall *rx, Fcall *tx) void rwstat(Fcall *rx, Fcall *tx) { - char *e; + char *e, *opath, *npath; char *p, *old, *new, *dir; gid_t gid; Dir d; @@ -960,9 +976,10 @@ rwstat(Fcall *rx, Fcall *tx) * leave truncate until last. * (see above comment about atomicity). */ - if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){ + opath = estrdup(rootpath(fid->path)); + if((u32int)d.mode != (u32int)~0 && chmod(opath, unixmode(&d)) < 0){ if(chatty9p) - fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d)); + fprint(2, "chmod(%s, 0%luo) failed\n", opath, unixmode(&d)); seterror(tx, strerror(errno)); return; } @@ -972,18 +989,18 @@ rwstat(Fcall *rx, Fcall *tx) t.actime = 0; t.modtime = d.mtime; - if(utime(fid->path, &t) < 0){ + if(utime(opath, &t) < 0){ if(chatty9p) - fprint(2, "utime(%s) failed\n", fid->path); + fprint(2, "utime(%s) failed\n", opath); seterror(tx, strerror(errno)); return; } } if(gid != (gid_t)-1 && gid != fid->st.st_gid){ - if(chown(fid->path, (uid_t)-1, gid) < 0){ + if(chown(opath, (uid_t)-1, gid) < 0){ if(chatty9p) - fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid); + fprint(2, "chgrp(%s, %d) failed\n", opath, gid); seterror(tx, strerror(errno)); return; } @@ -999,21 +1016,25 @@ rwstat(Fcall *rx, Fcall *tx) return; } new = estrpath(dir, d.name, 1); - if(strcmp(old, new) != 0 && rename(old, new) < 0){ + npath = rootpath(new); + if(strcmp(old, new) != 0 && rename(opath, npath) < 0){ if(chatty9p) fprint(2, "rename(%s, %s) failed\n", old, new); seterror(tx, strerror(errno)); free(new); free(dir); + free(opath); return; } fid->path = new; free(old); free(dir); + free(opath); + opath = npath; } - if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){ - fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length); + if((u64int)d.length != (u64int)~0 && truncate(opath, d.length) < 0){ + fprint(2, "truncate(%s, %lld) failed\n", opath, d.length); seterror(tx, strerror(errno)); return; } @@ -1330,8 +1351,11 @@ freefid(Fid *f) int fidstat(Fid *fid, char **ep) { - if(stat(fid->path, &fid->st) < 0){ - fprint(2, "fidstat(%s) failed\n", fid->path); + char *rpath; + + rpath = rootpath(fid->path); + if(stat(rpath, &fid->st) < 0){ + fprint(2, "fidstat(%s) failed\n", rpath); if(ep) *ep = strerror(errno); return -1; @@ -1420,7 +1444,7 @@ groupchange(User *u, User *g, char **ep) int userperm(User *u, char *path, int type, int need) { - char *p, *q; + char *p, *q, *rpath; int i, have; struct stat st; User *g; @@ -1430,13 +1454,15 @@ userperm(User *u, char *path, int type, int need) fprint(2, "bad type %d in userperm\n", type); return -1; case Tdot: - if(stat(path, &st) < 0){ - fprint(2, "userperm: stat(%s) failed\n", path); + rpath = rootpath(path); + if(stat(rpath, &st) < 0){ + fprint(2, "userperm: stat(%s) failed\n", rpath); return -1; } break; case Tdotdot: - p = estrdup(path); + rpath = rootpath(path); + p = estrdup(rpath); if((q = strrchr(p, '/'))==nil){ fprint(2, "userperm(%s, ..): bad path\n", p); free(p); @@ -1448,7 +1474,7 @@ userperm(User *u, char *path, int type, int need) *(q+1) = '\0'; if(stat(p, &st) < 0){ fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", - p, path); + p, rpath); free(p); return -1; } @@ -1485,11 +1511,12 @@ userperm(User *u, char *path, int type, int need) int userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) { - char *npath; + char *npath, *rpath; struct stat st; npath = estrpath(*path, elem, 1); - if(stat(npath, &st) < 0){ + rpath = rootpath(npath); + if(stat(rpath, &st) < 0){ free(npath); *ep = strerror(errno); return -1; @@ -1504,6 +1531,7 @@ int useropen(Fid *fid, int omode, char **ep) { int a, o; + char *rpath; /* * Check this anyway, to try to head off problems later. @@ -1545,7 +1573,8 @@ useropen(Fid *fid, int omode, char **ep) *ep = Eperm; return -1; } - if((fid->dir = opendir(fid->path)) == nil){ + rpath = rootpath(fid->path); + if((fid->dir = opendir(rpath)) == nil){ *ep = strerror(errno); return -1; } @@ -1560,7 +1589,8 @@ useropen(Fid *fid, int omode, char **ep) } * */ - if((fid->fd = open(fid->path, o)) < 0){ + rpath = rootpath(fid->path); + if((fid->fd = open(rpath, o)) < 0){ *ep = strerror(errno); return -1; } @@ -1573,10 +1603,11 @@ int usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) { int o, m; - char *opath, *npath; + char *opath, *npath, *rpath; struct stat st, parent; - if(stat(fid->path, &parent) < 0){ + rpath = rootpath(fid->path); + if(stat(rpath, &parent) < 0){ *ep = strerror(errno); return -1; } @@ -1593,7 +1624,7 @@ usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) m = (perm & DMDIR) ? 0777 : 0666; perm = perm & (~m | (fid->st.st_mode & m)); - npath = estrpath(fid->path, elem, 1); + npath = estrpath(rpath, elem, 1); if(perm & DMDIR){ if((omode&~ORCLOSE) != OREAD){ *ep = Eperm; @@ -1646,7 +1677,7 @@ usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) } opath = fid->path; - fid->path = npath; + fid->path = estrpath(opath, elem, 1); if(fidstat(fid, ep) < 0){ fprint(2, "stat after create on %s failed\n", npath); remove(npath); /* race */ @@ -1669,7 +1700,10 @@ usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) int userremove(Fid *fid, char **ep) { - if(remove(fid->path) < 0){ + char *rpath; + + rpath = rootpath(fid->path); + if(remove(rpath) < 0){ *ep = strerror(errno); return -1; } @@ -1756,8 +1790,7 @@ main(int argc, char **argv) umask(0); if(argc == 1) - if(chroot(argv[0]) < 0) - sysfatal("chroot '%s' failed", argv[0]); + root = argv[0]; none = uname2user("none"); if(none == nil) From 9661fbe323d3920b7a5e3f350626ac06e422289c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 2024 16:45:15 +0000 Subject: [PATCH 183/402] sys/src/cmd/unix/u9fs: use Plan 9 error message in userwalk (thanks Richard Miller) --- sys/src/cmd/unix/u9fs/u9fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/unix/u9fs/u9fs.c b/sys/src/cmd/unix/u9fs/u9fs.c index 8574f39e81..abc6002418 100644 --- a/sys/src/cmd/unix/u9fs/u9fs.c +++ b/sys/src/cmd/unix/u9fs/u9fs.c @@ -1518,7 +1518,7 @@ userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) rpath = rootpath(npath); if(stat(rpath, &st) < 0){ free(npath); - *ep = strerror(errno); + *ep = errno == ENOENT? "file does not exist" : strerror(errno); return -1; } *qid = stat2qid(&st); From 16ecc6c4b274c4d82111d5eef5ea3d827d8bec86 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 22 Jun 2024 18:48:56 +0000 Subject: [PATCH 184/402] sys/src/cmd/unix/u9fs: fix size on dirread (thanks Richard Miller) --- sys/src/cmd/unix/u9fs/u9fs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/cmd/unix/u9fs/u9fs.c b/sys/src/cmd/unix/u9fs/u9fs.c index abc6002418..99d6a0401a 100644 --- a/sys/src/cmd/unix/u9fs/u9fs.c +++ b/sys/src/cmd/unix/u9fs/u9fs.c @@ -786,6 +786,8 @@ rread(Fcall *rx, Fcall *tx) continue; } free(path); + if(S_ISDIR(st.st_mode)) + st.st_size = 0; stat2dir(fid->dirent->d_name, &st, &d); if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ) break; From 0b59132d8698db5f1df501f7766d398207718baf Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 29 Apr 2016 23:43:10 +0000 Subject: [PATCH 185/402] sys/src/cmd/ip/iscsisrv: import ip/iscsisrv, an iSCSI target (thanks Geoff Collyer) --- sys/man/8/iscsisrv | 71 +++ sys/src/cmd/ip/iscsi.h | 367 +++++++++++ sys/src/cmd/ip/iscsisrv.c | 1206 +++++++++++++++++++++++++++++++++++++ sys/src/cmd/ip/mkfile | 1 + 4 files changed, 1645 insertions(+) create mode 100644 sys/man/8/iscsisrv create mode 100644 sys/src/cmd/ip/iscsi.h create mode 100644 sys/src/cmd/ip/iscsisrv.c diff --git a/sys/man/8/iscsisrv b/sys/man/8/iscsisrv new file mode 100644 index 0000000000..722baabe65 --- /dev/null +++ b/sys/man/8/iscsisrv @@ -0,0 +1,71 @@ +.TH ISCSISRV 8 +.SH NAME +iscsisrv \- iSCSI target: provide remote access via iSCSI +.SH SYNOPSIS +.B ip/iscsisrv +[ +.B -dr +] [ +.B -l +.I len +] [ +.B -a +.I dialstring +] +.I target +.SH DESCRIPTION +.I Iscsisrv +presents the file +.I target +by speaking a restricted form of the iSCSI protocol. +It defaults to communicating on file descriptors 0 and 1, +assumed to be a network connection as passed from +.IR listen (8) +via +.BR /bin/service/tcp3260 . +If the +.B -a +option is supplied, it will instead listen for connections on +the specified dialstring. +.P +Changes are written through to +.I target +unless the +.B -r +option is given. +If +.B -l +is supplied, +.I iscsisrv +will claim that +.I target +is +.I len +bytes long. +.SH EXAMPLES +Export a target, +.LR /dev/sdC0/iscsi-test : +.IP +.EX +disk/iscsisrv /dev/sdC0/iscsi-test +.EE +.PP +Export a dummy target over TCP: +.IP +.EX +disk/iscsisrv -rl 10240000 -a tcp!*!3260 /dev/zero +.EE +.SH SOURCE +.B /sys/src/cmd/ip/iscsisrv.c +.SH SEE ALSO +.IR iscsifs (4) +.SH BUGS +Does not authenticate incoming connections. +.PP +Implements only one connection per session. +.PP +Implements only lun 0. +.PP +Implements immediate execution, whether requested or not. +.PP +Trusts TCP, so does not implement framing (FIM) nor CRCs (digests). diff --git a/sys/src/cmd/ip/iscsi.h b/sys/src/cmd/ip/iscsi.h new file mode 100644 index 0000000000..fb2238b1e1 --- /dev/null +++ b/sys/src/cmd/ip/iscsi.h @@ -0,0 +1,367 @@ +/* + * iscsi - scsi over tcp/ip + * + * observations: + * iscsi names may be 223 bytes long. + * two namespaces, "iqn." and "eui.". + * don't need FIM when using tcp. + * rfc3720 §3.2.8.1 demonstrates that the authors don't understand (or + * don't trust) tcp: data isn't quietly dropped. + * + * we're not going to implement the optional digests (crcs), + * so those are omitted. + */ + +enum { + Bhdrsz = 48, + + /* initiator opcodes (requests) */ + Iopnopout= 0, + Iopcmd, + Ioptask, + Ioplogin, + Ioptext, + Iopdataout, /* write */ + Ioplogout, + Iopsnack= 0x10, + + /* target opcodes (responses) */ + Topnopin= 0x20, + Topresp, + Toptask, + Toplogin, + Toptext, + Topdatain, /* read */ + Toplogout, + Topr2t = 0x31, + Topasync, + Topreject= 0x3f, + + Immed = 1<<6, + Oprsrvd = 1<<7, + + /* opspfc */ + Finalpkt= 1<<7, +}; + +typedef struct Datainpkt Datainpkt; +typedef struct Iscsiasynch Iscsiasynch; +typedef struct Iscsicmdreq Iscsicmdreq; +typedef struct Iscsicmdresp Iscsicmdresp; +typedef struct Iscsidatain Iscsidatain; +typedef struct Iscsidataout Iscsidataout; +typedef struct Iscsijustbhdr Iscsijustbhdr; +typedef struct Iscsiloginreq Iscsiloginreq; +typedef struct Iscsiloginresp Iscsiloginresp; +typedef struct Iscsilogoutreq Iscsilogoutreq; +typedef struct Iscsilogoutresp Iscsilogoutresp; +typedef struct Iscsinopreq Iscsinopreq; /* nop out */ +typedef struct Iscsinopresp Iscsinopresp; /* nop in */ +typedef struct Iscsiready Iscsiready; +typedef struct Iscsireject Iscsireject; +typedef struct Iscsisnackreq Iscsisnackreq; +typedef struct Iscsistate Iscsistate; +typedef struct Iscsitaskreq Iscsitaskreq; +typedef struct Iscsitaskresp Iscsitaskresp; +typedef struct Iscsitextreq Iscsitextreq; +typedef struct Iscsitextresp Iscsitextresp; +typedef struct Pkt Pkt; +typedef struct Pkts Pkts; +typedef struct Resppkt Resppkt; + +/* + * iscsi on-the-wire packet formats + * + * all integers are stored big-endian. + * common pkt start is bhs, 48 bytes. + */ + +/* + * first 20 bytes are common *and* defined; another 28 follow but vary. + */ +#define Iscsibhdr \ + uchar op; \ + uchar opspfc[3]; \ + uchar totahslen; \ + uchar dseglen[3]; \ + uchar lun[8]; \ + uchar itt[4] /* initiator task tag */ + +struct Iscsijustbhdr { + Iscsibhdr; +}; + +struct Iscsiasynch { + Iscsibhdr; + + uchar _pad1[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + + uchar event; + uchar vcode; + uchar param1[2]; + uchar param2[2]; + uchar param3[2]; + uchar _pad2[4]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsiloginreq { + Iscsibhdr; + + uchar cid[2]; + uchar _pad1[2]; + uchar cmdseq[4]; + uchar expstsseq[4]; + + uchar _pad2[16]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +struct Iscsiloginresp { + Iscsibhdr; + + uchar _pad1[4]; + uchar stsseq[4]; + uchar expstsseq[4]; + uchar maxstsseq[4]; + + uchar stsclass; + uchar stsdetail; + uchar _pad2[10]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsilogoutreq { + Iscsibhdr; + + uchar cid[2]; + uchar _pad1[2]; + uchar cmdseq[4]; + uchar expstsseq[4]; + uchar _pad2[16]; +}; + +struct Iscsilogoutresp { + Iscsibhdr; + + uchar _pad1[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar _pad2[4]; + uchar waittime[2]; + uchar retaintime[2]; + uchar _pad3[4]; +}; + + +struct Iscsinopreq { /* nop-out */ + Iscsibhdr; + + uchar ttt[4]; + uchar cmdseq[4]; + uchar expcmdseq[4]; + uchar _pad2[16]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +struct Iscsinopresp { /* nop-in */ + Iscsibhdr; + + uchar ttt[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar _pad2[12]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsiready { + Iscsibhdr; + + uchar ttt[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar r2tseq[4]; + uchar bufoff[4]; + uchar xferlen[4]; +}; + +struct Iscsireject { + Iscsibhdr; + + uchar _pad2[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar r2tseq[4]; + uchar _pad3[4+4]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsicmdreq { + Iscsibhdr; + + uchar expxferlen[4]; + uchar cmdseq[4]; + uchar expstsseq[4]; + + uchar cdb[16]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +struct Iscsicmdresp { + Iscsibhdr; + + uchar snacktag[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar expdataseq[4]; + uchar readresid[4]; + uchar resid[4]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsidatain { + Iscsibhdr; + + uchar ttt[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar dataseq[4]; + uchar buffoff[4]; + uchar resid[4]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +struct Iscsidataout { /* a.k.a. data-out */ + Iscsibhdr; + + uchar ttt[4]; + uchar _pad1[4]; + uchar expstsseq[4]; + uchar _pad2[4]; + uchar dataseq[4]; + uchar buffoff[4]; + uchar _pad3[4]; + uchar dseg[]; /* dseg[dseglen] */ +}; + + +struct Iscsisnackreq { + Iscsibhdr; + + uchar ttt[4]; + uchar _pad1[4]; + uchar expstsseq[4]; + uchar _pad2[8]; + uchar begrun[4]; + uchar runlen[4]; +}; + + +struct Iscsitaskreq { + Iscsibhdr; + + uchar rtt[4]; + uchar cmdseq[4]; + uchar expstsseq[4]; + uchar refcmdseq[4]; + uchar expdataseq[4]; + uchar _pad1[8]; +}; + +struct Iscsitaskresp { + Iscsibhdr; + + uchar _pad2[4]; + uchar stsseq[4]; + uchar expcmdseq[4]; + uchar maxcmdseq[4]; + uchar _pad4[12]; +}; + + +/* req & resp identical? */ +struct Iscsitextreq { + Iscsibhdr; + + uchar ttt[4]; + uchar cmdseq[4]; + uchar expstsseq[4]; + uchar _pad1[16]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +struct Iscsitextresp { + Iscsibhdr; + + uchar ttt[4]; + uchar cmdseq[4]; + uchar expstsseq[4]; + uchar _pad1[16]; + uchar dseg[]; /* dseg[dseglen] */ +}; + +/* + * packet-specific data + */ +struct Pkt { + union { + Iscsijustbhdr *pkthdr; + uchar *pkt; + }; + uint len; +}; +struct Resppkt { + Iscsicmdresp *resppkt; + uint resplen; +}; +struct Datainpkt { + Iscsidatain *datapkt; + uint datalen; +}; + +/* + * a request packet (pkt), its response packet (Resppkt), + * and an optional data-in packet for cmd read operations. + */ +struct Pkts { + int op; + int immed; + ulong totahslen; + ulong dseglen; + ulong itt; + + Pkt; + Datainpkt; + Resppkt; +}; + +/* + * iscsi state, maintained by both parties. + * some are per-connection, some per-session. + */ +struct Iscsistate { + ulong cmdseq; /* to be assigned to next command pkt */ + ulong expcmdseq; /* next cmd expected by target; previous done */ + ulong maxcmdseq; /* maxcmdseq-expcmdseq+1 is target's queue depth */ + + ulong stsseq; + ulong expstsseq; /* all previous sts seen */ + + ulong dataseq; + ulong r2tseq; + + ulong maxrcvseglen; +}; diff --git a/sys/src/cmd/ip/iscsisrv.c b/sys/src/cmd/ip/iscsisrv.c new file mode 100644 index 0000000000..442911f28a --- /dev/null +++ b/sys/src/cmd/ip/iscsisrv.c @@ -0,0 +1,1206 @@ +/* + * iscsisrv target - serve target via iscsi + * + * invoked by listen(8) via /bin/service/tcp3260, + * so tcp connection is on fds 0-2. + */ +#include +#include +#include +#include /* for scsi cmds */ +#include +#include "iscsi.h" + +#define ROUNDUP(s, sz) (((s) + ((sz)-1)) & ~((sz)-1)) + +enum { + Noreply, + Reply, + + Blksz = 512, + Maxtargs= 256, + + Inqlen = 36, /* bytes of inquiry data returned */ +}; + +int net; /* fd of tcp conn. to target */ +int targfd = -1; +int rdonly; +int debug; +vlong claimlen; +ulong time0; +char *targfile; +char *advtarg = "the-target"; +char *inquiry = "iscsi disk"; + +static char sendtargall[] = "SendTargets=All"; +static char targnm[] = "TargetName="; +static char hdrdig[] = "HeaderDigest="; +static char datadig[] = "DataDigest="; +static char maxconns[] = "MaxConnections="; +static char initr2t[] = "InitialR2T="; +static char immdata[] = "ImmediateData="; +static char *agreekeys[] = { + "MaxBurstLength=", + "FirstBurstLength=", + "ErrorRecoveryLevel=", + nil, +}; + +Iscsistate istate; + +void * +emalloc(uint n) +{ + void *v; + + v = mallocz(n, 1); + if (v == nil) + sysfatal("out of memory"); + return v; +} + +void * +erealloc(void *v, uint n) +{ + v = realloc(v, n); + if (v == nil) + sysfatal("out of memory"); + return v; +} + +ulong +getbe3(uchar *p) +{ + return p[0]<<16 | p[1]<<8 | p[2]; +} + +ulong +getbe4(uchar *p) +{ + return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]; +} + +uvlong +getbe8(uchar *p) +{ + return (uvlong)getbe4(p) << 32 | getbe4(p+4); +} + +void +putbe2(uchar *p, ushort us) +{ + *p++ = us >> 8; + *p = us; +} + +void +putbe3(uchar *p, ulong ul) +{ + *p++ = ul >> 16; + *p++ = ul >> 8; + *p = ul; +} + +void +putbe4(uchar *p, ulong ul) +{ + *p++ = ul >> 24; + *p++ = ul >> 16; + *p++ = ul >> 8; + *p = ul; +} + +void +dump(void *v, int bytes) +{ + uchar *p; + + if (!debug) + return; + p = v; + while (bytes-- > 0) + fprint(2, " %2.2x", *p++); + fprint(2, "\n"); +} + +void +dumptext(char *tag, char *text, int len) +{ + int plen, left; + char *p; + + if (!debug) + return; + for (p = text; len > 0; p += plen + 1, len -= plen + 1) { + /* paranoia: last pair might not be NUL-terminated */ + plen = 0; + for (left = len; left > 0 && p[plen] != '\0'; --left) + plen++; + fprint(2, "%s text `%.*s'\n", tag, plen, p); + } +} + +void +dumpresppkt(Iscsicmdresp *resp) +{ + if (!debug) + return; + fprint(2, "resp pkt: op %#x opspfc %#x %#x %#x dseglen %ld\n", + resp->op, resp->opspfc[0], resp->opspfc[1], resp->opspfc[2], + getbe3(resp->dseglen)); + fprint(2, "\titt %ld sts seq %ld exp cmd seq %ld\n", getbe4(resp->itt), + getbe4(resp->stsseq), getbe4(resp->expcmdseq)); +} + +/* set only the seq. nos. common to all response packets */ +void +setbhdrseqs(Pkts *pk) +{ + Iscsicmdreq *req; + Iscsicmdresp *resp; + + req = (Iscsicmdreq *)pk->pkt; + resp = (Iscsicmdresp *)pk->resppkt; + + /* + * by returning expcmdseq one past cmdseq, we're saying that we've + * executed commands numbered 1—cmdseq. + */ + istate.expcmdseq = getbe4(req->cmdseq) + 1; + /* + * give it what it expects for stsseq + */ + istate.stsseq = getbe4(req->expstsseq); + if (debug) + fprint(2, "\tsts seq %ld exp cmd seq %ld max cmd seq %ld\n", + istate.stsseq, istate.expcmdseq, istate.expcmdseq + 1); + putbe4(resp->stsseq, istate.stsseq); + putbe4(resp->expcmdseq, istate.expcmdseq); + putbe4(resp->maxcmdseq, istate.expcmdseq + 1); +} + +/* + * append sense data to response pkt. only permitted for check condition + * sense data or ireject returned headers; all other data read must + * be sent via a data-out packet (see appdata). + */ +void +appsensedata(Resppkt *rp, uchar *data, uint len) +{ + int olen; + Iscsijustbhdr *resp; + + olen = rp->resplen; + rp->resplen += ROUNDUP(len, 4); + + rp->resppkt = erealloc(rp->resppkt, rp->resplen); + resp = (Iscsijustbhdr *)rp->resppkt; + memmove((char *)resp + olen, data, len); + /* dseglen excludes padding */ + putbe3(resp->dseglen, getbe3(resp->dseglen) + len); +} + +void +appsense(Pkts *pk, uchar *sense, ushort len) +{ + uchar dseg[128]; + + if (len + 2 > sizeof dseg) + sysfatal("dseg too small in appsense for %d bytes", len); + putbe2(dseg, len); /* iscsi puts sense length first */ + memmove(dseg + 2, sense, len); + appsensedata(pk, dseg, len + 2); /* sense data */ +} + +/* + * append non-sense data to data-in pkt. + */ +void +appdata(Datainpkt *rp, uchar *data, uint len) +{ + int olen; + Iscsijustbhdr *dpkt; + + olen = rp->datalen; + rp->datalen += ROUNDUP(len, 4); + + rp->datapkt = erealloc(rp->datapkt, rp->datalen); + dpkt = (Iscsijustbhdr *)rp->datapkt; + memmove((char *)dpkt + olen, data, len); + /* dseglen excludes padding */ + putbe3(dpkt->dseglen, getbe3(dpkt->dseglen) + len); +} + +/* copy basic header from request to response; there's no dseg yet */ +void +req2resp(Iscsijustbhdr *resp, Iscsijustbhdr *req) +{ + memmove(resp, req, Bhdrsz); /* plausible defaults */ + resp->op &= ~(Immed | Oprsrvd); + resp->op += Topnopin - Iopnopout; /* req op -> resp op */ + resp->totahslen = 0; + memset(resp->dseglen, 0, sizeof resp->dseglen); +} + +void +newpkt(Iscsijustbhdr *pkt, int op) +{ + memset(pkt, 0, Bhdrsz); + pkt->op = op; +} + +int +ireject(Pkts *pk) +{ + Iscsijustbhdr *resp; + + free(pk->resppkt); + pk->resppkt = emalloc(sizeof *pk->resppkt); + pk->resplen = sizeof *pk->resppkt; + + resp = (Iscsijustbhdr *)pk->resppkt; + newpkt(resp, Topreject); + resp->opspfc[0] = Finalpkt; + resp->opspfc[1] = 4; /* protocol error */ + putbe4(resp->itt, ~0); + appsensedata(pk, pk->pkt, Bhdrsz); /* bad pkt hdr as dseg */ + if (debug) + fprint(2, "** sent reject pkt\n"); + free(pk->datapkt); /* discard any data to be returned */ + pk->datapkt = nil; + return Reply; +} + +int +keymatch(char *keyval, char **keys) +{ + int keylen; + char *p; + + p = strchr(keyval, '='); + if (p == nil) + sysfatal("key-value pair missing '='"); + keylen = p - keyval; + for (; *keys != nil; keys++) + if (strncmp(keyval, *keys, keylen) == 0) + return 1; + return 0; +} + +void +opneg(Pkts *pk) +{ + int plen, left, len; + char *p, *resptxt, *txtstart, *eq; + Iscsiloginresp *resp; + Iscsiloginreq *req; + + req = (Iscsiloginreq *)pk->pkt; + resp = (Iscsiloginresp *)pk->resppkt; + resptxt = txtstart = (char *)resp->dseg; + + resp->lun[7] = 1; /* non-zero tsih */ + + /* + * parse keys, generate responses to some (only non-declarative ones). + */ + for (p = (char *)req->dseg, len = pk->dseglen; len > 0; + p += plen + 1, len -= plen + 1) { + /* paranoia: last pair might not be NUL-terminated */ + plen = 0; + for (left = len; left > 0 && p[plen] != '\0'; --left) + plen++; + if (keymatch(p, agreekeys)) { + strcpy(resptxt, p); /* agree to value */ + resptxt += strlen(resptxt) + 1; + } else if (strncmp(p, sendtargall, sizeof sendtargall -1) == 0){ + strcpy(resptxt, targnm); + strcat(resptxt, advtarg); + resptxt += strlen(resptxt) + 1; + } else if (strncmp(p, hdrdig, sizeof hdrdig - 1) == 0 || + strncmp(p, datadig, sizeof datadig - 1) == 0) { + eq = strchr(p, '='); + assert(eq); + memmove(resptxt, p, eq + 1 - p); + resptxt[eq + 1 - p] = '\0'; + strcat(resptxt, "None"); + resptxt += strlen(resptxt) + 1; + } else if (strncmp(p, maxconns, sizeof maxconns - 1) == 0) { + strcpy(resptxt, maxconns); + strcat(resptxt, "1"); + resptxt += strlen(resptxt) + 1; + } else if (strncmp(p, initr2t, sizeof initr2t - 1) == 0) { + strcpy(resptxt, initr2t); + strcat(resptxt, "No"); + resptxt += strlen(resptxt) + 1; + } else if (strncmp(p, immdata, sizeof immdata - 1) == 0) { + strcpy(resptxt, immdata); + strcat(resptxt, "Yes"); + resptxt += strlen(resptxt) + 1; + } + assert(resptxt < txtstart + Maxtargs); + } + + /* append our own demands */ + /* try to prevent initiator generating data-out pkts */ + strcpy(resptxt, "MaxRecvDataSegmentLength=10485760"); + resptxt += strlen(resptxt) + 1; + assert(resptxt < txtstart + Maxtargs); + + putbe3(resp->dseglen, resptxt - txtstart); + pk->resplen = ROUNDUP(resptxt - (char *)pk->resppkt, 4); + if (debug) + fprint(2, "negotiated operational params for target %s:\n", + advtarg); + dumptext("sent", (char *)resp->dseg, getbe3(resp->dseglen)); +} + +/* + * phases: 0, security negotiation + * 1, operational negotiation + * 2, there is no number 2 + * 3, full-feature + */ +int +ilogin(Pkts *pk) +{ + int trans, cont, csg, nsg, vmax, vmin; + Iscsiloginresp *resp; + Iscsiloginreq *req; + + req = (Iscsiloginreq *)pk->pkt; + trans = req->opspfc[0] >> 7; + cont = (req->opspfc[0] >> 6) & 1; + csg = (req->opspfc[0] >> 2) & 3; + nsg = req->opspfc[0] & 3; + vmax = req->opspfc[1]; + vmin = req->opspfc[2]; + if (debug) { + fprint(2, "login req T %d C %d csg %d nsg %d vmax %d vmin %d\n", + trans, cont, csg, nsg, vmax, vmin); + fprint(2, "\tcmd seq %ld exp sts seq %ld\n", + getbe4(req->cmdseq), getbe4(req->expstsseq)); + } + + /* lun is isid[6], tsih[2] */ + if (req->lun[6] || req->lun[7]) + sysfatal("only one connection per session allowed"); + assert(cont == 0); + dumptext("got", (char *)req->dseg, getbe3(req->dseglen)); + + pk->resplen += Maxtargs + 1; + pk->resppkt = erealloc(pk->resppkt, sizeof *resp + Maxtargs + 1); + + resp = (Iscsiloginresp *)pk->resppkt; + resp->opspfc[0] &= ~0300; + resp->opspfc[0] |= 1<<7; /* T bit, not C bit */ + resp->stsclass = resp->stsdetail = 0; /* ok */ + memset(resp->_pad2, 0, sizeof resp->_pad2); /* reserved */ + + switch (csg) { + case 0: + sysfatal("not willing to negotiate security; sorry"); + case 1: + opneg(pk); + break; + case 3: + /* full-feature phase */ + resp->lun[7] = 1; /* non-zero tsih */ + if (debug) + fprint(2, "logged in, connected to target %s\n", + advtarg); + break; + default: + sysfatal("bad csg %d", csg); + } + + if (debug) + fprint(2, "-> replying to login req in csg %d\n", csg); + dumpresppkt(pk->resppkt); + return Reply; +} + +int +itext(Pkts *pk) +{ + char *p, *resptxt, *txtstart; + int trans, cont, len, plen, left; + Iscsitextresp *resp; + Iscsitextreq *req; + + req = (Iscsitextreq *)pk->pkt; + trans = req->opspfc[0] >> 7; + cont = (req->opspfc[0] >> 6) & 1; + if (debug) { + fprint(2, "text req T %d C %d\n", trans, cont); + fprint(2, "\tcmd seq %ld exp sts seq %ld\n", + getbe4(req->cmdseq), getbe4(req->expstsseq)); + } + assert(cont == 0); + assert(req->totahslen == 0); + + pk->resplen += Maxtargs + 1; + pk->resppkt = erealloc(pk->resppkt, sizeof *resp + Maxtargs + 1); + + resp = (Iscsitextresp *)pk->resppkt; + resptxt = txtstart = (char *)resp->dseg; + resp->opspfc[0] &= ~0300; + resp->opspfc[0] |= 1<<7; /* T bit, not C bit */ + + dumptext("got", (char *)req->dseg, pk->dseglen); + + for (p = (char *)req->dseg, len = pk->dseglen; len > 0; + p += plen + 1, len -= plen + 1) { + /* paranoia: last pair might not be NUL-terminated */ + plen = 0; + for (left = len; left > 0 && p[plen] != '\0'; --left) + plen++; + if (strncmp(p, sendtargall, sizeof sendtargall - 1) == 0) { + strcpy(resptxt, targnm); + strcat(resptxt, advtarg); + resptxt += strlen(resptxt) + 1; + assert(resptxt < txtstart + Maxtargs); + } + } + putbe3(resp->dseglen, resptxt - txtstart); + + if (debug) + fprint(2, "-> replying to text req"); + pk->resplen = ROUNDUP(resptxt - (char *)pk->resppkt, 4); + if (debug) { + if (pk->resplen > 0) + fprint(2, " with %s", txtstart); + fprint(2, "\n"); + } + dumptext("sent", (char *)resp->dseg, getbe3(resp->dseglen)); + return Reply; +} + +/* + * linux's iscsi initiator sends nops at about the rate of + * one per second, which obscures debugging, so print less. + * itt != ~0 means `send a reply'; otherwise do not send one. + * set sequence numbers in state from the packet. + */ +int +inop(Pkts *pk) +{ + int trans, cont; + Iscsinopresp *resp; + Iscsinopreq *req; + + req = (Iscsinopreq *)pk->pkt; + trans = req->opspfc[0] >> 7; + cont = (req->opspfc[0] >> 6) & 1; +// fprint(2, "nop req T %d C %d\n", trans, cont); + if (debug) + fprint(2, "[nop]"); + USED(trans); + assert(cont == 0); + assert(req->totahslen == 0); + if (debug) + fprint(2, " dseglen %ld lun %#llux cmd seq %ld expcmd seq %ld ", + getbe4(req->dseglen), getbe8(req->lun), + getbe4(req->cmdseq), getbe4(req->expcmdseq)); + + if (getbe4(req->itt) == ~0ul) + return Noreply; + + resp = (Iscsinopresp *)pk->resppkt; + resp->opspfc[0] &= ~0300; + resp->opspfc[0] |= 1<<7; /* T bit, not C bit */ + memset(resp->ttt, ~0, sizeof resp->ttt); + if (debug) + fprint(2, "[nop reply]"); + return Reply; +} + +void +targopen(void) +{ + if (targfd >= 0) + return; + targfd = open(targfile, (rdonly? OREAD: ORDWR)); + if (targfd >= 0) + return; + if (!rdonly) /* user didn't say -r, but target could be read-only */ + targfd = open(targfile, OREAD); + if (targfd >= 0) { + rdonly = 1; + return; + } + sysfatal("can't open target %s: %r", targfile); +} + +vlong +targlen(void) +{ + vlong len; + Dir *dir; + + targopen(); + dir = dirfstat(targfd); + if (dir == nil) + return 0; + len = dir->length; + free(dir); + return len; +} + +void +targread(Pkts *pk, vlong blockno, int nblks) +{ + int n; + uchar *blks; + + if (nblks <= 0) + return; + blks = emalloc(nblks*Blksz); + if (debug) + fprint(2, "reading %d block(s) @ block %lld of %s\n", + nblks, blockno, targfile); + targopen(); + if (seek(targfd, blockno*Blksz, 0) < 0) + sysfatal("seek on target failed: %r"); + n = read(targfd, blks, nblks*Blksz); + if (n < 0) + n = 0; + appdata(pk, blks, n); + free(blks); +} + +void +chkcond(Pkts *pk) +{ + uchar sense[18]; + + pk->resppkt->opspfc[2] = 2; /* status: check condition */ + + memset(sense, 0, sizeof sense); + sense[0] = 0x70; /* sense data format */ + sense[7] = sizeof sense - 7; + sense[12] = 5; /* illegal request */ + sense[13] = 0x25; /* lun unsupported */ + appsense(pk, sense, sizeof sense); +} + +void +targwrite(Pkts *pk, vlong blockno, int nblks) +{ + int n; + uchar *blks; + Iscsicmdreq *req; + + if (nblks <= 0) + return; + /* write dseg of dseglen bytes to target */ + req = (Iscsicmdreq *)pk->pkt; + blks = (uchar *)req + Bhdrsz; + if (debug) + fprint(2, "writing %d block(s) @ block %lld of %s\n", + nblks, blockno, targfile); + if(nblks*Blksz > getbe3(req->dseglen)) { + /* + * if this happens, the initiator will send data-out pkts + * with the remaining data. we try to prevent this by + * setting MaxRecvDataSegmentLength=10485760 during login + * negotiation. + */ + fprint(2, "** nblks %d * Blksz %d = %d > dseglen %lud\n", + nblks, Blksz, nblks*Blksz, getbe3(req->dseglen)); + chkcond(pk); + return; + } + targopen(); + if (seek(targfd, blockno*Blksz, 0) < 0) + sysfatal("seek on target failed: %r"); + n = write(targfd, blks, nblks*Blksz); + if (n != nblks*Blksz) + chkcond(pk); /* write error */ +} + +int +getcdblun(Pkts *pk) +{ + int lun; + Iscsicmdreq *req; + + req = (Iscsicmdreq *)pk->pkt; + lun = req->cdb[1] >> 5; + if (lun != 0) { + fprint(2, "unsupported non-zero lun %d\n", lun); + chkcond(pk); + return -1; + } + return lun; +} + +void +cmdinq(Pkts *pk) +{ + int alen, lun, evpd, page; + uchar inq[Inqlen]; + Iscsicmdreq *req; + + req = (Iscsicmdreq *)pk->pkt; + if (debug) + fprint(2, "inquiry\n"); + lun = getcdblun(pk); + if (lun < 0) + return; + evpd = req->cdb[1] & 1; + if (evpd != 0) { + fprint(2, "** evpd %d in inquiry\n", evpd); + chkcond(pk); + return; + } + page = req->cdb[2]; + if (page != 0) + fprint(2, "** page %d in inquiry\n", page); + alen = req->cdb[4]; + if (debug) + fprint(2, "req alloc len %d\n", alen); /* often 36 */ + + /* return a plausible inquiry string for a disk */ + memset(inq, 0, Inqlen); + inq[0] = 0; /* disk; tape is 1 */ + inq[2] = 2; /* scsi-2 device */ + inq[3] = 2; /* scsi-2 inq data format */ + inq[4] = Inqlen - 4; /* additional length */ + inq[7] = 1<<6 | 1<<5 | 1<<4; /* wbus32 | wbus16 | sync */ + memmove((char*)&inq[8], "plan 9 " "the-target " "1.00", Inqlen-8); + appdata(pk, inq, (alen > Inqlen? Inqlen: alen)); +} + +uchar * +newpage(uchar *p, int page, int len) +{ + *p++ = page; + *p++ = len; + return p + len; +} + +void +cmdmodesense(Pkts *pk) +{ + int alen, lun, page, rlen; + uvlong bytes; + uchar *p; + uchar sense[255]; + Iscsicmdreq *req; + + req = (Iscsicmdreq *)pk->pkt; + page = req->cdb[2] & ((1<<6) - 1); + if (debug) + fprint(2, "mode sense (6) page %d\n", page); + lun = getcdblun(pk); + if (lun < 0) + return; + /* req->cdb[4] is bytes permitted for sense data */ + alen = req->cdb[4]; + if (alen > sizeof sense) + sysfatal("sense array too small (%d bytes for %d asked)", + sizeof sense, alen); + + memset(sense, 0, sizeof sense); + /* mode parameter header */ + sense[0] = sizeof sense; + sense[1] = 0; /* medium type */ + sense[2] = 0; /* device-specific param for disk */ + sense[3] = 1 * 8; /* block descriptor len (for 1 bd) */ + /* block descriptor */ + sense[4] = 0; /* density */ + bytes = claimlen? claimlen: targlen(); + putbe3(sense + 5, bytes/Blksz); + putbe3(sense + 9, Blksz); + p = sense + 4 + 8; + + /* + * only pages 63 (all) & 8 are requested by linux. + * return pages in page number order. + */ + if (page == 63 || page == 2) { + putbe2(p + 10, 16); /* max sectors per transfer */ + p = newpage(p, 2, 14); /* disconnect/reconnect page */ + } + if (page == 63 || page == 3) { + putbe2(p + 12, Blksz); + p = newpage(p, 3, 22); /* format device page */ + } + if (page == 63 || page == 8) + p = newpage(p, 8, 10); /* caching page */ + if (page == 63 || page == 0xa) + p = newpage(p, 0xa, 6); /* control page */ + + assert(p <= sense + sizeof sense); + sense[0] = rlen = p - sense; /* amount we want to return */ + + if (rlen > alen) + rlen = alen; /* truncate result */ + appdata(pk, sense, rlen); +} + +void +cmdreqsense(Pkts *pk) +{ + int lun, alen; + uchar sense[18]; + Iscsicmdreq *req; + + req = (Iscsicmdreq *)pk->pkt; + lun = getcdblun(pk); + if (lun < 0) + return; + alen = req->cdb[4]; + if (alen >= sizeof sense) { + /* report ok */ + memset(sense, 0, sizeof sense); + sense[0] = 0x70; /* sense data format */ + sense[7] = sizeof sense - 7; + appdata(pk, sense, sizeof sense); + } +} + +// ScmdRewind = 0x01, /* rezero/rewind */ +// ScmdFormat = 0x04, /* format unit */ +// ScmdRblimits = 0x05, /* read block limits */ +// ScmdSeek = 0x0B, /* seek */ +// ScmdFmark = 0x10, /* write filemarks */ +// ScmdSpace = 0x11, /* space forward/backward */ +// ScmdMselect6 = 0x15, /* mode select */ +// ScmdMselect10 = 0x55, /* mode select */ +// ScmdMsense10 = 0x5A, /* mode sense */ +// ScmdStart = 0x1B, /* start/stop unit */ +// ScmdRcapacity16 = 0x9e, /* long read capacity */ +// ScmdRformatcap = 0x23, /* read format capacity */ +// ScmdExtseek = 0x2B, /* extended seek */ + // 0xa1 is ata command pass through (12) + // 0x85 is ata command pass through (16) + +int +execcdb(Pkts *pk) +{ + int rd, wr; + vlong bytes; + uchar *cdb; + uchar cap[8]; + Iscsicmdreq *req; + + req = (Iscsicmdreq *)pk->pkt; + rd = (req->opspfc[0] >> 6) & 1; + wr = (req->opspfc[0] >> 5) & 1; + + if (debug) + fprint(2, "=> scsi cmd: "); + cdb = req->cdb; + switch (cdb[0]) { + case ScmdInq: /* inquiry */ + cmdinq(pk); + break; + case ScmdTur: /* test unit ready */ + case ScmdRsense: /* request sense (error status) */ + if (debug) + fprint(2, "%s\n", cdb[0] == ScmdTur? "test unit ready": + "request sense (6)"); + cmdreqsense(pk); + break; + case ScmdRcapacity: /* read capacity */ + if (debug) + fprint(2, "read capacity\n"); + bytes = claimlen? claimlen: targlen(); + putbe4(cap, bytes/Blksz - 1); + putbe4(cap+4, Blksz); + appdata(pk, cap, sizeof cap); + break; + case ScmdMsense6: /* mode sense */ + cmdmodesense(pk); + break; + case ScmdExtread: /* extended read (10 bytes) */ + if (debug) + fprint(2, "extread\n"); + if (!rd) + return ireject(pk); + targread(pk, getbe4(cdb + 2), cdb[7]<<8 | cdb[8]); + break; + case ScmdRead: /* read (6 bytes) */ + if (debug) + fprint(2, "read\n"); + targread(pk, getbe4(cdb + 1) & ((1<<29)-1), cdb[4]); + break; + case ScmdRead16: + if (debug) + fprint(2, "read16\n"); + // adjust cdb offsets: + // targread(pk, getbe4(cdb + 2), cdb[7]<<8 | cdb[8]); + return ireject(pk); + case ScmdExtwrite: /* extended write (10 bytes) */ + case ScmdExtwritever: /* extended write and verify (10) */ + if (debug) + fprint(2, "extwrite\n"); + if (!wr || rdonly) + return ireject(pk); + targwrite(pk, getbe4(cdb + 2), cdb[7]<<8 | cdb[8]); + break; + case ScmdWrite: /* write */ + case ScmdWrite16: /* long write (16 bytes) */ + if (!wr || rdonly) + return ireject(pk); + // adjust cdb offsets + // targwrite(pk, getbe4(cdb + 2), cdb[7]<<8 | cdb[8]); + return ireject(pk); + default: + if (debug) + fprint(2, "** unknown scsi cmd %#x in cmd req\n", cdb[0]); + /* + * apparently ireject is too big a club, at least for the + * the linux initiator. + */ + chkcond(pk); + break; + } + return Reply; +} + +/* + * process an incoming scsi command (includes cdb) + * + * for some reason, the iscsi spec. allows immediate data for + * write operations, so the entire exchange is just cmd request + * and cmd response, yet for read operations, immediate data is + * not allowed (except for check condition sense data), so the + * is cmd request, data out, cmd response. + */ +int +icmd(Pkts *pk) +{ + int follow, rd, wr, attr, rlen, repl; + vlong lun; + Iscsicmdresp *resp; + Iscsicmdreq *req; + Iscsidatain *dpkt; + + req = (Iscsicmdreq *)pk->pkt; + follow = req->opspfc[0] >> 7; + rd = (req->opspfc[0] >> 6) & 1; + wr = (req->opspfc[0] >> 5) & 1; + attr = req->opspfc[0] & 7; + if (debug) + fprint(2, "cmd immed %d req F %d R %d W %d attr %d\n", + pk->immed, follow, rd, wr, attr); + assert(req->totahslen == 0); + if (follow == 0 && wr == 0) + sysfatal("write cmd req with no following data"); + + if (debug) { + fprint(2, "cdb: "); + dump(req->cdb, 16); /* decode cdb */ + } + + if (rd && wr) + sysfatal("don't support bidirectional transfers"); + + resp = (Iscsicmdresp *)pk->resppkt; + resp->opspfc[0] = 1<<7; /* final pkt of this response */ + resp->opspfc[1] = 0; /* response: cmd completed (optimism) */ + resp->opspfc[2] = 0; /* good status (optimism) */ + memset(resp->snacktag, 0, sizeof resp->snacktag); + memset(resp->readresid, 0, sizeof resp->readresid); + memset(resp->resid, 0, sizeof resp->resid); + memset(resp->expdataseq, 0, sizeof resp->expdataseq); + setbhdrseqs(pk); + if (debug) + fprint(2, "\texp xfer len %ld cmd seq %ld exp sts seq %ld\n", + getbe4(req->expxferlen), getbe4(req->cmdseq), + getbe4(req->expstsseq)); + + lun = getbe8(req->lun); + if (lun != 0) { + fprint(2, "unsupported non-zero lun %,llud (%#llux) in cmd req\n", + lun, lun); + chkcond(pk); + return Reply; + } + if (rd) { + /* clone response packet to get initial data-in packet */ + pk->datalen = sizeof *pk->datapkt; + pk->datapkt = dpkt = emalloc(pk->datalen); + memmove(dpkt, resp, pk->datalen); + + dpkt->op = Topdatain; + putbe4(dpkt->ttt, ~0); + putbe4(dpkt->buffoff, 0); + } + + repl = execcdb(pk); + + /* in case of a realloc above */ + resp = (Iscsicmdresp *)pk->resppkt; + dpkt = pk->datapkt; + + putbe4(resp->expdataseq, 0); + putbe4(resp->readresid, 0); + putbe4(resp->resid, 0); + + if (rd) { + /* if execcdb produced a data-in packet, send it */ + if (pk->datalen > Bhdrsz) { + rlen = ROUNDUP(pk->datalen, 4); + if (debug) + fprint(2, "-> sending data-in pkt of %d bytes\n", + rlen); + if (write(net, dpkt, rlen) != rlen) + sysfatal("error sending data pkt: %r"); + } + free(dpkt); + pk->datapkt = nil; + } + if (debug && repl) { + fprint(2, "-> replying to cmd req, %d bytes:\n", pk->resplen); + dump(resp, Bhdrsz); + if (pk->resplen > Bhdrsz) { + fprint(2, "\t"); + dump((uchar *)resp + Bhdrsz, pk->resplen - Bhdrsz); + } + } + return repl; +} + +int +itask(Pkts *pk) +{ + Iscsitaskresp *resp; + Iscsitaskreq *req; + + req = (Iscsitaskreq *)pk->pkt; + if (debug) + fprint(2, "task req func %d\n", req->opspfc[0] & 0177); + assert(req->totahslen == 0); + + resp = (Iscsitaskresp *)pk->resppkt; + resp->opspfc[0] = 1<<7; + resp->opspfc[1] = 0; /* done */ + + if (debug) + fprint(2, "-> replying to task req\n"); + return Reply; +} + +int +ilogout(Pkts *pk) +{ + + int trans, cont, csg, nsg, vmax, vmin; + Iscsilogoutresp *resp; + Iscsilogoutreq *req; + + req = (Iscsilogoutreq *)pk->pkt; + trans = req->opspfc[0] >> 7; + cont = (req->opspfc[0] >> 6) & 1; + csg = (req->opspfc[0] >> 2) & 3; + nsg = req->opspfc[0] & 3; + vmax = req->opspfc[1]; + vmin = req->opspfc[2]; + if (debug) { + fprint(2, "logout req T %d C %d csg %d nsg %d vmax %d vmin %d\n", + trans, cont, csg, nsg, vmax, vmin); + fprint(2, "\tcmd seq %ld exp sts seq %ld\n", + getbe4(req->cmdseq), getbe4(req->expstsseq)); + } + + /* lun is isid[6], tsih[2] */ + if (req->lun[6] || req->lun[7]) + sysfatal("only one connection per session allowed"); + assert(cont == 0); + + pk->resppkt = erealloc(pk->resppkt, sizeof *resp); + + resp = (Iscsilogoutresp *)pk->resppkt; + resp->opspfc[0] &= ~0300; + resp->opspfc[0] |= 1<<7; /* T bit, not C bit */ + memset(resp->_pad2, 0, sizeof resp->_pad2); /* reserved */ + + if (debug) + fprint(2, "-> replying to logout req in csg %d\n", csg); + dumpresppkt(pk->resppkt); + return Reply; +} + +void +process(int net, Iscsijustbhdr *bhdr) +{ + int op, repl, rlen; + long n; + uchar *pkt; + Pkts *pk; + + op = bhdr->op & ~(Immed | Oprsrvd); + + pk = emalloc(sizeof *pk); /* holds pointers to in & out pkts */ + pk->immed = (bhdr->op & Immed) != 0; + pk->totahslen = bhdr->totahslen * sizeof(ulong); + pk->dseglen = getbe3(bhdr->dseglen); + pk->itt = getbe4(bhdr->itt); + if (op != Iopnopout && debug) + fprint(2, "\n<- iscsi op %#x totahslen %ld dseglen %ld itt %ld\n", + op, pk->totahslen, pk->dseglen, pk->itt); + + /* + * read the rest of the packet: variable bhdr part, ahses & data + * rounded to next word. + */ + n = (Bhdrsz - sizeof *bhdr) + pk->totahslen + ROUNDUP(pk->dseglen, 4); + pkt = emalloc(sizeof *bhdr + n); + memmove(pkt, bhdr, sizeof *bhdr); + + if (readn(net, pkt + sizeof *bhdr, n) != n) + sysfatal("truncated packet read"); + + pk->pkt = pkt; + pk->len = n; + + /* allocate response pkt and fill w plausible default values */ + pk->resplen = sizeof *pk->resppkt; + pk->resppkt = emalloc(pk->resplen); + req2resp((Iscsijustbhdr *)pk->resppkt, (Iscsijustbhdr *)pk->pkt); + repl = 0; + + switch (op) { + case Iopnopout: + repl = inop(pk); + break; + case Iopcmd: + repl = icmd(pk); + break; + case Ioptask: + repl = itask(pk); + break; + case Ioplogin: + repl = ilogin(pk); + break; + case Ioptext: + repl = itext(pk); + break; + case Ioplogout: + repl = ilogout(pk); + break; + + case Iopdataout: /* do not want */ + case Iopsnack: + repl = ireject(pk); + break; + default: + sysfatal("bad iscsi opcode %#x", op); + } + if (repl) { + rlen = ROUNDUP(pk->resplen, 4); + if (write(net, pk->resppkt, rlen) != rlen) + sysfatal("error sending response pkt: %r"); + } + free(pk->resppkt); + free(pkt); + memset(pk, 0, sizeof *pk); + free(pk); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-dr] [-l len] [-a dialstring] target\n", argv0); + exits("usage"); +} + +void +callhandler(void) +{ + Iscsijustbhdr justbhdr; + + if (debug) + mainmem->flags |= POOL_ANTAGONISM | POOL_PARANOIA | POOL_NOREUSE; + + if (debug) + fprint(2, "\nserving target %s\n", targfile); + while (readn(net, &justbhdr, sizeof justbhdr) == sizeof justbhdr) + process(net, &justbhdr); + if (debug) + fprint(2, "\ninitiator closed connection\n"); +} + +void +tcpserver(char *dialstring) +{ + char dir[40], ndir[40]; + int ctl, nctl; + + ctl = announce(dialstring, dir); + if (ctl < 0) { + fprint(2, "Can't announce on %s: %r\n", dialstring); + exits("announce"); + } + + for (;;) { + nctl = listen(dir, ndir); + if (nctl < 0) { + fprint(2, "Listen failed: %r\n"); + exits("listen"); + } + + switch(rfork(RFFDG|RFNOWAIT|RFPROC)) { + case -1: + close(nctl); + fprint(2, "failed to fork, exiting: %r\n"); + exits("fork"); + case 0: + net = accept(nctl, ndir); + if (net < 0) { + fprint(2, "Accept failed: %r\n"); + exits("accept"); + } + callhandler(); + exits(nil); + default: + close(nctl); + } + } +} + + +void +main(int argc, char **argv) +{ + char *dialstring; + + quotefmtinstall(); + time0 = time(0); + debug = 0; + dialstring = nil; + + ARGBEGIN{ + case 'd': + debug++; + break; + case 'l': + claimlen = atoll(EARGF(usage())); + break; + case 'r': + rdonly = 1; + break; + case 'a': + dialstring = EARGF(usage()); + break; + default: + usage(); + }ARGEND + + if (argc != 1) + usage(); + targfile = argv[0]; + + if (dialstring) { + tcpserver(dialstring); + exits(nil); + } + net = 0; + callhandler(); + exits(nil); +} diff --git a/sys/src/cmd/ip/mkfile b/sys/src/cmd/ip/mkfile index 45bfa6f34a..8073a87a1d 100644 --- a/sys/src/cmd/ip/mkfile +++ b/sys/src/cmd/ip/mkfile @@ -6,6 +6,7 @@ TARG = 6in4\ gping\ hogports\ httpfile\ + iscsisrv\ linklocal\ ping\ pppoe\ From a7ad063d07eef94cd82111b00a10586f4ebaae34 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 186/402] sys/src/cmd/jtagfs: import jtagfs (thanks Gorka Guardiola) --- sys/lib/acid/jtag | 245 +++++ sys/man/4/jtagfs | 202 ++++ sys/src/cmd/jtagfs/README | 33 + sys/src/cmd/jtagfs/TODO | 36 + sys/src/cmd/jtagfs/bebo.c | 76 ++ sys/src/cmd/jtagfs/bebo.h | 6 + sys/src/cmd/jtagfs/chain.c | 219 ++++ sys/src/cmd/jtagfs/chain.h | 23 + sys/src/cmd/jtagfs/debug.c | 35 + sys/src/cmd/jtagfs/debug.h | 24 + sys/src/cmd/jtagfs/genrtab.c | 45 + sys/src/cmd/jtagfs/guide | 85 ++ sys/src/cmd/jtagfs/h2acid | 30 + sys/src/cmd/jtagfs/icert.c | 970 ++++++++++++++++++ sys/src/cmd/jtagfs/icert.h | 273 +++++ sys/src/cmd/jtagfs/jtag.c | 77 ++ sys/src/cmd/jtagfs/jtag.h | 47 + sys/src/cmd/jtagfs/jtagfs.c | 1590 ++++++++++++++++++++++++++++++ sys/src/cmd/jtagfs/lebo.c | 77 ++ sys/src/cmd/jtagfs/lebo.h | 6 + sys/src/cmd/jtagfs/ma.c | 820 +++++++++++++++ sys/src/cmd/jtagfs/maexamples | 16 + sys/src/cmd/jtagfs/maexamplesbad | 11 + sys/src/cmd/jtagfs/matest | 10 + sys/src/cmd/jtagfs/mkfile | 62 ++ sys/src/cmd/jtagfs/mmu.c | 125 +++ sys/src/cmd/jtagfs/mmu.h | 36 + sys/src/cmd/jtagfs/mpsse.c | 648 ++++++++++++ sys/src/cmd/jtagfs/mpsse.h | 59 ++ sys/src/cmd/jtagfs/mpssetest.c | 193 ++++ sys/src/cmd/jtagfs/tap.c | 269 +++++ sys/src/cmd/jtagfs/tap.h | 53 + 32 files changed, 6401 insertions(+) create mode 100644 sys/lib/acid/jtag create mode 100644 sys/man/4/jtagfs create mode 100644 sys/src/cmd/jtagfs/README create mode 100644 sys/src/cmd/jtagfs/TODO create mode 100644 sys/src/cmd/jtagfs/bebo.c create mode 100644 sys/src/cmd/jtagfs/bebo.h create mode 100644 sys/src/cmd/jtagfs/chain.c create mode 100644 sys/src/cmd/jtagfs/chain.h create mode 100644 sys/src/cmd/jtagfs/debug.c create mode 100644 sys/src/cmd/jtagfs/debug.h create mode 100644 sys/src/cmd/jtagfs/genrtab.c create mode 100644 sys/src/cmd/jtagfs/guide create mode 100644 sys/src/cmd/jtagfs/h2acid create mode 100644 sys/src/cmd/jtagfs/icert.c create mode 100644 sys/src/cmd/jtagfs/icert.h create mode 100644 sys/src/cmd/jtagfs/jtag.c create mode 100644 sys/src/cmd/jtagfs/jtag.h create mode 100644 sys/src/cmd/jtagfs/jtagfs.c create mode 100644 sys/src/cmd/jtagfs/lebo.c create mode 100644 sys/src/cmd/jtagfs/lebo.h create mode 100644 sys/src/cmd/jtagfs/ma.c create mode 100644 sys/src/cmd/jtagfs/maexamples create mode 100644 sys/src/cmd/jtagfs/maexamplesbad create mode 100644 sys/src/cmd/jtagfs/matest create mode 100644 sys/src/cmd/jtagfs/mkfile create mode 100644 sys/src/cmd/jtagfs/mmu.c create mode 100644 sys/src/cmd/jtagfs/mmu.h create mode 100644 sys/src/cmd/jtagfs/mpsse.c create mode 100644 sys/src/cmd/jtagfs/mpsse.h create mode 100644 sys/src/cmd/jtagfs/mpssetest.c create mode 100644 sys/src/cmd/jtagfs/tap.c create mode 100644 sys/src/cmd/jtagfs/tap.h diff --git a/sys/lib/acid/jtag b/sys/lib/acid/jtag new file mode 100644 index 0000000000..6e231f3b14 --- /dev/null +++ b/sys/lib/acid/jtag @@ -0,0 +1,245 @@ +include("/sys/lib/acid/arm"); + +// feroceon memory definitions +TmrWDenable=1<<4; +PHYSIO=0xf1000000; +TIMERREG=0xf1020300; +PsrMsvc=0x00000013; +timerctl=0; +KZERO=0x60000000; + +ureg = 0; +complex Ureg ureg; +uregtypeaddr=60; //kludge + +//generated from 8c -a +sizeofMMURegs = 32; +aggr MMURegs +{ + 'U' 0 cpid; + 'U' 4 control; + 'U' 8 ttb; + 'U' 12 dac; + 'U' 16 fsr; + 'U' 20 far; + 'U' 24 ct; + 'U' 28 pid; +}; + +defn +remapdata() +{ + mps = map(); + + while mps do { + m = head mps; + name = head m; + if name == "*data" then { + dend = head tail tail m; + map({"*data", KZERO, dend, KZERO}); + } + mps = tail mps; + } +} +//I want to be able to access MACH and other stuff +remapdata(); +memmap=map(); +//TO DO is there any arm with fpregs? +map({"regs", 0, sizeofUreg+sizeofMMURegs, 0}); + +defn +MMURegs(addr) { + complex MMURegs addr; + print(" cpid ", addr.cpid\X, "\n"); + print(" control ", addr.control\X, "\n"); + print(" ttb ", addr.ttb\X, "\n"); + print(" dac ", addr.dac\X, "\n"); + print(" fsr ", addr.fsr\X, "\n"); + print(" far ", addr.far\X, "\n"); + print(" ct ", addr.ct\X, "\n"); + print(" pid ", addr.pid\X, "\n"); +}; + +complex MMURegs mmuregs; +mmuregs=sizeofUreg; // plus size of floating point registers + +defn +mmuregs() +{ + MMURegs(mmuregs); +} + +defn +stopwdog() +{ + // change to svc mode to be able to access the address + stype = ureg.type; + *uregtypeaddr=PsrMsvc; + timerctl=*TIMERREG; + *TIMERREG = ~TmrWDenable&*TIMERREG; + *uregtypeaddr=stype; +} + +defn +startwdog() +{ + stype = ureg.type; + *uregtypeaddr=PsrMsvc; + *TIMERREG = TmrWDenable|timerctl; + *uregtypeaddr=stype; +} + +defn +hwbpset(addr, mask) +{ + printto("/proc/"+itoa(pid)+"/ctl", "breakpoint ", itoa(addr), " ", itoa(mask)); +} + +defn +veccatch(vecstr) +{ + printto("/proc/"+itoa(pid)+"/ctl", "veccatch ", vecstr); +} + +defn +reset() +{ + printto("/proc/"+itoa(pid)+"/ctl", "reset "); +} + +defn +debug(dbstr) +{ + printto("/proc/"+itoa(pid)+"/ctl", "debug ", dbstr); +} + +defn +cpuid() +{ + printto("/proc/"+itoa(pid)+"/ctl", "cpuid"); +} + +defn +jtaginfo() +{ + rc("cat /proc/"+itoa(pid)+"/ctl"); +} + +defn +sheevastop() +{ + stop(pid); + stopwdog(); +} + +defn +sheevastart() +{ + startwdog(); + start(pid); +} + +defn +sheevawaitstop() +{ + waitstop(pid); + stopwdog(); +} + +// FROM here down on, UNTRIED BUG BUG BUG!!!!! + +//CpCONTROL, h2acid +CpCmmu = 0x00000001; +CpCalign = 0x00000002; +CpCdcache = 0x00000004; +CpCwb = 0x00000008; +CpCi32 = 0x00000010; +CpCd32 = 0x00000020; +CpCbe = 0x00000080; +CpCsystem = 0x00000100; +CpCrom = 0x00000200; +CpCicache = 0x00001000; +CpChv = 0x00002000; + +//MMU definitions, h2acid +KB=1024; +MB=1024*1024; +Mbo = 0x10; +Coarse = (Mbo|1); +Section = (Mbo|2); +Fine = (Mbo|3); + +defn +ismmuon() +{ + mmu = mmuregs; + complex MMURegs mmu; + return mmu.control&CpCmmu; +} + +defn +l1x(vaddr) +{ + return ((vaddr>>20) & 0x0fff)<<2; +} + +defn +l2x(vaddr) +{ + return ((vaddr>>12) & 0xff)<<2; +} + +defn +pgsz(type) +{ + if type == Fine then { + return KB; + } else if type == Section then { + return MB; + } else if type == Coarse then { + return 4*KB; + } + return 4*KB; +} + +defn +kaddr(vaddr) +{ + return KZERO|vaddr; //very non portable +} + +defn +ttbpaddr(ttb, vaddr) +{ + if ! ismmuon() then { + print("paddr: mmu is off\n"); + return 0; + } + l1idx = l1x(vaddr); + l2idx = l2x(vaddr); + pte1 = *((kaddr(ttb)&~0x1fff) + l1idx); + if pte1 == 0 then { + return 0; + } + type = pte1 & (Fine|Section|Coarse); + sz = pgsz(type); + if type == Section then { + return (pte1 & ~(sz - 1)) + (vaddr & (sz - 1)); + } + + l2addr = pte1 & ~(sz - 1); + if l2addr == 0 then { + return 0; + } + pte2 = *(kaddr(l2addr) + l2idx); + return (pte2 & ~(sz - 1)) + (vaddr & (sz - 1)); +} + +defn +paddr(vaddr) +{ + mmu = mmuregs; + complex MMURegs mmu; + return ttbpaddr(mmu.ttb, vaddr); +} + diff --git a/sys/man/4/jtagfs b/sys/man/4/jtagfs new file mode 100644 index 0000000000..095567596f --- /dev/null +++ b/sys/man/4/jtagfs @@ -0,0 +1,202 @@ +.TH JTAGFS 4 +.SH NAME +jtagfs \- jtag kernel debugging file system +.SH SYNOPSIS +.B jtagfs +[ +.B -d +.I debugstr +] +[ +.B -b +.I motherbname +] +[ +.B -t +.I text +] +[ +.B -m +.I mountpoint +] +[ +.B -s +.I srvfile +] +.I jtagfile +.SH DESCRIPTION +.I Jjagfs +presents in +.BI /n/jtagfs/ctl +a set of process files for debugging +a kernel running on an arm over a jtag +.I device +in a manner similarly to +.IR rdbfs (4) +but without any need for the kernel collaborating. +In debug mode an arm stops and isolates itself from the +surroundings and can be probed and instructions injected +at will. +There are a number of options: +.TP +.B -d +Can be used to set the debug string, see below. +.TP +.B -m +and +.B -s +Set the mount point and srv name respectively. By default +the mount point is +.BI /n/jtagfs/ctl . +.TP +.B -b +Motherboard kind jtagfs is going to be run against. Valid parameters +are +.B sheeva, +which stands for the Feroceon Guruplug and the sheevaplug and is the default and +.B gurudisp +which stands for the Armada Guru Display. +.TP +.B -t +The +.B text +file presented is just a copy of +.I text +(default +.BR /arm/s9plug ). +It can usually be ignored, since +the debuggers open kernel +files directly rather than +using +.BI /proc/ n /text\fR. +.PP +Kernels can be remotely debugged only when they are +stopped and put in debug mode. This can be done +through instruction breakpoints, vector catching (on entry +to interrupts) or on demand using +.B stop(). +.PP +An acid library to use with the most common operations +called jtag is provided to make most common operations +simpler. In particular +.B start(), +.B stop() +and +.B waitstop() +have jtag specific variants +(for example +.B sheevastart() +) +which disable and reenable the watchdog. +Other than this functions and the symbol translations, this +program can be used to debug kernels from other operating systems. +.PP +The function +.B veccatch(str) +can be used to set a vectorcatch, which stops the processor right after +an interrupt. The string describes which interrupts to cacth. +Each caracter represents a type of interrupt: +.sp +.EX +.ta 4n +6n + 'R' Reset + 'S' SWI + 'P' PAbort + 'D' DAbort + 'I' Irq + 'F' Fiq +.fi +.EE +.PP +The function +.B debug(str) +can be used to set different levels of debug. Each character on +the string represent a different software layer: +.PP +.EX +.ta 6n +2n +4n +4n +4n +4n +4n +.sp +DFile = 'f', /* Reads, writes, flushes*/ +DPath = 'p', /* path for state transitions for tap debugging */ +DState = 's', /* state calculation and changes on tap interface */ +Dinst = 'i', /* mpsse instruction assembling debug */ +Dassln = 'a', /* print instructions before assembling */ +Dmach = 'm', /* print mpsse machine code and op results */ +Djtag = 'j', /* print jtag level operations */ +Dice = 'e', /* print icert level operations */ +Dchain = 'h', /* print icert chains */ +Dmmu = 'u', /* print MMU ops */ +Dctxt = 'c', /* dump context in and out */ +Darm = 'w', /* standard insts and so */ +Dmem = 'y', /* memory ops */ +Dfs = 'k', /* filesystem ops */ +DAll = 'A' +.fi +.EE +.SH EXAMPLES +.EX +jtagfs /dev/eiaU*/jtag +bind /n/jtagfs /proc/1 +term% acid -l jtag -k 1 /arm/s9plug +/arm/s9plug:ARM plan 9 boot image +/sys/lib/acid/port +/sys/lib/acid/arm +acid: reset() +acid: sheevastop() +ID: 0x20a023d3 +Must be 1: 1 +Manufacturer id: 0x1e9 +Part no: 0xa02 +Version: 0x2 +1: SVC/SWI Exception 0xc02e1094 no instruction +acid: dump(0xc02e1094, 4, "Xi") +0xc02e1094: 0x1204e0ff CMP.S $#0x100,R0 +0xc02e109c: 0xe0266003 B.NE etext+0x5fa536bc +0xc02e10a4: 0xe20c2040 AND $#0x8,R12,R0 +0xc02e10ac: 0xe20e1080 AND $#0x1,R14,R3 +0xc02e10b4: 0xe1811002 ORR (R0<<4),R3,R3 +acid: regs() +R0 0x5e20a2dc R1 0xf5518723 R2 0x001d1d00 +R3 0x369244e0 R4 0x2b9244fd R5 0xbbc54739 +R6 0x5e20a2dc R7 0x00000eb0 R8 0xdfd7ceb0 +R9 0x00000006 R10 0xc08c1f20 R11 0xc08c1f04 +R12 0x1d00001d R13 0xc08c1ea0 R14 0x00000000 +R15 0xc031fa8c +acid: sheevastart() +.EE +.SH SOURCE +.B /sys/src/cmd/jtag +.br +.B /sys/lib/acid/jtag +.SH "SEE ALSO" +.IR acid (1), +.IR db (1). +.br +``ARM9E-S Technical Reference Manual''. +.br +``ARM7TDMI-S Core Technical Reference Manual". +.br +``Application note 205 "Writing JTAG Sequences for Arm 9 Processors". +.br +``Design and Implementation of an On-Chip Debug for Embedded Target Systems", +Dominic Rath. +.br +``IEEE Standard 1149-1-2001 Test Access Port and Boundary Scan Architecture", +JTag IEEE standard. +.br +``AN2232C-01 Command Processor for MPSSE and MCU Host Bus Emulation Modes", +Future Technology Devices International Ltd. +.SH BUGS +After a while of the machine being on, the jtag will stop +working; maybe an autentication register needs to be set. +If this is the case +.B cpuid() +will return error. +Reset always works. +Reading and writing from memory is slow. +The filesystems needs a lot of cleaning. +Only the feroceon cpu and sheeva/guruplug boards are +supported, though more can be added. +Error report is sparse. +Jtagfs should be rewritten using the 9p library and it would shrink +to half. diff --git a/sys/src/cmd/jtagfs/README b/sys/src/cmd/jtagfs/README new file mode 100644 index 0000000000..392dca170b --- /dev/null +++ b/sys/src/cmd/jtagfs/README @@ -0,0 +1,33 @@ +To install + +cp acidjtag /sys/lib/acid/jtag +cp acidarm /sys/lib/acid/arm +cp jtagfs.man /sys/man/4/jtagfs +mkdir /sys/src/cmd/jtagfs +cp * /sys/src/cmd/jtagfs +cd /sys/src/cmd/jtagfs +mk install + +change attachproc in libmach so that we can modify the kernel +registers. + +/sys/src/libmach/map.c:94 +< mode = ORDWR; +--- +> mode = OREAD; +recompile libmach and acid +It could also be done through acid using map(), but in this case +it is better this way. + +The armada implementation has never been run even once. + + +Byte endianness. As it is now, it depends on endianness of ARM being the +same as 386. Specifically, the /proc served is in the machine where it runs +order (i.e. in a little endian machine it would not work). This should be +changed on jtagfs, just before serving them. + +MMU state is served after the Uregs (there is no floating point, if not, it would +be after the floating point too). A map has been added to map it in read only. +h2acid for constants and macros + diff --git a/sys/src/cmd/jtagfs/TODO b/sys/src/cmd/jtagfs/TODO new file mode 100644 index 0000000000..df96e8de1a --- /dev/null +++ b/sys/src/cmd/jtagfs/TODO @@ -0,0 +1,36 @@ + +Use openocd on a fake GURU to see reset +Unknown + +Fix start + +Fix the sheeva nsrst must be asserted while stopping/cpuiding +but this is just for the feroceon, an extra reset state before +cpuid/request. The order is strictly this: + +- UNTESTED +reset 0 1 +cpuid +set DBGRQ +reset 0 0 +wait halt + +It may work to break it into: +reset 0 1 +cpuid +reset 0 0 + +and + +reset 0 1 +set DBGRQ +reset 0 0 + + +Put currentch inside the tap description in an Armtap state. + +Add a ctl to identify the motherboard, not sure how to call initmpsse... +break it in two pieces maybe. +Identify which part is board dependant. + +Get more info about the GURU display. diff --git a/sys/src/cmd/jtagfs/bebo.c b/sys/src/cmd/jtagfs/bebo.c new file mode 100644 index 0000000000..5f3686e744 --- /dev/null +++ b/sys/src/cmd/jtagfs/bebo.c @@ -0,0 +1,76 @@ +#include +#include + +void +hbeputv(void *p, uvlong v) +{ + uchar *a; + + a = p; + a[0] = v>>56; + a[1] = v>>48; + a[2] = v>>40; + a[3] = v>>32; + a[4] = v>>24; + a[5] = v>>16; + a[6] = v>>8; + a[7] = v; +} + +void +hbeputl(void *p, uint v) +{ + uchar *a; + + a = p; + a[0] = v>>24; + a[1] = v>>16; + a[2] = v>>8; + a[3] = v; +} + +void +hbeputs(void *p, ushort v) +{ + uchar *a; + + a = p; + a[0] = v>>8; + a[1] = v; +} + +uvlong +behgetv(void *p) +{ + uchar *a; + uvlong v; + + a = p; + v = (uvlong)a[0]<<56; + v |= (uvlong)a[1]<<48; + v |= (uvlong)a[2]<<40; + v |= (uvlong)a[3]<<32; + v |= a[4]<<24; + v |= a[5]<<16; + v |= a[6]<<8; + v |= a[7]<<0; + return v; +} + +uint +behgetl(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); +} + +ushort +behgets(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<8)|(a[1]<<0); +} diff --git a/sys/src/cmd/jtagfs/bebo.h b/sys/src/cmd/jtagfs/bebo.h new file mode 100644 index 0000000000..2b496a595f --- /dev/null +++ b/sys/src/cmd/jtagfs/bebo.h @@ -0,0 +1,6 @@ +extern uint behgetl(void *p); +extern ushort behgets(void *p); +extern uvlong behgetv(void *p); +extern void hbeputl(void *p, uint v); +extern void hbeputs(void *p, ushort v); +extern void hbeputv(void *p, uvlong v); diff --git a/sys/src/cmd/jtagfs/chain.c b/sys/src/cmd/jtagfs/chain.c new file mode 100644 index 0000000000..d6423bffc4 --- /dev/null +++ b/sys/src/cmd/jtagfs/chain.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include "lebo.h" +#include "bebo.h" +#include "debug.h" +#include "chain.h" + +/* functions to deal with bit chains, weird bit orderings an such */ + +#define Upper(byte, nbits) ((byte)>>(nbits)) +#define Lower(byte, nbits) ((bytes)&MSK(nbits)) +#define IsCut(bbits, ebits) (((ebits)/8 - (bbits)/8) > 0) + +/* 8: H L | 8: Next */ +/* Put at most 8 bits*/ +static void +put8bits(Chain *ch, void *p, int nbits) +{ + int e, nbye, nbie, nle; + uchar low, high, byte; + + byte = *(uchar *)p; + e = ch->e+nbits-1; /* offset of last bit to put in */ + nbie = ch->e%8; + nbye = ch->e/8; + nle = 8 - nbie; + + + if(IsCut(ch->e, e)) + ch->buf[nbye + 1] = byte >> nle; + + high = (byte & MSK(nle)) << nbie; + low = ch->buf[nbye]&MSK(nbie); + + + ch->buf[nbye] = low|high; + ch->e += nbits; +} + +/* Get at most 8 bits*/ +static uchar +get8bits(Chain *ch, int nbits) +{ + int b, nbyb, nbib, nlb; + uchar low, high, res; + + b = ch->b+nbits-1; + nbib = ch->b % 8; + nbyb = ch->b / 8; + nlb = 8 - nbib; + if(nlb > nbits) + nlb = nbits; + + low = MSK(nlb) & (ch->buf[nbyb] >> nbib); + if(IsCut(ch->b, b)) + high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb; + else + high = 0; + res = MSK(nbits)&(high | low); + ch->b += nbits; + return res; +} + +/* + * Putbits and getbits could be made more efficient + * simply by using memmove in the special case where + * a bunch of bytes is aligned, but I don't care. + * Packing in words would also help the so inclined. + */ +void +putbits(Chain *ch, void *p, int nbits) +{ + int nby, nbi, i; + uchar *vp; + + vp = p; + nby = nbits / 8; + nbi = nbits % 8; + + for(i = 0; i < nby; i++) + put8bits(ch, vp++, 8); + + if(nbi != 0) + put8bits(ch, vp, nbi); +} + +void +getbits(void *p, Chain *ch, int nbits) +{ + int nby, nbi, i; + uchar *vp; + + assert(ch->e >= ch->b); + nby = nbits / 8; + nbi = nbits % 8; + + vp = p; + for(i = 0; i < nby; i++) + *vp++ = get8bits(ch, 8); + + if(nbi != 0) + *vp = get8bits(ch, nbi); +} + +static void +revbych(Chain *ch) +{ + int i, nb; + + nb = (ch->e-ch->b+7)/8; + + for(i = 0; i < nb; i++) + ch->buf[i] = rtab[ch->buf[i]]; +} + +void +printchain(Chain *ch) +{ + int i, ng, nb; + uchar msk, c; + Chain *ch2; + + fprint(2, "chain buf:%#p b:%d e:%d\n", ch->buf, ch->b, ch->e); + ch2 = malloc(sizeof(Chain)); + if(ch2 == nil) + sysfatal("no memory"); + memmove(ch2, ch, sizeof(Chain)); + + + ng = 8; + nb = (ch2->e-ch2->b+7)/8; + + for(i = 0; i < nb; i++){ + if(ch2->e - ch2->b < ng) + ng = ch2->e - ch2->b; + getbits(&c, ch2, ng); + if(i != 0 && i%15 == 0) + fprint(2, "\n"); + if(ng < 8){ + msk = MSK(ng); + fprint(2, "%#2.2x ", c&msk); + } + else + fprint(2, "%#2.2x ", c); + + } + if(i%16 != 0) + fprint(2, "\n"); + + free(ch2); +} + +/* Good for debugging */ +static void +printchslice(Chain *ch, int b, int e) +{ + Chain *ch2; + + fprint(2, "Slice [%d, %d], b:%d e:%d\n", b, e, ch->b, ch->e); + ch2 = malloc(sizeof(Chain)); + if(ch2 == nil) + sysfatal("memory"); + memmove(ch2, ch, sizeof(Chain)); + if(b > e){ + fprint(2, "bad args in region\n"); + return; + } + if(b < ch2->b || b > ch2->e || e > ch2-> e || e < ch2->b){ + fprint(2, "bad region\n"); + return; + } + ch2->b = b; + ch2->e = e; + + fprint(2, "Slice - "); + printchain(ch2); + free(ch2); +} + + +static u32int +revbytes(u32int *v) +{ + u32int rv; + uchar *a, *b; + + a = (uchar *)v; + b = (uchar *)&rv; + + b[3] = rtab[a[3]]; + b[2] = rtab[a[2]]; + b[1] = rtab[a[1]]; + b[0] = rtab[a[0]]; + + return rv; +} + +u32int +hmsbputl(u32int *v) +{ + u32int rv, bev; + + hbeputl(&bev, *v); + rv = revbytes(&bev); + + return rv; +} + +u32int +msbhgetl(u32int *v) +{ + u32int rv, rev; + + rev = revbytes(v); + rv = lehgetl(&rev); + return rv; +} + diff --git a/sys/src/cmd/jtagfs/chain.h b/sys/src/cmd/jtagfs/chain.h new file mode 100644 index 0000000000..3b9d1ce592 --- /dev/null +++ b/sys/src/cmd/jtagfs/chain.h @@ -0,0 +1,23 @@ +typedef struct Chain Chain; + +extern uchar rtab[]; /* generated by genrtab.c */ + +#define MSK(nbits) ((1UL<<(nbits))-1) + +enum{ + MaxChLen = 128, /* bytes */ +}; + + +/* bit chain, can put at the beginning, get at the end */ +struct Chain { + int b; /* offset start in bits, (first full) */ + int e; /* offset end in bits (first empty) */ + uchar buf[MaxChLen]; +}; + +extern void getbits(void *p, Chain *ch, int nbits); +extern u32int hmsbputl(u32int *v); +extern u32int msbhgetl(u32int *v); +extern void printchain(Chain *ch); +extern void putbits(Chain *ch, void *p, int nbits); diff --git a/sys/src/cmd/jtagfs/debug.c b/sys/src/cmd/jtagfs/debug.c new file mode 100644 index 0000000000..db15da078f --- /dev/null +++ b/sys/src/cmd/jtagfs/debug.c @@ -0,0 +1,35 @@ +#include +#include + +uchar debug[255]; + +int +dprint(char d, char *fmt, ...) +{ + int n; + va_list args; + + if(!debug['A'] && !debug[d]) + return -1; + va_start(args, fmt); + n = vfprint(2, fmt, args); + va_end(args); + return n; +} + + +void +dumpbuf(char d, uchar *buf, int bufsz) +{ + int i; + + if(d != 0 && !debug[d]) + return; + for(i = 0; i < bufsz; i++){ + fprint(2, "%#2.2x ", buf[i]); + if(i != 0 && (i + 1) % 8 == 0) + fprint(2, "\n"); + } + if(i %16 != 0) + fprint(2, "\n"); +} diff --git a/sys/src/cmd/jtagfs/debug.h b/sys/src/cmd/jtagfs/debug.h new file mode 100644 index 0000000000..72ee2d68f2 --- /dev/null +++ b/sys/src/cmd/jtagfs/debug.h @@ -0,0 +1,24 @@ +extern uchar debug[]; + +enum { + DXFlush = 'x', /* special markers for debugging on the commands, disrupts behaviour*/ + + DFile = 'f', /* Reads, writes, flushes*/ + DPath = 'p', /* path for state transitions for tap debugging */ + DState = 's', /* state calculation and changes on tap interface */ + Dinst = 'i', /* mpsse instruction assembling debug */ + Dassln = 'a', /* print instructions before assembling */ + Dmach = 'm', /* print mpsse machine code and op results */ + Djtag = 'j', /* print jtag level operations */ + Dice = 'e', /* print icert level operations */ + Dchain = 'h', /* print icert chains */ + Dmmu = 'u', /* print MMU ops */ + Dctxt = 'c', /* dump context in and out */ + Darm = 'w', /* arm insts and so */ + Dmem = 'y', /* memory ops */ + Dfs = 'k', /* filesystem ops */ + DAll = 'A' +}; + +extern int dprint(char d, char *fmt, ...); +extern void dumpbuf(char d, uchar *buf, int bufsz); diff --git a/sys/src/cmd/jtagfs/genrtab.c b/sys/src/cmd/jtagfs/genrtab.c new file mode 100644 index 0000000000..a60e0291cd --- /dev/null +++ b/sys/src/cmd/jtagfs/genrtab.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "debug.h" + +static uchar +reverse(uchar c) +{ + uchar rc; + int i, j, ns; + + rc = 0; + for(i = 0, j = 1; i < 8; i++, j <<= 1){ + ns = (7 - 2*i); + if( ns < 0){ + ns = -ns; + rc |= (c&j) >> ns; + } + else + rc |= (c&j) << ns; + } + return rc; +} + + +void +main(int , char *[]) +{ + int i; + + print("/* Generated automatically, *DO NOT EDIT* */\n\n"); + print("#include \n"); + print("#include \n\n"); + print("uchar rtab[256]=\n"); + print("{\n\t"); + for(i = 0; i < 256; i++){ + print("%#2.2ux, ", reverse(i)); + if(i != 0 && (i + 1) % 8 == 0) + print("\n\t"); + } + print("\n};"); + exits(nil); +} + diff --git a/sys/src/cmd/jtagfs/guide b/sys/src/cmd/jtagfs/guide new file mode 100644 index 0000000000..8612c627c0 --- /dev/null +++ b/sys/src/cmd/jtagfs/guide @@ -0,0 +1,85 @@ +hwbpset(0x60800c28, 0x3ff) +hwbpset(_vpabt, 0x0) +hwbpset(_vsvc, 0x0) +hwbpset(_vdabt, 0x0) +hwbpset(_vund, 0x0) +hwbpset(_virq, 0x0) +veccatch("SPDIF") + +dump(_vrst, 30, "Xi") + +usb/serial + +echo b115200 s15 l8 pn > /dev/eiaU3.1/eiaUctl +window -m +window -m +con /dev/eiaU3.1/eiaU + +echo debug . > /n/jtagfs/ctl + +window -scroll -r 0 5 700 369 plug + + +kill 8.tagfs|rc +/usr/paurea/src/jtag/8.jtagfs /dev/jtag*/jtag +echo reset > /n/jtagfs/ctl + +#start the jtag +echo cpuid > /n/jtagfs/ctl +echo breakpoint 0xc02dc244 0x0 > /n/jtagfs/ctl + +echo breakpoint 0x0062822c 0x00000000 > /n/jtagfs/ctl + echo breakpoint 0xc0208124 0xffff0000 > /n/jtagfs/ctl + +#see debug.h for the string +echo debugstr kc> /n/jtagfs/ctl + +BR 9 , pcadjust -5 works well +BR 6, 2 works well + +cat /n/jtagfs/ctl +echo stop > /n/jtagfs/ctl +echo start > /n/jtagfs/ctl + + echo debustr ew > /n/jtagfs/ctl +#/n/jtagfs/mem can be used to read raw memory at an arbitrary offset + + +# set entry on exceptions +# changed so that turn it is turn on in debug state +# + +#wait for entry in debug state (with timeout) + + +echo veccatch D > /n/jtagfs/ctl + +echo waitstop > /n/jtagfs/ctl +echo start > /n/jtagfs/ctl + + +window -scroll -r 0 5 700 369 plug + +bind /n/jtagfs /proc/1 +echo stop > /n/jtagfs/ctl +echo debug ky > /proc/1/ctl +acid -l /usr/paurea/src/jtag/acidjtag -k 1 /arm/s9plug + +_tiki: + //B _tiki +dump(*R15, 4, "X") +dump(*R15, 4, "Xi") +dump(0xc03207fc, 4, "X") +mem(0x00621120, "X") +regs() +troff -man jtagfs.man|page -w + +bootcmd=bootp ; bootp; tftp 0x1000 /srv/tftp/plugini ; bootp ; tftp 0x800000 /srv/tftp/9plug ; go 0x800000 + + + +boot linux: + +setenv bootargs $(bootargs) $(mtdpartitions) $(bootargs_root); +nand read.e 0x00800000 0x00100000 0x00400000; +bootm 0x00800000; diff --git a/sys/src/cmd/jtagfs/h2acid b/sys/src/cmd/jtagfs/h2acid new file mode 100644 index 0000000000..c34fa03f28 --- /dev/null +++ b/sys/src/cmd/jtagfs/h2acid @@ -0,0 +1,30 @@ +#!/bin/awk -f + +# cat /sys/src/9/kw/mem.h /sys/src/9/kw/arm.h|h2acid|grep -v define + +BEGIN{ + isparen=0 +} + + +/#define ?[^ \(]+\(/{ + isparen=1 + fullname=$0 + sub(/\/\*.*\*\//, "", fullname) + sub(/\/\/.*/, "", fullname) + sub(/[ ]+$/, "", fullname); + name=$2 + sub(/\(.*/, "", name); + params=fullname + sub(/[^\(]+\(/, "", params) + sub(/\).*/, "", params); + val=fullname + sub(/[^\)]+\)/, "", val); + print("\ndefn", name"("params")", " {\n\t"name "res = " val ";\n}\n") +} + +/#define.*/ && !isparen{ + print($2 " = " $3 ";"); +} + +/.*/{ isparen = 0} diff --git a/sys/src/cmd/jtagfs/icert.c b/sys/src/cmd/jtagfs/icert.c new file mode 100644 index 0000000000..727303920c --- /dev/null +++ b/sys/src/cmd/jtagfs/icert.c @@ -0,0 +1,970 @@ +#include +#include +#include +#include "chain.h" +#include "debug.h" +#include "tap.h" +#include "lebo.h" +#include "bebo.h" +#include "jtag.h" +#include "icert.h" +#include "mpsse.h" +#include "/sys/src/9/kw/arm.h" +#include "mmu.h" + +/* + * Read, paying special atention to anything called + * embedded-ice/debug of the arm core, normally + * there is a chapter called Debug or Debugging and some + * details sprinkled around. + * - ARM9E-S "Technical Reference Manual" + * - ARM7TDMI-S "Core Technical Reference Manual" + * - Open On-Chip Debugger thesis + * "Design and Implementation of an On-Chip Debug for Embedded + * Target Systems" + * - Application note 205 "Writing JTAG Sequences for Arm 9 Processors" + * The bit ordering on the last one is confusing/wrong, but the + * procedures for doing things clarify a lot. + */ + + +/* + * BUG: print pack and unpack could be generated automatically + * except for the wild endianness of the instr. Minilanguage? + */ + +static char * +printech1(EiceChain1 *ec1, char *s, int ssz) +{ + char *e, *te; + + te = s + ssz -1; + + e = seprint(s, te, "rwdata: %#8.8ux\n", ec1->rwdata); + e = seprint(e, te, "wptandbkpt: %1.1d\n", ec1->wptandbkpt); + e = seprint(e, te, "sysspeed: %1.1d\n", ec1->sysspeed); + e = seprint(e, te, "instr: %#8.8ux\n", ec1->instr); + return e; +} + +static int +packech1(Chain *ch, EiceChain1 *ec1) +{ + EiceChain1 lec; + uchar unused; + + unused = 0; + + lec.instr = hmsbputl(&ec1->instr); + hbeputl(&lec.rwdata, ec1->rwdata); + + putbits(ch, &lec.rwdata, RWDataSz); + putbits(ch, &unused, 1); + putbits(ch, &lec.wptandbkpt, WpTanDBKptSz); + + putbits(ch, &ec1->sysspeed, SysSpeedSz); + putbits(ch, &lec.instr, InstrSz); + + return 0; +} + +static int +unpackech1(EiceChain1 *ec1, Chain *ch) +{ + uchar unused; + + unused = 0; + + + getbits(&ec1->rwdata, ch, RWDataSz); + getbits(&unused, ch, 1); + getbits(&ec1->wptandbkpt, ch, WpTanDBKptSz); + getbits(&ec1->sysspeed, ch, SysSpeedSz); + getbits(&ec1->instr, ch, InstrSz); + + ec1->instr = msbhgetl(&ec1->instr); + ec1->rwdata = lehgetl(&ec1->rwdata); + + return 0; +} + + +static char * +printech2(EiceChain2 *ec2, char *s, int ssz) +{ + char *e, *te; + + te = s + ssz -1; + + e = seprint(s, te, "data: %#8.8ux\n", ec2->data); + e = seprint(e, te, "addr: %#2.2ux\n", ec2->addr); + e = seprint(e, te, "rw: %1.1d\n", ec2->rw); + return e; +} + +static int +valregaddr(uchar addr) +{ + if(addr <= CtlMskReg) + return 1; + if( (addr&Wp0) <= CtlMskReg || (addr&Wp1) <= CtlMskReg) + return 1; + return 0; +} + +static int +packech2(Chain *ch, EiceChain2 *ec2) +{ + EiceChain2 lec; + + if(!valregaddr(ec2->addr)) + return -1; + + hleputl(&lec.data, ec2->data); + + putbits(ch, &lec.data, DataSz); + putbits(ch, &ec2->addr, AddrSz); + putbits(ch, &ec2->rw, RWSz); + return 0; +} + +static int +unpackech2(EiceChain2 *ec2, Chain *ch) +{ + + getbits(&ec2->data, ch, DataSz); + getbits(&ec2->addr, ch, AddrSz); + getbits(&ec2->rw, ch, RWSz); + + if(!valregaddr(ec2->addr)) + return -1; + + ec2->data = lehgetl(&ec2->data); + + return 0; +} + + +static char * +printwp(EiceWp *wp, char *s, int ssz) +{ + char *e, *te; + + te = s + ssz -1; + + e = seprint(s, te, "addrval: %#8.8ux\n", wp->addrval); + e = seprint(e, te, "addmsk: %#8.8ux\n", wp->addrmsk); + e = seprint(e, te, "dataval: %#8.8ux\n", wp->dataval); + e = seprint(e, te, "datamsk: %#8.8ux\n", wp->datamsk); + + e = seprint(e, te, "ctlval: %#4.4ux\n", wp->ctlval); + e = seprint(e, te, "ctlmsk: %#2.2ux\n", wp->ctlmsk); + return e; +} + +static char * +printregs(EiceRegs *regs, char *s, int ssz) +{ + char *e, *te, i; + + te = s + ssz -1; + + e = seprint(s, te, "debug: %#2.2ux\n", regs->debug); + e = seprint(e, te, "debsts: %#2.2ux\n", regs->debsts); + e = seprint(e, te, "veccat: %#2.2ux\n", regs->veccat); + e = seprint(e, te, "debcomctl: %#2.2ux\n", regs->debcomctl); + e = seprint(e, te, "debcomdata: %#8.8ux\n", regs->debcomdata); + + for(i = 0; iwp); i++) + e = printwp(regs->wp + i, e, ssz+(s-e)); + return e; +} + +static u32int +unpackcpuid(uchar *v) +{ + u32int id; + + id = lehgetl(v); + return id; +} + +static void +prcpuid(u32int id) +{ + + fprint(2, "ID: %#8.8ux\n", id); + fprint(2, "Must be 1: %d\n", id&1); + fprint(2, "Manufacturer id: %#lux\n", MANID(id)); + fprint(2, "Part no: %#lux\n", PARTNO(id)); + fprint(2, "Version: %#lux\n", VERS(id)); + return; +} + + + +int +setinst(JMedium *jmed, uchar inst, int nocommit) +{ + int res, com; + ShiftTDesc req; + uchar buf[1+ShiftMarg]; + + memset(buf, 0, 5); + buf[0] = inst; + com = 0; + + dprint(Djtag, "Setting jtag instr: %#2.2ux, commit: %d\n", + inst, !nocommit); + if(nocommit) + com = ShiftNoCommit; + req.reg = TapIR; + req.buf = buf; + req.nbits = InLen; + req.op = ShiftOut|com; + + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0){ + werrstr("setinst: shifting instruction %#2.2ux for jtag", inst); + return -1; + } + return res; +} + +int +icesetreg(JMedium *jmed, int regaddr, u32int val) +{ + Chain ch; + ShiftTDesc req; + EiceChain2 ec2; + char debugstr[128]; + int res; + + dprint(Dice, "Set eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, val); + ec2.data = val; + ec2.addr = regaddr; + ec2.rw = 1; + memset(&ch, 0, sizeof ch); + + + res = packech2(&ch, &ec2); + if(res < 0) + return -1; + if(debug[Dchain] || debug[DAll]){ + printech2(&ec2, debugstr, sizeof debugstr); + fprint(2, "%s", debugstr); + printchain(&ch); + } + req.reg = TapDR; + req.buf = ch.buf; + req.nbits = EiceCh2Len; + req.op = ShiftOut; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + + return 0; +} + + +u32int +icegetreg(JMedium *jmed, int regaddr) +{ + Chain ch; + ShiftTDesc req; + int res; + EiceChain2 ec2; + char debugstr[128]; + + ec2.data = 0; + ec2.addr = regaddr; + ec2.rw = 0; + memset(&ch, 0, sizeof ch); + + res = packech2(&ch, &ec2); + if(res < 0) + return -1; + if(debug[Dchain] || debug[DAll]){ + printech2(&ec2, debugstr, sizeof debugstr); + fprint(2, "%s", debugstr); + printchain(&ch); + } + req.reg = TapDR; + req.buf = ch.buf; + req.nbits = EiceCh2Len; + req.op = ShiftOut; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + req.reg = TapDR; + req.buf = ch.buf; + req.nbits = EiceCh2Len; + req.op = ShiftOut|ShiftIn; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + ch.b = 0; + ch.e = EiceCh2Len; + res = unpackech2(&ec2, &ch); + if(res < 0) + return -1; + if(debug[Dice] || debug[DAll]){ + printchain(&ch); + printech2(&ec2, debugstr, sizeof debugstr); + fprint(2, "Get eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, ec2.data); + } + return ec2.data; +} + +int +setchain(JMedium *jmed, int commit, uchar chain) +{ + ShiftTDesc req; + uchar data[1+ShiftMarg]; + int res, com; + + dprint(Dice, "Set chain %d, chain before %d\n", chain, jmed->currentch); + if(jmed->currentch == chain) + return 0; + res = setinst(jmed, InScanN, 1); + if(res < 0) + return -1; + data[0] = chain; + com = 0; + if(!commit) + com = ShiftNoCommit; + req.reg = TapDR; + req.buf = data; + req.nbits = 5; + req.op = ShiftPauseIn|ShiftOut|com; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + res = setinst(jmed, InTest, 1); + if(res < 0) + return -1; + jmed->currentch = chain; + return 0; +} + + +int +armgofetch(JMedium *jmed, u32int instr, int sysspeed) +{ + char debugstr[128]; + ShiftTDesc req; + EiceChain1 ec1; + Chain ch; + int res; + + ec1.instr = instr; + ec1.sysspeed = sysspeed; + ec1.wptandbkpt = 0; + ec1.rwdata = 0; + memset(&ch, 0, sizeof (Chain)); + res = packech1(&ch, &ec1); + if(res < 0) + return -1; + if(debug[Dchain] || debug[DAll]){ + printech1(&ec1, debugstr, sizeof debugstr); + fprint(2, "%s", debugstr); + printchain(&ch); + } + req.reg = TapDR; + req.buf = ch.buf; + req.nbits = ch.e-ch.b; + req.op = ShiftOut|ShiftPauseOut|ShiftPauseIn; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + return 0; + +} + +int +armgetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst) +{ + ShiftTDesc req; + int i, res, flags; + uchar *buf; + ShiftRDesc *replies; + + dprint(Darm, "Exec: %#8.8ux\n", inst); + replies = mallocz(nregs*sizeof(ShiftRDesc), 1); + if(replies == nil) + sysfatal("read, no mem %r"); + buf = mallocz(EiceCh1Len+ShiftMarg, 1); + if(buf == nil) + sysfatal("read, no mem %r"); + armgofetch(jmed, inst, 0); + /* INST in decode stage */ + armgofetch(jmed, ARMNOP, 0); + /* INST in execute stage */ + armgofetch(jmed, ARMNOP, 0); + /* INST in access stage */ + flags = ShiftAsync|ShiftIn|ShiftPauseIn|ShiftPauseOut; + for(i = 0; i < nregs; i++){ + req.reg = TapDR; + req.buf = buf; + req.nbits = EiceCh1Len; + req.op = flags; + res = tapshift(jmed, &req, &replies[i], jmed->tapcpu); + if(res < 0) + return -1; + } + for(i = 0; i < nregs; i++){ + res = jmed->rdshiftrep(jmed, buf, &replies[i]); + if(res < 0) + return -1; + regs[i] = *(u32int *)buf; + dprint(Darm, "Read [%d]: %#8.8ux\n", i, regs[i]); + } + armgofetch(jmed, ARMNOP, 0); + /* INST in writeback stage */ + armgofetch(jmed, ARMNOP, 0); + /* INST end, pipeline full of NOPs */ + + free(buf); + free(replies); + return 0; +} + +int +armsetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst) +{ + ShiftTDesc req; + int i, res, flags; + uchar *buf; + + ShiftRDesc *replies; + + dprint(Darm, "Exec: %#8.8ux\n", inst); + replies = mallocz(nregs*sizeof(ShiftRDesc), 1); + if(replies == nil) + sysfatal("read, no mem %r"); + buf = mallocz(EiceCh1Len+ShiftMarg, 1); + if(buf == nil) + sysfatal("readregs, no mem %r"); + armgofetch(jmed, inst, 0); + /* STMIA in decode stage */ + armgofetch(jmed, ARMNOP, 0); + /* STMIA in execute stage */ + armgofetch(jmed, ARMNOP, 0); + /* STMIA in memory acess stage */ + flags = ShiftOut|ShiftPauseIn|ShiftPauseOut; + for(i = 0; i < nregs; i++){ + *(u32int *)buf = regs[i]; + dprint(Darm, "Set [%d]: %#8.8ux\n", i, regs[i]); + req.reg = TapDR; + req.buf = buf; + req.nbits = EiceCh1Len; + req.op = flags; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + return -1; + } + armgofetch(jmed, ARMNOP, 0); + /* STMIA in writeback stage */ + armgofetch(jmed, ARMNOP, 0); + /* STMIA end, pipeline full of NOPs */ + + free(buf); + free(replies); + return 0; +} + +/* reads r0-r15 to regs if bits of mask are 1 */ +static int +armgetregs(JMedium *jmed, u32int mask, u32int *regs) +{ + int ireps, nregs, r, i; + u32int *regrd; + + nregs = 0; + ireps = 0; + for(i = 0; i < 16; i++){ + if( (1 << i) & mask) + nregs++; + } + regrd = mallocz(nregs*sizeof(u32int), 1); + if(regrd == nil) + sysfatal("read, no mem %r"); + + r = armgetexec(jmed, nregs, regrd, ARMSTMIA|mask); + if(r < 0) + return -1; + + for(i = 0; i < 16; i++){ + if( (1 << i) & mask){ + regs[i] = regrd[ireps++]; + dprint(Darm, "rd register r%d: %#8.8ux\n", i, regs[i]); + } + } + free(regrd); + return 0; +} +/* sets r0-r15 to regs if bits of mask are 1 */ +int +armsetregs(JMedium *jmed, int mask, u32int *regs) +{ + int ireps, nregs, r, i; + u32int *regrw; + + nregs = 0; + ireps = 0; + for(i = 0; i < 16; i++){ + if( (1 << i) & mask) + nregs++; + } + regrw = mallocz(nregs*sizeof(u32int), 1); + if(regrw == nil) + sysfatal("read, no mem %r"); + for(i = 0; i < 16; i++){ + if( (1 << i) & mask){ + regrw[ireps++] = regs[i]; + dprint(Darm, "wr register r%d: %#8.8ux\n", i, regs[i]); + } + } + r = armsetexec(jmed, nregs, regrw, ARMLDMIA|mask); + if(r < 0) + return -1; + + free(regrw); + return 0; +} + +static void +armprctxt(ArmCtxt *ctxt) +{ + int i; + + fprint(2, "Arm is in debug: %d\nregs\n", ctxt->debug); + for(i = 0; i < 16; i++) + fprint(2, "r%d: %#8.8ux\n", i, ctxt->r[i]); + fprint(2, "cpsr: %#8.8ux\n", ctxt->cpsr); + fprint(2, "spsr: %#8.8ux\n", ctxt->spsr); +} + +char * +armsprctxt(ArmCtxt *ctxt, char *s, int ssz) +{ + char *e, *te; + int i; + + te = s + ssz -1; + + e = seprint(s, te, "Arm is in debug: %d\nregs\n", ctxt->debug); + for(i = 0; i < 16; i++) + e = seprint(e, te, "r%d: %#8.8ux\n", i, ctxt->r[i]); + e = seprint(e, te, "cpsr: %#8.8ux\n", ctxt->cpsr); + e = seprint(e, te, "spsr: %#8.8ux\n", ctxt->spsr); + return e; +} + +static char dbgstr[4*1024]; + +int +armsavectxt(JMedium *jmed, ArmCtxt *ctxt) +{ + int res; + + res = setchain(jmed, 0, 1); + if(res < 0) + goto Error; + + res = armgetregs(jmed, 0xffff, ctxt->r); + if(res < 0) + goto Error; + res = armgofetch(jmed, ARMMRSr0CPSR, 0); + if(res < 0) + goto Error; + res = armgetexec(jmed, 1, &ctxt->cpsr, ARMSTMIA|0x0001); + if(res < 0) + goto Error; + res = armgofetch(jmed, ARMMRSr0SPSR, 0); + if(res < 0) + goto Error; + res = armgetexec(jmed, 1, &ctxt->spsr, ARMSTMIA|0x0001); + if(res < 0) + goto Error; + res = mmurdregs(jmed, ctxt); + if(res < 0){ + werrstr("mmurdregs %r"); + return -1; + } + if(debug[Dmmu] || debug[DAll]){ + printmmuregs(ctxt, dbgstr, sizeof dbgstr); + dprint(Dfs, "MMU state:\n%s\n", dbgstr); + } + if(debug[Dctxt] || debug[DAll]){ + fprint(2, "Arm save ctxt\n"); + armprctxt(ctxt); + } + return 0; +Error: + return -1; +} + +static int +armjmpctxt(JMedium *jmed, ArmCtxt *ctxt) +{ + int res; + + if(debug[Dctxt] || debug[DAll]){ + fprint(2, "Arm jmp ctxt\n"); + armprctxt(ctxt); + } + res = armsetexec(jmed, 1, &ctxt->cpsr, ARMLDMIA|0x0001); + if(res < 0) + return -1; + res = armgofetch(jmed, ARMMSRr0CPSR, 0); + if(res < 0) + return -1; + /* it is quite important this is the last instr for PC calculations */ + ctxt->r[15] += ctxt->pcadjust; + res = armsetregs(jmed, 0xffff, ctxt->r); + if(res < 0) + return -1; + + return 0; +} + + +int +armfastexec(JMedium *jmed, u32int inst) +{ + int res; + + dprint(Darm, "Exec: %#8.8ux\n", inst); + res = armgofetch(jmed, ARMNOP, 0); + if(res < 0) + return -1; + + res = armgofetch(jmed, ARMNOP, 0); + if(res < 0) + return -1; + res = armgofetch(jmed, ARMNOP, 0); + if(res < 0) + return -1; + res = armgofetch(jmed, inst, 0); + if(res < 0) + return -1; + res = armgofetch(jmed, ARMNOP, 1); + if(res < 0) + return -1; + return 0; +} + +int +icedebugstate(JMedium *jmed) +{ + int res; + + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return 0; + return icegetreg(jmed, DebStsReg) & DBGACK; +} + +int +icewaitdebug(JMedium *jmed) +{ + int i, res; + + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + + for(i = 0; i < 20; i ++){ + if(icedebugstate(jmed)) + break; + sleep(100); + } + if( i == 20) + return -1; + + icesetreg(jmed, DebugCtlReg, INTDIS|DBGACK); /* clear RQ */ + return 0; +} + +int +armrdmemwd(JMedium *jmed, u32int addr, u32int *data, int sz) +{ + int res; + u32int d, byte; + + res = setchain(jmed, ChCommit, 1); + if(res < 0) + sysfatal("setchain %r"); + byte = 0; + if(sz == 1) + byte = BYTEWDTH; + /* load address in r0 */ + res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001); + if(res < 0) + return -1; + + /* LDR r1, [r0] place data in r1 */ + res = armfastexec(jmed, byte|ARMLDRindr1xr0); + if(res < 0) + return -1; + + setinst(jmed, InRestart, 0); + res = icewaitdebug(jmed); + if(res < 0) + return -1; + res = setchain(jmed, ChCommit, 1); + if(res < 0) + sysfatal("setchain %r"); + armgetexec(jmed, 1, &d, byte|ARMSTMIA|0x0002); + + *data = d; + dprint(Dmem, "Read data %#8.8ux addr %#8.8ux \n", + d, addr); + return sz; +} + +int +armwrmemwd(JMedium *jmed, u32int addr, u32int data, int sz) +{ + int res; + u32int byte; + + dprint(Dmem, "Write data %#8.8ux addr %#8.8ux \n", + data, addr); + res = setchain(jmed, ChCommit, 1); + if(res < 0) + sysfatal("setchain %r"); + byte = 0; + if(sz == 1) + byte = BYTEWDTH; + /* load address in r0 */ + res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001); + if(res < 0) + return -1; + /* load data in r1 */ + res = armsetexec(jmed, 1, &data, byte|ARMLDMIA|0x0002); + if(res < 0) + return -1; + + /* STR [r0], r1 place data in [r0] */ + res = armfastexec(jmed, ARMSTRindxr0r1); + if(res < 0) + return -1; + + setinst(jmed, InRestart, 0); + res = icewaitdebug(jmed); + if(res < 0) + return -1; + return sz; +} + + +u32int +armidentify(JMedium *jmed) +{ + uchar *buf; + ShiftTDesc req; + u32int cpuid; + int res, i; + + //if(jmed->motherb == Sheeva) + // jmed->resets(jmed->mdata, 0, 1); + buf = malloc(sizeof(u32int)*0x100+ ShiftMarg); + if(buf == nil) + sysfatal("memory"); + + for(i = 0; i < sizeof(u32int)*0x100; i++) + buf[i] = i; /* just a pattern to see in debugging */ + + req.reg = TapDR; + req.buf = buf; + req.nbits = sizeof(u32int)*0x100; /* Bug by 8? */ + req.op = ShiftOut|ShiftIn; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0){ + free(buf); + return ~0; + } + //if(jmed->motherb == Sheeva) + // jmed->resets(jmed->mdata, 0, 0); + cpuid = unpackcpuid(buf); + if(cpuid != jmed->taps[jmed->tapcpu].hwid){ + fprint(2, "cpuid: %#8.8ux != %#8.8ux\n", cpuid, jmed->taps[jmed->tapcpu].hwid); + free(buf); + return ~0; + } + prcpuid(cpuid); + free(buf); + return cpuid; +} + +/* see if the fixed bypass value is ok */ +int +armbpasstest(JMedium *jmed) +{ + ShiftTDesc req; + uchar buf[2+ShiftMarg]; + int res; + + memset(buf, 0xff, sizeof(buf)); + req.reg = TapIR; + req.buf = buf; + req.nbits = 2+InLen; + req.op = ShiftOut|ShiftIn; + res = tapshift(jmed, &req, nil, jmed->tapcpu); + if(res < 0) + sysfatal("jmed->regshift %r"); + if((buf[0] & 0xf) != 0x1){ + fprint(2, "bad bypass: %#2.2ux\n", buf[0]); + return -1; + } + + return 0; +} + +/* BUG: werrstr in the inner functions to indicate error, warnings... */ + + +int +icewaitentry(JMedium *jmed, ArmCtxt *ctxt) +{ + int res; + + if(ctxt->debugreas == NoReas){ + werrstr("No debug activated"); + return -1; + } + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + res = icewaitdebug(jmed); + if(res < 0) + return -1; + + res = setchain(jmed, ChNoCommit, 1); + if(res < 0) + return -1; + + /* BUG: should change to Arm from Thumb or Jazelle, adjust, keep PC. + * If I ever come down to doing this, Remember to repeat Thumb inst + * to be endian independant... + */ + res = armsavectxt(jmed, ctxt); + if(res < 0) + return -1; + ctxt->debug = 1; + + ctxt->pcadjust = 0; /* BUG: Thumb not impl */ + ctxt->r[15] -= 6*ArmInstSz; + switch(ctxt->debugreas){ + case BreakReas: + case VeccatReas: + ctxt->pcadjust = -2*ArmInstSz; + break; + case DebugReas: + break; + } + return 0; +} + +int +iceenterdebug(JMedium *jmed, ArmCtxt *ctxt) +{ + int res; + + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + + //if(jmed->motherb == Sheeva) + // jmed->resets(jmed->mdata, 0, 1); + if(!(icegetreg(jmed, DebStsReg) & DBGACK)){ + icesetreg(jmed, DebugCtlReg, DBGRQ); /* freeze */ + } + + //if(jmed->motherb == Sheeva) + // jmed->resets(jmed->mdata, 0, 0); + ctxt->debugreas = DebugReas; + res = icewaitentry(jmed, ctxt); + if(res < 0) + return -1; + ctxt->exitreas = NoReas; + return 0; +} + + +/* + * The branch is the way to exit debug permanently + * no branch and you fall back to debug + * The context needs to be restored (some register needs + * to be written), don't know why + * but you will fall back to debug if not, no matter what doc says. + * The bypass is not mentioned to be necessary anywhere, but + * the feroceon will not restart without it. + */ + +int +iceexitdebug(JMedium *jmed, ArmCtxt *ctxt) +{ + int res, i; + uchar wctl; + u32int sts; + + res = setchain(jmed, ChCommit, 1); + if(res < 0) + return -1; + + res = armjmpctxt(jmed, ctxt); + if(res < 0) + return -1; + + /* 4 entry to debug, Store(does not count) 3 NOPS, Branch = -8 */ + res = armfastexec(jmed, ARMBRIMM|0xfffffb); + if(res < 0) + return -1; + + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + + wctl = icegetreg(jmed, Wp0|CtlValReg); + if(ctxt->exitreas != BreakReqReas) + icesetreg(jmed, Wp0|CtlValReg, wctl&~EnableWPCtl); + + if(ctxt->exitreas != VeccatReqReas) + icesetreg(jmed, VecCatReg, 0); + icesetreg(jmed, DebugCtlReg, 0); /* clear all,*/ + setinst(jmed, InBypass, 0); + setinst(jmed, InRestart, 0); + sleep(100); + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + + for(i = 0; i < 10; i ++){ + sts = icegetreg(jmed, DebStsReg); + if((sts&DBGACK) == 0) + break; + sleep(100); + } + if( i == 10) + return -1; + + switch(ctxt->exitreas){ + case NoReas: + ctxt->debugreas = NoReas; + break; + case VeccatReqReas: + ctxt->debugreas = VeccatReas; + break; + case BreakReqReas: + ctxt->debugreas = BreakReas; + break; + default: + ctxt->debugreas = NoReas; + break; + } + ctxt->debug = 0; + return 0; +} diff --git a/sys/src/cmd/jtagfs/icert.h b/sys/src/cmd/jtagfs/icert.h new file mode 100644 index 0000000000..36b9d2855e --- /dev/null +++ b/sys/src/cmd/jtagfs/icert.h @@ -0,0 +1,273 @@ +typedef struct ArmCtxt ArmCtxt; +typedef struct EiceChain1 EiceChain1; +typedef struct EiceChain2 EiceChain2; +typedef struct EiceRegs EiceRegs; +typedef struct EiceWp EiceWp; +typedef struct MMURegs MMURegs; +typedef struct PackedSz PackedSz; + +enum{ + /* + * This is an arm 926, except no MOE, only 1 Wpoint + * I think this means "mcr access" + * for the MMU. It would be good knowing for real + * what the good doc for it is or if it is just + * random mix and match!!. + */ + FeroceonId = 0x20a023d3, + + /* Looks like a pxa/feroceon frankenstein */ + ArmadaId = 0x304113d3, + + ArmInstSz = 4, + ThumbInstSz = 2, +}; + + +/* instructions for the IR, 4 bits */ +enum { + InExtest = 0x0, + InScanN = 0x2, /* shift the scan chain id, 5 bits */ + InSampPre = 0x3, + InRestart = 0x4, + InHighZ = 0x7, + InClampZ = 0x9, + InTest = 0xc, + InIdCode = 0xe, + InBypass = 0xf, + + InGuruTapctl = 0x98, + InGuruLen = 9, + DrGuruTapctl = 0x00a, + DrGuruLen = 16, + + InLen = 4, /* bits */ + EiceCh1Len = 67, /* bits */ + EiceCh2Len = 38, /* bits */ +}; + +/* sizes are in bits */ +#define WpN(nreg, field) ((nreg<<(nreg))|(field)) + +enum { + + /* chain 1 */ + InstrSz = 32, + SysSpeedSz = 1, + WpTanDBKptSz = 1, + Ch1ResvdSz, + RWDataSz = 32, + + + /* chain 2, here registers are directed through addr */ + DataSz = 32, + AddrSz = 5, + RWSz = 1, + + DebugCtlReg = 0x00, + DebStsReg = 0x01, + VecCatReg = 0x02, + DebComCtlReg = 0x04, + DebComDataReg = 0x05, + + Wp0 = 1<<4, /* Wp0|AddrValReg and so on */ + Wp1 = 1<<5, /* Wp1|AddrValReg and so on */ + + AddrValReg = 0x00, + AddrMskReg = 0x01, + DataValReg = 0x02, + DataMskReg = 0x03, + CtlValReg = 0x04, + CtlMskReg = 0x05, + + /* sizes in bits */ + DebugCtlRegSz = 6, + DebStsRegSz = 10, /* in feroceon 5, no Moe */ + VecCatRegSz = 8, + DebComCtlRegSz = 6, + DebComDataRegSz = 32, + + AddrValRegSz = 32, + AddrMskRegSz = 32, + DataValRegSz = 32, + DataMskRegSz = 32, + CtlValRegSz = 9, + CtlMskRegSz = 8, + + /* DebugCtlReg (write) */ + DBGACK = 1, /* I am dealing with debug mode */ + DBGRQ = 1<<1, /* Enter debug mode */ + INTDIS = 1<<2, /* Disable interrupts */ + SBZ0 = 1<<3, /* Should be Zero */ + MONENAB = 1<<4, /* Monitor mode/halt mode */ + EICEDISAB = 1<<5, /* Power down */ + + /* DebugSTSReg (read) + * two first bits same as ctl + */ + IFEN = 1<<2, /* Are interrupts enabled */ + SYSCOMP = 1<<3, /* Memory access complete */ + ITBIT = 1<<4, /* Thumb/Arm mode */ + SBZ1 = 1<<5, + MOEMSK = 0xf<<6, /* Method of entry */ + + /* VecCatReg (write), one bit per exception to catch */ + ResetCat = 1, + UndefCat = 1<<1, + SWICat = 1<<2, + PAbortCat = 1<<3, + DAbortCat = 1<<4, + RsvdCat = 1<<5, + IrqCat = 1<<6, + FiqCat = 1<<7, + + /* + * Watchpoint control registers: + * CtlValReg CtlMskReg + * Bit 1 in Msk makes condition ignored. + */ + + /* Data version of CtlValReg bits 6, 7, 8 are shared */ + DnRWWPCtl = 1, /* 0 access is read 1 write */ + DmasWPCtlMsk = 3<<1, /* this two bits represent size of access */ + DataWPCtl = 1<<3, /* compare against data/0 is inst */ + DnTransWPCtl = 1<<4, /* 0 user 1 privileged */ + DbgExtWPCtl = 1<<5, /* External condition for watchpoint */ + ChainWPCtl = 1<<6, /* Chain together watchpoints */ + RangeWPCtl = 1<<7, /* Range connecting watchpoints together */ + EnableWPCtl = 1<<8, /* Cannot be masked */ + /* Inst version of CtlValReg */ + IgnWPCtl = 1, /* ignored */ + ITbitWPCtlMsk = 3<<1, /* 1 Thumb */ + IJbitWPCtl = 1<<2, /* 1 Jazelle */ + InTransWPCtl = 1<<4, /* 0 user 1 privileged */ + + + /* Id code */ + ManIdSz = 11, + PartNoSz = 16, + VerSz = 4, + +}; + +enum{ + ChNoCommit = 0, + ChCommit = 1, +}; + +struct PackedSz { + uchar unpkSz; + uchar pkSz; +}; + +/* + * The bit ordering on this one is peculiar, see packech1() + * in particular the instruction is upside down, + */ + +struct EiceChain1 { + u32int instr; /* 32 bits */ + uchar sysspeed; /* 1 bit */ + uchar wptandbkpt; /* 1 bit */ + /* 1 bit rsvd */ + u32int rwdata; /* 32 bits */ +}; + +struct EiceChain2 { + u32int data; /* 32 bits */ + uchar addr; /* 5 bits */ + uchar rw; /* 1 bit */ +}; + +struct EiceWp { + u32int addrval; /* 32 bits */ + u32int addrmsk; /* 32 bits */ + u32int dataval; /* 32 bits */ + u32int datamsk; /* 32 bits */ + u16int ctlval; /* 9 bits */ + uchar ctlmsk; /* 8 bits */ +}; + +struct EiceRegs { + uchar debug; /* 4 bits */ + uchar debsts; /* 5 bits */ + uchar veccat; /* 8 bits */ + uchar debcomctl; /* 6 bits */ + u32int debcomdata; /* 32 bits */ + EiceWp wp[2]; +}; + +enum{ + ARMSTMIA = 0xe8800000, + ARMLDMIA = 0xe8900000, + BYTEWDTH = 0x00400000, + ARMLDRindr1xr0 = 0xe5901000, /* LDR r1, [r0] || [r0]->r1*/ + ARMSTRindxr0r1 = 0xe5801000, /* STR [r0], r1 || r1->[r0] */ + ARMNOP = 0xe1a08008, + ARMMRSr0CPSR = 0xE10F0000, + ARMMSRr0CPSR = 0xE12FF000, + SPSR = 1<<22, + ARMMRSr0SPSR = ARMMRSr0CPSR|SPSR, + ARMMSRr0SPSR = ARMMSRr0CPSR|SPSR, + ARMBRIMM = 0xea000000, +}; + + +#define MOE(dbgreg) (((dbgreg)&MOEMSK)>>6); + +#define MANID(id) (((id)>>1)&MSK(ManIdSz)) +#define PARTNO(id) (((id)>>ManIdSz+1)&MSK(PartNoSz)) +#define VERS(id) (((id)>>ManIdSz+1+PartNoSz)&MSK(VerSz)) + +struct MMURegs { + u32int cpid; /* main ID */ + u32int control; /* control */ + u32int ttb; /* translation table base */ + u32int dac; /* domain access control */ + u32int fsr; /* fault status */ + u32int far; /* fault address */ + u32int ct; /* cache type */ + u32int pid; /* address translation pid */ +}; + +enum{ + NoReas, + BreakReqReas, + BreakReas, + VeccatReqReas, + VeccatReas, + DebugReas, +}; + +struct ArmCtxt { + int pcadjust; + int debug; + int debugreas; + int exitreas; + int cpuid; + u32int r[16]; + u32int cpsr; + u32int spsr; + MMURegs; +}; + +extern int armbpasstest(JMedium *jmed); +extern int armfastexec(JMedium *jmed, u32int inst); +extern int armgetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst); +extern int armgofetch(JMedium *jmed, u32int instr, int sysspeed); +extern u32int armidentify(JMedium *jmed); +extern int armrdmemwd(JMedium *jmed, u32int addr, u32int *data, int sz); +extern int armsavectxt(JMedium *jmed, ArmCtxt *ctxt); +extern int armsetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst); +extern int armsetregs(JMedium *jmed, int mask, u32int *regs); +extern int armwrmemwd(JMedium *jmed, u32int addr, u32int data, int sz); +extern int icedebugstate(JMedium *jmed); +extern int iceenterdebug(JMedium *jmed, ArmCtxt *ctxt); +extern int iceexitdebug(JMedium *jmed, ArmCtxt *ctxt); +extern u32int icegetreg(JMedium *jmed, int regaddr); +extern int icesetreg(JMedium *jmed, int regaddr, u32int val); +extern int icewaitdebug(JMedium *jmed); +extern int icewaitentry(JMedium *jmed, ArmCtxt *ctxt); +extern int setchain(JMedium *jmed, int commit, uchar chain); +extern int setinst(JMedium *jmed, uchar inst, int nocommit); +extern char * armsprctxt(ArmCtxt *ctxt, char *s, int ssz); diff --git a/sys/src/cmd/jtagfs/jtag.c b/sys/src/cmd/jtagfs/jtag.c new file mode 100644 index 0000000000..72937a6115 --- /dev/null +++ b/sys/src/cmd/jtagfs/jtag.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include "debug.h" +#include "tap.h" +#include "chain.h" +#include "jtag.h" + +/* + We will only have one active tap at a time. + For now we will suppose they are concatenated. + IR will be 1s for the rest of the bits (Bypass the rest) + DR will be 1 bit per ignored Tap +*/ + +static uchar bufch[4*1024]; +int +tapshift(JMedium *jmed, ShiftTDesc *req, ShiftRDesc *rep, int tapidx) +{ + int i; + u32int ones; + ShiftTDesc lreq; + Chain *ch; + + lreq = *req; + ones = ~0; + memset(bufch, 0, sizeof bufch); + ch = (Chain *)bufch; + + for(i = 0; i < jmed->ntaps; i++){ + if(req->reg == TapDR){ + if(i == tapidx){ + dprint(DState, "tap %d, DR\n", tapidx); + putbits(ch, req->buf, req->nbits); + } + else { + dprint(DState, "tap %d, ignoring DR\n", i); + putbits(ch, &ones, 1); + } + } + else if(req->reg == TapIR){ + if(i == tapidx){ + dprint(DState, "tap %d, IR\n", tapidx); + putbits(ch, req->buf, req->nbits); + } + else { + dprint(DState, "tap %d, IR\n", tapidx); + putbits(ch, &ones, jmed->taps[tapidx].irlen); + } + } + } + + lreq.buf = ch->buf; + lreq.nbits = ch->e - ch->b; + jmed->TapSm = jmed->taps[tapidx].TapSm; + if(jmed->regshift(jmed, &lreq, rep) < 0) + return -1; + jmed->taps[tapidx].TapSm = jmed->TapSm; + + if(req->op & ShiftIn) + for(i = 0; i < jmed->ntaps; i++){ + if(req->reg == TapDR){ + if(i == tapidx) + getbits(req->buf, ch, ch->e - ch->b); + else + getbits(&ones, ch, 1); + } + else if(req->reg == TapIR){ + if(i == tapidx) + getbits(req->buf, ch, ch->e - ch->b); + else + getbits(&ones, ch, jmed->taps[tapidx].irlen); + } + } + + return 0; +} diff --git a/sys/src/cmd/jtagfs/jtag.h b/sys/src/cmd/jtagfs/jtag.h new file mode 100644 index 0000000000..e4e39c61bf --- /dev/null +++ b/sys/src/cmd/jtagfs/jtag.h @@ -0,0 +1,47 @@ +typedef struct JMedium JMedium; +typedef struct ShiftTDesc ShiftTDesc; +typedef struct ShiftRDesc ShiftRDesc; + + +/* descriptor for a shift if not there are too many parameters */ +struct ShiftTDesc { + int reg; + uchar *buf; + int nbits; + int op; +}; + +/* descriptor for a reply to do async replies, timing agh... */ +struct ShiftRDesc{ + int nbyread; /* total bytes */ + int nbiprelast; /* bits of next to last */ + int nbilast; /* bits of last */ +}; + +/* this is the interface for the medium */ +struct JMedium { + TapSm; /* of the tap I am currently addressing */ + int motherb; + int tapcpu; + Tap taps[16]; + int ntaps; + uchar currentch; /* BUG: in tap[tapcpu]->private */ + void *mdata; + int (*regshift)(JMedium *jmed, ShiftTDesc *req, ShiftRDesc *rep); + int (*flush)(void *mdata); + int (*term)(void *mdata); + int (*resets)(void *mdata, int trst, int srst); + int (*rdshiftrep)(JMedium *jmed, uchar *buf, ShiftRDesc *rep); +}; + +enum{ + ShiftMarg = 4, /* Max number of extra bytes in response */ + + ShiftIn = 1, + ShiftOut = 2, + ShiftNoCommit = 4, /* Normally you want to commit... */ + ShiftPauseOut = 8, /* go through pause on the way out */ + ShiftPauseIn = 16, /* go through pause on the way in */ + ShiftAsync = 32, /* do not read reply synch */ +}; +extern int tapshift(JMedium *jmed, ShiftTDesc *req, ShiftRDesc *rep, int tapidx); diff --git a/sys/src/cmd/jtagfs/jtagfs.c b/sys/src/cmd/jtagfs/jtagfs.c new file mode 100644 index 0000000000..df1d808ac1 --- /dev/null +++ b/sys/src/cmd/jtagfs/jtagfs.c @@ -0,0 +1,1590 @@ +#include +#include +#include +#include +#include +#include +#include "debug.h" +#include "tap.h" +#include "chain.h" +#include "jtag.h" +#include "icert.h" +#include "mmu.h" +#include "mpsse.h" +#include "/sys/src/9/kw/arm.h" +#include "/arm/include/ureg.h" +#include "lebo.h" + +/* + * Like rdbfs + jtag icert control for arm cores. + * Memory just goes through in arm order, registers get translated + * to host order and back after. + */ + +typedef struct Fid Fid; +typedef struct Fs Fs; +enum +{ + OPERM = 0x3, /* mask of all permission types in open mode */ + Nfidhash = 32, + + /* + * qids + */ + Qroot = 1, + Qctl, + Qnote, + Qmem, + /* copied from rdbfs */ + Qkregs, + Qfpregs, + Qproc, + Qregs, + Qtext, + Qstatus, +}; + +static int textfd; +static char* textfile = "/arm/s9plug"; + + +struct Fid +{ + Lock; + Fid *next; + Fid **last; + uint fid; + int ref; /* number of fcalls using the fid */ + int attached; /* fid has beed attached or cloned and not clunked */ + + int open; + Qid qid; +}; + +static int dostat(int, uchar*, int); +static void* emalloc(uint); +static void fatal(char*, ...); +static void usage(void); + +struct Fs +{ + Lock; /* for fids */ + + Fid *hash[Nfidhash]; + uchar statbuf[1024]; /* plenty big enough */ + JMedium *jmed; +}; + +static void fsrun(Fs*, int); +static Fid* getfid(Fs*, uint); +static Fid* mkfid(Fs*, uint); +static void putfid(Fs*, Fid*); +static char* fsversion(Fs*, Fcall*); +static char* fsauth(Fs*, Fcall*); +static char* fsattach(Fs*, Fcall*); +static char* fswalk(Fs*, Fcall*); +static char* fsopen(Fs*, Fcall*); +static char* fscreate(Fs*, Fcall*); +static char* fsread(Fs*, Fcall*); +static char* fswrite(Fs*, Fcall*); +static char* fsclunk(Fs*, Fcall*); +static char* fsremove(Fs*, Fcall*); +static char* fsstat(Fs*, Fcall*); +static char* fswstat(Fs*, Fcall*); + +static char *(*fcalls[])(Fs*, Fcall*) = +{ + [Tversion] fsversion, + [Tattach] fsattach, + [Tauth] fsauth, + [Twalk] fswalk, + [Topen] fsopen, + [Tcreate] fscreate, + [Tread] fsread, + [Twrite] fswrite, + [Tclunk] fsclunk, + [Tremove] fsremove, + [Tstat] fsstat, + [Twstat] fswstat +}; + +static char Eperm[] = "permission denied"; +static char Enotdir[] = "not a directory"; +static char Enotexist[] = "file does not exist"; +static char Eisopen[] = "file already open for I/O"; +static char Einuse[] = "fid is already in use"; +static char Enofid[] = "no such fid"; +static char Enotopen[] = "file is not open"; +static char Ebadcmd[] = "error in jtag operation"; + +static ArmCtxt ctxt; +static Fs fs; +static int messagesize = 8192+IOHDRSZ; + +static int +cmdsetdebug(uchar *deb) +{ + int i; + + memset(debug, 0, 255); + for(i = 0; i < strlen((char *)deb); i++){ + debug[deb[i]]++; + } + return 0; +} + + + +void +main(int argc, char **argv) +{ + char buf[12], *mnt, *srv, *mbname; + int fd, p[2], mb; + uchar *deb; + + deb = nil; + mb = Sheeva; + mbname = nil; + mnt = "/n/jtagfs"; + srv = nil; + ARGBEGIN{ + case 'b': + mbname = EARGF(usage()); + break; + case 's': + srv = ARGF(); + mnt = nil; + break; + case 'm': + mnt = ARGF(); + break; + case 'd': + deb = (uchar *)EARGF(usage()); + break; + case 't': + textfile = EARGF(usage()); + break; + }ARGEND + + fmtinstall('F', fcallfmt); + if(deb != nil) + cmdsetdebug(deb); + if(argc != 1) + usage(); + print("jtagfs: %s\n", argv[0]); + fd = open(argv[0], ORDWR); + if(fd < 0) + fatal("can't open jtag file %s: %r", argv[0]); + + if(mbname == nil) + mb = Sheeva; + else if(strncmp(mbname, "sheeva", 6) == 0) + mb = Sheeva; + else if(strncmp(mbname, "gurudisp", 6) == 0) + mb = GuruDisp; + fs.jmed = initmpsse(fd, mb); + if(fs.jmed == nil) + fatal("jtag initialization %r"); + + if(pipe(p) < 0) + fatal("pipe failed"); + + switch(rfork(RFPROC|RFMEM|RFNOTEG|RFNAMEG)){ + case 0: + fsrun(&fs, p[0]); + exits(nil); + case -1: + fatal("fork failed"); + } + + if(mnt == nil){ + if(srv == nil) + usage(); + fd = create(srv, OWRITE, 0666); + if(fd < 0){ + remove(srv); + fd = create(srv, OWRITE, 0666); + if(fd < 0){ + close(p[1]); + fatal("create of %s failed", srv); + } + } + sprint(buf, "%d", p[1]); + if(write(fd, buf, strlen(buf)) < 0){ + close(p[1]); + fatal("writing %s", srv); + } + close(p[1]); + exits(nil); + } + + if(mount(p[1], -1, mnt, MREPL, "") < 0){ + close(p[1]); + fatal("mount failed"); + } + close(p[1]); + exits(nil); +} + +static void +fsrun(Fs *fs, int fd) +{ + Fcall rpc; + char *err; + uchar *buf; + int n; + + buf = emalloc(messagesize); + for(;;){ + /* + * reading from a pipe or a network device + * will give an error after a few eof reads + * however, we cannot tell the difference + * between a zero-length read and an interrupt + * on the processes writing to us, + * so we wait for the error + */ + n = read9pmsg(fd, buf, messagesize); + if(n == 0) + continue; + if(n < 0) + fatal("mount read"); + + rpc.data = (char*)buf + IOHDRSZ; + if(convM2S(buf, n, &rpc) == 0) + continue; + // fprint(2, "recv: %F\n", &rpc); + + + /* + * TODO: flushes are broken + */ + if(rpc.type == Tflush) + continue; + else if(rpc.type >= Tmax || !fcalls[rpc.type]) + err = "bad fcall type"; + else + err = (*fcalls[rpc.type])(fs, &rpc); + if(err){ + rpc.type = Rerror; + rpc.ename = err; + } + else + rpc.type++; + n = convS2M(&rpc, buf, messagesize); + // fprint(2, "send: %F\n", &rpc); + if(write(fd, buf, n) != n) + fatal("mount write"); + } +} + +static Fid* +mkfid(Fs *fs, uint fid) +{ + Fid *f; + int h; + + h = fid % Nfidhash; + for(f = fs->hash[h]; f; f = f->next){ + if(f->fid == fid) + return nil; + } + + f = emalloc(sizeof *f); + f->next = fs->hash[h]; + if(f->next != nil) + f->next->last = &f->next; + f->last = &fs->hash[h]; + fs->hash[h] = f; + + f->fid = fid; + f->ref = 1; + f->attached = 1; + f->open = 0; + return f; +} + +static Fid* +getfid(Fs *fs, uint fid) +{ + Fid *f; + int h; + + h = fid % Nfidhash; + for(f = fs->hash[h]; f; f = f->next){ + if(f->fid == fid){ + if(f->attached == 0) + break; + f->ref++; + return f; + } + } + return nil; +} + +static void +putfid(Fs *, Fid *f) +{ + f->ref--; + if(f->ref == 0 && f->attached == 0){ + *f->last = f->next; + if(f->next != nil) + f->next->last = f->last; + free(f); + } +} + +static char* +fsversion(Fs *, Fcall *rpc) +{ + if(rpc->msize < 256) + return "version: message size too small"; + if(rpc->msize > messagesize) + rpc->msize = messagesize; + messagesize = rpc->msize; + if(strncmp(rpc->version, "9P2000", 6) != 0) + return "unrecognized 9P version"; + rpc->version = "9P2000"; + return nil; +} + +static char* +fsauth(Fs *, Fcall *) +{ + return "searchfs: authentication not required"; +} + +static char* +fsattach(Fs *fs, Fcall *rpc) +{ + Fid *f; + + f = mkfid(fs, rpc->fid); + if(f == nil) + return Einuse; + f->open = 0; + f->qid.type = QTDIR; + f->qid.path = Qroot; + f->qid.vers = 0; + rpc->qid = f->qid; + putfid(fs, f); + return nil; +} + +typedef struct DEntry DEntry; +struct DEntry { + uvlong path; + char *name; +}; + +DEntry entries[] = { + {Qctl, "ctl"}, + {Qmem, "mem"}, + {Qkregs, "kregs"}, + {Qfpregs, "fpregs"}, + {Qproc, "proc"}, + {Qregs, "regs"}, + {Qtext, "text"}, + {Qstatus, "status"}, + {Qnote, "note"}, + {~0, nil}, +}; + +static uvlong +nm2qpath(char *name) +{ + int i; + + for(i = 0; entries[i].name != nil; i++) + if(strcmp(name, entries[i].name) == 0) + return entries[i].path; + + return ~0; +} + +static char* +fswalk(Fs *fs, Fcall *rpc) +{ + Fid *f, *nf; + int nqid, nwname, type; + char *err, *name; + ulong path, fpath; + + f = getfid(fs, rpc->fid); + if(f == nil) + return Enofid; + nf = nil; + if(rpc->fid != rpc->newfid){ + nf = mkfid(fs, rpc->newfid); + if(nf == nil){ + putfid(fs, f); + return Einuse; + } + nf->qid = f->qid; + putfid(fs, f); + f = nf; /* walk f */ + } + + err = nil; + path = f->qid.path; + nwname = rpc->nwname; + for(nqid=0; nqidwname[nqid]; + /* BUG this is a kludge, rewrite */ + fpath = nm2qpath(name); + if(fpath != ~0){ + type = QTFILE; + path = fpath; + } + else if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + type = QTDIR; + else { + err = Enotexist; + break; + } + + rpc->wqid[nqid] = (Qid){path, 0, type}; + } + + if(nwname > 0){ + if(nf != nil && nqid < nwname) + nf->attached = 0; + if(nqid == nwname) + f->qid = rpc->wqid[nqid-1]; + } + + putfid(fs, f); + rpc->nwqid = nqid; + f->open = 0; + return err; +} + +static char * +fsopen(Fs *fs, Fcall *rpc) +{ + Fid *f; + int mode; + char buf[512]; + + f = getfid(fs, rpc->fid); + if(f == nil) + return Enofid; + if(f->open){ + putfid(fs, f); + return Eisopen; + } + mode = rpc->mode & OPERM; + if(mode == OEXEC + || f->qid.path == Qroot && (mode == OWRITE || mode == ORDWR)){ + putfid(fs, f); + return Eperm; + } + if(f->qid.path == Qtext){ + close(textfd); + textfd = open(textfile, OREAD); + if(textfd < 0) { + snprint(buf, sizeof buf, "text: %r"); + putfid(fs, f); + return "opening text file"; + } + } + f->open = 1; + rpc->qid = f->qid; + rpc->iounit = messagesize-IOHDRSZ; + putfid(fs, f); + return nil; +} + +static char * +fscreate(Fs *, Fcall *) +{ + return Eperm; +} + +static int +readbuf(Fcall *rpc, void *s, long n) +{ + int count; + count = rpc->count; + if(rpc->offset >= n){ + count = 0; + } + if(rpc->offset+count > n) + count = n - rpc->offset; + memmove(rpc->data, (char*)s+rpc->offset, count); + rpc->count = count; + return count; +} + +enum{ + Maxctl = 4*1024, +}; + +static char ctlread[Maxctl]; + +static int +readctl(Fs *fs, Fcall *rpc) +{ + char *e; + int ssz; + + ssz = Maxctl; + ctxt.debug = icedebugstate(fs->jmed); + + if(ctxt.debug == 0){ + e = seprint(ctlread, ctlread+Maxctl, "Arm is in debug: %d", ctxt.debug); + ssz = readbuf(rpc, ctlread, e - ctlread); + return ssz; + } + e = armsprctxt(&ctxt, ctlread, ssz); + if(e >= ctlread + Maxctl) + return e - ctlread; + ssz = Maxctl - (ctlread - e); + e = printmmuregs(&ctxt, e, ssz); + + ssz = readbuf(rpc, ctlread, e - ctlread); + return ssz; + +} + +static int +readbytes(JMedium *jmed, u32int startaddr, u32int nbytes, u32int dataoff, Fcall *rpc) +{ + u32int i, data; + int nb, res; + + nb = 0; + for(i = startaddr; i < startaddr+nbytes; i++){ + res = armrdmemwd(jmed, i, &data, 1); + if(res < 0){ + fprint(2, "Error reading [%#8.8ux]\n", + i); + werrstr("read error"); + return -1; + break; + } + nb += res; + rpc->data[dataoff] = (char)data; + dprint(Dfs, "[B%#8.8ux] = %#2.2ux \n", + i, data); + } + return nb; + +} + +/* + * BUG: This is horrifyingly slow, could be made much (10x) + * faster using load multiple/store multiple + * both on memory and while reading back the registers. + * but it doesn't matter for acid (normally it reads words + * or byte long chunks). There may also be another way + * where you can inject instructions without waiting for + * debug mode on the way back. I haven't been able to + * make it work. + */ +static int +readmem(Fs *fs, Fcall *rpc) +{ + u32int count, i, data, addr, prenb, nb, postnb, st; + int res; + + count = (u32int)rpc->count; + + addr = (u32int)rpc->offset; + dprint(Dfs, "[%#8.8ux, %ud] =?\n", + addr, count); + + prenb = 0; + nb = 0; + /* The start is not aligned */ + if(addr & 0x3U){ + prenb = sizeof(u32int) - (addr & 0x3U); + res = readbytes(fs->jmed, addr, prenb, 0, rpc); + if(res < 0){ + werrstr("read error"); + return -1; + } + nb += res; + dprint(Dfs, "readmem: aligned now\n"); + } + for(i = prenb; i/4 < (count-prenb)/sizeof(u32int); i += sizeof(u32int)){ + res = armrdmemwd(fs->jmed, addr+i, &data, 4); + if(res < 0){ + fprint(2, "Error reading %#8.8ux [%#8.8ux]\n", + addr+i, i); + werrstr("read error"); + return -1; + break; + } + nb += res; + + *(u32int *)(rpc->data+i) = data; + dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n", + i, addr+i, data); + } + + dprint(Dfs, "readmem: end of aligned\n"); + /* The end is not aligned */ + if((count-prenb) & 0x3U){ + postnb = (count-prenb)%sizeof(u32int); + st = addr + 1 + ((count-prenb)& 0x3U); + res = readbytes(fs->jmed, st, postnb, nb, rpc); + if(res < 0){ + werrstr("read error"); + return -1; + } + nb += res; + dprint(Dfs, "readmem: end of non aligned\n"); + } + return nb; +} + +static int +writebytes(JMedium *jmed, u32int startaddr, u32int nbytes, u32int dataoff, Fcall *rpc) +{ + u32int i, data; + int nb, res; + + nb = 0; + for(i = startaddr; i < startaddr+nbytes; i++){ + data = (char)rpc->data[dataoff]; + res = armwrmemwd(jmed, i, data, 1); + if(res < 0){ + fprint(2, "Error writing [%#8.8ux]\n", + i); + werrstr("read error"); + return -1; + break; + } + nb += res; + dprint(Dfs, "[B%#8.8ux] = %#2.2ux \n", + i, data); + } + return nb; + +} + +static int +writemem(Fs *fs, Fcall *rpc) +{ + u32int count, i, addr, *p, prenb, nb, postnb, st; + int res; + + count = rpc->count; + addr = rpc->offset; + + prenb = 0; + nb = 0; + /* not aligned offset */ + if(addr & 0x3U){ + prenb = sizeof(u32int) - (addr & 0x3U); + res = writebytes(fs->jmed, addr, prenb, 0, rpc); + if(res < 0){ + werrstr("write error"); + return -1; + } + nb += res; + dprint(Dfs, "writemem: aligned now\n"); + } + for(i = prenb; i/4 < (count-prenb)/sizeof(u32int); i += sizeof(u32int)){ + p = (u32int *)(rpc->data + i); + dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n", + i, addr+i, *p); + res = armwrmemwd(fs->jmed, addr + i, *p, 4); + if(res < 0){ + fprint(2, "Error writing %#8.8ux [%#8.8ux]\n", + addr+i, i); + werrstr("write error"); + return -1; + break; + } + nb += res; + } + dprint(Dfs, "writemem: end of aligned\n"); + /* not aligned end */ + if((count-prenb) & 0x3U){ + postnb = (count-prenb)%sizeof(u32int); + st = addr + 1 + ((count-prenb)& 0x3U); + res = writebytes(fs->jmed, st, postnb, nb, rpc); + if(res < 0){ + werrstr("write error"); + return -1; + } + nb += res; + dprint(Dfs, "writemem: end of non aligned\n"); + } + return nb; +} + +/* host to Arm (le) */ +static void +setkernur(Ureg *kur, ArmCtxt *context) +{ + int i; + u32int *p; + + kur->type = context->cpsr&PsrMask; + hleputl(&kur->type, kur->type); + + kur->psr = context->spsr; + hleputl(&kur->psr, kur->psr); + + p = (u32int *)kur; + for(i = 0; i < 14; i++) + hleputl(p + i, context->r[i]); + kur->pc = context->r[15]; + hleputl(&kur->pc, kur->pc); +} + +typedef struct Regs Regs; +struct Regs { + Ureg kur; + MMURegs mmust; +}; + +static Regs procregs; /* kludge: just for reading */ + +/* host to Arm (le) */ +static void +setmmust(MMURegs *mmust, ArmCtxt *context) +{ + int i; + u32int *o, *d; + d = (u32int *)mmust; + o = (u32int *) &context->MMURegs; + for(i = 0; i < sizeof(MMURegs)/sizeof(u32int); i++) + hleputl(d + i, o[i]); +} + +static char* +fsread(Fs *fs, Fcall *rpc) +{ + Fid *f; + int off, count, len, i; + uchar *rptr; + char buf[512]; + + f = getfid(fs, rpc->fid); + if(f == nil) + return Enofid; + if(!f->open){ + putfid(fs, f); + return Enotopen; + } + count = rpc->count; + off = rpc->offset; + if(f->qid.path == Qroot){ + if(off > 0) + rpc->count = 0; + else { + rpc->count = 0; + for(i = 0; entries[i].name != nil; i++) + rpc->count += dostat(entries[i].path, + rpc->count+(uchar*)rpc->data, count-rpc->count); + } + + putfid(fs, f); + if(off == 0 && rpc->count <= BIT16SZ) + return "directory read count too small"; + return nil; + } + len = 0; + if(f->qid.path == Qctl){ + dprint(Dfs, "ctlread\n"); + len = readctl(fs, rpc); + dprint(Dfs, "ctlread read %d %s\n", len, ctlread); + if(len < 0){ + putfid(fs, f); + return "ctl read"; + } + } + else if(f->qid.path == Qmem){ + dprint(Dfs, "readmem\n"); + len = readmem(fs, rpc); + dprint(Dfs, "readmem read %d %s\n", len, ctlread); + if(len < 0){ + putfid(fs, f); + return "readmem read"; + } + } + else if(f->qid.path == Qkregs){ + dprint(Dfs, "kregs read n %d off %d\n", rpc->count, rpc->offset); + memset(&procregs, 0, sizeof(Regs)); + setkernur(&procregs.kur, &ctxt); + setmmust(&procregs.mmust, &ctxt); + rptr = (uchar*)&procregs; + len = readbuf(rpc, rptr, sizeof(Regs)); + } + else if(f->qid.path == Qtext){ + dprint(Dfs, "text\n"); + len = pread(textfd, rpc->data, rpc->count, rpc->offset); + if(len < 0) { + rerrstr(buf, sizeof buf); + fprint(2, "error reading text: %r"); + putfid(fs, f); + return "text read"; + } + } + else if(f->qid.path == Qstatus){ + dprint(Dfs, "status\n"); + len = snprint(buf, sizeof buf, "%-28s%-28s%-28s", "remote", "system", "New"); + for(i = 0; i < 9; i++) + len += snprint(buf + len, sizeof buf - len, "%-12d", 0); + len = readbuf(rpc, buf, len); + + } + putfid(fs, f); + rpc->count = len; + return nil; +} + +typedef struct Cmdbuf Cmdbuf; +typedef struct Cmdtab Cmdtab; +struct Cmdbuf +{ + char *buf; + char **f; + int nf; +}; + +struct Cmdtab +{ + int index; /* used by client to switch on result */ + char *cmd; /* command name */ + int narg; /* expected #args; 0 ==> variadic */ +}; +/* + * Generous estimate of number of fields, including terminal nil pointer + */ +static int +ncmdfield(char *p, int n) +{ + int white, nwhite; + char *ep; + int nf; + + if(p == nil) + return 1; + + nf = 0; + ep = p+n; + white = 1; /* first text will start field */ + while(p < ep){ + nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */ + if(white && !nwhite) /* beginning of field */ + nf++; + white = nwhite; + } + return nf+1; /* +1 for nil */ +} + +/* + * parse a command written to a device + */ +static Cmdbuf* +parsecmd(char *p, int n) +{ + Cmdbuf *cb; + int nf; + char *sp; + + nf = ncmdfield(p, n); + + /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ + sp = malloc(sizeof(*cb) + nf * sizeof(char*) + n + 1); + if(sp == nil) + sysfatal("memory"); + cb = (Cmdbuf*)sp; + cb->f = (char**)(&cb[1]); + cb->buf = (char*)(&cb->f[nf]); + + memmove(cb->buf, p, n); + + /* dump new line and null terminate */ + if(n > 0 && cb->buf[n-1] == '\n') + n--; + cb->buf[n] = '\0'; + + cb->nf = tokenize(cb->buf, cb->f, nf-1); + cb->f[cb->nf] = nil; + + return cb; +} + +/* + * Look up entry in table + */ + +static Cmdtab* +lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) +{ + int i; + Cmdtab *ct; + + if(cb->nf == 0){ + werrstr("empty control message"); + return nil; + } + + for(ct = ctab, i=0; icmd, "*") !=0) /* wildcard always matches */ + if(strcmp(ct->cmd, cb->f[0]) != 0) + continue; + if(ct->narg != 0 && ct->narg != cb->nf){ + werrstr("bad # args to command"); + return nil; + } + return ct; + } + + werrstr("unknown control message"); + return nil; +} + +enum { + CMcpuid, + CMdebug, + CMreset, + CMstop, + CMstartstop, + CMwaitstop, + CMstart, + CMdump, + CMveccatch, + CMbreakpoint, +}; + +static Cmdtab ctab[] = { + CMdebug, "debug", 2, + CMreset, "reset", 1, + CMcpuid, "cpuid", 1, + CMstop, "stop", 1, + CMstart, "start", 1, + CMdump, "dump", 3, + CMveccatch, "veccatch", 2, + CMwaitstop, "waitstop", 1, + CMstartstop, "startstop", 1, + CMbreakpoint, "breakpoint", 0, /* 2 or 3 args, optional mask */ +}; + +static int +cmdcpuid(JMedium *jmed) +{ + u32int cpuid; + + cpuid = armidentify(jmed); + dprint(Dfs, "---- Cpuid --- %8.8ux\n", cpuid); + if(cpuid == ~0){ + werrstr("not feroceon or nstrs bug..."); + return -1; + } + + dprint(Dfs, "---- Bypass probe --- \n"); + if(armbpasstest(jmed) < 0){ + fprint(2, "error in bypass\n"); + werrstr("bypass test"); + return -1; + } + ctxt.cpuid = cpuid; + return 0; +} + +static int +checkcpuid(JMedium *jmed) +{ + if(ctxt.cpuid != 0) + return 0; + + return cmdcpuid(jmed); +} + + +typedef struct VecMode VecMode; +struct VecMode{ + char c; + u32int mode; +}; + +static VecMode vmode[] = { + {'R', ResetCat}, + {'S', SWICat}, + {'P', PAbortCat}, + {'D', DAbortCat}, + {'I', IrqCat}, + {'F', FiqCat}, +}; + +static u32int +vecval(char *conds) +{ + int i, j; + u32int vcregval; + + vcregval = 0; + for(i = 0; i < strlen(conds); i++){ + for(j = 0; j < nelem(vmode); j++){ + if(vmode[j].c == conds[i]) + vcregval |= vmode[j].mode; + } + } + + return vcregval; +} +/* if running, stop, set catch, start, else, set catch, not start*/ +static int +cmdveccatch(JMedium *jmed, char *conds) +{ + u32int vcregval; + int res, wasdebug; + + wasdebug = ctxt.debug; + if(!wasdebug){ + res = iceenterdebug(jmed, &ctxt); + if(res< 0){ + werrstr("entering debug to set veccat"); + return -1; + } + } + + vcregval = vecval(conds); + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + fprint(Dice, "veccatch: %#8.8ux\n", vcregval); + res = icesetreg(jmed, VecCatReg, vcregval); + if(res < 0) + return -1; + + ctxt.exitreas = VeccatReqReas; + if(!wasdebug){ + res = iceexitdebug(jmed, &ctxt); + if(res < 0){ + werrstr("exiting debug to set veccat"); + return -1; + } + } + + return 0; +} + +/* if running, stop, set breakpoint, start, else, set breakpoint, not start*/ +static int +cmdbreakpoint(JMedium *jmed, u32int addr, u32int mask) +{ + int res, wasdebug; + + wasdebug = ctxt.debug; + if(!wasdebug){ + if(ctxt.debugreas != BreakReas && ctxt.debugreas != NoReas){ + werrstr("already waiting debug"); + return -1; + } + res = iceenterdebug(jmed, &ctxt); + if(res< 0){ + werrstr("entering debug to set breakpoint"); + return -1; + } + } + + res = setchain(jmed, ChCommit, 2); + if(res < 0) + return -1; + res = icesetreg(jmed, Wp0|AddrValReg, addr); + if(res < 0) + return -1; + + res = icesetreg(jmed, Wp0|AddrMskReg, mask); + if(res < 0) + return -1; + + res = icesetreg(jmed, Wp0|DataMskReg, 0xffffffff); + if(res < 0) + return -1; + + res = icesetreg(jmed, Wp0|CtlMskReg, 0xff&~DataWPCtl); + if(res < 0) + return -1; + res = icesetreg(jmed, Wp0|CtlValReg, EnableWPCtl); + if(res < 0) + return -1; + fprint(Dice, "breakpoint: addr %#8.8ux msk %#8.8ux \n", addr, mask); + + ctxt.exitreas = BreakReqReas; + if(!wasdebug){ + res = iceexitdebug(jmed, &ctxt); + if(res < 0){ + werrstr("exiting debug to set breakpoint"); + return -1; + } + } + return 0; +} + +static char dbgstr[4*1024]; + +static int +cmdstop(JMedium *jmed) +{ + int res; + + res = iceenterdebug(jmed, &ctxt); + if(res < 0){ + return -1; + } + + ctxt.debug = icedebugstate(fs.jmed); + return 0; +} + +static int +cmdwaitstop(JMedium *jmed) +{ + int res; + + res = icewaitentry(jmed, &ctxt); + if(res < 0){ + werrstr("timeout waiting for entry to debug state"); + return -1; + } + return 0; +} + +static int +cmdstart(JMedium *jmed) +{ + int res; + res = iceexitdebug(jmed, &ctxt); + if(res < 0){ + werrstr("could not exit debug"); + return -1; + } + ctxt.debug = icedebugstate(fs.jmed); + return 0; +} + +static int +cmddump(JMedium *jmed, u32int start, u32int end) +{ + int res, i; + u32int data; + debug[Dctxt] = 1; + + + for(i = 0; i < end-start; i+=4){ + res = armrdmemwd(jmed, start+i, &data, 4); + if(res < 0){ + fprint(2, "Error reading %#8.8ux [%#8.8ux]\n", start+i, i); + werrstr("read error"); + return -1; + break; + } + dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n", + i, start+i, data); + } + return 0; +} + +static int +cmdhwreset(Fs *fs) +{ + JMedium *jmed; + + jmed = fs->jmed; + if(jmed->flush(jmed->mdata)){ + werrstr("flush"); + return -1; + } + + fs->jmed = resetmpsse(fs->jmed); + if(fs->jmed == nil) + return -1; + ctxt.debug = 0; + + jmed = fs->jmed; + /* BUG make this medium independant..., add a send 5 TMS to interface */ + if(pushcmd(jmed->mdata, "TmsCsOut EdgeDown LSB B0x7 0x7f") < 0) { + werrstr("going to reset"); + return -1; + } + if(jmed->flush(jmed->mdata)){ + werrstr("flush"); + return -1; + } + sleep(1000); + jmed->resets(jmed->mdata, 1, 0); + sleep(200); + jmed->resets(jmed->mdata, 1, 1); + sleep(200); + jmed->resets(jmed->mdata, 0, 1); + sleep(200); + jmed->resets(jmed->mdata, 0, 0); + sleep(200); + if(jmed->flush(jmed->mdata)){ + werrstr("flush"); + return -1; + } + memset(&ctxt, 0, sizeof(ArmCtxt)); + return 0; +} + +static int +cmdstartstop(JMedium *jmed) +{ + if(cmdstart(jmed) < 0){ + werrstr("starting"); + return -1; + } + if(cmdstop(jmed) < 0){ + werrstr("stopping"); + return -1; + } + return 0; +} + + +static int +runcmd(Fs *fs, char *data, int count) +{ + Cmdtab *t; + Cmdbuf *cb; + int res; + u32int st, end, addr, msk; + + cb = parsecmd(data, count); + if(cb->nf < 1){ + werrstr("empty control message"); + free(cb); + return -1; + } + + t = lookupcmd(cb, ctab, nelem(ctab)); + if(t == nil){ + free(cb); + return -1; + } + + if(t->index != CMreset && t->index != CMcpuid && + t->index != CMdebug && + checkcpuid(fs->jmed) < 0) + return -1; + + switch(t->index){ + case CMdebug: + res = cmdsetdebug((uchar *)cb->f[1]); + break; + case CMreset: + dprint(Dfs, "reset\n"); + res = cmdhwreset(fs); + break; + case CMcpuid: + dprint(Dfs, "cpuid\n"); + res = checkcpuid(fs->jmed); + break; + case CMstop: + dprint(Dfs, "stop\n"); + res = cmdstop(fs->jmed); + break; + case CMwaitstop: + dprint(Dfs, "waitstop\n"); + res = cmdwaitstop(fs->jmed); + break; + case CMstart: + dprint(Dfs, "start\n"); + res = cmdstart(fs->jmed); + break; + case CMdump: + st = atol(cb->f[1]); + end = atol(cb->f[2]); + dprint(Dfs, "dump %#8.8ux %#8.8ux\n", st, end); + res = cmddump(fs->jmed, st, end); + break; + case CMveccatch: + dprint(Dfs, "veccatch %s\n", cb->f[1]); + res = cmdveccatch(fs->jmed, cb->f[1]); + break; + case CMbreakpoint: + addr = atol(cb->f[1]); + if(cb->nf > 0 && cb->nf == 3) + msk = atol(cb->f[2]); + else if(cb->nf > 0 && cb->nf == 2) + msk = 0; + else { + res = -1; + goto Exit; + } + + dprint(Dfs, "breakpoint addr %#8.8ux mask %#8.8ux\n", addr, msk); + res = cmdbreakpoint(fs->jmed, addr, msk); + break; + default: + res = -1; + } +Exit: + free(cb); + return res; +} + +/* Arm (le) order to host */ +static void +getkernur(ArmCtxt *ct, Ureg *kur) +{ + int i; + + ct->cpsr = (ct->cpsr&~PsrMask) | kur->type; + ct->cpsr = lehgetl(&ct->cpsr); + + ct->spsr = kur->psr; + ct->spsr = lehgetl(&ct->spsr); + + memmove(ct->r, kur, 14*sizeof(u32int)); + ct->r[15] = kur->pc; + for(i = 0; i < 15; i++) + ct->r[i] = lehgetl(ct->r + i); +} + +static int +setkregs(Fs *fs, Fcall *rpc) +{ + Ureg kur; + ArmCtxt lc; + u32int mask, *lp, *gp; + int res, nb, i; + char *p; + JMedium *jmed; + + jmed = fs->jmed; + + nb = 0; + lc = ctxt; + setkernur(&kur, &ctxt); + p = (char *)&kur; + if(rpc->count + rpc->offset > sizeof(Ureg)) /* cannot write mmuregs*/ + return -1; + else + memmove(p + rpc->offset, rpc->data, rpc->count); + + getkernur(&ctxt, &kur); + + /* BUG? hmm, order matters here, if I get both I am not sure of what to do */ + if(ctxt.cpsr != lc.cpsr){ + res = armsetexec(jmed, 1, &ctxt.cpsr, ARMLDMIA|0x0001); + if(res < 0) + return -1; + res = armgofetch(jmed, ARMMSRr0CPSR, 0); + if(res < 0) + return -1; + nb += sizeof(u32int); + } + + if(ctxt.spsr != lc.spsr){ + res = armsetexec(jmed, 1, &ctxt.spsr, ARMLDMIA|0x0001); + if(res < 0) + return -1; + res = armgofetch(jmed, ARMMSRr0SPSR, 0); + if(res < 0) + return -1; + nb += sizeof(u32int); + } + + + + /* last I update the registers */ + lp = (u32int *)&lc; + gp = (u32int *)&ctxt; + mask = 0; + for(i = 0; i < 16; i++){ + if(lp[i] != gp[i]){ /* see which ones changed */ + mask |= (1 << i); + nb += sizeof(u32int); + } + } + mask |= 0x0001; /* this one I contaminated myself */ + res = armsetregs(jmed, mask, ctxt.r); + if(res < 0) + return -1; + return nb; +} + +static char* +fswrite(Fs *fs, Fcall *rpc) +{ + Fid *f; + int res, len; + + f = getfid(fs, rpc->fid); + if(f == nil) + return Enofid; + if(!f->open){ + putfid(fs, f); + return Enotopen; + } + + if(f->qid.path == Qctl){ + res = runcmd(fs, rpc->data, rpc->count); + if(res < 0){ + fprint(2, "error %r\n"); + putfid(fs, f); + return Ebadcmd; + } + } + else if(f->qid.path == Qmem){ + len = writemem(fs, rpc); + if(len < 0){ + putfid(fs, f); + return "reading memory"; + } + } + else if(f->qid.path == Qkregs){ + dprint(Dfs, "kregs write n %d off %d\n", rpc->count, rpc->offset); + len = setkregs(fs, rpc); + if(len < 0){ + putfid(fs, f); + return "writing kregs"; + } + } + else { + putfid(fs, f); + return Eperm; + } + putfid(fs, f); + return nil; +} + +static char * +fsclunk(Fs *fs, Fcall *rpc) +{ + Fid *f; + + f = getfid(fs, rpc->fid); + if(f != nil){ + f->attached = 0; + putfid(fs, f); + } + return nil; +} + +static char * +fsremove(Fs *, Fcall *) +{ + return Eperm; +} + +static char * +fsstat(Fs *fs, Fcall *rpc) +{ + Fid *f; + + f = getfid(fs, rpc->fid); + if(f == nil) + return Enofid; + rpc->stat = fs->statbuf; + rpc->nstat = dostat(f->qid.path, rpc->stat, sizeof fs->statbuf); + putfid(fs, f); + if(rpc->nstat <= BIT16SZ) + return "stat count too small"; + return nil; +} + +static char * +fswstat(Fs *, Fcall *) +{ + return Eperm; +} + +static int +dostat(int path, uchar *buf, int nbuf) +{ + Dir d; + + switch(path){ + case Qroot: + d.name = "."; + d.mode = DMDIR|0555; + d.qid.type = QTDIR; + break; + case Qctl: + d.name = "ctl"; + d.mode = 0666; + d.qid.type = QTFILE; + break; + case Qmem: + d.name = "mem"; + d.mode = 0666; + d.qid.type = QTFILE; + break; + case Qkregs: + d.name = "kregs"; + d.mode = 0666; + d.qid.type = QTFILE; + break; + case Qfpregs: + d.name = "fpregs"; + d.mode = 0666; + d.qid.type = QTFILE; + break; + case Qproc: + d.name = "proc"; + d.mode = 0444; + d.qid.type = QTFILE; + break; + case Qregs: + d.name = "regs"; + d.mode = 0666; + d.qid.type = QTFILE; + break; + case Qtext: + d.name = "text"; + d.mode = 0444; + d.qid.type = QTFILE; + break; + case Qstatus: + d.name = "status"; + d.mode = 0444; + d.qid.type = QTFILE; + break; + } + d.qid.path = path; + d.qid.vers = 0; + d.length = 0; + d.uid = d.gid = d.muid = "none"; + d.atime = d.mtime = time(nil); + return convD2M(&d, buf, nbuf); +} + +static void +fatal(char *fmt, ...) +{ + va_list arg; + char buf[1024]; + + write(2, "jtagfs: ", 8); + va_start(arg, fmt); + vseprint(buf, buf+1024, fmt, arg); + va_end(arg); + write(2, buf, strlen(buf)); + write(2, "\n", 1); + exits(fmt); +} + +static void * +emalloc(uint n) +{ + void *p; + + p = malloc(n); + if(p == nil) + fatal("out of memory"); + memset(p, 0, n); + return p; +} + +static void +usage(void) +{ + fprint(2, "usage: jtagfs [-t text] [-d debug] [-m mountpoint] [-s srvfile] jtag\n"); + exits("usage"); +} diff --git a/sys/src/cmd/jtagfs/lebo.c b/sys/src/cmd/jtagfs/lebo.c new file mode 100644 index 0000000000..1fa34f9ad1 --- /dev/null +++ b/sys/src/cmd/jtagfs/lebo.c @@ -0,0 +1,77 @@ +#include +#include +#include + +void +hleputv(void *p, uvlong v) +{ + uchar *a; + + a = p; + a[7] = v>>56; + a[6] = v>>48; + a[5] = v>>40; + a[4] = v>>32; + a[3] = v>>24; + a[2] = v>>16; + a[1] = v>>8; + a[0] = v; +} + +void +hleputl(void *p, uint v) +{ + uchar *a; + + a = p; + a[3] = v>>24; + a[2] = v>>16; + a[1] = v>>8; + a[0] = v; +} + +void +hleputs(void *p, ushort v) +{ + uchar *a; + + a = p; + a[1] = v>>8; + a[0] = v; +} + +uvlong +lehgetv(void *p) +{ + uchar *a; + uvlong v; + + a = p; + v = (uvlong)a[7]<<56; + v |= (uvlong)a[6]<<48; + v |= (uvlong)a[5]<<40; + v |= (uvlong)a[4]<<32; + v |= a[3]<<24; + v |= a[2]<<16; + v |= a[1]<<8; + v |= a[0]<<0; + return v; +} + +uint +lehgetl(void *p) +{ + uchar *a; + + a = p; + return (a[3]<<24)|(a[2]<<16)|(a[1]<<8)|(a[0]<<0); +} + +ushort +lehgets(void *p) +{ + uchar *a; + + a = p; + return (a[1]<<8)|(a[0]<<0); +} diff --git a/sys/src/cmd/jtagfs/lebo.h b/sys/src/cmd/jtagfs/lebo.h new file mode 100644 index 0000000000..883776a9a3 --- /dev/null +++ b/sys/src/cmd/jtagfs/lebo.h @@ -0,0 +1,6 @@ +uint lehgetl(void *p); +ushort lehgets(void *p); +uvlong lehgetv(void *p); +void hleputl(void *p, uint v); +void hleputs(void *p, ushort v); +void hleputv(void *p, uvlong v); diff --git a/sys/src/cmd/jtagfs/ma.c b/sys/src/cmd/jtagfs/ma.c new file mode 100644 index 0000000000..bfd9c9549e --- /dev/null +++ b/sys/src/cmd/jtagfs/ma.c @@ -0,0 +1,820 @@ +#include +#include +#include /* BUG: yes I know... ascii*/ +#include +#include "debug.h" +#include "tap.h" +#include "jtag.h" +#include "icert.h" /* BUG: separate medium and ice */ +#include "mpsse.h" + +/* + * Mpsse assembler + * Based on AN2232C-01 Command Processor for MPSSE and MCU Host Bus + * and various magical commands from source code all around. + */ + + +enum{ + /* MPSSE */ + + /* + * This are used only to make opcodes + * for Clocking in/out data to TD0 to TDI + */ + OpModOut = 0x10, + OpTmsCs = 0x4a, /* clock data to TmsCs */ + + /* Modifiers for both */ + OpModShort = 0x02, /* len only one byte */ + OpModOutFalling = 0x01, + OpModInFalling = 0x04, + OpModLSB = 0x08, + OpModIn = 0x20, + + OpModBitsH = 0x02, + OpModBitsIn = 0x01, + OpSetBits = 0x80, /* value(?)/direction on pins*/ + + OpLoop = 0x84, /* loop connect TDI/DO with TDO/DI */ + OpBreakLoop = 0x85, /* break loop */ + OpTckSkDiv = 0x86, /* valL valH, ?? description of reset */ + + OpDiv5ClkEnab = 0x8b, + OpDiv5ClkDisab = 0x8a, + + + /* MCU host emulation */ + OpModLong = 0x01, /* addrH addrL */ + + OpMCURd = 0x90, /* addr */ + OpMCUWr = 0x92, /* addr Data */ + + OpBad = 0, /* made this up */ + + /* Both modes */ + OpSendImm = 0x87, /* flush buffer back to PC ??? */ + OpWaitIOHigh = 0x88, /* IO high, GPIOH in MPSSE, I/O1 on MCU */ + OpWaitIOLow = 0x89, /* IO low, GPIOH in MPSSE, I/O1 on MCU */ + + OpAdaptClkEnab = 0x96, + OpAdaptClkDisab = 0x97, + RBad = 0xFA, /* followed by the bad command */ + + MaxDataSz = 0xffff+1, +}; + +typedef struct Inst Inst; +struct Inst{ + int hasresp; + int isshort; + int islsb; /* bits come/go LSB */ + int nedge; + uchar edge[2]; + uchar opcode; + int lensz; + uchar len[2]; + int immsz; + uchar imm[3]; + int datasz; + uchar data[1]; +}; + +enum{ + DataIn, + DataOut, + DataOutIn, + TmsCsOut, + TmsCsOutIn, + SetBitsL, + SetBitsH, + TckSkDiv, + MCURd, /* from this down, no param */ + MCUWr, + SendImm, + WaitIOHigh, + WaitIOLow, + AdaptClkEnab, + AdaptClkDisab, + Div5ClkEnab, + Div5ClkDisab, + GetBitsL, + GetBitsH, + Loop, + BreakLoop, + ILast, +}; + +static char *inst[] = { + [DataIn] "DataIn", + [DataOut] "DataOut", + [DataOutIn] "DataOutIn", + [TmsCsOut] "TmsCsOut", + [TmsCsOutIn] "TmsCsOutIn", + [SetBitsL] "SetBitsL", + [SetBitsH] "SetBitsH", + [TckSkDiv] "TckSkDiv", + [MCURd] "MCURd", + [MCUWr] "MCUWr", + [SendImm] "SendImm", + [WaitIOHigh] "WaitIOHigh", + [WaitIOLow] "WaitIOLow", + [AdaptClkEnab] "AdaptClkEnab", + [AdaptClkDisab] "AdaptClkDisab", + [Div5ClkEnab] "Div5ClkEnab", + [Div5ClkDisab] "Div5ClkDisab", + [GetBitsL] "GetBitsL", + [GetBitsH] "GetBitsH", + [Loop] "Loop", + [BreakLoop] "BreakLoop", + [ILast] nil, + +}; + + +enum{ + EdgeNone, + EdgeUp, + EdgeDown, + EdgeBad, +}; + +static uchar +dataopcode(Inst *inst, int instid, int issh, int islsb) +{ + uchar opcode = 0; + + switch(instid){ + case DataOutIn: + if(inst->edge[1] == EdgeDown) + opcode = OpModInFalling; + /* fall through */ + case DataOut: + opcode |= OpModOut; + if (inst->edge[0] == EdgeDown) + opcode |= OpModOutFalling; + break; + case DataIn: + if (inst->edge[0] == EdgeDown) + opcode |= OpModInFalling; + break; + } + + opcode |= inst->hasresp? OpModIn : 0; + opcode |= issh? OpModShort : 0; + opcode |= islsb? OpModLSB : 0; + + return opcode; +} + + +static uchar +opcode(Inst *inst, int instid) +{ + int issh, islsb; + uchar opcode; + + opcode = 0; + issh = inst->isshort; + islsb = inst->islsb; + + if(instid != TmsCsOutIn && instid != TmsCsOut&& instid != DataOutIn) + if(inst->edge[1] != EdgeNone){ + werrstr("should not have edge"); + return OpBad; + } + + switch(instid){ + case DataOutIn: + case DataOut: + case DataIn: + opcode = dataopcode(inst, instid, issh, islsb); + break; + + case TmsCsOutIn: + opcode = OpModIn; + if (inst->edge[1] == EdgeDown) + opcode |= OpModInFalling; + /* fall through */ + case TmsCsOut: + opcode |= OpTmsCs; + if(!issh || (inst->len[0] + 1) > 7){ + werrstr("len too big: %d, issh:%d", + inst->len[0]+1, issh); + return OpBad; + } + if (inst->edge[0] == EdgeDown) + opcode |= OpModOutFalling; + opcode |= OpModShort; + opcode |= OpModLSB; + break; + case MCURd: + opcode = OpMCURd; + opcode |= !issh? OpModLong : 0; + break; + case MCUWr: + opcode = OpMCUWr; + opcode |= !issh? OpModLong : 0; + break; + case SendImm: + opcode = OpSendImm; + break; + case WaitIOHigh: + opcode = OpWaitIOHigh; + break; + case TckSkDiv: + opcode = OpTckSkDiv; + break; + case WaitIOLow: + opcode = OpWaitIOLow; + break; + case AdaptClkEnab: + opcode = OpAdaptClkEnab; + break; + case AdaptClkDisab: + opcode = OpAdaptClkDisab; + break; + case Div5ClkEnab: + opcode = OpDiv5ClkEnab; + break; + case Div5ClkDisab: + opcode = OpDiv5ClkDisab; + break; + case GetBitsH: + case SetBitsH: + opcode = OpModBitsH; + case GetBitsL: + /* fall through */ + if(instid == GetBitsL || instid == GetBitsH) + opcode |= OpModBitsIn; + case SetBitsL: + opcode |= OpSetBits; + break; + case Loop: + opcode = OpLoop; + break; + case BreakLoop: + opcode = OpBreakLoop; + break; + default: + werrstr("unknown instruction"); + return OpBad; + } + return opcode; +} + +enum { + ParLen = 'L', /* Data len 2 bytes or 1 byte (bit len) */ + ParShLen = 'l', /* bit len Bnumber */ + ParData = 'D', /* data or @ to place data later */ + ParShData = 'd', /* short data, 1 byte at most */ + ParImm = 'I', /* immediate operator, 2/1 bytes */ + ParLImm = 'i', /* immediate operator, 2 bytes */ + ParShImm = 'c', /* immediate operator, 1 byte */ + ParEdge = 'E', /* EdgeUp or EdgeDown */ + ParEndian = 'N', /* LSB or MSB */ + ParLsb = 'n', /* LSB */ +}; + +typedef struct InstDesc InstDesc; +struct InstDesc +{ + char *name; + char *desc; + int hasresp; +}; + +static InstDesc idesc[] = { + [DataIn] {"DataIn", "ENL", 1}, + [DataOut] {"DataOut", "ENLD", 0}, + [DataOutIn] {"DataOutIn", "EENLD", 1}, + [TmsCsOut] {"TmsCsOut", "ENld", 0}, + [TmsCsOutIn] {"TmsCsOutIn", "EENld", 1}, + [MCURd] {"MCURd", "I", 1}, + [MCUWr] {"MCUWr", "Id", 0}, + [SendImm] {"SendImm", "", 0}, + [WaitIOHigh] {"WaitIOHigh", "", 0}, + [WaitIOLow] {"WaitIOLow", "", 0}, + [AdaptClkEnab] {"AdaptClkEnab", "", 0}, + [AdaptClkDisab] {"AdaptClkDisab", "", 0}, + [Div5ClkEnab] {"Div5ClkEnab", "", 0}, + [Div5ClkDisab] {"Div5ClkDisab", "", 0}, + [SetBitsL] {"SetBitsL", "cc", 0}, + [GetBitsL] {"GetBitsL", "c", 0}, + [SetBitsH] {"SetBitsH", "cc", 0}, + [GetBitsH] {"GetBitsH", "c", 0}, + [TckSkDiv] {"TckSkDiv", "i", 0}, + [Loop] {"Loop", "", 0}, + [BreakLoop] {"BreakLoop", "", 0}, + [ILast] {nil, nil, 0}, +}; + + +static int +nametoid(char *name) +{ + int i; + for (i = 0; i < ILast; i++){ + if(strcmp(inst[i], name) == 0) + break; + } + if(i == ILast) + return -1; + return i; +} + +static int +edgetoid(char *edgename) +{ + if(strcmp(edgename, "EdgeUp") == 0) + return EdgeUp; + else if(strcmp(edgename, "EdgeDown") == 0) + return EdgeDown; + + return EdgeBad; +} + +static int +isendian(char *endianname) +{ + if(strcmp(endianname, "LSB") == 0) + return 1; + else if(strcmp(endianname, "MSB") == 0) + return 1; + + return 0; +} + + +static int +datalen(Inst *inst, char *p) +{ + int len; + if(p[0] == 'B'){ + inst->isshort++; + p++; + } + else + inst->isshort = 0; + len = atoi(p); //strtol and check + if(inst->isshort && len > 8) + return -1; + if(len > MaxDataSz) + return -1; + return len; +} + +static void +setlen(Inst *inst, int dlen) +{ + if(dlen != 0){ + inst->lensz++; + inst->len[0] = (dlen - 1 ) & 0xff; + if(!inst->isshort){ + inst->len[1] = 0xff & ((dlen - 1) >> 8); + inst->lensz++; + } + } +} + + +static int +setdata(Inst *inst, char *nm, char *p, char *te, int bdlen) +{ + int i; + char *e; + + if(p == nil){ + werrstr("%s: should have data", nm); + return -1; + } + if(*p == '@'){ + inst->datasz = bdlen; + return 0; + } + + if(te != p) + p[strlen(p)] = ' '; /* untokenize */ + + for (i = 0; i < bdlen; i++){ + inst->data[i] = strtol(p, &e, 0); + if(!isspace(*e) && i != bdlen-1) + return -1; + p = e; + } + inst->datasz = i; + return 0; + +} + +static int +hasresp(int instid) +{ + return idesc[instid].hasresp; +} + + +static int +hasnoparam(int instid) +{ + return strlen(idesc[instid].desc) == 0; +} + +static char * +endfield(char *p) +{ + char *s; + + s = p; + if(*p =='\0') + return nil; + while(*p != '\0'){ + if(isspace(*p)){ + if(s == p) + return nil; + return p; + } + p++; + } + return p; +} + +enum{ + LongSz, + ShortSz, + AnySz, +}; + +static int +setimm(Inst *inst, int imm, int kindsz) +{ + int isl, immh, imml; + + isl = imm&~0xff; + + if(isl && kindsz == ShortSz) + return -1; + + + if(isl || kindsz == LongSz){ + immh = (imm >> 8)&0xff; + inst->imm[inst->immsz++] = immh; /* High, then low */ + } + imml = imm&0xff; + inst->imm[inst->immsz++] = imml; + return 0; +} + +static Inst* +parseinst(int instid, char *pars, char *idname) +{ + char *tok[15], *err, *e; + char tf; + int i, ntok, tnf, dlen, bdlen, imm, ndata; + Inst *inst; + + tf = '\0'; + dlen = bdlen = 0; + err = ""; + inst = mallocz(sizeof(Inst) + 1, 1); + if(inst == nil) + return nil; + tnf = strlen(idesc[instid].desc); + e = pars + strlen(pars) + 1; + ntok = tokenize(pars, tok, tnf); + if(tnf != ntok){ + werrstr("%s: bad nr param %d!=%d", idname, tnf, ntok); + return nil; + } + + for(i = 0; i < tnf; i++){ + tf = idesc[instid].desc[i]; + switch(tf){ + case ParLen: + dlen = datalen(inst, tok[i]); + if(dlen < 0){ + err = "bad len"; + goto Err; + } + if(inst->isshort) + bdlen = 1; + else { + bdlen = dlen; + inst = realloc(inst, sizeof(Inst) + bdlen); + if(inst == nil) + return nil; + } + break; + case ParShLen: + dlen = datalen(inst, tok[i]); + if(dlen < 0){ + err = "bad len"; + goto Err; + } + bdlen = 1; + if(!inst->isshort) { + err = "should be short"; + goto Err; + } + break; + case ParData: + if(bdlen != 0){ + ndata = setdata(inst, idname, tok[i], e, bdlen); + if(ndata < 0){ + err = "short data"; + goto Err; + } + } + else { + err = "no data"; + goto Err; + } + break; + case ParShData: + if(bdlen != 0){ + ndata = setdata(inst, idname, tok[i], e, bdlen); + if(ndata < 0){ + err = "short data"; + goto Err; + } + } + else { + err = "no data"; + goto Err; + } + if(ndata > 1){ + err = "more than 1 byte data"; + goto Err; + } + break; + case ParImm: + imm = atoi(tok[i]); + if(setimm(inst, imm, AnySz) < 0) + goto Err; + break; + case ParLImm: + imm = atoi(tok[i]); + if(setimm(inst, imm, LongSz) < 0) + goto Err; + break; + case ParShImm: + imm = atoi(tok[i]); + if(setimm(inst, imm, ShortSz) < 0) + goto Err; + break; + case ParEdge: + inst->edge[inst->nedge] = edgetoid(tok[i]); + if(inst->edge[inst->nedge] == EdgeBad) + goto Err; + inst->nedge++; + break; + case ParEndian: + inst->islsb = strcmp(tok[i], "LSB") == 0; + if(!isendian(tok[i])){ + err = "bad endianness"; + goto Err; + } + break; + case ParLsb: + inst->islsb = strcmp(tok[i], "LSB") == 0; + if(inst->islsb){ + err = "bad endianness: not LSB"; + goto Err; + } + break; + default: + err = "bad param"; + goto Err; + } + + if(bdlen > MaxDataSz || (inst->isshort && dlen > 8)){ + err = "len too big"; + goto Err; + } + } + + setlen(inst, dlen); + inst->hasresp = hasresp(instid); + inst->opcode = opcode(inst, instid); + if(inst->opcode == OpBad){ + err = "bad opcode"; + goto Err; + } + return inst; +Err: + werrstr("inst:%s, nf:%d, ftype:%c, fval:%s:%s\n", idname, i, tf, tok[i], err); + free(inst); + return nil; +} + +static Inst * +parseassln(char *assline) +{ + int instid, lnsz; + Inst *inst; + char *ef, inm[32]; + + dprint(Dassln, "%s\n", assline); + + lnsz = strlen(assline); + if(lnsz == 0){ + werrstr("%s: line does not match instruction", assline); + return nil; + } + + ef = endfield(assline); + if(ef == nil){ + werrstr("%s: empty inst", assline); + return nil; + } + strncpy(inm, assline, ef-assline); + inm[ef-assline] = '\0'; + instid = nametoid(inm); + if(instid < 0){ + werrstr("unrecognized instruction %s", inm); + return nil; + } + inst = parseinst(instid, ef, inm); + return inst; +} + +static int +unpacklen(Inst *inst) +{ + int len; + + if (inst->lensz == 0) + return 0; + len = ((inst->len[1]<<8) | inst->len[0]) + 1; + + return len; +} + +static int +instpacksz(Inst *inst) +{ + return 1 + inst->immsz + inst->lensz + inst->datasz; +} + +static void +sdumpinst(char *s, int ssz, Inst *inst) +{ + int i; + char *e, *te; + + e = s + ssz - 1; + te = e; + + e = seprint(s, te, "op: %#2.2ux\n", inst->opcode); + if(e >= te) + return; + if(inst->hasresp){ + e = seprint(e, te, "hasresp: %d\n", inst->hasresp); + if(e >= te) + return; + } + if(inst->isshort){ + e = seprint(e, te, "isshort: %d\n", inst->isshort); + if(e >= te) + return; + } + e = seprint(e, te, "islsb: %d\n", inst->islsb); + if(e >= te) + return; + + for(i = 0; i < inst->immsz; i++){ + e = seprint(e, te, "imm%d: %#2.2ux\n", i, inst->imm[i]); + if(e >= te) + return; + } + + if(inst->lensz != 0){ + e = seprint(e, te, "lensz: %d\n", inst->lensz); + if(e >= te) + return; + e = seprint(e, te, "len: %d\n", unpacklen(inst)); + if(e >= te) + return; + e = seprint(e, te, "datasz: %d\n", inst->datasz); + if(e >= te) + return; + for(i = 0; i < inst->datasz; i++){ + e = seprint(e, te, "%#2.2ux ", inst->data[i]); + if(e >= te) + return; + } + } +} + +static void +debpack(Inst *inst) +{ + int i; + if(!debug[Dmach] && !debug[DAll]) + return; + fprint(2, "%#2.2ux ", inst->opcode); + + for(i = 0; i < inst->immsz; i++) + fprint(2, "%#2.2ux ", inst->imm[i]); + for(i = 0; i < inst->lensz; i++) + fprint(2, "%#2.2ux ", inst->len[i]); + fprint(2, "\n"); + dumpbuf(Dmach, inst->data, inst->datasz); + fprint(2, "\n"); +} + + +static int +instpack(Mpsse *mpsse, Inst *inst) +{ + int n; + int sz; + Biobufhdr *bp; + + bp = &mpsse->bout; + + sz = instpacksz(inst); + if(sz + Bbuffered(bp) > MpsseBufSz){ + n = mpsseflush(mpsse); + if(n < 0) + return -1; + } + debpack(inst); + n = Bwrite(bp, &inst->opcode, 1); + if(n < 0) + return -1; + n = Bwrite(bp, inst->imm, inst->immsz); + if(n < 0) + return -1; + n = Bwrite(bp, inst->len, inst->lensz); + if(n < 0) + return -1; + n = Bwrite(bp, inst->data, inst->datasz); + if(n < 0) + return -1; + return 0; +} + +int +pushcmd(Mpsse *mpsse, char *ln) +{ + Inst *inst; + int res; + char *dmp, *lln; + + res = 0; + lln = strdup(ln); + inst = parseassln(lln); + free(lln); + + if(inst == nil) + return -1; + if(debug[Dinst]){ + dmp = malloc(255); + if(dmp == nil) + return -1; + sdumpinst(dmp, 255, inst); + fprint(2, "%s\n", dmp); + free(dmp); + } + + if(instpack(mpsse, inst) < 0) + res = -1; + free(inst); + return res; +} + +int +pushcmdwdata(Mpsse *mpsse, char *ln, uchar *buf, int buflen) +{ + Inst *inst; + int res; + char *dmp, *lln; + + res = 0; + lln = strdup(ln); + inst = parseassln(lln); + free(lln); + + if(inst == nil) + return -1; + if(inst->datasz != buflen){ + werrstr("wrong data in cmd %d != %d", inst->datasz, buflen); + return -1; + } + memmove(inst->data, buf, inst->datasz); + if(debug[Dinst]){ + dmp = malloc(255); + if(dmp == nil) + return -1; + sdumpinst(dmp, 255, inst); + fprint(2, "%s\n", dmp); + free(dmp); + } + + if(instpack(mpsse, inst) < 0) + res = -1; + free(inst); + return res; +} + diff --git a/sys/src/cmd/jtagfs/maexamples b/sys/src/cmd/jtagfs/maexamples new file mode 100644 index 0000000000..51c4614324 --- /dev/null +++ b/sys/src/cmd/jtagfs/maexamples @@ -0,0 +1,16 @@ +DataIn EdgeDown LSB 3 +DataIn EdgeDown LSB B3 +DataOutIn EdgeDown EdgeUp LSB 3 0x42 0x34 0x56 +DataOutIn EdgeDown EdgeDown LSB 3 @ +DataOutIn EdgeDown EdgeUp LSB B3 0x42 +DataOutIn EdgeDown EdgeDown LSB B3 @ +TmsCsOut EdgeDown MSB B0x7 0x7 +TmsCsOut EdgeDown LSB B7 0x7 +TmsCsOutIn EdgeDown EdgeUp LSB B0x7 0x7 +MCURd 0x34 +SendImm +WaitIOHigh +AdaptClkDisab +Div5ClkEnab +Loop +SetBitsL 0x32 0x34 diff --git a/sys/src/cmd/jtagfs/maexamplesbad b/sys/src/cmd/jtagfs/maexamplesbad new file mode 100644 index 0000000000..eeee9ae2c7 --- /dev/null +++ b/sys/src/cmd/jtagfs/maexamplesbad @@ -0,0 +1,11 @@ +DataOutIn EdgeDown LSB 3 +DataOutIn EdgeDown LSB 3 0x42 x34 0x56 +DataOutIn EdgeDown EdgeUp LSB 3 0x42 x34 0x56 +DataOutIn EdgeDown LSB B3 0x42 0x34 0x56 +TmsCsOut EdgeDown B0x7 0x7 +TmsCsOut EdgeDown B8 0x7 +TmsCsOut EdgeDown LSB 0x7 0x7 +TmsCsOutIn EdgeDown EdgeDown LSB 0x7 0x7 +TmsCsOutIn EdgeUp MSB 0x7 0x7 +TmsCsOutIn 0x2 0x7 +tiki diff --git a/sys/src/cmd/jtagfs/matest b/sys/src/cmd/jtagfs/matest new file mode 100644 index 0000000000..982ec8969f --- /dev/null +++ b/sys/src/cmd/jtagfs/matest @@ -0,0 +1,10 @@ +#!/bin/rc + +./8.mpssetest -t [2] errors +xd -c -bx xdg + +#this should all error: +./8.mpssetest -t < examplesbad xdb >[2] errors +cat errors +xd -c -bx xdb + diff --git a/sys/src/cmd/jtagfs/mkfile b/sys/src/cmd/jtagfs/mkfile new file mode 100644 index 0000000000..c038852bb8 --- /dev/null +++ b/sys/src/cmd/jtagfs/mkfile @@ -0,0 +1,62 @@ + rtab.c + +rtest:V: all + ./test + +pubfiles=`{ls} + + +/usr/paurea/src/jtag/jtag.tgz: $pubfiles + cd /usr/paurea/src/jtag/ && tar cv jtag/^$pubfiles|gzip > jtag.tgz + +dist:V: /usr/paurea/src/jtag/jtag.tgz + mk all && mk clean && 9fs sources && cp ../jtag.tgz /n/sources/contrib/paurea + diff --git a/sys/src/cmd/jtagfs/mmu.c b/sys/src/cmd/jtagfs/mmu.c new file mode 100644 index 0000000000..1f399797d3 --- /dev/null +++ b/sys/src/cmd/jtagfs/mmu.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include "chain.h" +#include "debug.h" +#include "tap.h" +#include "lebo.h" +#include "bebo.h" +#include "jtag.h" +#include "icert.h" +#include "mmu.h" +#include "mpsse.h" +#include "/sys/src/9/kw/arm.h" + +/* + * Feroceon's scan chain 15 does not work, I suspect it has the multi-ice + * 40 bits limit (even if it is only one core). Just pushing MCR/MRC and + * reading back seems to be more portable + * The only bad thing is that using chain 15 one can + * change things secondary effects (I cannot think of any, but there may be) + */ + +char * +printmmuregs(MMURegs *mmuregs, char *s, int ssz) +{ + char *e, *te; + + te = s + ssz - 1; + + e = seprint(s, te, "cpid: %#8.8ux\n", mmuregs->cpid); + e = seprint(e, te, "ct: %#8.8ux\n", mmuregs->ct); + e = seprint(e, te, "control: %#8.8ux\n", mmuregs->control); + e = seprint(e, te, "ttb: %#8.8ux\n", mmuregs->ttb); + e = seprint(e, te, "dac: %#8.8ux\n", mmuregs->dac); + e = seprint(e, te, "fsr: %#8.8ux\n", mmuregs->fsr); + e = seprint(e, te, "far: %#8.8ux\n", mmuregs->far); + e = seprint(e, te, "pid: %#8.8ux\n", mmuregs->pid); + return e; +} + +/* Chain 15 does not work properly and is not portable, use MCR/MRC */ + +static int +jtagmrc(JMedium *jmed, u32int *data, uchar op1, uchar op2, uchar crn, uchar crm) +{ + int res; + u32int d; + + res = armfastexec(jmed, ARMMRC(CpSC, op1, 0, crn, crm, op2)); + if(res < 0) + return -1; + + setinst(jmed, InRestart, 0); + res = icewaitdebug(jmed); + if(res < 0) + return -1; + res = setchain(jmed, ChCommit, 1); + if(res < 0) + sysfatal("setchain %r"); + armgetexec(jmed, 1, &d, ARMSTMIA|0x0001); + + *data = d; + dprint(Dmmu, "MCR data %#8.8ux \n", d); + return 0; +} + +static int +jtagmcr(JMedium *jmed, u32int data, uchar op1, uchar op2, uchar crn, uchar crm) +{ + int res; + dprint(Dmem, "MCR data %#8.8ux\n", + data); + /* load data in r0 */ + res = armsetexec(jmed, 1, &data, ARMLDMIA|0x0001); + if(res < 0) + return -1; + + res = armfastexec(jmed, ARMMCR(CpSC, op1, 0, crn, crm, op2)); + if(res < 0) + return -1; + + setinst(jmed, InRestart, 0); + res = icewaitdebug(jmed); + if(res < 0) + return -1; + return 0; +} + + +int +mmurdregs(JMedium *jmed, MMURegs *regs) +{ + int res; + res = setchain(jmed, ChCommit, 1); + if(res < 0) + sysfatal("setchain %r"); + res = jtagmrc(jmed, ®s->cpid, 0, CpIDid, C(CpID), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->control, 0, 0, C(CpCONTROL), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->ttb, 0, 0, C(CpTTB), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->dac, 0, 0, C(CpDAC), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->fsr, 0, 0, C(CpFSR), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->far, 0, 0, C(CpFAR), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->ct, 0, CpIDct, C(CpID), C(0)); + if(res < 0) + return -1; + res = jtagmrc(jmed, ®s->pid, 0, 0, C(CpPID), C(0)); + if(res < 0) + return -1; + + return 0; +} + + diff --git a/sys/src/cmd/jtagfs/mmu.h b/sys/src/cmd/jtagfs/mmu.h new file mode 100644 index 0000000000..66e3cf7404 --- /dev/null +++ b/sys/src/cmd/jtagfs/mmu.h @@ -0,0 +1,36 @@ +typedef struct MMUMcrChain15 MMUMcrChain15; + +/* Version of the 15 Chain for mcr access */ +struct MMUMcrChain15 { + uchar rw; /* 1bit */ + uchar op1; /* 3 bits */ + uchar op2; /* 3 bits */ + uchar crn; /* 4 bits */ + uchar crm; /* 4 bits */ + uchar access; /* 1 bit */ + u32int data; /* 32 bits */ +}; + +enum { + /* other sizes taken from icert.h */ + AccessSz = 1, + OpSz = 3, + CrxSz = 4, +}; + +enum{ + ARMMCROP = 0xee000010, + ARMMRCLFLAG = 0x00100000, +}; + +#define C(cr) ((cr)&0x7) +#define ARMMCR(cp, op1, rd, crn, crm, op2) (ARMMCROP | \ + crm | (op2 << 5) | (cp<<8) | \ + (rd<<12) | (crn<<16) | (op1<<21)) + + +#define ARMMRC(cp, op1, rd, crn, crm, op2) (ARMMRCLFLAG | \ + ARMMCR(cp, op1, rd, crn, crm, op2)) + +extern int mmurdregs(JMedium *jmed, MMURegs *regs); +extern char * printmmuregs(MMURegs *mmuregs, char *s, int ssz); diff --git a/sys/src/cmd/jtagfs/mpsse.c b/sys/src/cmd/jtagfs/mpsse.c new file mode 100644 index 0000000000..6070e0ef38 --- /dev/null +++ b/sys/src/cmd/jtagfs/mpsse.c @@ -0,0 +1,648 @@ +#include +#include +#include +#include "debug.h" +#include "lebo.h" +#include "tap.h" +#include "chain.h" +#include "jtag.h" +#include "icert.h" +#include "mpsse.h" + +/* + See schematics, openocd code. + Guessing for the GuruDisp... + */ + +static uchar cablingH[][4] = { + [Sheeva] {[TRST] 0x2, [SRST] 0x0, [TRSTnOE]0x0, [SRSTnOE] 0x04,}, + [GuruDisp] {[TRST] 0x2, [SRST] 0x0, [TRSTnOE]0x0, [SRSTnOE] 0x04,}, +}; + +static uchar cablingL[][5] = { + [Sheeva] {[TCK] 0x01, [TDI] 0x02, [TDO]0x04, [TMS] 0x08, [nOE] 0x10,}, + [GuruDisp] {[TCK] 0x01, [TDI] 0x02, [TDO]0x04, [TMS] 0x08, [nOE] 0x10,}, +}; + +static uchar valcabling[][2] = { + [Sheeva] {isPushPull, isOpenDrain}, + [GuruDisp] {isPushPull, isPushPull}, +}; + +static u32int cpuids[] = { + [Sheeva] FeroceonId, + [GuruDisp] ArmadaId, +}; + +static uchar +hinitvalH(int motherb, int trst, int srst) +{ + uchar hout; + + hout = 0; + + if(trst){ + hout |= cablingH[motherb][TRSTnOE]; + hout &= ~cablingH[motherb][TRST]; + } + else{ + hout &= ~cablingH[motherb][TRSTnOE]; + hout |= cablingH[motherb][TRST]; + } + if(srst){ + hout &= ~cablingH[motherb][SRSTnOE]; + hout |= cablingH[motherb][SRST]; + } + else{ + hout |= cablingH[motherb][SRSTnOE]; + hout &= ~cablingH[motherb][SRST]; + } + + return hout; +} + +static uchar +hinitdirH(int motherb) +{ + USED(motherb); + //int i; + //uchar dir; + //dir = 0; + //for(i = 0; i < 4; i++) + // dir |= cablingH[motherb][i]; /* BUG: TODO */ + return 0xf; +} + +int +mpsseflush(void *mdata) +{ + int r, nb; + ushort s; + Mpsse *mpsse; + + mpsse = mdata; + s = 0xbebe; + + r = 0; + + nb = Bbuffered(&mpsse->bout); + if(debug[DFile] || debug[DAll]) + fprint(2, "Flush %d\n", nb); + + if(debug[DXFlush]) + Bwrite(&mpsse->bout, &s, sizeof s); + if(nb && Bflush(&mpsse->bout) == Beof) + r = -1; + + return r; +} + +static int +mpsseresets(void *mdata, int trst, int srst) +{ + char cmd[128]; + uchar hout, hdir; + int motherb; + Mpsse *mpsse; + + mpsse = mdata; + motherb = mpsse->motherb; + + hdir = hinitdirH(motherb); + hout = hinitvalH(motherb, trst, srst); + + snprint(cmd, sizeof(cmd), "SetBitsH %#2.2ux %#2.2ux", hout, hdir); + if(pushcmd(mpsse, cmd) < 0) + return -1; + if(mpsseflush(mpsse) < 0) + return -1; + return 0; +} + + +static int +initpins(Mpsse *mpsse) +{ + char cmd[128]; + uchar hout, hdir; + int motherb; + Biobufhdr *bout; + + motherb = mpsse->motherb; + bout = &mpsse->bout; + + /* value of this also depends on opendrain etc?, seems it does not */ + hout = cablingL[motherb][TMS]; + hdir = cablingL[motherb][TCK]|cablingL[motherb][TDI]; + hdir |= cablingL[motherb][TMS]|cablingL[motherb][nOE]; + snprint(cmd, sizeof(cmd), "SetBitsL %#2.2ux %#2.2ux", hout, hdir); + if(pushcmd(mpsse, cmd) < 0){ + Bterm(bout); + return -1; + } + if(mpsseflush(mpsse) < 0) + return -1; + + /* is this Board dependant? */ + if(mpsseresets(mpsse, 0, 0) < 0) + return -1; + + return 0; +} + +static int +mpsseterm(void *mdata) +{ + Mpsse *mpsse; + int r; + + mpsse = mdata; + r = Bterm(&mpsse->bout); + free(mpsse); + + return r; +} + +/* I always work with bits on the lsb side, nbits count the + * n less significant bits, no matter msb or lsb order + * I know that mpsse works with lsb on the lsb side and + * msb I am not sure how it is codified msb on lsb side would be + * 00001234, instead of lsb on msb side 12340000 + * In any case I never use msb on the mpsse, + * just on the paths for convenience and they are lsb side + * like 000001234 + * in other words, nbits always counts from lsb bit + */ +static ulong +msb2lsb(ulong msbl, int nbits) +{ + int i; + ulong lsbl, bit; + + lsbl = 0; + for(i = 0; i < nbits; i++){ + bit = (msbl >> (nbits - i - 1))&1; + lsbl |= bit << i; + } + return lsbl; +} + +/* how many clk bits takes to clock out a data bit */ +static int +tmsdata2clk(int nbits) +{ + return ((nbits + 6)/7) * 3; +} + +#define takebits(byte, nbits, offset) (((byte) >> (offset)) & ((1U << (nbits))-1)) + +static void +dropbits(Mpsse *mpsse, int nbits) +{ + int nby, nbi; + + nby = nbits / 8; + nbi = nbits % 8; + + assert(mpsse->nbits >= nbits); + + mpsse->nbits -= 8*nby; + mpsse->rb += nby; + + mpsse->rbits = (mpsse->rbits + nbi) %8; + + mpsse->nbits -= nbi; +} + +static int +runpath(JMedium *jmed, SmPath *pth, int isrd, int issend) +{ + SmPath pref; + uchar tmslsb, lastbit; + int nclkbits; + char cmd[128]; + Mpsse *mpsse; + + mpsse = jmed->mdata; + lastbit = 0; + nclkbits = 0; + if(issend && mpsse->nbits != 0){ + lastbit = mpsse->lastbit; + mpsse->nbits--; + nclkbits = 1; + } + + while(pth->ptmslen != 0){ + pref = takepathpref(pth, MaxNbitsT); + tmslsb = msb2lsb(pref.ptms, pref.ptmslen); + + if(issend && nclkbits--){ + tmslsb |= lastbit<<7; + } + if(isrd) + snprint(cmd, sizeof(cmd), "TmsCsOutIn EdgeDown EdgeUp LSB B%#2.2ux %#2.2ux", + (uchar)pref.ptmslen, tmslsb); + else + snprint(cmd, sizeof(cmd), "TmsCsOut EdgeDown LSB B%#2.2ux %#2.2ux", + (uchar)pref.ptmslen, tmslsb); + + if(pushcmd(mpsse, cmd) < 0) + return -1; + } + + moveto(jmed, pth->st); + return 0; +} + +static int +sendbytes(Mpsse *mpsse, int nbytes, int op) +{ + char cmd[128]; + int totbytes, nwbytes; + uchar *buf; + + buf = mpsse->rb; + totbytes = mpsse->nbits/8; + nwbytes = nbytes; + if(totbytes < nbytes){ + werrstr("sendbytes: not enough %d<%d", totbytes, nbytes); + return -1; + } + if( (op&ShiftIn ) && !(op&ShiftOut) ){ + snprint(cmd, sizeof(cmd), "DataIn EdgeUp LSB %#2.2ux", + nbytes); + nwbytes = 0; + } + else if( !(op&ShiftIn) && (op&ShiftOut) ) + snprint(cmd, sizeof(cmd), "DataOut EdgeDown LSB %#2.2ux @", + nbytes); + else if( (op&ShiftIn) && (op&ShiftOut) ) + + snprint(cmd, sizeof(cmd), "DataOutIn EdgeDown EdgeUp LSB %#2.2ux @", + nbytes); + else + return -1; + + + if(pushcmdwdata(mpsse, cmd, buf, nwbytes) < 0) + return -1; + + dropbits(mpsse, 8*nbytes); + return 0; +} + + +static int +sendbits(Mpsse *mpsse, int nbits, int op) +{ + char cmd[128]; + uchar lastbyte, obyte; + + lastbyte = *mpsse->rb; + if(nbits > 8){ + werrstr("too many bits %d>%d", nbits, MaxNbitsS); + return -1; + } + + + obyte = takebits(lastbyte, nbits, mpsse->rbits); + + if( (op&ShiftIn ) && !(op&ShiftOut) ) + snprint(cmd, sizeof(cmd), "DataIn EdgeUp LSB B%#2.2ux", + nbits); + else if( !(op&ShiftIn) && (op&ShiftOut) ) + snprint(cmd, sizeof(cmd), "DataOut EdgeDown LSB B%#2.2ux %#2.2ux", + nbits, obyte); + else if( (op&ShiftIn) && (op&ShiftOut) ) + + snprint(cmd, sizeof(cmd), "DataOutIn EdgeDown EdgeUp LSB B%#2.2ux %#2.2ux", + nbits, obyte); + else + return -1; + + + if(pushcmd(mpsse, cmd) < 0) + return -1; + + dropbits(mpsse, nbits); + return 0; +} + +static int +movetost(JMedium *jmed, int dst, int isrd, int issend) +{ + SmPath pth; + int len; + + pth = pathto(jmed, dst); + len = pth.ptmslen; + if(runpath(jmed, &pth, isrd, issend) < 0) + return -1; + return len; +} + +static int +stayinst(JMedium *jmed, int nclock) +{ + SmPath pth; + + pth.ptms = 0; + pth.ptmslen = nclock; + if(runpath(jmed, &pth, 0, 0) < 0) + return -1; + return nclock; +} + +static int +mpsserdshiftrep(JMedium *jmed, uchar *buf, ShiftRDesc *rep) +{ + int nr, npartial, nby; + uchar msk; + + Mpsse *mpsse; + + mpsse = jmed->mdata; + dprint(DFile, "Reading %d\n", rep->nbyread); + + nr = readn(mpsse->jtagfd, buf, rep->nbyread); + + npartial = 0; + + dprint(DFile, "Read %d\n", nr); + dumpbuf(DFile, buf, nr); + if(nr <= 0) + return -1; + if(rep->nbiprelast != 0){ + npartial++; + } + if(rep->nbilast != 0){ + npartial++; + } + nby = rep->nbyread - npartial; + if(rep->nbiprelast != 0){ + buf[nby] = buf[nby] >> (8 - rep->nbiprelast); + } + if(rep->nbilast != 0){ + msk = MSK(rep->nbilast); + buf[nby] |= (buf[nby+1] & msk) << (8 - rep->nbilast); + } + return (7 + nby + npartial) / 8; /* readjust after compacting */ +} + +/* + * May need a couple of two or three bytes of margin for reading, + * do not call it with just enough bytes +*/ + +static int +mpsseregshift(JMedium *jmed, ShiftTDesc *req, ShiftRDesc *rep) +{ + int npsend, nr, nl, isrd, nback, nby, ntrail, reg, nbits, op; + ShiftRDesc rr; + uchar *buf; + Mpsse *mpsse; + + reg = req->reg; + buf = req->buf; + nbits = req->nbits; + op = req->op; + + mpsse = jmed->mdata; + if(rep == nil) + rep = &rr; + + nr = 0; + nby = 0; + nback = 0; + npsend = 0; + + + if(reg != TapDR && reg != TapIR) + sysfatal("unknown register"); + + isrd = op&ShiftIn; + + /* + * May need to go to Pause to cross capture before starting + * May still have a trailing bit from last shifting + */ + + if(op&ShiftPauseIn){ + nl = movetost(jmed, TapPauseDR+reg, 0, mpsse->nbits != 0); + if(nl < 0){ + werrstr("regshift: going to pause in"); + return -1; + } + } + + if(movetost(jmed, TapShiftDR+reg, 0, mpsse->nbits != 0) < 0){ + werrstr("regshift: going to shift"); + return -1; + } + + mpsse->nbits = nbits; + mpsse->rb = buf; + mpsse->rbits = 0; + + if((mpsse->nbits / 8) > 1){ + nby = mpsse->nbits / 8; + if(mpsse->nbits % 8 == 0) + nby--; + if(sendbytes(mpsse, nby, op) < 0){ + werrstr("regshift: shifting bytes"); + return -1; + } + nback = nby; + } + + + if(mpsse->nbits > 1){ + nback++; /* each op gives a partial byte */ + npsend = mpsse->nbits; + if(mpsse->nbits > 7) /* apparently hw does not like 8 bytes */ + npsend = MaxNbitsS; + npsend -= 1; /* one is for the way */ + if(sendbits(mpsse, npsend, op) < 0){ + werrstr("regshift: shifting bits"); + return -1; + } + mpsse->lastbit = takebits(*mpsse->rb, 1, mpsse->rbits); + } + + + /* I only go through pause if I need extra time to shift + * for example, I need a command to read or if I am told + */ + + if(isrd || (op&ShiftPauseOut)){ + nback++; + nl = movetost(jmed, TapPauseDR+reg, isrd, mpsse->nbits != 0); + if(nl < 0){ + werrstr("regshift: going to pause out"); + return -1; + } + } + + if(! (op&ShiftNoCommit)){ + nl = movetost(jmed, TapIdle, 0, mpsse->nbits != 0); + if(nl < 0){ + werrstr("regshift: going to idle out"); + return -1; + } + } + if(isrd){ + if(mpsseflush(mpsse) < 0){ + werrstr("regshift: flushing"); + return -1; + } + + ntrail = nbits - npsend - 8*nby; + rep->nbyread = nback; + rep->nbiprelast = npsend; + rep->nbilast = ntrail; + if( !(op&ShiftAsync) ) + nr = mpsserdshiftrep(jmed, buf, rep); + } + return nr; +} + +JMedium * +newmpsse(int fd, int motherb) +{ + Mpsse *mpsse; + Biobufhdr *bout; + JMedium *jmed; + int i; + + jmed = mallocz(sizeof(JMedium), 1); + if(jmed == nil) + return nil; + + mpsse = malloc(sizeof(Mpsse)); + if(mpsse == nil) + return nil; + + jmed->motherb = motherb; + jmed->mdata = mpsse; + jmed->regshift = mpsseregshift; + jmed->rdshiftrep = mpsserdshiftrep; + jmed->flush = mpsseflush; + jmed->term = mpsseterm; + jmed->resets = mpsseresets; + + /* BUG: configuration file? */ + if(motherb == Sheeva){ + jmed->ntaps = 1; + jmed->tapcpu = 0; + jmed->taps[0].hwid = FeroceonId; + jmed->taps[0].irlen = InLen; + } + else if(motherb == GuruDisp){ + /* BUG: set concatenating mode */ + jmed->ntaps = 3; + jmed->taps[0].hwid = 0; + jmed->taps[0].irlen = 1; + jmed->tapcpu = 1; + jmed->taps[1].hwid = ArmadaId; + jmed->taps[1].irlen = InLen; + jmed->taps[2].hwid = 0; + jmed->taps[2].irlen = 9; + } + else + sysfatal("Unkwown motherboard"); + + for(i = 0; i < jmed->ntaps; i++) + jmed->taps[i].state = TapUnknown; + jmed->state = TapUnknown; + + mpsse->jtagfd = fd; + mpsse->motherb = motherb; + + + bout = &mpsse->bout; + + if(Binits(bout, fd, OWRITE, mpsse->bp, MpsseBufSz) == Beof){ + free(mpsse); + return nil; + } + return jmed; +} + +JMedium * +initmpsse(int fd, int motherb) +{ + Mpsse *mpsse; + JMedium *jmed; + uchar buf[32]; + ShiftTDesc req; + + + jmed = newmpsse(fd, motherb); + if(jmed == nil){ + free(jmed); + return nil; + } + mpsse = jmed->mdata; + + if(initpins(mpsse) < 0) + goto Err; + + if(pushcmd(mpsse, "TckSkDiv 0x0200") < 0) + goto Err; + if(mpsseflush(mpsse) < 0) + goto Err; + + if(pushcmd(mpsse, "BreakLoop") < 0) + goto Err; + if(mpsseflush(mpsse) < 0) + goto Err; + + /* Board dependant ? */ + if(mpsseresets(mpsse, 0, 0) < 0) + goto Err; + + if(motherb == GuruDisp){ /* set concat mode */ + req.reg = TapIR; + hleputs(buf, InGuruTapctl); + req.buf = buf; + req.nbits = InGuruLen; + req.op = ShiftOut; + + jmed->regshift(jmed, &req, nil); + req.reg = TapDR; + hleputs(buf, DrGuruTapctl); + req.buf = buf; + req.nbits = 16; + req.op = ShiftOut; + jmed->regshift(jmed, &req, nil); + jmed->taps[2].TapSm = jmed->TapSm; + } + return jmed; +Err: + mpsseterm(mpsse); + free(jmed); + return nil; +} + +static void +termmpsse(JMedium *jmed) +{ + mpsseterm(jmed->mdata); + free(jmed); +} + + +JMedium * +resetmpsse(JMedium *jmed) +{ + Mpsse mpsse; + JMedium *jmnew; + + mpsse = *(Mpsse *)jmed->mdata; + mpsseflush((Mpsse *)jmed->mdata); + free(jmed->mdata); + + jmnew = initmpsse(mpsse.jtagfd, mpsse.motherb); + return jmnew; +} + diff --git a/sys/src/cmd/jtagfs/mpsse.h b/sys/src/cmd/jtagfs/mpsse.h new file mode 100644 index 0000000000..925ce08bb3 --- /dev/null +++ b/sys/src/cmd/jtagfs/mpsse.h @@ -0,0 +1,59 @@ +typedef struct Mpsse Mpsse; + +enum { + KHz = 1000, + FtdiHSpeedClk = 30*KHz, /* 2232H 4232H */ + FtdiMaxClk = 60*KHz, /* 2232C */ + FtdiReqTck = -1, +}; + +enum{ + isPushPull, + notPushPull, + isOpenDrain, + notOpenDrain, +}; + +enum{ + MpsseBufSz = 131072, /* from openocd, noone knows why */ + MaxNbitsT = 7, /* maximum bits per state transition */ + MaxNbitsS = 7, /* maximum bits of data clocked */ + + nOE = 0, + TDI, + TDO, + TMS, + TCK, + + TRSTnOE = 0, + TRST, + SRSTnOE, + SRST, + + Sheeva = 0, + GuruDisp = 1, +}; + + +struct Mpsse{ + int nread; /* bytes left to read */ + int nbits; /* length of bits left to process */ + uchar *rb; /* current point of buf processing */ + int rbits; /* offset in the last bit to process counting from LSB */ + int lastbit; + int motherb; + int jtagfd; + Biobufhdr bout; + uchar bp[Bungetsize+MpsseBufSz]; +}; + +int mpsseflush(void *mdata); /* internal, for ma.c */ + +/* from ma.c */ +extern int pushcmd(Mpsse *mpsse, char *ln); +extern int pushcmdwdata(Mpsse *mpsse, char *ln, uchar *buf, int buflen); + +/* from mpsse.c */ +extern JMedium * initmpsse(int fd, int motherb); +extern JMedium * newmpsse(int fd, int motherb); +extern JMedium * resetmpsse(JMedium *jmed); diff --git a/sys/src/cmd/jtagfs/mpssetest.c b/sys/src/cmd/jtagfs/mpssetest.c new file mode 100644 index 0000000000..58aa0bed53 --- /dev/null +++ b/sys/src/cmd/jtagfs/mpssetest.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include "debug.h" +#include "tap.h" +#include "chain.h" +#include "jtag.h" +#include "icert.h" +#include "mmu.h" +#include "mpsse.h" + +static Biobuf bin; + +static void +testsh(JMedium *jmed) +{ + char *ln; + while(ln = Brdstr(&bin, '\n', 1)){ + if(ln == nil) + break; + fprint(2, "[%s]\n", ln); + if(strcmp(ln, "") == 0 || ln[0] == '#'){ + free(ln); + continue; + } + if(pushcmd(jmed->mdata, ln) < 0) + fprint(2, "error: %r\n"); + free(ln); + } +} + +static void +hwreset(JMedium *jmed) +{ + /* BUG make this medium independant... */ + if(pushcmd(jmed->mdata, "TmsCsOut EdgeDown LSB B0x7 0x7f") < 0) + sysfatal("resetting %r"); + if(jmed->flush(jmed->mdata)) + sysfatal("resetting %r"); + sleep(1000); + jmed->resets(jmed->mdata, 1, 0); + sleep(200); + jmed->resets(jmed->mdata, 1, 1); + sleep(200); + jmed->resets(jmed->mdata, 0, 1); + sleep(200); + jmed->resets(jmed->mdata, 0, 0); + sleep(200); +} + +static void +usage(void) +{ + fprint(2, "Usage: %s [-t] [-r] [-d 'a'...] jtagfile\n", argv0); + exits("usage"); +} + +static Chain ch; +static EiceChain1 ec1; +static EiceChain2 ec2; +static char dbgstr[256]; + +static ArmCtxt ctxt; +static u32int regs[16]; + +static void +testice(JMedium *jmed) +{ + int res, i; + u32int cpuid, data; + debug[Dctxt] = 1; + + cpuid = armidentify(jmed); + fprint(2, "---- Cpuid --- %8.8ux\n", cpuid); + if(cpuid == ~0) + sysfatal("not feroceon or WFI bug..."); + + fprint(2, "---- Bypass probe --- \n"); + if(armbpasstest(jmed) < 0) + sysfatal("bypass test"); + + fprint(2, "---- Check state --- \n"); + res = setchain(jmed, ChCommit, 2); + if(res < 0) + sysfatal("setchain %r"); + + icegetreg(jmed, DebStsReg); + + fprint(2, "---- Freeze --- \n"); + res = iceenterdebug(jmed, &ctxt); + if(res < 0) + sysfatal("could not enter debug"); + fprint(2, "\n\n\tIn debug state for 1 sec\n\n"); + sleep(1000); + fprint(2, "---- MMU test --- \n"); + res = mmurdregs(jmed, &ctxt); + if(res < 0) + sysfatal("mmurdregs %r"); + + printmmuregs(&ctxt, dbgstr, sizeof dbgstr); + fprint(2, "MMU state:\n%s\n", dbgstr); + + fprint(2, "---- Read mem --- \n"); + for(i = 0; i < 10; i++){ + res = armrdmemwd(jmed, ctxt.r[15]+4*i, &data, 4); + if(res < 0){ + fprint(2, "Error reading %#8.8ux pc[%d]\n", ctxt.r[15]+4*i, i); + break; + } + fprint(2, "Read data %#8.8ux addr %#8.8ux pc[%d]\n", + data, ctxt.r[15]+4*i, i); + } + + fprint(2, "---- Write mem (dangerous test) --- \n"); + + if(0) + for(i = 0; i < 10; i++){ + data = 0; + fprint(2, "Write data %#8.8ux addr %#8.8ux pc[%d]\n", data, ctxt.r[15]+4*i, i); + res = armwrmemwd(jmed, ctxt.r[15]+4*i, data, 4); + if(res < 0){ + fprint(2, "Error reading %#8.8ux pc[%d]\n", ctxt.r[15]+4*i, i); + break; + } + } + + fprint(2, "---- Unfreeze --- \n"); + res = iceexitdebug(jmed, &ctxt); + if(res < 0) + sysfatal("could not exit debug"); +} + + +void +main(int argc, char *argv[]) +{ + JMedium *jmed; + int tsh, rsh, i, jtagfd; + char *deb; + + deb = nil; + argv0 = "mpssetest"; + tsh = rsh = 0; + + ARGBEGIN{ + case 't': + tsh = 1; + break; + case 'r': + rsh = 1; + break; + case 'd': + deb = EARGF(usage()); + break; + default: + usage(); + } ARGEND + + if(argc != 1) + usage(); + + jtagfd = open(argv[0], ORDWR); + if(jtagfd < 0) + sysfatal("cannot open jtag file"); + + if(deb != nil) + for(i = 0; i < strlen(deb); i++) + debug[deb[i]]++; + Binit(&bin, 0, OREAD); + + if(tsh){ + jmed = newmpsse(jtagfd, Sheeva); + if(jmed == nil) + sysfatal("newmpsse %r"); + testsh(jmed); + } + else if(rsh){ + jmed = initmpsse(jtagfd, Sheeva); + if(jmed == nil) + sysfatal("initialization %r"); + hwreset(jmed); + } + else { + jmed = initmpsse(jtagfd, Sheeva); + if(jmed == nil) + sysfatal("initialization %r"); + + testice(jmed); + } + Bterm(&bin); + jmed->term(jmed); +} diff --git a/sys/src/cmd/jtagfs/tap.c b/sys/src/cmd/jtagfs/tap.c new file mode 100644 index 0000000000..00ea53895f --- /dev/null +++ b/sys/src/cmd/jtagfs/tap.c @@ -0,0 +1,269 @@ +#include +#include +#include "debug.h" +#include "tap.h" + + +static stdebug = 1; + +/* + !8c -FVw tap.c + !8l -o tap tap.8 + !tap > /tmp/l +*/ + +static char *stnames[] = { + [TapReset] "TapReset", + [TapIdle] "TapIdle", + [TapSelDR] "TapSelDR", + [TapCaptureDR] "TapCaptureDR" , + [TapShiftDR] "TapShiftDR", + [TapExit1DR] "TapExit1DR", + [TapPauseDR] "TapPauseDR", + [TapExit2DR] "TapExit2DR", + [TapUpdateDR] "TapUpdateDR", + [TapSelIR] "TapSelIR", + [TapCaptureIR] "TapCaptureIR", + [TapShiftIR] "TapShiftIR", + [TapExit1IR] "TapExit1IR", + [TapPauseIR] "TapPauseIR", + [TapExit2IR] "TapExit2IR", + [TapUpdateIR] "TapUpdateIR", + [NStates] "", + [TapUnknown] "TapUnknown", +}; + +typedef struct TapState TapState; +struct TapState { + int next[2]; +}; + + +static TapState sm[] = { + [TapReset] {TapIdle, TapReset}, + [TapIdle] {TapIdle, TapSelDR}, + [TapSelDR] {TapCaptureDR, TapSelIR}, + [TapCaptureDR] {TapShiftDR, TapExit1DR}, + [TapShiftDR] {TapShiftDR, TapExit1DR,}, + [TapExit1DR] {TapPauseDR, TapUpdateDR}, + [TapPauseDR] {TapPauseDR, TapExit2DR}, + [TapExit2DR] {TapShiftDR, TapUpdateDR}, + [TapUpdateDR] {TapIdle, TapSelDR}, + [TapSelIR] {TapCaptureIR, TapReset}, + [TapCaptureIR] {TapShiftIR, TapExit1IR}, + [TapShiftIR] {TapShiftIR, TapExit1IR}, + [TapExit1IR] {TapPauseIR, TapUpdateIR}, + [TapPauseIR] {TapPauseIR, TapExit2IR}, + [TapExit2IR] {TapShiftIR, TapUpdateIR}, + [TapUpdateIR] {TapIdle, TapSelDR}, +}; + +static int state=TapReset; + +static int +isvalidst(int state) +{ + if(state < 0 || state >= NStates && state != TapUnknown){ + fprint(2, "invalid state: %d\n", state); + return 0; + } + return 1; +} + +static int +tapsmmove(int state, int tms) +{ + assert(tms == 0 || tms == 1); + + state = sm[state].next[tms]; + + return state; +} + +/* + * To find the shortest path from here to a state + * go in parallel through all neighbour states till I find it + * with memoization of advancing passed states + * (Breadth First Search) + * (all paths weight the same, simple topology) + * could probably use this to generate a lookup table + * but all time is spent waiting for usb anyway + */ + +static void +movepath(SmPath *path, int tms, int newst) +{ + path->st = newst; + path->ptmslen++; + path->ptms <<= 1; + path->ptms |= tms; +} + + +static SmPath +findpath(int origin, int dest) +{ + int np, memost, tms, nc, i, j, ip, st; + SmPath paths[NStates], nextp, newp; + + memset(paths, 0, sizeof(SmPath)); + paths[0].st = origin; + np = 1; + memost = 0; + if(origin == dest) + return *paths; + + for(i = 0; i < NStates; i++){ + for(j = 0; j < np; j++){ + nc = 0; + nextp = paths[j]; + for(tms = 0; tms < 2; tms++){ + newp = nextp; + st = tapsmmove(newp.st, tms); + if((1 << st) & memost){ + if(++nc == 2) /*trapped state kill*/ + paths[j] = paths[--np]; + continue; + } + movepath(&newp, tms, st); + memost |= 1 << newp.st; + + if(newp.st == dest) + return newp; + if(tms == 0) + ip = j; + else + ip = np++; + paths[ip] = newp; + + } + } + } + fprint(2, "should not come through here\n"); + newp.st = -1; + return newp; +} + + +static void +concatpath(SmPath *p1, SmPath *p2) +{ + ulong msk; + assert(p1->ptmslen < 8*sizeof(p1->ptms)); + + msk = (1 << p2->ptmslen)-1; + p1->ptms = (p1->ptms << p2->ptmslen)|(p2->ptms & msk); + p1->ptmslen += p2->ptmslen; + p1->st = p2->st; +} + +static void +dumppath(SmPath *pth) +{ + uchar frstbit; + int i; + + fprint(2, "\n("); + for(i = 0; i < pth->ptmslen; i++){ + frstbit = (pth->ptms >> (pth->ptmslen-i-1))&1; + fprint(2, "tms[%d] = %ud ", i, frstbit); + } + fprint(2, ")\n"); +} + +SmPath +pathto(TapSm *sm, int dest) +{ + SmPath pth1, pth2; + + if(!isvalidst(sm->state) || !isvalidst(dest)) + sysfatal("invalid state"); + dprint(DState, "pathto: %s -> %s\n", + stnames[sm->state], stnames[dest]); + if(sm->state == TapUnknown){ + pth1.ptmslen = 5; /* resynch */ + pth1.ptms = 0x1f; + pth2 = findpath(TapReset, dest); + + concatpath(&pth1, &pth2); + if(debug[DPath]) + dumppath(&pth1); + return pth1; + } + pth1 = findpath(sm->state, dest); + if(debug[DPath]) + dumppath(&pth1); + return pth1; +} + +void +moveto(TapSm *sm, int dest) +{ + dprint(DState, "moveto: %s -> %s\n", + stnames[sm->state], stnames[dest]); + sm->state = dest; +} + +static ulong +pathpref(SmPath *pth, int nbits) +{ + ulong msk; + assert(pth->ptmslen >= nbits); + + msk = (1 << nbits)-1; + return msk & (pth->ptms >> (pth->ptmslen - nbits)); +} + +SmPath +takepathpref(SmPath *pth, int nbits) +{ + SmPath pref; + + pref.ptmslen = 0; + if(pth->ptmslen == 0) + return pref; + if(nbits > pth->ptmslen) + nbits = pth->ptmslen; + pref.ptmslen = nbits; + pref.ptms = pathpref(pth, nbits); + pth->ptmslen -= nbits; + return pref; +} + +/* + * Testing + +void +main(int, char *[]) +{ + SmPath pth; + TapSm sm; + int orig, dest; + + orig = TapReset; + dest = TapExit2DR; + + print("origin %s dest %s\n", stnames[orig], stnames[dest]); + pth = findpath(orig, dest); + print("\n"); + dumppath(&pth); + orig = TapShiftIR; + dest = TapExit2DR; + + print("origin %s dest %s\n", stnames[orig], stnames[dest]); + pth = findpath(orig, dest); + print("\n"); + dumppath(&pth); + orig = TapIdle; + dest = TapExit2IR; + + print("origin %s dest %s\n", stnames[orig], stnames[dest]); + pth = findpath(orig, dest); + print("\n"); + dumppath(&pth); + sm.state = TapUnknown; + pth = pathto(&sm, TapExit2DR); + dumppath(&pth); + +} +*/ diff --git a/sys/src/cmd/jtagfs/tap.h b/sys/src/cmd/jtagfs/tap.h new file mode 100644 index 0000000000..b684db7d24 --- /dev/null +++ b/sys/src/cmd/jtagfs/tap.h @@ -0,0 +1,53 @@ +typedef struct SmPath SmPath; +typedef struct TapSm TapSm; +typedef struct Tap Tap; + +enum{ + TapReset, + TapIdle, + TapSelDR, + TapCaptureDR, + TapShiftDR, + TapExit1DR, + TapPauseDR, + TapExit2DR, + TapUpdateDR, + TapSelIR, + TapCaptureIR, + TapShiftIR, + TapExit1IR, + TapPauseIR, + TapExit2IR, + TapUpdateIR, + NStates, + TapUnknown, +}; + + +enum { + TapDR, + TapIR = TapSelIR-TapSelDR, +}; + +struct TapSm{ + int state; +}; + +struct SmPath{ + ulong ptms; /* msb order on the lsb side, see comment on msb2lsb */ + ulong ptmslen; + int st; +}; + +struct Tap { + TapSm; + u32int hwid; + int irlen; + int drlen; + char name[32]; + void *private; +}; + +extern void moveto(TapSm *sm, int dest); +extern SmPath pathto(TapSm *sm, int dest); +extern SmPath takepathpref(SmPath *pth, int nbits); From aca801d3f708e60c81b8b3913b238e4144aabd34 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 7 Nov 2016 13:46:44 +0000 Subject: [PATCH 187/402] sys/src/cmd: import random command (thanks Geoff Collyer) --- sys/man/1/random | 24 ++++++++++++++++++++ sys/src/cmd/random.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 sys/man/1/random create mode 100644 sys/src/cmd/random.c diff --git a/sys/man/1/random b/sys/man/1/random new file mode 100644 index 0000000000..c8d5bcc095 --- /dev/null +++ b/sys/man/1/random @@ -0,0 +1,24 @@ +.TH RANDOM 1 +.SH NAME +random - print truly random probability or string +.SH SYNOPSIS +.B random +[ +.B -s +chars +] +.SH DESCRIPTION +.I Random +normally prints a truly random number between 0 and 1. +Given +.BR -s , +it instead prints a base-64-encoded truly random string of +.I chars +characters. +.SH SOURCE +.B /sys/src/cmd/random.c +.SH SEE ALSO +.IR rand (2), +.B /dev/random +in +.IR cons (3) diff --git a/sys/src/cmd/random.c b/sys/src/cmd/random.c new file mode 100644 index 0000000000..60478af7b8 --- /dev/null +++ b/sys/src/cmd/random.c @@ -0,0 +1,53 @@ +/* + * random - print a random number or string + */ + +#include +#include +#include +#include + +static int string, prchars, low, high; + +static void +usage(void) +{ + fprint(2, "usage: %s [-s nch]\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + char *buf, *out; + + ARGBEGIN { + case 's': + ++string; + prchars = atoi(EARGF(usage())); + break; + default: + usage(); + break; + } ARGEND + + if (!string) { + print("%f\n", (double)ntruerand(~0ul) / (1ull<<32)); + exits(0); + } + + /* fill buf from /dev/random */ + buf = malloc(prchars + 1); + if (buf == nil) + sysfatal("out of memory: %r"); + genrandom((uchar *)buf, prchars); + buf[prchars] = '\0'; + + /* encode as printable (base64) and print truncated */ + fmtinstall('[', encodefmt); + out = smprint("%.*[", prchars, buf); + if (out == nil) + sysfatal("out of memory: %r"); + print("%.*s\n", prchars, out); + exits(0); +} From 03fb05eaa7ea42bc466937cbb427c10323b761d8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 14 Sep 2017 21:05:55 +0000 Subject: [PATCH 188/402] sys/src/cmd: fix a bug folding newlines in strings constants in C code snippets in yacc (thanks Dan Cross) --- sys/src/cmd/yacc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/yacc.c b/sys/src/cmd/yacc.c index 251343054d..6e70ae82b6 100644 --- a/sys/src/cmd/yacc.c +++ b/sys/src/cmd/yacc.c @@ -2095,11 +2095,12 @@ cpyact(int offset) c = Bgetrune(finput); if(c == '\n') lineno++; - } else + } else { if(c == match) goto lcopy; if(c == '\n') error("newline in string or char. const."); + } Bputrune(faction, c); } error("EOF in string or character constant"); From 2e01b2fe77a058a26ff40a81333c0b76743cf22e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 1 May 2021 10:59:31 +0000 Subject: [PATCH 189/402] sys/src/cmd/lzip: import lzip (thanks Geoff Collyer) --- sys/man/1/gzip | 57 +- sys/src/cmd/lzip/AUTHORS | 7 + sys/src/cmd/lzip/COPYING | 338 +++++++++++ sys/src/cmd/lzip/ChangeLog | 115 ++++ sys/src/cmd/lzip/NEWS | 21 + sys/src/cmd/lzip/README | 126 ++++ sys/src/cmd/lzip/README.plan9 | 2 + sys/src/cmd/lzip/decoder.c | 294 +++++++++ sys/src/cmd/lzip/decoder.h | 354 +++++++++++ sys/src/cmd/lzip/encoder.c | 735 +++++++++++++++++++++++ sys/src/cmd/lzip/encoder.h | 323 ++++++++++ sys/src/cmd/lzip/encoder_base.c | 203 +++++++ sys/src/cmd/lzip/encoder_base.h | 559 ++++++++++++++++++ sys/src/cmd/lzip/fast_encoder.c | 188 ++++++ sys/src/cmd/lzip/fast_encoder.h | 71 +++ sys/src/cmd/lzip/lzip.h | 497 ++++++++++++++++ sys/src/cmd/lzip/main.c | 883 ++++++++++++++++++++++++++++ sys/src/cmd/lzip/mkfile | 21 + sys/src/cmd/lzip/testsuite/check.sh | 265 +++++++++ sys/src/cmd/lzip/testsuite/test.txt | 676 +++++++++++++++++++++ 20 files changed, 5725 insertions(+), 10 deletions(-) create mode 100644 sys/src/cmd/lzip/AUTHORS create mode 100644 sys/src/cmd/lzip/COPYING create mode 100644 sys/src/cmd/lzip/ChangeLog create mode 100644 sys/src/cmd/lzip/NEWS create mode 100644 sys/src/cmd/lzip/README create mode 100644 sys/src/cmd/lzip/README.plan9 create mode 100644 sys/src/cmd/lzip/decoder.c create mode 100644 sys/src/cmd/lzip/decoder.h create mode 100644 sys/src/cmd/lzip/encoder.c create mode 100644 sys/src/cmd/lzip/encoder.h create mode 100644 sys/src/cmd/lzip/encoder_base.c create mode 100644 sys/src/cmd/lzip/encoder_base.h create mode 100644 sys/src/cmd/lzip/fast_encoder.c create mode 100644 sys/src/cmd/lzip/fast_encoder.h create mode 100644 sys/src/cmd/lzip/lzip.h create mode 100644 sys/src/cmd/lzip/main.c create mode 100644 sys/src/cmd/lzip/mkfile create mode 100644 sys/src/cmd/lzip/testsuite/check.sh create mode 100644 sys/src/cmd/lzip/testsuite/test.txt diff --git a/sys/man/1/gzip b/sys/man/1/gzip index f56a6a2466..84c18c4987 100644 --- a/sys/man/1/gzip +++ b/sys/man/1/gzip @@ -1,12 +1,12 @@ .TH GZIP 1 .SH NAME -gzip, gunzip, bzip2, bunzip2, compress, uncompress, zip, unzip \- compress and expand data +gzip, gunzip, bzip2, bunzip2, lzip, lunzip, compress, uncompress, zip, unzip \- compress and expand data .SH SYNOPSIS .B gzip .RB [ -cvD [ 1-9 ]] .RI [ file .BR ... ] -.PP +.br .B gunzip .RB [ -ctTvD ] .RI [ file @@ -16,12 +16,22 @@ gzip, gunzip, bzip2, bunzip2, compress, uncompress, zip, unzip \- compress and e .RB [ -cvD [ 1-9 ]] .RI [ file .BR ... ] -.PP +.br .B bunzip2 .RB [ -cvD ] .RI [ file .BR ... ] .PP +.B lzip +.RB [ -cvD [ 1-9 ]] +.RI [ file +.BR ... ] +.br +.B lunzip +.RB [ -cvD ] +.RI [ file +.BR ... ] +.PP .B compress [ .B -cv @@ -29,7 +39,7 @@ gzip, gunzip, bzip2, bunzip2, compress, uncompress, zip, unzip \- compress and e .I file .B ... ] -.PP +.br .B uncompress [ .B -cv @@ -44,7 +54,7 @@ gzip, gunzip, bzip2, bunzip2, compress, uncompress, zip, unzip \- compress and e .IR zipfile ] .I file .RB [ ... ] -.PP +.br .B unzip .RB [ -cistTvD ] .RB [ -f @@ -86,7 +96,9 @@ are similar in interface to and .IR gunzip , but use a modified Burrows-Wheeler block sorting -compression algorithm. +compression algorithm, +which often produces smaller compressed files than +.IR gzip . The default suffix for output files is .BR .bz2 , with @@ -99,6 +111,32 @@ recognizes the extension as a synonym for .BR .tbz . .PP +.I Lzip +and +.I lunzip +are also similar in interface to +.I gzip +and +.IR gunzip , +but use a specific LZMA (Lempel-Ziv-Markov) compression algorithm, +which often produces smaller compressed files than +.IR bzip2 . +The default suffix for output files is +.BR .lz , +with +.B .tar.lz +becoming +.BR .tlz . +Note that the popular +.I xz +compression program uses different LZMA compression algorithms +and so files compressed by it will not be understood by +.I lunzip +and vice versa +(and may not even be understood by other +.I xz +implementations). +.PP .I Compress and .I uncompress @@ -130,7 +168,8 @@ None of these programs removes the original files. If the process fails, the faulty output files are removed. .PP The options are: -.TP 0.6i +.\" .TP 0.6i +.TP 0.3i .B -a Automaticialy creates directories as needed, needed for zip files created by broken implementations which omit directories. @@ -183,9 +222,7 @@ prints the names of files on standard error as they are compressed or decompress .B -D Produce debugging output. .SH SOURCE -.B /sys/src/cmd/gzip -.br -.B /sys/src/cmd/bzip2 +.B /sys/src/cmd/*zip* .br .B /sys/src/cmd/compress .SH SEE ALSO diff --git a/sys/src/cmd/lzip/AUTHORS b/sys/src/cmd/lzip/AUTHORS new file mode 100644 index 0000000000..3b49e65a70 --- /dev/null +++ b/sys/src/cmd/lzip/AUTHORS @@ -0,0 +1,7 @@ +Clzip was written by Antonio Diaz Diaz. + +The ideas embodied in clzip are due to (at least) the following people: +Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for +the definition of Markov chains), G.N.N. Martin (for the definition of +range encoding), Igor Pavlov (for putting all the above together in +LZMA), and Julian Seward (for bzip2's CLI). diff --git a/sys/src/cmd/lzip/COPYING b/sys/src/cmd/lzip/COPYING new file mode 100644 index 0000000000..4ad17aece1 --- /dev/null +++ b/sys/src/cmd/lzip/COPYING @@ -0,0 +1,338 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sys/src/cmd/lzip/ChangeLog b/sys/src/cmd/lzip/ChangeLog new file mode 100644 index 0000000000..88b6ab21a0 --- /dev/null +++ b/sys/src/cmd/lzip/ChangeLog @@ -0,0 +1,115 @@ +2017-04-13 Antonio Diaz Diaz + + * Version 1.9 released. + * The option '-l, --list' has been ported from lziprecover. + * Don't allow mixing different operations (-d, -l or -t). + * Compression time of option '-0' has been reduced by 6%. + * Compression time of options -1 to -9 has been reduced by 1%. + * Decompression time has been reduced by 7%. + * main.c: Continue testing if any input file is a terminal. + * main.c: Show trailing data in both hexadecimal and ASCII. + * file_index.c: Improve detection of bad dict and trailing data. + * lzip.h: Unified messages for bad magic, trailing data, etc. + * clzip.texi: Added missing chapters from lzip.texi. + +2016-05-13 Antonio Diaz Diaz + + * Version 1.8 released. + * main.c: Added new option '-a, --trailing-error'. + * main.c (decompress): Print up to 6 bytes of trailing data + when '-vvvv' is specified. + * decoder.c (LZd_verify_trailer): Removed test of final code. + * main.c (main): Delete '--output' file if infd is a terminal. + * main.c (main): Don't use stdin more than once. + * clzip.texi: Added chapter 'Trailing data'. + * configure: Avoid warning on some shells when testing for gcc. + * Makefile.in: Detect the existence of install-info. + * testsuite/check.sh: A POSIX shell is required to run the tests. + * testsuite/check.sh: Don't check error messages. + +2015-07-07 Antonio Diaz Diaz + + * Version 1.7 released. + * Ported fast encoder and option '-0' from lzip. + * Makefile.in: Added new targets 'install*-compress'. + +2014-08-28 Antonio Diaz Diaz + + * Version 1.6 released. + * Compression ratio of option '-9' has been slightly increased. + * main.c (close_and_set_permissions): Behave like 'cp -p'. + * clzip.texinfo: Renamed to clzip.texi. + * License changed to GPL version 2 or later. + +2013-09-17 Antonio Diaz Diaz + + * Version 1.5 released. + * Show progress of compression at verbosity level 2 (-vv). + * main.c (show_header): Don't show header version. + * Ignore option '-n, --threads' for compatibility with plzip. + * configure: Options now accept a separate argument. + +2013-02-18 Antonio Diaz Diaz + + * Version 1.4 released. + * Multi-step trials have been implemented. + * Compression ratio has been slightly increased. + * Compression time has been reduced by 10%. + * Decompression time has been reduced by 8%. + * Makefile.in: Added new target 'install-as-lzip'. + * Makefile.in: Added new target 'install-bin'. + * main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2. + * main.c: Define 'strtoull' to 'strtoul' on Windows. + +2012-02-25 Antonio Diaz Diaz + + * Version 1.3 released. + * main.c (close_and_set_permissions): Inability to change output + file attributes has been downgraded from error to warning. + * encoder.c (Mf_init): Return false if out of memory instead of + calling cleanup_and_fail. + * Small change in '--help' output and man page. + * Changed quote characters in messages as advised by GNU Standards. + * configure: 'datadir' renamed to 'datarootdir'. + +2011-05-18 Antonio Diaz Diaz + + * Version 1.2 released. + * main.c: Added new option '-F, --recompress'. + * main.c (decompress): Print only one status line for each + multimember file when only one '-v' is specified. + * encoder.h (Lee_update_prices): Update high length symbol prices + independently of the value of 'pos_state'. This gives better + compression for large values of '--match-length' without being + slower. + * encoder.h encoder.c: Optimize pair price calculations. This + reduces compression time for large values of '--match-length' + by up to 6%. + +2011-01-11 Antonio Diaz Diaz + + * Version 1.1 released. + * Code has been converted to 'C89 + long long' from C99. + * main.c: Fixed warning about fchown return value being ignored. + * decoder.c: '-tvvvv' now shows compression ratio. + * main.c: Match length limit set by options -1 to -8 has been + reduced to extend range of use towards gzip. Lower numbers now + compress less but faster. (-1 now takes 43% less time for only + 20% larger compressed size). + * Compression ratio of option '-9' has been slightly increased. + * main.c (open_instream): Don't show the message + " and '--stdout' was not specified" for directories, etc. + * New examples have been added to the manual. + +2010-04-05 Antonio Diaz Diaz + + * Version 1.0 released. + * Initial release. + * Translated to C from the C++ source of lzip 1.10. + + +Copyright (C) 2010-2017 Antonio Diaz Diaz. + +This file is a collection of facts, and thus it is not copyrightable, +but just in case, you have unlimited permission to copy, distribute and +modify it. diff --git a/sys/src/cmd/lzip/NEWS b/sys/src/cmd/lzip/NEWS new file mode 100644 index 0000000000..1f85396b0e --- /dev/null +++ b/sys/src/cmd/lzip/NEWS @@ -0,0 +1,21 @@ +Changes in version 1.9: + +The option '-l, --list' has been ported from lziprecover. + +It is now an error to specify two or more different operations in the +command line (--decompress, --list or --test). + +Compression time of option '-0' has been reduced by 6%. + +Compression time of options '-1' to '-9' has been reduced by 1%. + +Decompression time has been reduced by 7%. + +In test mode, clzip now continues checking the rest of the files if any +input file is a terminal. + +Trailing data are now shown both in hexadecimal and as a string of +printable ASCII characters. + +Three missing chapters have been added to the manual, which now contains +all the chapters of the lzip manual. diff --git a/sys/src/cmd/lzip/README b/sys/src/cmd/lzip/README new file mode 100644 index 0000000000..cc5fd73911 --- /dev/null +++ b/sys/src/cmd/lzip/README @@ -0,0 +1,126 @@ +Description + +Clzip is a C language version of lzip, fully compatible with lzip-1.4 or +newer. As clzip is written in C, it may be easier to integrate in +applications like package managers, embedded devices, or systems lacking +a C++ compiler. + +Lzip is a lossless data compressor with a user interface similar to the +one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0), +or compress most files more than bzip2 (lzip -9). Decompression speed is +intermediate between gzip and bzip2. Lzip is better than gzip and bzip2 +from a data recovery perspective. + +The lzip file format is designed for data sharing and long-term +archiving, taking into account both data integrity and decoder +availability: + + * The lzip format provides very safe integrity checking and some data + recovery means. The lziprecover program can repair bit-flip errors + (one of the most common forms of data corruption) in lzip files, + and provides data recovery capabilities, including error-checked + merging of damaged copies of a file. + + * The lzip format is as simple as possible (but not simpler). The + lzip manual provides the source code of a simple decompressor along + with a detailed explanation of how it works, so that with the only + help of the lzip manual it would be possible for a digital + archaeologist to extract the data from a lzip file long after + quantum computers eventually render LZMA obsolete. + + * Additionally the lzip reference implementation is copylefted, which + guarantees that it will remain free forever. + +A nice feature of the lzip format is that a corrupt byte is easier to +repair the nearer it is from the beginning of the file. Therefore, with +the help of lziprecover, losing an entire archive just because of a +corrupt byte near the beginning is a thing of the past. + +Clzip uses the same well-defined exit status values used by lzip and +bzip2, which makes it safer than compressors returning ambiguous warning +values (like gzip) when it is used as a back end for other programs like +tar or zutils. + +Clzip will automatically use the smallest possible dictionary size for +each file without exceeding the given limit. Keep in mind that the +decompression memory requirement is affected at compression time by the +choice of dictionary size limit. + +The amount of memory required for compression is about 1 or 2 times the +dictionary size limit (1 if input file size is less than dictionary size +limit, else 2) plus 9 times the dictionary size really used. The option +'-0' is special and only requires about 1.5 MiB at most. The amount of +memory required for decompression is about 46 kB larger than the +dictionary size really used. + +When compressing, clzip replaces every file given in the command line +with a compressed version of itself, with the name "original_name.lz". +When decompressing, clzip attempts to guess the name for the decompressed +file from that of the compressed file as follows: + +filename.lz becomes filename +filename.tlz becomes filename.tar +anyothername becomes anyothername.out + +(De)compressing a file is much like copying or moving it; therefore clzip +preserves the access and modification dates, permissions, and, when +possible, ownership of the file just as "cp -p" does. (If the user ID or +the group ID can't be duplicated, the file permission bits S_ISUID and +S_ISGID are cleared). + +Clzip is able to read from some types of non regular files if the +"--stdout" option is specified. + +If no file names are specified, clzip compresses (or decompresses) from +standard input to standard output. In this case, clzip will decline to +write compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +Clzip will correctly decompress a file which is the concatenation of two +or more compressed files. The result is the concatenation of the +corresponding uncompressed files. Integrity testing of concatenated +compressed files is also supported. + +Clzip can produce multimember files, and lziprecover can safely recover +the undamaged members in case of file damage. Clzip can also split the +compressed output in volumes of a given size, even when reading from +standard input. This allows the direct creation of multivolume +compressed tar archives. + +Clzip is able to compress and decompress streams of unlimited size by +automatically creating multimember output. The members so created are +large, about 2 PiB each. + +In spite of its name (Lempel-Ziv-Markov chain-Algorithm), LZMA is not a +concrete algorithm; it is more like "any algorithm using the LZMA coding +scheme". For example, the option '-0' of lzip uses the scheme in almost +the simplest way possible; issuing the longest match it can find, or a +literal byte if it can't find a match. Inversely, a much more elaborated +way of finding coding sequences of minimum size than the one currently +used by lzip could be developed, and the resulting sequence could also +be coded using the LZMA coding scheme. + +Clzip currently implements two variants of the LZMA algorithm; fast +(used by option '-0') and normal (used by all other compression levels). + +The high compression of LZMA comes from combining two basic, well-proven +compression ideas: sliding dictionaries (LZ77/78) and markov models (the +thing used by every compression algorithm that uses a range encoder or +similar order-0 entropy coder as its last stage) with segregation of +contexts according to what the bits are used for. + +The ideas embodied in clzip are due to (at least) the following people: +Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for +the definition of Markov chains), G.N.N. Martin (for the definition of +range encoding), Igor Pavlov (for putting all the above together in +LZMA), and Julian Seward (for bzip2's CLI). + + +Copyright (C) 2010-2017 Antonio Diaz Diaz. + +This file is free documentation: you have unlimited permission to copy, +distribute and modify it. + +The file Makefile.in is a data file used by configure to produce the +Makefile. It has the same copyright owner and permissions that configure +itself. diff --git a/sys/src/cmd/lzip/README.plan9 b/sys/src/cmd/lzip/README.plan9 new file mode 100644 index 0000000000..08bb1c5939 --- /dev/null +++ b/sys/src/cmd/lzip/README.plan9 @@ -0,0 +1,2 @@ +This is clzip 1.9, tuned and somewhat beautified. +It's still not pretty but it's legible. diff --git a/sys/src/cmd/lzip/decoder.c b/sys/src/cmd/lzip/decoder.c new file mode 100644 index 0000000000..01485ed708 --- /dev/null +++ b/sys/src/cmd/lzip/decoder.c @@ -0,0 +1,294 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +#include "lzip.h" +#include "decoder.h" + +void +Pp_show_msg(Pretty_print *pp, char *msg) +{ + if (verbosity >= 0) { + if (pp->first_post) { + unsigned i; + + pp->first_post = false; + fprintf(stderr, "%s: ", pp->name); + for (i = strlen(pp->name); i < pp->longest_name; ++i) + fputc(' ', stderr); + if (!msg) + fflush(stderr); + } + if (msg) + fprintf(stderr, "%s\n", msg); + } +} + +/* Returns the number of bytes really read. + If returned value < size and no read error, means EOF was reached. + */ +int +readblock(int fd, uchar *buf, int size) +{ + int n, sz; + + for (sz = 0; sz < size; sz += n) { + n = read(fd, buf + sz, size - sz); + if (n <= 0) + break; + } + return sz; +} + +/* Returns the number of bytes really written. + If (returned value < size), it is always an error. + */ +int +writeblock(int fd, uchar *buf, int size) +{ + int n, sz; + + for (sz = 0; sz < size; sz += n) { + n = write(fd, buf + sz, size - sz); + if (n != size - sz) + break; + } + return sz; +} + +bool +Rd_read_block(Range_decoder *rdec) +{ + if (!rdec->at_stream_end) { + rdec->stream_pos = readblock(rdec->infd, rdec->buffer, rd_buffer_size); + if (rdec->stream_pos != rd_buffer_size && errno) { + show_error( "Read error", errno, false ); + cleanup_and_fail(1); + } + rdec->at_stream_end = (rdec->stream_pos < rd_buffer_size); + rdec->partial_member_pos += rdec->pos; + rdec->pos = 0; + } + return rdec->pos < rdec->stream_pos; +} + +void +LZd_flush_data(LZ_decoder *d) +{ + if (d->pos > d->stream_pos) { + int size = d->pos - d->stream_pos; + CRC32_update_buf(&d->crc, d->buffer + d->stream_pos, size); + if (d->outfd >= 0 && + writeblock(d->outfd, d->buffer + d->stream_pos, size) != size) { + show_error( "Write error", errno, false ); + cleanup_and_fail(1); + } + if (d->pos >= d->dict_size) { + d->partial_data_pos += d->pos; + d->pos = 0; + d->pos_wrapped = true; + } + d->stream_pos = d->pos; + } +} + +static bool +LZd_verify_trailer(LZ_decoder *d, Pretty_print *pp) +{ + File_trailer trailer; + int size = Rd_read_data(d->rdec, trailer, Ft_size); + uvlong data_size = LZd_data_position(d); + uvlong member_size = Rd_member_position(d->rdec); + bool error = false; + + if (size < Ft_size) { + error = true; + if (verbosity >= 0) { + Pp_show_msg(pp, 0); + fprintf( stderr, "Trailer truncated at trailer position %d;" + " some checks may fail.\n", size ); + } + while (size < Ft_size) + trailer[size++] = 0; + } + + if (Ft_get_data_crc(trailer) != LZd_crc(d)) { + error = true; + if (verbosity >= 0) { + Pp_show_msg(pp, 0); + fprintf( stderr, "CRC mismatch; trailer says %08X, data CRC is %08X\n", + Ft_get_data_crc(trailer), LZd_crc(d)); + } + } + if (Ft_get_data_size(trailer) != data_size) { + error = true; + if (verbosity >= 0) { + Pp_show_msg(pp, 0); + fprintf( stderr, "Data size mismatch; trailer says %llud, data size is %llud (0x%lluX)\n", + Ft_get_data_size(trailer), data_size, data_size); + } + } + if (Ft_get_member_size(trailer) != member_size) { + error = true; + if (verbosity >= 0) { + Pp_show_msg(pp, 0); + fprintf(stderr, "Member size mismatch; trailer says %llud, member size is %llud (0x%lluX)\n", + Ft_get_member_size(trailer), member_size, member_size); + } + } + if (0 && !error && verbosity >= 2 && data_size > 0 && member_size > 0) + fprintf(stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", + (double)data_size / member_size, + (8.0 * member_size) / data_size, + 100.0 * (1.0 - (double)member_size / data_size)); + if (!error && verbosity >= 4) + fprintf( stderr, "CRC %08X, decompressed %9llud, compressed %8llud. ", + LZd_crc(d), data_size, member_size); + return !error; +} + +/* Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF, + 3 = trailer error, 4 = unknown marker found. */ +int +LZd_decode_member(LZ_decoder *d, Pretty_print *pp) +{ + Range_decoder *rdec = d->rdec; + Bit_model bm_literal[1<= start_dis_model) { + unsigned dis_slot = distance; + int direct_bits = (dis_slot >> 1) - 1; + distance = (2 | (dis_slot & 1)) << direct_bits; + if (dis_slot < end_dis_model) + distance += Rd_decode_tree_reversed(rdec, + bm_dis + (distance - dis_slot), direct_bits); + else { + distance += + Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits; + distance += Rd_decode_tree_reversed4(rdec, bm_align); + if (distance == 0xFFFFFFFFU) /* marker found */ { + Rd_normalize(rdec); + LZd_flush_data(d); + if (len == min_match_len) /* End Of Stream marker */ { + if (LZd_verify_trailer(d, pp)) +/* code folded from here */ + return 0; +/* unfolding */ + else +/* code folded from here */ + return 3; +/* unfolding */ + } + if (len == min_match_len + 1) /* Sync Flush marker */ { + Rd_load(rdec); + continue; + } + if (verbosity >= 0) { + Pp_show_msg(pp, 0); + fprintf( stderr, "Unsupported marker code '%d'\n", len ); + } + return 4; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance; + state = St_set_match(state); + if (rep0 >= d->dict_size || (rep0 >= d->pos && !d->pos_wrapped)) { + LZd_flush_data(d); + return 1; + } + } + LZd_copy_block(d, rep0, len); + } + } + LZd_flush_data(d); + return 2; +} + diff --git a/sys/src/cmd/lzip/decoder.h b/sys/src/cmd/lzip/decoder.h new file mode 100644 index 0000000000..5f000e7f09 --- /dev/null +++ b/sys/src/cmd/lzip/decoder.h @@ -0,0 +1,354 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +enum { rd_buffer_size = 16384 }; + +typedef struct LZ_decoder LZ_decoder; +typedef struct Range_decoder Range_decoder; + +struct Range_decoder { + uvlong partial_member_pos; + uchar * buffer; /* input buffer */ + int pos; /* current pos in buffer */ + int stream_pos; /* when reached, a new block must be read */ + uint32_t code; + uint32_t range; + int infd; /* input file descriptor */ + bool at_stream_end; +}; + +bool Rd_read_block(Range_decoder *rdec); + +static bool +Rd_init(Range_decoder *rdec, int ifd) +{ + rdec->partial_member_pos = 0; + rdec->buffer = (uchar *)malloc(rd_buffer_size); + if (!rdec->buffer) + return false; + rdec->pos = 0; + rdec->stream_pos = 0; + rdec->code = 0; + rdec->range = 0xFFFFFFFFU; + rdec->infd = ifd; + rdec->at_stream_end = false; + return true; +} + +static void +Rd_free(Range_decoder *rdec) +{ + free(rdec->buffer); +} + +static bool +Rd_finished(Range_decoder *rdec) +{ + return rdec->pos >= rdec->stream_pos && !Rd_read_block(rdec); +} + +static uvlong +Rd_member_position(Range_decoder *rdec) +{ + return rdec->partial_member_pos + rdec->pos; +} + +static void +Rd_reset_member_position(Range_decoder *rdec) +{ + rdec->partial_member_pos = 0; + rdec->partial_member_pos -= rdec->pos; +} + +static uchar +Rd_get_byte(Range_decoder *rdec) +{ + /* 0xFF avoids decoder error if member is truncated at EOS marker */ + if (Rd_finished(rdec)) + return 0xFF; + return rdec->buffer[rdec->pos++]; +} + +static int Rd_read_data(Range_decoder *rdec, uchar *outbuf, int size) +{ + int sz = 0; + + while (sz < size && !Rd_finished(rdec)) { + int rd, rsz = size - sz; + int rpos = rdec->stream_pos - rdec->pos; + + if (rsz < rpos) + rd = rsz; + else + rd = rpos; + memcpy(outbuf + sz, rdec->buffer + rdec->pos, rd); + rdec->pos += rd; + sz += rd; + } + return sz; +} + +static void +Rd_load(Range_decoder *rdec) +{ + int i; + rdec->code = 0; + for (i = 0; i < 5; ++i) + rdec->code = (rdec->code << 8) | Rd_get_byte(rdec); + rdec->range = 0xFFFFFFFFU; + rdec->code &= rdec->range; /* make sure that first byte is discarded */ +} + +static void +Rd_normalize(Range_decoder *rdec) +{ + if (rdec->range <= 0x00FFFFFFU) { + rdec->range <<= 8; + rdec->code = (rdec->code << 8) | Rd_get_byte(rdec); + } +} + +static unsigned +Rd_decode(Range_decoder *rdec, int num_bits) +{ + unsigned symbol = 0; + int i; + for (i = num_bits; i > 0; --i) { + bool bit; + Rd_normalize(rdec); + rdec->range >>= 1; + /* symbol <<= 1; */ + /* if(rdec->code >= rdec->range) { rdec->code -= rdec->range; symbol |= 1; } */ + bit = (rdec->code >= rdec->range); + symbol = (symbol << 1) + bit; + rdec->code -= rdec->range & (0U - bit); + } + return symbol; +} + +static unsigned +Rd_decode_bit(Range_decoder *rdec, Bit_model *probability) +{ + uint32_t bound; + Rd_normalize(rdec); + bound = (rdec->range >> bit_model_total_bits) * *probability; + if (rdec->code < bound) { + rdec->range = bound; + *probability += (bit_model_total - *probability) >> bit_model_move_bits; + return 0; + } else { + rdec->range -= bound; + rdec->code -= bound; + *probability -= *probability >> bit_model_move_bits; + return 1; + } +} + +static unsigned +Rd_decode_tree3(Range_decoder *rdec, Bit_model bm[]) +{ + unsigned symbol = 1; + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + return symbol & 7; +} + +static unsigned +Rd_decode_tree6(Range_decoder *rdec, Bit_model bm[]) +{ + unsigned symbol = 1; + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + return symbol & 0x3F; +} + +static unsigned +Rd_decode_tree8(Range_decoder *rdec, Bit_model bm[]) +{ + unsigned symbol = 1; + int i; + for (i = 0; i < 8; ++i) + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]); + return symbol & 0xFF; +} + +static unsigned +Rd_decode_tree_reversed(Range_decoder *rdec, Bit_model bm[], int num_bits) +{ + unsigned model = 1; + unsigned symbol = 0; + int i; + for (i = 0; i < num_bits; ++i) { + unsigned bit = Rd_decode_bit(rdec, &bm[model]); + model = (model << 1) + bit; + symbol |= (bit << i); + } + return symbol; +} + +static unsigned +Rd_decode_tree_reversed4(Range_decoder *rdec, Bit_model bm[]) +{ + unsigned symbol = Rd_decode_bit(rdec, &bm[1]); + unsigned model = 2 + symbol; + unsigned bit = Rd_decode_bit(rdec, &bm[model]); + model = (model << 1) + bit; + symbol |= (bit << 1); + bit = Rd_decode_bit(rdec, &bm[model]); + model = (model << 1) + bit; + symbol |= (bit << 2); + symbol |= (Rd_decode_bit(rdec, &bm[model]) << 3); + return symbol; +} + +static unsigned +Rd_decode_matched(Range_decoder *rdec, Bit_model bm[], unsigned match_byte) +{ + unsigned symbol = 1; + unsigned mask = 0x100; + while (true) { + unsigned match_bit = (match_byte <<= 1) & mask; + unsigned bit = Rd_decode_bit(rdec, &bm[symbol+match_bit+mask]); + symbol = (symbol << 1) + bit; + if (symbol > 0xFF) + return symbol & 0xFF; + mask &= ~(match_bit ^ (bit << 8)); /* if(match_bit != bit) mask = 0; */ + } +} + +static unsigned +Rd_decode_len(struct Range_decoder *rdec, Len_model *lm, int pos_state) +{ + if (Rd_decode_bit(rdec, &lm->choice1) == 0) + return Rd_decode_tree3(rdec, lm->bm_low[pos_state]); + if (Rd_decode_bit(rdec, &lm->choice2) == 0) + return len_low_syms + Rd_decode_tree3(rdec, lm->bm_mid[pos_state]); + return len_low_syms + len_mid_syms + Rd_decode_tree8(rdec, lm->bm_high); +} + +struct LZ_decoder { + uvlong partial_data_pos; + struct Range_decoder *rdec; + unsigned dict_size; + uchar * buffer; /* output buffer */ + unsigned pos; /* current pos in buffer */ + unsigned stream_pos; /* first byte not yet written to file */ + uint32_t crc; + int outfd; /* output file descriptor */ + bool pos_wrapped; +}; + +void LZd_flush_data(LZ_decoder *d); + +static uchar +LZd_peek_prev(LZ_decoder *d) +{ + if (d->pos > 0) + return d->buffer[d->pos-1]; + if (d->pos_wrapped) + return d->buffer[d->dict_size-1]; + return 0; /* prev_byte of first byte */ +} + +static uchar +LZd_peek(LZ_decoder *d, +unsigned distance) +{ + unsigned i = ((d->pos > distance) ? 0 : d->dict_size) + + d->pos - distance - 1; + return d->buffer[i]; +} + +static void +LZd_put_byte(LZ_decoder *d, uchar b) +{ + d->buffer[d->pos] = b; + if (++d->pos >= d->dict_size) + LZd_flush_data(d); +} + +static void +LZd_copy_block(LZ_decoder *d, unsigned distance, unsigned len) +{ + unsigned lpos = d->pos, i = lpos -distance -1; + bool fast, fast2; + + if (lpos > distance) { + fast = (len < d->dict_size - lpos); + fast2 = (fast && len <= lpos - i); + } else { + i += d->dict_size; + fast = (len < d->dict_size - i); /* (i == pos) may happen */ + fast2 = (fast && len <= i - lpos); + } + if (fast) /* no wrap */ { + d->pos += len; + if (fast2) /* no wrap, no overlap */ + memcpy(d->buffer + lpos, d->buffer + i, len); + else + for (; len > 0; --len) + d->buffer[lpos++] = d->buffer[i++]; + } else + for (; len > 0; --len) { + d->buffer[d->pos] = d->buffer[i]; + if (++d->pos >= d->dict_size) + LZd_flush_data(d); + if (++i >= d->dict_size) + i = 0; + } +} + +static bool +LZd_init(struct LZ_decoder *d, Range_decoder *rde, unsigned dict_size, int ofd) +{ + d->partial_data_pos = 0; + d->rdec = rde; + d->dict_size = dict_size; + d->buffer = (uchar *)malloc(d->dict_size); + if (!d->buffer) + return false; + d->pos = 0; + d->stream_pos = 0; + d->crc = 0xFFFFFFFFU; + d->outfd = ofd; + d->pos_wrapped = false; + return true; +} + +static void +LZd_free(LZ_decoder *d) +{ + free(d->buffer); +} + +static unsigned +LZd_crc(LZ_decoder *d) +{ + return d->crc ^ 0xFFFFFFFFU; +} + +static uvlong +LZd_data_position(LZ_decoder *d) +{ + return d->partial_data_pos + d->pos; +} + +int LZd_decode_member(struct LZ_decoder *d, Pretty_print *pp); diff --git a/sys/src/cmd/lzip/encoder.c b/sys/src/cmd/lzip/encoder.c new file mode 100644 index 0000000000..5b0e782597 --- /dev/null +++ b/sys/src/cmd/lzip/encoder.c @@ -0,0 +1,735 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +#include "lzip.h" +#include "encoder_base.h" +#include "encoder.h" + +CRC32 crc32; + +/* + * starting at data[len] and data[len-delta], what's the longest match + * up to len_limit? + */ +int +maxmatch(uchar *data, int delta, int len, int len_limit) +{ + uchar *pdel, *p; + + p = &data[len]; + pdel = p - delta; + while (*pdel++ == *p++ && len < len_limit) + ++len; + return len; +} + +static int +findpairmaxlen(LZ_encoder *e, Pair **pairsp, int *npairsp, int maxlen, int pos1, + int len_limit, int min_pos, uchar *data, int np2, int np3) +{ + int num_pairs; + Pair *pairs; + + pairs = *pairsp; + num_pairs = *npairsp; + if (np2 > min_pos && e->eb.mb.buffer[np2-1] == data[0]) { + pairs[0].dis = e->eb.mb.pos - np2; + pairs[0].len = maxlen = 2; + num_pairs = 1; + } + if (np2 != np3 && np3 > min_pos && e->eb.mb.buffer[np3-1] == data[0]) { + maxlen = 3; + np2 = np3; + pairs[num_pairs].dis = e->eb.mb.pos - np2; + ++num_pairs; + } + if (num_pairs > 0) { + maxlen = maxmatch(data, pos1 - np2, maxlen, len_limit); + pairs[num_pairs-1].len = maxlen; + if (maxlen >= len_limit) + *pairsp = nil; /* done. now just skip */ + } + if (maxlen < 3) + maxlen = 3; + *npairsp = num_pairs; + return maxlen; +} + +int +LZe_get_match_pairs(LZ_encoder *e, Pair *pairs) +{ + int len = 0, len0, len1, maxlen, num_pairs, len_limit, avail; + int pos1, min_pos, cyclic_pos, delta, count, key2, key3, key4, newpos1; + int32_t *ptr0, *ptr1, *newptr, *prevpos; + uchar *data; + uchar *p; + unsigned tmp; + + len_limit = e->match_len_limit; + avail = Mb_avail_bytes(&e->eb.mb); + if (len_limit > avail) { + len_limit = avail; + if (len_limit < 4) + return 0; + } + + data = Mb_ptr_to_current_pos(&e->eb.mb); + tmp = crc32[data[0]] ^ data[1]; + key2 = tmp & (Nprevpos2 - 1); + tmp ^= (unsigned)data[2] << 8; + key3 = Nprevpos2 + (tmp & (Nprevpos3 - 1)); + key4 = Nprevpos2 + Nprevpos3 + + ((tmp ^ (crc32[data[3]] << 5)) & e->eb.mb.key4_mask); + + min_pos = (e->eb.mb.pos > e->eb.mb.dict_size) ? + e->eb.mb.pos - e->eb.mb.dict_size : 0; + pos1 = e->eb.mb.pos + 1; + prevpos = e->eb.mb.prev_positions; + maxlen = 0; + num_pairs = 0; + if (pairs) + maxlen = findpairmaxlen(e, &pairs, &num_pairs, maxlen, pos1, + len_limit, min_pos, data, prevpos[key2], prevpos[key3]); + newpos1 = prevpos[key4]; + prevpos[key2] = prevpos[key3] = prevpos[key4] = pos1; + + cyclic_pos = e->eb.mb.cyclic_pos; + ptr0 = e->eb.mb.pos_array + (cyclic_pos << 1); + ptr1 = ptr0 + 1; + len0 = len1 = 0; + for (count = e->cycles; ;) { + if (newpos1 <= min_pos || --count < 0) { + *ptr0 = *ptr1 = 0; + break; + } + + delta = pos1 - newpos1; + newptr = e->eb.mb.pos_array + ((cyclic_pos - delta + + (cyclic_pos >= delta? 0: e->eb.mb.dict_size + 1)) << 1); + p = &data[len]; + if (p[-delta] == *p) { + len = maxmatch(data, delta, len + 1, len_limit); + if (pairs && maxlen < len) { + pairs[num_pairs].dis = delta - 1; + pairs[num_pairs].len = maxlen = len; + ++num_pairs; + } + if (len >= len_limit) { + *ptr0 = newptr[0]; + *ptr1 = newptr[1]; + break; + } + p = &data[len]; + } + if (p[-delta] < *p) { + *ptr0 = newpos1; + ptr0 = newptr + 1; + newpos1 = *ptr0; + len0 = len; + if (len1 < len) + len = len1; + } else { + *ptr1 = newpos1; + ptr1 = newptr; + newpos1 = *ptr1; + len1 = len; + if (len0 < len) + len = len0; + } + } + return num_pairs; +} + +static void +LZe_update_distance_prices(LZ_encoder *e) +{ + int dis, len_state; + + for (dis = start_dis_model; dis < modeled_distances; ++dis) { + int dis_slot = dis_slots[dis]; + int direct_bits = (dis_slot >> 1) - 1; + int base = (2 | (dis_slot & 1)) << direct_bits; + int price = price_symbol_reversed(e->eb.bm_dis + (base - dis_slot), + dis - base, direct_bits); + + for (len_state = 0; len_state < len_states; ++len_state) + e->dis_prices[len_state][dis] = price; + } + + for (len_state = 0; len_state < len_states; ++len_state) { + int *dsp = e->dis_slot_prices[len_state]; + int *dp = e->dis_prices[len_state]; + Bit_model * bmds = e->eb.bm_dis_slot[len_state]; + int slot = 0; + + for (; slot < end_dis_model; ++slot) + dsp[slot] = price_symbol6(bmds, slot); + for (; slot < e->num_dis_slots; ++slot) + dsp[slot] = price_symbol6(bmds, slot) + + ((((slot >> 1) - 1) - dis_align_bits) << price_shift_bits); + + for (dis = 0; dis < start_dis_model; ++dis) + dp[dis] = dsp[dis]; + for (; dis < modeled_distances; ++dis) + dp[dis] += dsp[dis_slots[dis]]; + } +} + +static int +pricestate2(LZ_encoder *e, int price, int *ps2p, State *st2p, int len2) +{ + int pos_state2; + State state2; + + state2 = *st2p; + pos_state2 = *ps2p; + + pos_state2 = (pos_state2 + 1) & pos_state_mask; + state2 = St_set_char(state2); + price += price1(e->eb.bm_match[state2][pos_state2]) + + price1(e->eb.bm_rep[state2]) + + LZe_price_rep0_len(e, len2, state2, pos_state2); + + *ps2p = pos_state2; + *st2p = state2; + return price; +} + +static int +encinit(LZ_encoder *e, int reps[num_rep_distances], + int replens[num_rep_distances], State state, int main_len, + int num_pairs, int rep_index, int *ntrialsp) +{ + int i, rep, num_trials, len; + int pos_state = Mb_data_position(&e->eb.mb) & pos_state_mask; + int match_price = price1(e->eb.bm_match[state][pos_state]); + int rep_match_price = match_price + price1(e->eb.bm_rep[state]); + uchar prev_byte = Mb_peek(&e->eb.mb, 1); + uchar cur_byte = Mb_peek(&e->eb.mb, 0); + uchar match_byte = Mb_peek(&e->eb.mb, reps[0] + 1); + + e->trials[1].price = price0(e->eb.bm_match[state][pos_state]); + if (St_is_char(state)) + e->trials[1].price += LZeb_price_literal(&e->eb, + prev_byte, cur_byte); + else + e->trials[1].price += LZeb_price_matched(&e->eb, + prev_byte, cur_byte, match_byte); + e->trials[1].dis4 = -1; /* literal */ + + if (match_byte == cur_byte) + Tr_update(&e->trials[1], rep_match_price + + LZeb_price_shortrep(&e->eb, state, pos_state), 0, 0); + num_trials = replens[rep_index]; + if (num_trials < main_len) + num_trials = main_len; + *ntrialsp = num_trials; + if (num_trials < min_match_len) { + e->trials[0].price = 1; + e->trials[0].dis4 = e->trials[1].dis4; + Mb_move_pos(&e->eb.mb); + return 1; + } + + e->trials[0].state = state; + for (i = 0; i < num_rep_distances; ++i) + e->trials[0].reps[i] = reps[i]; + + for (len = min_match_len; len <= num_trials; ++len) + e->trials[len].price = infinite_price; + + for (rep = 0; rep < num_rep_distances; ++rep) { + int price, replen; + + if (replens[rep] < min_match_len) + continue; + price = rep_match_price + LZeb_price_rep(&e->eb, rep, + state, pos_state); + replen = replens[rep]; + for (len = min_match_len; len <= replen; ++len) + Tr_update(&e->trials[len], price + + Lp_price(&e->rep_len_prices, len, pos_state), rep, 0); + } + + if (main_len > replens[0]) { + int dis, normal_match_price = match_price + + price0(e->eb.bm_rep[state]); + int replp1 = replens[0] + 1; + int i = 0, len = max(replp1, min_match_len); + + while (len > e->pairs[i].len) + ++i; + for (;;) { + dis = e->pairs[i].dis; + Tr_update(&e->trials[len], normal_match_price + + LZe_price_pair(e, dis, len, pos_state), + dis + num_rep_distances, 0); + if (++len > e->pairs[i].len && ++i >= num_pairs) + break; + } + } + return 0; +} + +static void +finalvalues(LZ_encoder *e, int cur, Trial *cur_trial, State *cstatep) +{ + int i; + int dis4 = cur_trial->dis4; + int prev_index = cur_trial->prev_index; + int prev_index2 = cur_trial->prev_index2; + State cur_state; + + if (prev_index2 == single_step_trial) { + cur_state = e->trials[prev_index].state; + if (prev_index + 1 == cur) { /* len == 1 */ + if (dis4 == 0) + cur_state = St_set_short_rep(cur_state); + else + cur_state = St_set_char(cur_state); /* literal */ + } else if (dis4 < num_rep_distances) + cur_state = St_set_rep(cur_state); + else + cur_state = St_set_match(cur_state); + } else { + if (prev_index2 == dual_step_trial) /* dis4 == 0 (rep0) */ + --prev_index; + else /* prev_index2 >= 0 */ + prev_index = prev_index2; + cur_state = 8; /* St_set_char_rep(); */ + } + cur_trial->state = cur_state; + for (i = 0; i < num_rep_distances; ++i) + cur_trial->reps[i] = e->trials[prev_index].reps[i]; + mtf_reps(dis4, cur_trial->reps); /* literal is ignored */ + *cstatep = cur_state; +} + +static int +litrep0(LZ_encoder *e, State cur_state, int cur, Trial *cur_trial, + int num_trials, int triable_bytes, int pos_state, int next_price) +{ + int len = 1, endtrials, limit, mlpl1, dis; + uchar *data = Mb_ptr_to_current_pos(&e->eb.mb); + + dis = cur_trial->reps[0] + 1; + mlpl1 = e->match_len_limit + 1; + limit = min(mlpl1, triable_bytes); + len = maxmatch(data, dis, len, limit); + if (--len >= min_match_len) { + int pos_state2, price; + State state2; + + pos_state2 = (pos_state + 1) & pos_state_mask; + state2 = St_set_char(cur_state); + price = next_price + price1(e->eb.bm_match[state2][pos_state2])+ + price1(e->eb.bm_rep[state2]) + + LZe_price_rep0_len(e, len, state2, pos_state2); + endtrials = cur + 1 + len; + while (num_trials < endtrials) + e->trials[++num_trials].price = infinite_price; + Tr_update2(&e->trials[endtrials], price, cur + 1); + } + return num_trials; +} + +static int +repdists(LZ_encoder *e, State cur_state, int cur, Trial *cur_trial, + int num_trials, int triable_bytes, int pos_state, + int rep_match_price, int len_limit, int *stlenp) +{ + int i, rep, len, price, dis, start_len; + + start_len = *stlenp; + for (rep = 0; rep < num_rep_distances; ++rep) { + uchar *data = Mb_ptr_to_current_pos(&e->eb.mb); + + dis = cur_trial->reps[rep] + 1; + if (data[0-dis] != data[0] || data[1-dis] != data[1]) + continue; + len = maxmatch(data, dis, min_match_len, len_limit); + while (num_trials < cur + len) + e->trials[++num_trials].price = infinite_price; + price = rep_match_price + LZeb_price_rep(&e->eb, rep, + cur_state, pos_state); + for (i = min_match_len; i <= len; ++i) + Tr_update(&e->trials[cur+i], price + + Lp_price(&e->rep_len_prices, i, pos_state), rep, cur); + + if (rep == 0) + start_len = len + 1; /* discard shorter matches */ + + /* try rep + literal + rep0 */ + { + int pos_state2, endtrials, limit, mlpl2, len2; + State state2; + + len2 = len + 1; + mlpl2 = e->match_len_limit + len2; + limit = min(mlpl2, triable_bytes); + len2 = maxmatch(data, dis, len2, limit); + len2 -= len + 1; + if (len2 < min_match_len) + continue; + + pos_state2 = (pos_state + len) & pos_state_mask; + state2 = St_set_rep(cur_state); + price += Lp_price(&e->rep_len_prices, len, pos_state) + + price0(e->eb.bm_match[state2][pos_state2]) + + LZeb_price_matched(&e->eb, data[len-1], + data[len], data[len-dis]); + price = pricestate2(e, price, &pos_state2, + &state2, len2); + endtrials = cur + len + 1 + len2; + while (num_trials < endtrials) + e->trials[++num_trials].price = infinite_price; + Tr_update3(&e->trials[endtrials], price, rep, + endtrials - len2, cur); + } + } + *stlenp = start_len; + return num_trials; +} + +static int +trymatches(LZ_encoder *e, State cur_state, int cur, int num_trials, + int triable_bytes, int pos_state, int num_pairs, + int normal_match_price, int start_len) +{ + int i, dis, len, price; + + i = 0; + while (e->pairs[i].len < start_len) + ++i; + dis = e->pairs[i].dis; + for (len = start_len; ; ++len) { + price = normal_match_price + LZe_price_pair(e, dis, len, pos_state); + Tr_update(&e->trials[cur+len], price, dis + num_rep_distances, cur); + + /* try match + literal + rep0 */ + if (len == e->pairs[i].len) { + uchar *data = Mb_ptr_to_current_pos(&e->eb.mb); + int endtrials, mlpl2, limit; + int dis2 = dis + 1, len2 = len + 1; + + mlpl2 = e->match_len_limit + len2; + limit = min(mlpl2, triable_bytes); + len2 = maxmatch(data, dis2, len2, limit); + len2 -= len + 1; + if (len2 >= min_match_len) { + int pos_state2 = (pos_state + len) &pos_state_mask; + State state2 = St_set_match(cur_state); + + price += price0(e->eb.bm_match[state2][pos_state2]) + + LZeb_price_matched(&e->eb, data[len-1], data[len], data[len-dis2]); + price = pricestate2(e, price, + &pos_state2, &state2, len2); + endtrials = cur + len + 1 + len2; + while (num_trials < endtrials) + e->trials[++num_trials].price = infinite_price; + Tr_update3(&e->trials[endtrials], + price, dis + + num_rep_distances, + endtrials - len2, cur); + } + if (++i >= num_pairs) + break; + dis = e->pairs[i].dis; + } + } + return num_trials; +} + +/* + * Returns the number of bytes advanced (ahead). + trials[0]..trials[ahead-1] contain the steps to encode. + (trials[0].dis4 == -1) means literal. + A match/rep longer or equal than match_len_limit finishes the sequence. + */ +static int +LZe_sequence_optimizer(LZ_encoder *e, int reps[num_rep_distances], State state) +{ + int main_len, num_pairs, i, num_trials; + int rep_index = 0, cur = 0; + int replens[num_rep_distances]; + + if (e->pending_num_pairs > 0) { /* from previous call */ + num_pairs = e->pending_num_pairs; + e->pending_num_pairs = 0; + } else + num_pairs = LZe_read_match_distances(e); + main_len = (num_pairs > 0) ? e->pairs[num_pairs-1].len : 0; + + for (i = 0; i < num_rep_distances; ++i) { + replens[i] = Mb_true_match_len(&e->eb.mb, 0, reps[i] + 1); + if (replens[i] > replens[rep_index]) + rep_index = i; + } + if (replens[rep_index] >= e->match_len_limit) { + e->trials[0].price = replens[rep_index]; + e->trials[0].dis4 = rep_index; + LZe_move_and_update(e, replens[rep_index]); + return replens[rep_index]; + } + + if (main_len >= e->match_len_limit) { + e->trials[0].price = main_len; + e->trials[0].dis4 = e->pairs[num_pairs-1].dis + num_rep_distances; + LZe_move_and_update(e, main_len); + return main_len; + } + + if (encinit(e, reps, replens, state, main_len, num_pairs, rep_index, + &num_trials) > 0) + return 1; + + /* + * Optimize price. + */ + for (;;) { + Trial *cur_trial, *next_trial; + int newlen, pos_state, triable_bytes, len_limit; + int next_price, match_price, rep_match_price; + int start_len = min_match_len; + State cur_state; + uchar prev_byte, cur_byte, match_byte; + + Mb_move_pos(&e->eb.mb); + if (++cur >= num_trials) { /* no more initialized trials */ + LZe_backward(e, cur); + return cur; + } + + num_pairs = LZe_read_match_distances(e); + newlen = num_pairs > 0? e->pairs[num_pairs-1].len: 0; + if (newlen >= e->match_len_limit) { + e->pending_num_pairs = num_pairs; + LZe_backward(e, cur); + return cur; + } + + /* give final values to current trial */ + cur_trial = &e->trials[cur]; + finalvalues(e, cur, cur_trial, &cur_state); + + pos_state = Mb_data_position(&e->eb.mb) & pos_state_mask; + prev_byte = Mb_peek(&e->eb.mb, 1); + cur_byte = Mb_peek(&e->eb.mb, 0); + match_byte = Mb_peek(&e->eb.mb, cur_trial->reps[0] + 1); + + next_price = cur_trial->price + + price0(e->eb.bm_match[cur_state][pos_state]); + if (St_is_char(cur_state)) + next_price += LZeb_price_literal(&e->eb, prev_byte, cur_byte); + else + next_price += LZeb_price_matched(&e->eb, prev_byte, + cur_byte, match_byte); + + /* try last updates to next trial */ + next_trial = &e->trials[cur+1]; + + Tr_update(next_trial, next_price, -1, cur); /* literal */ + + match_price = cur_trial->price + + price1(e->eb.bm_match[cur_state][pos_state]); + rep_match_price = match_price + price1(e->eb.bm_rep[cur_state]); + + if (match_byte == cur_byte && next_trial->dis4 != 0 && + next_trial->prev_index2 == single_step_trial) { + int price = rep_match_price + + LZeb_price_shortrep(&e->eb, cur_state, pos_state); + if (price <= next_trial->price) { + next_trial->price = price; + next_trial->dis4 = 0; /* rep0 */ + next_trial->prev_index = cur; + } + } + + int trm1mcur = max_num_trials - 1 - cur; + + triable_bytes = Mb_avail_bytes(&e->eb.mb); + if (triable_bytes > trm1mcur) + triable_bytes = trm1mcur; + if (triable_bytes < min_match_len) + continue; + + len_limit = min(e->match_len_limit, triable_bytes); + + /* try literal + rep0 */ + if (match_byte != cur_byte && next_trial->prev_index != cur) + num_trials = litrep0(e, cur_state, cur, cur_trial, + num_trials, triable_bytes, pos_state, next_price); + + /* try rep distances */ + num_trials = repdists(e, cur_state, cur, cur_trial, + num_trials, triable_bytes, pos_state, + rep_match_price, len_limit, &start_len); + + /* try matches */ + if (newlen >= start_len && newlen <= len_limit) { + int normal_match_price = match_price + + price0(e->eb.bm_rep[cur_state]); + + while (num_trials < cur + newlen) + e->trials[++num_trials].price = infinite_price; + + num_trials = trymatches(e, cur_state, cur, num_trials, + triable_bytes, pos_state, num_pairs, + normal_match_price, start_len); + } + } +} + +static int +encrepmatch(LZ_encoder *e, State state, int len, int dis, int pos_state) +{ + int bit = (dis == 0); + + Re_encode_bit(&e->eb.renc, &e->eb.bm_rep0[state], !bit); + if (bit) + Re_encode_bit(&e->eb.renc, &e->eb.bm_len[state][pos_state], + len > 1); + else { + Re_encode_bit(&e->eb.renc, &e->eb.bm_rep1[state], dis > 1); + if (dis > 1) + Re_encode_bit(&e->eb.renc, &e->eb.bm_rep2[state], + dis > 2); + } + if (len == 1) + state = St_set_short_rep(state); + else { + Re_encode_len(&e->eb.renc, &e->eb.rep_len_model, len, pos_state); + Lp_decr_counter(&e->rep_len_prices, pos_state); + state = St_set_rep(state); + } + return state; +} + +bool +LZe_encode_member(LZ_encoder *e, uvlong member_size) +{ + uvlong member_size_limit = member_size - Ft_size - max_marker_size; + bool best = (e->match_len_limit > 12); + int dis_price_count = best? 1: 512; + int align_price_count = best? 1: dis_align_size; + int price_count = (e->match_len_limit > 36? 1013 : 4093); + int price_counter = 0; /* counters may decrement below 0 */ + int dis_price_counter = 0; + int align_price_counter = 0; + int ahead, i; + int reps[num_rep_distances]; + State state = 0; + + for (i = 0; i < num_rep_distances; ++i) + reps[i] = 0; + + if (Mb_data_position(&e->eb.mb) != 0 || + Re_member_position(&e->eb.renc) != Fh_size) + return false; /* can be called only once */ + + if (!Mb_data_finished(&e->eb.mb)) { /* encode first byte */ + uchar prev_byte = 0; + uchar cur_byte = Mb_peek(&e->eb.mb, 0); + + Re_encode_bit(&e->eb.renc, &e->eb.bm_match[state][0], 0); + LZeb_encode_literal(&e->eb, prev_byte, cur_byte); + CRC32_update_byte(&e->eb.crc, cur_byte); + LZe_get_match_pairs(e, 0); + Mb_move_pos(&e->eb.mb); + } + + while (!Mb_data_finished(&e->eb.mb)) { + if (price_counter <= 0 && e->pending_num_pairs == 0) { + /* recalculate prices every these many bytes */ + price_counter = price_count; + if (dis_price_counter <= 0) { + dis_price_counter = dis_price_count; + LZe_update_distance_prices(e); + } + if (align_price_counter <= 0) { + align_price_counter = align_price_count; + for (i = 0; i < dis_align_size; ++i) + e->align_prices[i] = price_symbol_reversed( + e->eb.bm_align, i, dis_align_bits); + } + Lp_update_prices(&e->match_len_prices); + Lp_update_prices(&e->rep_len_prices); + } + + ahead = LZe_sequence_optimizer(e, reps, state); + price_counter -= ahead; + + for (i = 0; ahead > 0;) { + int pos_state = (Mb_data_position(&e->eb.mb) - ahead) & + pos_state_mask; + int len = e->trials[i].price; + int dis = e->trials[i].dis4; + bool bit = (dis < 0); + + Re_encode_bit(&e->eb.renc, &e->eb.bm_match[state][pos_state], + !bit); + if (bit) { /* literal byte */ + uchar prev_byte = Mb_peek(&e->eb.mb, ahead+1); + uchar cur_byte = Mb_peek(&e->eb.mb, ahead); + + CRC32_update_byte(&e->eb.crc, cur_byte); + if (St_is_char(state)) + LZeb_encode_literal(&e->eb, prev_byte, + cur_byte); + else { + uchar match_byte = Mb_peek(&e->eb.mb, + ahead + reps[0] + 1); + + LZeb_encode_matched(&e->eb, prev_byte, + cur_byte, match_byte); + } + state = St_set_char(state); + } else { /* match or repeated match */ + CRC32_update_buf(&e->eb.crc, + Mb_ptr_to_current_pos(&e->eb.mb) - ahead, + len); + mtf_reps(dis, reps); + bit = (dis < num_rep_distances); + Re_encode_bit(&e->eb.renc, &e->eb.bm_rep[state], + bit); + if (bit) /* repeated match */ + state = encrepmatch(e, state, len, dis, + pos_state); + else { /* match */ + dis -= num_rep_distances; + LZeb_encode_pair(&e->eb, dis, len, + pos_state); + if (dis >= modeled_distances) + --align_price_counter; + --dis_price_counter; + Lp_decr_counter( + &e->match_len_prices, pos_state); + state = St_set_match(state); + } + } + ahead -= len; + i += len; + if (Re_member_position(&e->eb.renc) >= member_size_limit) { + if (!Mb_dec_pos(&e->eb.mb, ahead)) + return false; + LZeb_full_flush(&e->eb, state); + return true; + } + } + } + LZeb_full_flush(&e->eb, state); + return true; +} diff --git a/sys/src/cmd/lzip/encoder.h b/sys/src/cmd/lzip/encoder.h new file mode 100644 index 0000000000..fba7e2d867 --- /dev/null +++ b/sys/src/cmd/lzip/encoder.h @@ -0,0 +1,323 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +typedef struct Len_prices Len_prices; +struct Len_prices { + struct Len_model *lm; + int len_syms; + int count; + int prices[pos_states][max_len_syms]; + int counters[pos_states]; /* may decrement below 0 */ +}; + +static void +Lp_update_low_mid_prices(Len_prices *lp, int pos_state) +{ + int *pps = lp->prices[pos_state]; + int tmp = price0(lp->lm->choice1); + int len = 0; + for (; len < len_low_syms && len < lp->len_syms; ++len) + pps[len] = tmp + price_symbol3(lp->lm->bm_low[pos_state], len); + if (len >= lp->len_syms) + return; + tmp = price1(lp->lm->choice1) + price0(lp->lm->choice2); + for (; len < len_low_syms + len_mid_syms && len < lp->len_syms; ++len) + pps[len] = tmp + + price_symbol3(lp->lm->bm_mid[pos_state], len - len_low_syms); +} + +static void +Lp_update_high_prices(Len_prices *lp) +{ + int tmp = price1(lp->lm->choice1) + price1(lp->lm->choice2); + int len; + for (len = len_low_syms + len_mid_syms; len < lp->len_syms; ++len) + /* using 4 slots per value makes "Lp_price" faster */ + lp->prices[3][len] = lp->prices[2][len] = + lp->prices[1][len] = lp->prices[0][len] = tmp + + price_symbol8(lp->lm->bm_high, len - len_low_syms - len_mid_syms); +} + +static void +Lp_reset(Len_prices *lp) +{ + int i; + for (i = 0; i < pos_states; ++i) + lp->counters[i] = 0; +} + +static void +Lp_init(Len_prices *lp, Len_model *lm, int match_len_limit) +{ + lp->lm = lm; + lp->len_syms = match_len_limit + 1 - min_match_len; + lp->count = (match_len_limit > 12) ? 1 : lp->len_syms; + Lp_reset(lp); +} + +static void +Lp_decr_counter(Len_prices *lp, int pos_state) +{ + --lp->counters[pos_state]; +} + +static void +Lp_update_prices(Len_prices *lp) +{ + int pos_state; + bool high_pending = false; + + for (pos_state = 0; pos_state < pos_states; ++pos_state) + if (lp->counters[pos_state] <= 0) { + lp->counters[pos_state] = lp->count; + Lp_update_low_mid_prices(lp, pos_state); + high_pending = true; + } + if (high_pending && lp->len_syms > len_low_syms + len_mid_syms) + Lp_update_high_prices(lp); +} + +typedef struct Pair Pair; +struct Pair { /* distance-length pair */ + int dis; + int len; +}; + +enum { + infinite_price = 0x0FFFFFFF, + max_num_trials = 1 << 13, + single_step_trial = -2, + dual_step_trial = -1 +}; + +typedef struct Trial Trial; +struct Trial { + State state; + int price; /* dual use var; cumulative price, match length */ + int dis4; /* -1 for literal, or rep, or match distance + 4 */ + int prev_index; /* index of prev trial in trials[] */ + int prev_index2; /* -2 trial is single step */ + /* -1 literal + rep0 */ + /* >= 0 (rep or match) + literal + rep0 */ + int reps[num_rep_distances]; +}; + +static void +Tr_update2(Trial *trial, int pr, int p_i) +{ + if (pr < trial->price) { + trial->price = pr; + trial->dis4 = 0; + trial->prev_index = p_i; + trial->prev_index2 = dual_step_trial; + } +} + +static void +Tr_update3(Trial *trial, int pr, int distance4, int p_i, int p_i2) +{ + if (pr < trial->price) { + trial->price = pr; + trial->dis4 = distance4; + trial->prev_index = p_i; + trial->prev_index2 = p_i2; + } +} + +typedef struct LZ_encoder LZ_encoder; +struct LZ_encoder { + LZ_encoder_base eb; + int cycles; + int match_len_limit; + Len_prices match_len_prices; + Len_prices rep_len_prices; + int pending_num_pairs; + Pair pairs[max_match_len+1]; + Trial trials[max_num_trials]; + + int dis_slot_prices[len_states][2*max_dict_bits]; + int dis_prices[len_states][modeled_distances]; + int align_prices[dis_align_size]; + int num_dis_slots; +}; + +static bool +Mb_dec_pos(struct Matchfinder_base *mb, int ahead) +{ + if (ahead < 0 || mb->pos < ahead) + return false; + mb->pos -= ahead; + if (mb->cyclic_pos < ahead) + mb->cyclic_pos += mb->dict_size + 1; + mb->cyclic_pos -= ahead; + return true; +} + +int LZe_get_match_pairs(struct LZ_encoder *e, struct Pair *pairs); + +/* move-to-front dis in/into reps; do nothing if(dis4 <= 0) */ +static void +mtf_reps(int dis4, int reps[num_rep_distances]) +{ + if (dis4 >= num_rep_distances) /* match */ { + reps[3] = reps[2]; + reps[2] = reps[1]; + reps[1] = reps[0]; + reps[0] = dis4 - num_rep_distances; + } else if (dis4 > 0) /* repeated match */ { + int distance = reps[dis4]; + int i; + for (i = dis4; i > 0; --i) + reps[i] = reps[i-1]; + reps[0] = distance; + } +} + +static int +LZeb_price_shortrep(struct LZ_encoder_base *eb, State state, int pos_state) +{ + return price0(eb->bm_rep0[state]) + price0(eb->bm_len[state][pos_state]); +} + +static int +LZeb_price_rep(struct LZ_encoder_base *eb, int rep, State state, int pos_state) +{ + int price; + if (rep == 0) + return price0(eb->bm_rep0[state]) + + price1(eb->bm_len[state][pos_state]); + price = price1(eb->bm_rep0[state]); + if (rep == 1) + price += price0(eb->bm_rep1[state]); + else { + price += price1(eb->bm_rep1[state]); + price += price_bit(eb->bm_rep2[state], rep - 2); + } + return price; +} + +static int +LZe_price_rep0_len(struct LZ_encoder *e, int len, State state, int pos_state) +{ + return LZeb_price_rep(&e->eb, 0, state, pos_state) + + Lp_price(&e->rep_len_prices, len, pos_state); +} + +static int +LZe_price_pair(struct LZ_encoder *e, int dis, int len, int pos_state) +{ + int price = Lp_price(&e->match_len_prices, len, pos_state); + int len_state = get_len_state(len); + if (dis < modeled_distances) + return price + e->dis_prices[len_state][dis]; + else + return price + e->dis_slot_prices[len_state][get_slot(dis)] + + e->align_prices[dis & (dis_align_size - 1)]; +} + +static int +LZe_read_match_distances(struct LZ_encoder *e) +{ + int num_pairs = LZe_get_match_pairs(e, e->pairs); + if (num_pairs > 0) { + int len = e->pairs[num_pairs-1].len; + if (len == e->match_len_limit && len < max_match_len) + e->pairs[num_pairs-1].len = + Mb_true_match_len(&e->eb.mb, len, e->pairs[num_pairs-1].dis + 1); + } + return num_pairs; +} + +static void +LZe_move_and_update(struct LZ_encoder *e, int n) +{ + while (true) { + Mb_move_pos(&e->eb.mb); + if (--n <= 0) + break; + LZe_get_match_pairs(e, 0); + } +} + +static void +LZe_backward(struct LZ_encoder *e, int cur) +{ + int dis4 = e->trials[cur].dis4; + while (cur > 0) { + int prev_index = e->trials[cur].prev_index; + struct Trial *prev_trial = &e->trials[prev_index]; + + if (e->trials[cur].prev_index2 != single_step_trial) { + prev_trial->dis4 = -1; /* literal */ + prev_trial->prev_index = prev_index - 1; + prev_trial->prev_index2 = single_step_trial; + if (e->trials[cur].prev_index2 >= 0) { + struct Trial *prev_trial2 = &e->trials[prev_index-1]; + prev_trial2->dis4 = dis4; + dis4 = 0; /* rep0 */ + prev_trial2->prev_index = e->trials[cur].prev_index2; + prev_trial2->prev_index2 = single_step_trial; + } + } + prev_trial->price = cur - prev_index; /* len */ + cur = dis4; + dis4 = prev_trial->dis4; + prev_trial->dis4 = cur; + cur = prev_index; + } +} + +enum { + Nprevpos3 = 1 << 16, + Nprevpos2 = 1 << 10 +}; + +static bool +LZe_init(struct LZ_encoder *e, int dict_size, int len_limit, int ifd, int outfd) +{ + enum { + before = max_num_trials, + /* bytes to keep in buffer after pos */ + after_size = (2 *max_match_len) + 1, + dict_factor = 2, + Nprevpos23 = Nprevpos2 + Nprevpos3, + pos_array_factor = 2 + }; + + if (!LZeb_init(&e->eb, before, dict_size, after_size, dict_factor, + Nprevpos23, pos_array_factor, ifd, outfd)) + return false; + e->cycles = (len_limit < max_match_len) ? 16 + (len_limit / 2) : 256; + e->match_len_limit = len_limit; + Lp_init(&e->match_len_prices, &e->eb.match_len_model, e->match_len_limit); + Lp_init(&e->rep_len_prices, &e->eb.rep_len_model, e->match_len_limit); + e->pending_num_pairs = 0; + e->num_dis_slots = 2 * real_bits(e->eb.mb.dict_size - 1); + e->trials[1].prev_index = 0; + e->trials[1].prev_index2 = single_step_trial; + return true; +} + +static void +LZe_reset(struct LZ_encoder *e) +{ + LZeb_reset(&e->eb); + Lp_reset(&e->match_len_prices); + Lp_reset(&e->rep_len_prices); + e->pending_num_pairs = 0; +} + +bool LZe_encode_member(struct LZ_encoder *e, uvlong member_size); diff --git a/sys/src/cmd/lzip/encoder_base.c b/sys/src/cmd/lzip/encoder_base.c new file mode 100644 index 0000000000..b7ff171fdc --- /dev/null +++ b/sys/src/cmd/lzip/encoder_base.c @@ -0,0 +1,203 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +#include "lzip.h" +#include "encoder_base.h" + +Dis_slots dis_slots; +Prob_prices prob_prices; + +bool +Mb_read_block(Matchfinder_base *mb) +{ + if (!mb->at_stream_end && mb->stream_pos < mb->buffer_size) { + int size = mb->buffer_size - mb->stream_pos; + int rd = readblock(mb->infd, mb->buffer + mb->stream_pos, size); + + mb->stream_pos += rd; + if (rd != size && errno) { + show_error( "Read error", errno, false ); + cleanup_and_fail(1); + } + if (rd < size) { + mb->at_stream_end = true; + mb->pos_limit = mb->buffer_size; + } + } + return mb->pos < mb->stream_pos; +} + +void +Mb_normalize_pos(Matchfinder_base *mb) +{ + if (mb->pos > mb->stream_pos) + internal_error( "pos > stream_pos in Mb_normalize_pos." ); + if (!mb->at_stream_end) { + int i, offset = mb->pos - mb->before_size - mb->dict_size; + int size = mb->stream_pos - offset; + + memmove(mb->buffer, mb->buffer + offset, size); + mb->partial_data_pos += offset; + mb->pos -= offset; /* pos = before_size + dict_size */ + mb->stream_pos -= offset; + for (i = 0; i < mb->num_prev_positions; ++i) + if (mb->prev_positions[i] < offset) + mb->prev_positions[i] = 0; + else + mb->prev_positions[i] -= offset; + for (i = 0; i < mb->pos_array_size; ++i) + if (mb->pos_array[i] < offset) + mb->pos_array[i] = 0; + else + mb->pos_array[i] -= offset; + Mb_read_block(mb); + } +} + +bool +Mb_init(Matchfinder_base *mb, int before, int dict_size, int after_size, int dict_factor, int num_prev_positions23, int pos_array_factor, int ifd) +{ + int buffer_size_limit = (dict_factor * dict_size) + before + after_size; + unsigned size; + int i; + + mb->partial_data_pos = 0; + mb->before_size = before; + mb->pos = 0; + mb->cyclic_pos = 0; + mb->stream_pos = 0; + mb->infd = ifd; + mb->at_stream_end = false; + + mb->buffer_size = max(65536, dict_size); + mb->buffer = (uchar *)malloc(mb->buffer_size); + if (!mb->buffer) + return false; + if (Mb_read_block(mb) && !mb->at_stream_end && + mb->buffer_size < buffer_size_limit) { + uchar * tmp; + mb->buffer_size = buffer_size_limit; + tmp = (uchar *)realloc(mb->buffer, mb->buffer_size); + if (!tmp) { + free(mb->buffer); + return false; + } + mb->buffer = tmp; + Mb_read_block(mb); + } + if (mb->at_stream_end && mb->stream_pos < dict_size) + mb->dict_size = max(min_dict_size, mb->stream_pos); + else + mb->dict_size = dict_size; + mb->pos_limit = mb->buffer_size; + if (!mb->at_stream_end) + mb->pos_limit -= after_size; + size = real_bits(mb->dict_size - 1) - 2; + if (size < 16) + size = 16; + size = 1 << size; +// if (mb->dict_size > (1 << 26)) /* 64 MiB */ +// size >>= 1; + mb->key4_mask = size - 1; + size += num_prev_positions23; + + mb->num_prev_positions = size; + mb->pos_array_size = pos_array_factor * (mb->dict_size + 1); + size += mb->pos_array_size; + if (size * sizeof mb->prev_positions[0] <= size) + mb->prev_positions = 0; + else + mb->prev_positions = + (int32_t *)malloc(size * sizeof mb->prev_positions[0]); + if (!mb->prev_positions) { + free(mb->buffer); + return false; + } + mb->pos_array = mb->prev_positions + mb->num_prev_positions; + for (i = 0; i < mb->num_prev_positions; ++i) + mb->prev_positions[i] = 0; + return true; +} + +void +Mb_reset(Matchfinder_base *mb) +{ + int i; + + if (mb->stream_pos > mb->pos) + memmove(mb->buffer, mb->buffer + mb->pos, mb->stream_pos - mb->pos); + mb->partial_data_pos = 0; + mb->stream_pos -= mb->pos; + mb->pos = 0; + mb->cyclic_pos = 0; + for (i = 0; i < mb->num_prev_positions; ++i) + mb->prev_positions[i] = 0; + Mb_read_block(mb); +} + +void +Re_flush_data(Range_encoder *renc) +{ + if (renc->pos > 0) { + if (renc->outfd >= 0 && + writeblock(renc->outfd, renc->buffer, renc->pos) != renc->pos) { + show_error( "Write error", errno, false ); + cleanup_and_fail(1); + } + renc->partial_member_pos += renc->pos; + renc->pos = 0; + show_progress(0, 0, 0, 0); + } +} + +/* End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) */ +void +LZeb_full_flush(LZ_encoder_base *eb, State state) +{ + int i; + int pos_state = Mb_data_position(&eb->mb) & pos_state_mask; + File_trailer trailer; + Re_encode_bit(&eb->renc, &eb->bm_match[state][pos_state], 1); + Re_encode_bit(&eb->renc, &eb->bm_rep[state], 0); + LZeb_encode_pair(eb, 0xFFFFFFFFU, min_match_len, pos_state); + Re_flush(&eb->renc); + Ft_set_data_crc(trailer, LZeb_crc(eb)); + Ft_set_data_size(trailer, Mb_data_position(&eb->mb)); + Ft_set_member_size(trailer, Re_member_position(&eb->renc) + Ft_size); + for (i = 0; i < Ft_size; ++i) + Re_put_byte(&eb->renc, trailer[i]); + Re_flush_data(&eb->renc); +} + +void +LZeb_reset(LZ_encoder_base *eb) +{ + Mb_reset(&eb->mb); + eb->crc = 0xFFFFFFFFU; + Bm_array_init(eb->bm_literal[0], (1 << literal_context_bits) * 0x300); + Bm_array_init(eb->bm_match[0], states * pos_states); + Bm_array_init(eb->bm_rep, states); + Bm_array_init(eb->bm_rep0, states); + Bm_array_init(eb->bm_rep1, states); + Bm_array_init(eb->bm_rep2, states); + Bm_array_init(eb->bm_len[0], states * pos_states); + Bm_array_init(eb->bm_dis_slot[0], len_states * (1 << dis_slot_bits)); + Bm_array_init(eb->bm_dis, modeled_distances - end_dis_model + 1); + Bm_array_init(eb->bm_align, dis_align_size); + Lm_init(&eb->match_len_model); + Lm_init(&eb->rep_len_model); + Re_reset(&eb->renc); +} diff --git a/sys/src/cmd/lzip/encoder_base.h b/sys/src/cmd/lzip/encoder_base.h new file mode 100644 index 0000000000..e2f85068ac --- /dev/null +++ b/sys/src/cmd/lzip/encoder_base.h @@ -0,0 +1,559 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . + */ + +#include "lzip.h" + +static void +Dis_slots_init(void) +{ + int i, size, slot; + for (slot = 0; slot < 4; ++slot) + dis_slots[slot] = slot; + for (i = 4, size = 2, slot = 4; slot < 20; slot += 2) { + memset(&dis_slots[i], slot, size); + memset(&dis_slots[i+size], slot + 1, size); + size <<= 1; + i += size; + } +} + +static uchar +get_slot(unsigned dis) +{ + if (dis < (1 << 10)) + return dis_slots[dis]; + if (dis < (1 << 19)) + return dis_slots[dis>> 9] + 18; + if (dis < (1 << 28)) + return dis_slots[dis>>18] + 36; + return dis_slots[dis>>27] + 54; +} + +static void +Prob_prices_init(void) +{ + int i, j; + for (i = 0; i < bit_model_total >> price_step_bits; ++i) { + unsigned val = (i * price_step) + (price_step / 2); + int bits = 0; /* base 2 logarithm of val */ + + for (j = 0; j < price_shift_bits; ++j) { + val = val * val; + bits <<= 1; + while (val >= (1 << 16)) { + val >>= 1; + ++bits; + } + } + bits += 15; /* remaining bits in val */ + prob_prices[i] = (bit_model_total_bits << price_shift_bits) - bits; + } +} + +static int +price_symbol3(Bit_model bm[], int symbol) +{ + int price; + bool bit = symbol & 1; + + symbol |= 8; + symbol >>= 1; + price = price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + return price + price_bit(bm[1], symbol & 1); +} + +static int +price_symbol6(Bit_model bm[], unsigned symbol) +{ + int price; + bool bit = symbol & 1; + + symbol |= 64; + symbol >>= 1; + price = price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + return price + price_bit(bm[1], symbol & 1); +} + +static int +price_symbol8(Bit_model bm[], int symbol) +{ + int price; + bool bit = symbol & 1; + symbol |= 0x100; + symbol >>= 1; + price = price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[symbol], bit); + return price + price_bit(bm[1], symbol & 1); +} + +static int +price_symbol_reversed(Bit_model bm[], int symbol, int num_bits) +{ + int price = 0; + int model = 1; + int i; + + for (i = num_bits; i > 0; --i) { + bool bit = symbol & 1; + symbol >>= 1; + price += price_bit(bm[model], bit); + model = (model << 1) | bit; + } + return price; +} + +static int +price_matched(Bit_model bm[], unsigned symbol, unsigned match_byte) +{ + int price = 0; + unsigned mask = 0x100; + + symbol |= mask; + for (;;) { + unsigned match_bit = (match_byte <<= 1) & mask; + bool bit = (symbol <<= 1) & 0x100; + + price += price_bit(bm[(symbol>>9) + match_bit + mask], bit); + if (symbol >= 0x10000) + return price; + mask &= ~(match_bit ^ symbol); + /* if(match_bit != bit) mask = 0; */ + } +} + +struct Matchfinder_base { + uvlong partial_data_pos; + uchar * buffer; /* input buffer */ + int32_t * prev_positions; /* 1 + last seen position of key. else 0 */ + int32_t * pos_array; /* may be tree or chain */ + int before_size; /* bytes to keep in buffer before dictionary */ + int buffer_size; + int dict_size; /* bytes to keep in buffer before pos */ + int pos; /* current pos in buffer */ + int cyclic_pos; /* cycles through [0, dict_size] */ + int stream_pos; /* first byte not yet read from file */ + int pos_limit; /* when reached, a new block must be read */ + int key4_mask; + int num_prev_positions; /* size of prev_positions */ + int pos_array_size; + int infd; /* input file descriptor */ + bool at_stream_end; /* stream_pos shows real end of file */ +}; + +bool Mb_read_block(Matchfinder_base *mb); +void Mb_normalize_pos(Matchfinder_base *mb); +bool Mb_init(Matchfinder_base *mb, int before, int dict_size, int after_size, int dict_factor, int num_prev_positions23, int pos_array_factor, int ifd); + +static void +Mb_free(Matchfinder_base *mb) +{ + free(mb->prev_positions); + free(mb->buffer); +} + +static int +Mb_avail_bytes(Matchfinder_base *mb) +{ + return mb->stream_pos - mb->pos; +} + +static uvlong +Mb_data_position(Matchfinder_base *mb) +{ + return mb->partial_data_pos + mb->pos; +} + +static bool +Mb_data_finished(Matchfinder_base *mb) +{ + return mb->at_stream_end && mb->pos >= mb->stream_pos; +} + +static int +Mb_true_match_len(Matchfinder_base *mb, int index, int distance) +{ + uchar * data = mb->buffer + mb->pos; + int i = index; + int len_limit = min(Mb_avail_bytes(mb), max_match_len); + while (i < len_limit && data[i-distance] == data[i]) + ++i; + return i; +} + +static void +Mb_move_pos(Matchfinder_base *mb) +{ + if (++mb->cyclic_pos > mb->dict_size) + mb->cyclic_pos = 0; + if (++mb->pos >= mb->pos_limit) + Mb_normalize_pos(mb); +} + +void Mb_reset(Matchfinder_base *mb); + +enum { re_buffer_size = 65536 }; + +typedef struct LZ_encoder_base LZ_encoder_base; +typedef struct Matchfinder_base Matchfinder_base; +typedef struct Range_encoder Range_encoder; + +struct Range_encoder { + uvlong low; + uvlong partial_member_pos; + uchar * buffer; /* output buffer */ + int pos; /* current pos in buffer */ + uint32_t range; + unsigned ff_count; + int outfd; /* output file descriptor */ + uchar cache; + File_header header; +}; + +void Re_flush_data(Range_encoder *renc); + +static void +Re_put_byte(Range_encoder *renc, uchar b) +{ + renc->buffer[renc->pos] = b; + if (++renc->pos >= re_buffer_size) + Re_flush_data(renc); +} + +static void +Re_shift_low(Range_encoder *renc) +{ + if (renc->low >> 24 != 0xFF) { + bool carry = (renc->low > 0xFFFFFFFFU); + Re_put_byte(renc, renc->cache + carry); + for (; renc->ff_count > 0; --renc->ff_count) + Re_put_byte(renc, 0xFF + carry); + renc->cache = renc->low >> 24; + } else + ++renc->ff_count; + renc->low = (renc->low & 0x00FFFFFFU) << 8; +} + +static void +Re_reset(Range_encoder *renc) +{ + int i; + renc->low = 0; + renc->partial_member_pos = 0; + renc->pos = 0; + renc->range = 0xFFFFFFFFU; + renc->ff_count = 0; + renc->cache = 0; + for (i = 0; i < Fh_size; ++i) + Re_put_byte(renc, renc->header[i]); +} + +static bool +Re_init(Range_encoder *renc, unsigned dict_size, int ofd) +{ + renc->buffer = (uchar *)malloc(re_buffer_size); + if (!renc->buffer) + return false; + renc->outfd = ofd; + Fh_set_magic(renc->header); + Fh_set_dict_size(renc->header, dict_size); + Re_reset(renc); + return true; +} + +static void +Re_free(Range_encoder *renc) +{ + free(renc->buffer); +} + +static uvlong +Re_member_position(Range_encoder *renc) +{ + return renc->partial_member_pos + renc->pos + renc->ff_count; +} + +static void +Re_flush(Range_encoder *renc) +{ + int i; + for (i = 0; i < 5; ++i) + Re_shift_low(renc); +} + +static void +Re_encode(Range_encoder *renc, int symbol, int num_bits) +{ + unsigned mask; + for (mask = 1 << (num_bits - 1); mask > 0; mask >>= 1) { + renc->range >>= 1; + if (symbol & mask) + renc->low += renc->range; + if (renc->range <= 0x00FFFFFFU) { + renc->range <<= 8; + Re_shift_low(renc); + } + } +} + +static void +Re_encode_bit(Range_encoder *renc, Bit_model *probability, bool bit) +{ + Bit_model prob = *probability; + uint32_t bound = (renc->range >> bit_model_total_bits) * prob; + + if (!bit) { + renc->range = bound; + *probability += (bit_model_total - prob) >> bit_model_move_bits; + } else { + renc->low += bound; + renc->range -= bound; + *probability -= prob >> bit_model_move_bits; + } + if (renc->range <= 0x00FFFFFFU) { + renc->range <<= 8; + Re_shift_low(renc); + } +} + +static void +Re_encode_tree3(Range_encoder *renc, Bit_model bm[], int symbol) +{ + int model = 1; + bool bit = (symbol >> 2) & 1; + + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + bit = (symbol >> 1) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + Re_encode_bit(renc, &bm[model], symbol & 1); +} + +static void +Re_encode_tree6(Range_encoder *renc, Bit_model bm[], unsigned symbol) +{ + int model = 1; + bool bit = (symbol >> 5) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + bit = (symbol >> 4) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + bit = (symbol >> 3) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + bit = (symbol >> 2) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + bit = (symbol >> 1) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + Re_encode_bit(renc, &bm[model], symbol & 1); +} + +static void +Re_encode_tree8(Range_encoder *renc, Bit_model bm[], int symbol) +{ + int model = 1; + int i; + for (i = 7; i >= 0; --i) { + bool bit = (symbol >> i) & 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + } +} + +static void +Re_encode_tree_reversed(Range_encoder *renc, Bit_model bm[], int symbol, int num_bits) +{ + int model = 1; + int i; + for (i = num_bits; i > 0; --i) { + bool bit = symbol & 1; + symbol >>= 1; + Re_encode_bit(renc, &bm[model], bit); + model = (model << 1) | bit; + } +} + +static void +Re_encode_matched(Range_encoder *renc, Bit_model bm[], unsigned symbol, unsigned match_byte) +{ + unsigned mask = 0x100; + symbol |= mask; + while (true) { + unsigned match_bit = (match_byte <<= 1) & mask; + bool bit = (symbol <<= 1) & 0x100; + Re_encode_bit(renc, &bm[(symbol>>9)+match_bit+mask], bit); + if (symbol >= 0x10000) + break; + mask &= ~(match_bit ^ symbol); + /* if(match_bit != bit) mask = 0; */ + } +} + +static void +Re_encode_len(struct Range_encoder *renc, Len_model *lm, int symbol, int pos_state) +{ + bool bit = ((symbol -= min_match_len) >= len_low_syms); + Re_encode_bit(renc, &lm->choice1, bit); + if (!bit) + Re_encode_tree3(renc, lm->bm_low[pos_state], symbol); + else { + bit = ((symbol -= len_low_syms) >= len_mid_syms); + Re_encode_bit(renc, &lm->choice2, bit); + if (!bit) + Re_encode_tree3(renc, lm->bm_mid[pos_state], symbol); + else + Re_encode_tree8(renc, lm->bm_high, symbol - len_mid_syms); + } +} + +enum { + max_marker_size = 16, + num_rep_distances = 4 /* must be 4 */ +}; + +struct LZ_encoder_base { + struct Matchfinder_base mb; + uint32_t crc; + + Bit_model bm_literal[1<mb, before, dict_size, after_size, dict_factor, + num_prev_positions23, pos_array_factor, ifd)) + return false; + if (!Re_init(&eb->renc, eb->mb.dict_size, outfd)) + return false; + LZeb_reset(eb); + return true; +} + +static void +LZeb_free(LZ_encoder_base *eb) +{ + Re_free(&eb->renc); + Mb_free(&eb->mb); +} + +static unsigned +LZeb_crc(LZ_encoder_base *eb) +{ + return eb->crc ^ 0xFFFFFFFFU; +} + +static int +LZeb_price_literal(LZ_encoder_base *eb, uchar prev_byte, uchar symbol) +{ + return price_symbol8(eb->bm_literal[get_lit_state(prev_byte)], symbol); +} + +static int +LZeb_price_matched(LZ_encoder_base *eb, uchar prev_byte, uchar symbol, uchar match_byte) +{ + return price_matched(eb->bm_literal[get_lit_state(prev_byte)], symbol, + match_byte); +} + +static void +LZeb_encode_literal(LZ_encoder_base *eb, uchar prev_byte, uchar symbol) +{ + Re_encode_tree8(&eb->renc, eb->bm_literal[get_lit_state(prev_byte)], + symbol); +} + +static void +LZeb_encode_matched(LZ_encoder_base *eb, uchar prev_byte, uchar symbol, uchar match_byte) +{ + Re_encode_matched(&eb->renc, eb->bm_literal[get_lit_state(prev_byte)], + symbol, match_byte); +} + +static void +LZeb_encode_pair(LZ_encoder_base *eb, unsigned dis, int len, int pos_state) +{ + unsigned dis_slot = get_slot(dis); + Re_encode_len(&eb->renc, &eb->match_len_model, len, pos_state); + Re_encode_tree6(&eb->renc, eb->bm_dis_slot[get_len_state(len)], dis_slot); + + if (dis_slot >= start_dis_model) { + int direct_bits = (dis_slot >> 1) - 1; + unsigned base = (2 | (dis_slot & 1)) << direct_bits; + unsigned direct_dis = dis - base; + + if (dis_slot < end_dis_model) + Re_encode_tree_reversed(&eb->renc, eb->bm_dis + (base - dis_slot), + direct_dis, direct_bits); + else { + Re_encode(&eb->renc, direct_dis >> dis_align_bits, + direct_bits - dis_align_bits); + Re_encode_tree_reversed(&eb->renc, eb->bm_align, direct_dis, dis_align_bits); + } + } +} + +void LZeb_full_flush(LZ_encoder_base *eb, State state); diff --git a/sys/src/cmd/lzip/fast_encoder.c b/sys/src/cmd/lzip/fast_encoder.c new file mode 100644 index 0000000000..1ece99966d --- /dev/null +++ b/sys/src/cmd/lzip/fast_encoder.c @@ -0,0 +1,188 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +#include "lzip.h" +#include "encoder_base.h" +#include "fast_encoder.h" + +int +FLZe_longest_match_len(FLZ_encoder *fe, int *distance) +{ + enum { len_limit = 16 }; + uchar *data = Mb_ptr_to_current_pos(&fe->eb.mb); + int32_t * ptr0 = fe->eb.mb.pos_array + fe->eb.mb.cyclic_pos; + int pos1 = fe->eb.mb.pos + 1; + int maxlen = 0, newpos1, count; + int available = min(Mb_avail_bytes(&fe->eb.mb), max_match_len); + + if (available < len_limit) + return 0; + + fe->key4 = ((fe->key4 << 4) ^ data[3]) & fe->eb.mb.key4_mask; + newpos1 = fe->eb.mb.prev_positions[fe->key4]; + fe->eb.mb.prev_positions[fe->key4] = pos1; + + for (count = 4; ;) { + int32_t * newptr; + int delta; + + if (newpos1 <= 0 || --count < 0 || + (delta = pos1 - newpos1) > fe->eb.mb.dict_size) { + *ptr0 = 0; + break; + } + newptr = fe->eb.mb.pos_array + + (fe->eb.mb.cyclic_pos - delta + + ((fe->eb.mb.cyclic_pos >= delta) ? 0 : fe->eb.mb.dict_size + 1)); + + if (data[maxlen-delta] == data[maxlen]) { + int len = 0; + while (len < available && data[len-delta] == data[len]) + ++len; + if (maxlen < len) { + maxlen = len; + *distance = delta - 1; + if (maxlen >= len_limit) { + *ptr0 = *newptr; + break; + } + } + } + + *ptr0 = newpos1; + ptr0 = newptr; + newpos1 = *ptr0; + } + return maxlen; +} + +bool +FLZe_encode_member(FLZ_encoder *fe, uvlong member_size) +{ + uvlong member_size_limit = member_size - Ft_size - max_marker_size; + int rep = 0, i; + int reps[num_rep_distances]; + State state = 0; + + for (i = 0; i < num_rep_distances; ++i) + reps[i] = 0; + + if (Mb_data_position(&fe->eb.mb) != 0 || + Re_member_position(&fe->eb.renc) != Fh_size) + return false; /* can be called only once */ + + if (!Mb_data_finished(&fe->eb.mb)) /* encode first byte */ { + uchar prev_byte = 0; + uchar cur_byte = Mb_peek(&fe->eb.mb, 0); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_match[state][0], 0); + LZeb_encode_literal(&fe->eb, prev_byte, cur_byte); + CRC32_update_byte(&fe->eb.crc, cur_byte); + FLZe_reset_key4(fe); + FLZe_update_and_move(fe, 1); + } + + while (!Mb_data_finished(&fe->eb.mb) && + Re_member_position(&fe->eb.renc) < member_size_limit) { + int match_distance; + int main_len = FLZe_longest_match_len(fe, &match_distance); + int pos_state = Mb_data_position(&fe->eb.mb) & pos_state_mask; + int len = 0; + + for (i = 0; i < num_rep_distances; ++i) { + int tlen = Mb_true_match_len(&fe->eb.mb, 0, reps[i] + 1); + if (tlen > len) { + len = tlen; + rep = i; + } + } + if (len > min_match_len && len + 3 > main_len) { + CRC32_update_buf(&fe->eb.crc, Mb_ptr_to_current_pos(&fe->eb.mb), len); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_match[state][pos_state], 1); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep[state], 1); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep0[state], rep != 0); + if (rep == 0) + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_len[state][pos_state], 1); + else { + int distance; + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep1[state], rep > 1); + if (rep > 1) + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep2[state], rep > 2); + distance = reps[rep]; + for (i = rep; i > 0; --i) + reps[i] = reps[i-1]; + reps[0] = distance; + } + state = St_set_rep(state); + Re_encode_len(&fe->eb.renc, &fe->eb.rep_len_model, len, pos_state); + Mb_move_pos(&fe->eb.mb); + FLZe_update_and_move(fe, len - 1); + continue; + } + + if (main_len > min_match_len) { + CRC32_update_buf(&fe->eb.crc, Mb_ptr_to_current_pos(&fe->eb.mb), main_len); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_match[state][pos_state], 1); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep[state], 0); + state = St_set_match(state); + for (i = num_rep_distances - 1; i > 0; --i) + reps[i] = reps[i-1]; + reps[0] = match_distance; + LZeb_encode_pair(&fe->eb, match_distance, main_len, pos_state); + Mb_move_pos(&fe->eb.mb); + FLZe_update_and_move(fe, main_len - 1); + continue; + } + + { + uchar prev_byte = Mb_peek(&fe->eb.mb, 1); + uchar cur_byte = Mb_peek(&fe->eb.mb, 0); + uchar match_byte = Mb_peek(&fe->eb.mb, reps[0] + 1); + Mb_move_pos(&fe->eb.mb); + CRC32_update_byte(&fe->eb.crc, cur_byte); + + if (match_byte == cur_byte) { + int short_rep_price = price1(fe->eb.bm_match[state][pos_state]) + + price1(fe->eb.bm_rep[state]) + + price0(fe->eb.bm_rep0[state]) + + price0(fe->eb.bm_len[state][pos_state]); + int price = price0(fe->eb.bm_match[state][pos_state]); + if (St_is_char(state)) + price += LZeb_price_literal(&fe->eb, prev_byte, cur_byte); + else + price += LZeb_price_matched(&fe->eb, prev_byte, cur_byte, match_byte); + if (short_rep_price < price) { + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_match[state][pos_state], 1); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep[state], 1); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_rep0[state], 0); + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_len[state][pos_state], 0); + state = St_set_short_rep(state); + continue; + } + } + + /* literal byte */ + Re_encode_bit(&fe->eb.renc, &fe->eb.bm_match[state][pos_state], 0); + if (St_is_char(state)) + LZeb_encode_literal(&fe->eb, prev_byte, cur_byte); + else + LZeb_encode_matched(&fe->eb, prev_byte, cur_byte, match_byte); + state = St_set_char(state); + } + } + + LZeb_full_flush(&fe->eb, state); + return true; +} diff --git a/sys/src/cmd/lzip/fast_encoder.h b/sys/src/cmd/lzip/fast_encoder.h new file mode 100644 index 0000000000..0feb0b9004 --- /dev/null +++ b/sys/src/cmd/lzip/fast_encoder.h @@ -0,0 +1,71 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . */ + +typedef struct FLZ_encoder FLZ_encoder; +struct FLZ_encoder { + struct LZ_encoder_base eb; + unsigned key4; /* key made from latest 4 bytes */ +}; + +static void +FLZe_reset_key4(FLZ_encoder *fe) +{ + int i; + fe->key4 = 0; + for (i = 0; i < 3 && i < Mb_avail_bytes(&fe->eb.mb); ++i) + fe->key4 = (fe->key4 << 4) ^ fe->eb.mb.buffer[i]; +} + +int FLZe_longest_match_len(FLZ_encoder *fe, int *distance); + +static void +FLZe_update_and_move(FLZ_encoder *fe, int n) +{ + while (--n >= 0) { + if (Mb_avail_bytes(&fe->eb.mb) >= 4) { + fe->key4 = ((fe->key4 << 4) ^ fe->eb.mb.buffer[fe->eb.mb.pos+3]) & + fe->eb.mb.key4_mask; + fe->eb.mb.pos_array[fe->eb.mb.cyclic_pos] = fe->eb.mb.prev_positions[fe->key4]; + fe->eb.mb.prev_positions[fe->key4] = fe->eb.mb.pos + 1; + } + Mb_move_pos(&fe->eb.mb); + } +} + +static bool +FLZe_init(FLZ_encoder *fe, int ifd, int outfd) +{ + enum { + before = 0, + dict_size = 65536, + /* bytes to keep in buffer after pos */ + after_size = max_match_len, + dict_factor = 16, + num_prev_positions23 = 0, + pos_array_factor = 1 + }; + + return LZeb_init(&fe->eb, before, dict_size, after_size, dict_factor, + num_prev_positions23, pos_array_factor, ifd, outfd); +} + +static void +FLZe_reset(FLZ_encoder *fe) +{ + LZeb_reset(&fe->eb); +} + +bool FLZe_encode_member(FLZ_encoder *fe, uvlong member_size); diff --git a/sys/src/cmd/lzip/lzip.h b/sys/src/cmd/lzip/lzip.h new file mode 100644 index 0000000000..fb3d94f1c5 --- /dev/null +++ b/sys/src/cmd/lzip/lzip.h @@ -0,0 +1,497 @@ +/* Clzip - LZMA lossless data compressor + Copyright (C) 2010-2017 Antonio Diaz Diaz. + + 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, see . + */ + +#ifndef _LZIP_H +#define _LZIP_H + +#include +#include +#include +#include + +#define exit(n) exits((n) == 0? 0: "err") +#define isatty(fd) 0 +#define lseek seek + +#ifndef max +#define max(x,y) ((x) >= (y) ? (x) : (y)) +#endif +#ifndef min +#define min(x,y) ((x) <= (y) ? (x) : (y)) +#endif + +typedef int State; +typedef long int32_t; +typedef ulong uint32_t; +typedef int bool; + +enum { false, true }; + +enum { states = 12 }; +enum { + min_dict_bits = 12, + min_dict_size = 1 << min_dict_bits, /* >= modeled_distances */ + max_dict_bits = 29, + max_dict_size = 1 << max_dict_bits, + min_member_size = 36, + literal_context_bits = 3, + literal_pos_state_bits = 0, /* not used */ + pos_state_bits = 2, + pos_states = 1 << pos_state_bits, + pos_state_mask = pos_states -1, + + len_states = 4, + dis_slot_bits = 6, + start_dis_model = 4, + end_dis_model = 14, + modeled_distances = 1 << (end_dis_model / 2), /* 128 */ + dis_align_bits = 4, + dis_align_size = 1 << dis_align_bits, + + len_low_bits = 3, + len_mid_bits = 3, + len_high_bits = 8, + len_low_syms = 1 << len_low_bits, + len_mid_syms = 1 << len_mid_bits, + len_high_syms = 1 << len_high_bits, + max_len_syms = len_low_syms + len_mid_syms + len_high_syms, + + min_match_len = 2, /* must be 2 */ + max_match_len = min_match_len + max_len_syms - 1, /* 273 */ + min_match_len_limit = 5, + + bit_model_move_bits = 5, + bit_model_total_bits = 11, + bit_model_total = 1 << bit_model_total_bits, +}; + +typedef struct Len_model Len_model; +typedef struct Pretty_print Pretty_print; +typedef struct Matchfinder_base Matchfinder_base; +typedef int Bit_model; + +struct Len_model { + Bit_model choice1; + Bit_model choice2; + Bit_model bm_low[pos_states][len_low_syms]; + Bit_model bm_mid[pos_states][len_mid_syms]; + Bit_model bm_high[len_high_syms]; +}; +struct Pretty_print { + char *name; + char *stdin_name; + ulong longest_name; + bool first_post; +}; + +typedef ulong CRC32[256]; /* Table of CRCs of all 8-bit messages. */ + +extern CRC32 crc32; + +#define errno 0 + +static uchar magic_string[4] = { "LZIP" }; + +typedef uchar File_header[6]; /* 0-3 magic bytes */ +/* 4 version */ +/* 5 coded_dict_size */ +enum { Fh_size = 6 }; + +typedef uchar File_trailer[20]; +/* 0-3 CRC32 of the uncompressed data */ +/* 4-11 size of the uncompressed data */ +/* 12-19 member size including header and trailer */ + +enum { Ft_size = 20 }; + +enum { + price_shift_bits = 6, + price_step_bits = 2, + price_step = 1 << price_step_bits, +}; + +typedef uchar Dis_slots[1<<10]; +typedef short Prob_prices[bit_model_total >> price_step_bits]; + +extern Dis_slots dis_slots; +extern Prob_prices prob_prices; + +#define get_price(prob) prob_prices[(prob) >> price_step_bits] +#define price0(prob) get_price(prob) +#define price1(prob) get_price(bit_model_total - (prob)) +#define price_bit(bm, bit) ((bit)? price1(bm): price0(bm)) + +#define Mb_ptr_to_current_pos(mb) ((mb)->buffer + (mb)->pos) +#define Mb_peek(mb, distance) (mb)->buffer[(mb)->pos - (distance)] + +#define Lp_price(lp, len, pos_state) \ + (lp)->prices[pos_state][(len) - min_match_len] + +#define Tr_update(trial, pr, distance4, p_i) \ +{ \ + if ((pr) < (trial)->price) { \ + (trial)->price = pr; \ + (trial)->dis4 = distance4; \ + (trial)->prev_index = p_i; \ + (trial)->prev_index2 = single_step_trial; \ + } else { \ + } \ +} + +/* these functions are now extern and must be defined exactly once */ +#ifdef _DEFINE_INLINES +#define _INLINES_DEFINED + +int +get_len_state(int len) +{ + int lenstm1, lenmmm; + + lenmmm = len - min_match_len; + lenstm1 = len_states - 1; + if (lenmmm < lenstm1) + return lenmmm; + else + return lenstm1; +} + +State +St_set_char(State st) +{ + static State next[states] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; + + assert((unsigned)st < nelem(next)); + return next[st]; +} + +int +get_lit_state(uchar prev_byte) +{ + return prev_byte >> (8 - literal_context_bits); +} + +void +Bm_init(Bit_model *probability) +{ + *probability = bit_model_total / 2; +} + +void +Bm_array_init(Bit_model bm[], int size) +{ + int i; + + for (i = 0; i < size; ++i) + Bm_init(&bm[i]); +} + +void +Lm_init(Len_model *lm) +{ + Bm_init(&lm->choice1); + Bm_init(&lm->choice2); + Bm_array_init(lm->bm_low[0], pos_states * len_low_syms); + Bm_array_init(lm->bm_mid[0], pos_states * len_mid_syms); + Bm_array_init(lm->bm_high, len_high_syms); +} + +void +Pp_init(Pretty_print *pp, char *filenames[], int num_filenames, int verbosity) +{ + unsigned stdin_name_len; + int i; + + pp->name = 0; + pp->stdin_name = "(stdin)"; + pp->longest_name = 0; + pp->first_post = false; + + if (verbosity <= 0) + return; + stdin_name_len = strlen(pp->stdin_name); + for (i = 0; i < num_filenames; ++i) { + char *s = filenames[i]; + unsigned len = strcmp(s, "-") == 0? stdin_name_len: strlen(s); + + if (len > pp->longest_name) + pp->longest_name = len; + } + if (pp->longest_name == 0) + pp->longest_name = stdin_name_len; +} + +void +Pp_set_name(Pretty_print *pp, char *filename) +{ + if ( filename && filename[0] && strcmp( filename, "-" ) != 0 ) + pp->name = filename; + else + pp->name = pp->stdin_name; + pp->first_post = true; +} + +void +Pp_reset(Pretty_print *pp) +{ + if (pp->name && pp->name[0]) + pp->first_post = true; +} + +void +Pp_show_msg(Pretty_print *pp, char *msg); + +void +CRC32_init(void) +{ + unsigned n; + + for (n = 0; n < 256; ++n) { + unsigned c = n; + int k; + for (k = 0; k < 8; ++k) { + if (c & 1) + c = 0xEDB88320U ^ (c >> 1); + else + c >>= 1; + } + crc32[n] = c; + } +} + +void +CRC32_update_byte(uint32_t *crc, uchar byte) +{ + *crc = crc32[(*crc^byte)&0xFF] ^ (*crc >> 8); +} + +void +CRC32_update_buf(uint32_t *crc, uchar *buffer, int size) +{ + int i; + uint32_t c = *crc; + for (i = 0; i < size; ++i) + c = crc32[(c^buffer[i])&0xFF] ^ (c >> 8); + *crc = c; +} + +bool +isvalid_ds(unsigned dict_size) +{ + return (dict_size >= min_dict_size && + dict_size <= max_dict_size); +} + +int +real_bits(unsigned value) +{ + int bits = 0; + + while (value > 0) { + value >>= 1; + ++bits; + } + return bits; +} + +void +Fh_set_magic(File_header data) +{ + memcpy(data, magic_string, 4); + data[4] = 1; +} + +bool +Fh_verify_magic(File_header data) +{ + return (memcmp(data, magic_string, 4) == 0); +} + +/* detect truncated header */ +bool +Fh_verify_prefix(File_header data, int size) +{ + int i; + for (i = 0; i < size && i < 4; ++i) + if (data[i] != magic_string[i]) + return false; + return (size > 0); +} + +uchar +Fh_version(File_header data) +{ + return data[4]; +} + +bool +Fh_verify_version(File_header data) +{ + return (data[4] == 1); +} + +unsigned +Fh_get_dict_size(File_header data) +{ + unsigned sz = (1 << (data[5] &0x1F)); + if (sz > min_dict_size) + sz -= (sz / 16) * ((data[5] >> 5) & 7); + return sz; +} + +bool +Fh_set_dict_size(File_header data, unsigned sz) +{ + if (!isvalid_ds(sz)) + return false; + data[5] = real_bits(sz - 1); + if (sz > min_dict_size) { + unsigned base_size = 1 << data[5]; + unsigned fraction = base_size / 16; + unsigned i; + for (i = 7; i >= 1; --i) + if (base_size - (i * fraction) >= sz) { + data[5] |= (i << 5); + break; + } + } + return true; +} + +unsigned +Ft_get_data_crc(File_trailer data) +{ + unsigned tmp = 0; + int i; + for (i = 3; i >= 0; --i) { + tmp <<= 8; + tmp += data[i]; + } + return tmp; +} + +void +Ft_set_data_crc(File_trailer data, unsigned crc) +{ + int i; + for (i = 0; i <= 3; ++i) { + data[i] = (uchar)crc; + crc >>= 8; + } +} + +uvlong +Ft_get_data_size(File_trailer data) +{ + uvlong tmp = 0; + int i; + for (i = 11; i >= 4; --i) { + tmp <<= 8; + tmp += data[i]; + } + return tmp; +} + +void +Ft_set_data_size(File_trailer data, uvlong sz) +{ + int i; + for (i = 4; i <= 11; ++i) { + data[i] = (uchar)sz; + sz >>= 8; + } +} + +uvlong +Ft_get_member_size(File_trailer data) +{ + uvlong tmp = 0; + int i; + for (i = 19; i >= 12; --i) { + tmp <<= 8; + tmp += data[i]; + } + return tmp; +} + +void +Ft_set_member_size(File_trailer data, uvlong sz) +{ + int i; + for (i = 12; i <= 19; ++i) { + data[i] = (uchar)sz; + sz >>= 8; + } +} +#else /* _DEFINE_INLINES */ +void Bm_array_init(Bit_model bm[], int size); +void Bm_init(Bit_model *probability); +void CRC32_init(void); +void CRC32_update_buf(uint32_t *crc, uchar *buffer, int size); +void CRC32_update_byte(uint32_t *crc, uchar byte); +unsigned Fh_get_dict_size(File_header data); +bool Fh_set_dict_size(File_header data, unsigned sz); +void Fh_set_magic(File_header data); +bool Fh_verify_magic(File_header data); +bool Fh_verify_prefix(File_header data, int size); +bool Fh_verify_version(File_header data); +uchar Fh_version(File_header data); +unsigned Ft_get_data_crc(File_trailer data); +uvlong Ft_get_data_size(File_trailer data); +uvlong Ft_get_member_size(File_trailer data); +void Ft_set_data_crc(File_trailer data, unsigned crc); +void Ft_set_data_size(File_trailer data, uvlong sz); +void Ft_set_member_size(File_trailer data, uvlong sz); +void Lm_init(Len_model *lm); +void Pp_init(Pretty_print *pp, char *filenames[], int num_filenames, int verbosity); +void Pp_reset(Pretty_print *pp); +void Pp_set_name(Pretty_print *pp, char *filename); +void Pp_show_msg(Pretty_print *pp, char *msg); +State St_set_char(State st); +int get_lit_state(uchar prev_byte); +int get_len_state(int len); +bool isvalid_ds(unsigned dict_size); +int real_bits(unsigned value); +#endif /* _DEFINE_INLINES */ + +#define St_is_char(state) ((state) < 7) +#define St_set_match(state) ((state) < 7? 7: 10) +#define St_set_rep(state) ((state) < 7? 8: 11) +#define St_set_short_rep(state) ((state) < 7? 9: 11) + +static char *bad_magic_msg = "Bad magic number (file not in lzip format)."; +static char *bad_dict_msg = "Invalid dictionary size in member header."; +static char *trailing_msg = "Trailing data not allowed."; + +/* defined in decoder.c */ +int readblock(int fd, uchar *buf, int size); +int writeblock(int fd, uchar *buf, int size); + +/* defined in main.c */ +extern int verbosity; +Dir; +char *bad_version(unsigned version); +char *format_ds(unsigned dict_size); +int open_instream(char *name, Dir *in_statsp, bool no_ofile, bool reg_only); +void *resize_buffer(void *buf, unsigned min_size); +void cleanup_and_fail(int retval); +void show_error(char *msg, int errcode, bool help); +void show_file_error(char *filename, char *msg, int errcode); +void internal_error(char *msg); +struct Matchfinder_base; +void show_progress(uvlong partial_size, Matchfinder_base *m, Pretty_print *p, + uvlong cfile_size); +#endif diff --git a/sys/src/cmd/lzip/main.c b/sys/src/cmd/lzip/main.c new file mode 100644 index 0000000000..a690fc15f9 --- /dev/null +++ b/sys/src/cmd/lzip/main.c @@ -0,0 +1,883 @@ +/* + * Clzip - LZMA lossless data compressor + * Copyright (C) 2010-2017 Antonio Diaz Diaz. + * + * 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, see . + */ +/* + * Exit status: 0 for a normal exit, 1 for environmental problems + * (file not found, invalid flags, I/O errors, etc), 2 to indicate a + * corrupt or invalid input file, 3 for an internal consistency error + * (eg, bug) which caused lzip to panic. + */ + +#define _DEFINE_INLINES +#include "lzip.h" +#include "decoder.h" +#include "encoder_base.h" +#include "encoder.h" +#include "fast_encoder.h" + +int verbosity = 0; + +char *argv0 = "lzip"; + +struct { + char * from; + char * to; +} known_extensions[] = { + { ".lz", "" }, + { ".tlz", ".tar" }, + { 0, 0 } +}; + +typedef struct Lzma_options Lzma_options; +struct Lzma_options { + int dict_size; /* 4 KiB .. 512 MiB */ + int match_len_limit; /* 5 .. 273 */ +}; + +enum Mode { m_compress, m_decompress, }; + +char *output_filename = nil; +int outfd = -1; +bool delete_output_on_interrupt = false; + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [-[0-9]cdv] [file...]\n", argv0); + exit(2); +} + +char * +bad_version(unsigned version) +{ + static char buf[80]; + + snprintf(buf, sizeof buf, "Version %ud member format not supported.", + version); + return buf; +} + +char * +format_ds(unsigned dict_size) +{ + enum { bufsize = 16, factor = 1024 }; + char *prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; + char *p = ""; + char *np = " "; + unsigned num = dict_size, i; + bool exact = (num % factor == 0); + static char buf[bufsize]; + + for (i = 0; i < 8 && (num > 9999 || (exact && num >= factor)); ++i) { + num /= factor; + if (num % factor != 0) + exact = false; + p = prefix[i]; + np = ""; + } + snprintf( buf, bufsize, "%s%4ud %sB", np, num, p ); + return buf; +} + +static void +show_header(unsigned dict_size) +{ + if (verbosity >= 3) + fprintf(stderr, "dictionary %s. ", format_ds( dict_size) ); +} + +static uvlong +getnum(char *ptr, uvlong llimit, uvlong ulimit) +{ + int bad; + uvlong result; + char *tail; + + bad = 0; + result = strtoull(ptr, &tail, 0); + if (tail == ptr) { + show_error( "Bad or missing numerical argument.", 0, true ); + exit(1); + } + + if (!errno && tail[0]) { + unsigned factor = (tail[1] == 'i') ? 1024 : 1000; + int i, exponent = 0; /* 0 = bad multiplier */ + + switch (tail[0]) { + case 'Y': + exponent = 8; + break; + case 'Z': + exponent = 7; + break; + case 'E': + exponent = 6; + break; + case 'P': + exponent = 5; + break; + case 'T': + exponent = 4; + break; + case 'G': + exponent = 3; + break; + case 'M': + exponent = 2; + break; + case 'K': + if (factor == 1024) + exponent = 1; + break; + case 'k': + if (factor == 1000) + exponent = 1; + break; + } + if (exponent <= 0) { + show_error( "Bad multiplier in numerical argument.", 0, true ); + exit(1); + } + for (i = 0; i < exponent; ++i) { + if (ulimit / factor >= result) + result *= factor; + else { + bad++; + break; + } + } + } + if (bad || result < llimit || result > ulimit) { + show_error( "Numerical argument out of limits.", 0, false ); + exit(1); + } + return result; +} + +static int +get_dict_size(char *arg) +{ + char *tail; + long bits = strtol(arg, &tail, 0); + + if (bits >= min_dict_bits && + bits <= max_dict_bits && *tail == 0) + return (1 << bits); + return getnum(arg, min_dict_size, max_dict_size); +} + +void +set_mode(enum Mode *program_modep, enum Mode new_mode) +{ + if (*program_modep != m_compress && *program_modep != new_mode) { + show_error( "Only one operation can be specified.", 0, true ); + exit(1); + } + *program_modep = new_mode; +} + +static int +extension_index(char *name) +{ + int eindex; + + for (eindex = 0; known_extensions[eindex].from; ++eindex) { + char * ext = known_extensions[eindex].from; + unsigned name_len = strlen(name); + unsigned ext_len = strlen(ext); + + if (name_len > ext_len && + strncmp(name + name_len - ext_len, ext, ext_len) == 0) + return eindex; + } + return - 1; +} + +int +open_instream(char *name, Dir *, bool, bool) +{ + int infd = open(name, OREAD); + + if (infd < 0) + show_file_error( name, "Can't open input file", errno ); + return infd; +} + +static int +open_instream2(char *name, Dir *in_statsp, enum Mode program_mode, + int eindex, bool recompress, bool to_stdout) +{ + bool no_ofile = to_stdout; + + if (program_mode == m_compress && !recompress && eindex >= 0) { + if (verbosity >= 0) + fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", + argv0, name, known_extensions[eindex].from); + return - 1; + } + return open_instream(name, in_statsp, no_ofile, false); +} + +/* assure at least a minimum size for buffer 'buf' */ +void * +resize_buffer(void *buf, unsigned min_size) +{ + buf = realloc(buf, min_size); + if (!buf) { + show_error("Not enough memory.", 0, false); + cleanup_and_fail(1); + } + return buf; +} + +static void +set_c_outname(char *name, bool multifile) +{ + output_filename = resize_buffer(output_filename, strlen(name) + 5 + + strlen(known_extensions[0].from) + 1); + strcpy(output_filename, name); + if (multifile) + strcat( output_filename, "00001" ); + strcat(output_filename, known_extensions[0].from); +} + +static void +set_d_outname(char *name, int eindex) +{ + unsigned name_len = strlen(name); + if (eindex >= 0) { + char * from = known_extensions[eindex].from; + unsigned from_len = strlen(from); + + if (name_len > from_len) { + output_filename = resize_buffer(output_filename, name_len + + strlen(known_extensions[eindex].to) + 1); + strcpy(output_filename, name); + strcpy(output_filename + name_len - from_len, known_extensions[eindex].to); + return; + } + } + output_filename = resize_buffer(output_filename, name_len + 4 + 1); + strcpy(output_filename, name); + strcat(output_filename, ".out"); + if (verbosity >= 1) + fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n", + argv0, name, output_filename); +} + +static bool +open_outstream(bool force, bool) +{ + int flags = OWRITE; + + if (force) + flags |= OTRUNC; + else + flags |= OEXCL; + + outfd = create(output_filename, flags, 0666); + if (outfd >= 0) + delete_output_on_interrupt = true; + else if (verbosity >= 0) + fprintf(stderr, "%s: Can't create output file '%s': %r\n", + argv0, output_filename); + return outfd >= 0; +} + +static bool +check_tty(int, enum Mode program_mode) +{ + if (program_mode == m_compress && isatty(outfd) || + program_mode == m_decompress && isatty(infd)) { + usage(); + return false; + } + return true; +} + +void +cleanup_and_fail(int retval) +{ + if (delete_output_on_interrupt) { + delete_output_on_interrupt = false; + if (verbosity >= 0) + fprintf(stderr, "%s: Deleting output file '%s', if it exists.\n", + argv0, output_filename); + if (outfd >= 0) { + close(outfd); + outfd = -1; + } + if (remove(output_filename) != 0) + fprintf(stderr, "%s: can't remove output file %s: %r\n", + argv0, output_filename); + } + exit(retval); +} + +/* Set permissions, owner and times. */ +static void +close_and_set_permissions(Dir *) +{ + if (close(outfd) != 0) { + show_error( "Error closing output file", errno, false ); + cleanup_and_fail(1); + } + outfd = -1; + delete_output_on_interrupt = false; +} + +static bool +next_filename(void) +{ + int i, j; + unsigned name_len = strlen(output_filename); + unsigned ext_len = strlen(known_extensions[0].from); + + if ( name_len >= ext_len + 5 ) /* "*00001.lz" */ + for (i = name_len - ext_len - 1, j = 0; j < 5; --i, ++j) { + if (output_filename[i] < '9') { + ++output_filename[i]; + return true; + } else + output_filename[i] = '0'; + } + return false; +} + +typedef struct Poly_encoder Poly_encoder; +struct Poly_encoder { + LZ_encoder_base *eb; + LZ_encoder *e; + FLZ_encoder *fe; +}; + +static int +compress(uvlong member_size, uvlong volume_size, + int infd, Lzma_options *encoder_options, Pretty_print *pp, + Dir *in_statsp, bool zero) +{ + int retval = 0; + uvlong in_size = 0, out_size = 0, partial_volume_size = 0; + uvlong cfile_size = in_statsp? in_statsp->length / 100: 0; + Poly_encoder encoder = { 0, 0, 0 }; /* polymorphic encoder */ + bool error = false; + + if (verbosity >= 1) + Pp_show_msg(pp, 0); + + if (zero) { + encoder.fe = (FLZ_encoder *)malloc(sizeof * encoder.fe); + if (!encoder.fe || !FLZe_init(encoder.fe, infd, outfd)) + error = true; + else + encoder.eb = &encoder.fe->eb; + } else { + File_header header; + + if (Fh_set_dict_size(header, encoder_options->dict_size) && + encoder_options->match_len_limit >= min_match_len_limit && + encoder_options->match_len_limit <= max_match_len) + encoder.e = (LZ_encoder *)malloc(sizeof * encoder.e); + else + internal_error( "invalid argument to encoder." ); + if (!encoder.e || !LZe_init(encoder.e, Fh_get_dict_size(header), + encoder_options->match_len_limit, infd, outfd)) + error = true; + else + encoder.eb = &encoder.e->eb; + } + if (error) { + Pp_show_msg( pp, "Not enough memory. Try a smaller dictionary size." ); + return 1; + } + + for(;;) { /* encode one member per iteration */ + uvlong size; + vlong freevolsz; + + size = member_size; + if (volume_size > 0) { + freevolsz = volume_size - partial_volume_size; + if (size > freevolsz) + size = freevolsz; /* limit size */ + } + show_progress(in_size, &encoder.eb->mb, pp, cfile_size); /* init */ + if ((zero && !FLZe_encode_member(encoder.fe, size)) || + (!zero && !LZe_encode_member(encoder.e, size))) { + Pp_show_msg( pp, "Encoder error." ); + retval = 1; + break; + } + in_size += Mb_data_position(&encoder.eb->mb); + out_size += Re_member_position(&encoder.eb->renc); + if (Mb_data_finished(&encoder.eb->mb)) + break; + if (volume_size > 0) { + partial_volume_size += Re_member_position(&encoder.eb->renc); + if (partial_volume_size >= volume_size - min_dict_size) { + partial_volume_size = 0; + if (delete_output_on_interrupt) { + close_and_set_permissions(in_statsp); + if (!next_filename()) { + Pp_show_msg( pp, "Too many volume files." ); + retval = 1; + break; + } + if (!open_outstream(true, !in_statsp)) { + retval = 1; + break; + } + } + } + } + if (zero) + FLZe_reset(encoder.fe); + else + LZe_reset(encoder.e); + } + + if (retval == 0 && verbosity >= 1) + if (in_size == 0 || out_size == 0) + fputs( " no data compressed.\n", stderr ); + else { + if (0) + fprintf(stderr, + "%6.3f:1, %6.3f bits/byte, %5.2f%% saved, ", + (double)in_size / out_size, + (8.0 * out_size) / in_size, + 100.0 * (1.0 - (double)out_size/in_size)); + fprintf(stderr, "%llud in, %llud out.\n", + in_size, out_size); + } + LZeb_free(encoder.eb); + if (zero) + free(encoder.fe); + else + free(encoder.e); + return retval; +} + +static uchar +xdigit(unsigned value) +{ + if (value <= 9) + return '0' + value; + if (value <= 15) + return 'A' + value - 10; + return 0; +} + +static bool +show_trailing_data(uchar *data, int size, Pretty_print *pp, bool all, + bool ignore_trailing) +{ + if (verbosity >= 4 || !ignore_trailing) { + char buf[128]; + int i, len = snprintf(buf, sizeof buf, "%strailing data = ", + all? "": "first bytes of "); + + if (len < 0) + len = 0; + for (i = 0; i < size && len + 2 < sizeof buf; ++i) { + buf[len++] = xdigit(data[i] >> 4); + buf[len++] = xdigit(data[i] & 0x0F); + buf[len++] = ' '; + } + if (len < sizeof buf) + buf[len++] = '\''; + for (i = 0; i < size && len < sizeof buf; ++i) { + if (isprint(data[i])) + buf[len++] = data[i]; + else + buf[len++] = '.'; + } + if (len < sizeof buf) + buf[len++] = '\''; + if (len < sizeof buf) + buf[len] = 0; + else + buf[sizeof buf - 1] = 0; + Pp_show_msg(pp, buf); + if (!ignore_trailing) + show_file_error(pp->name, trailing_msg, 0); + } + return ignore_trailing; +} + +static int +decompress(int infd, Pretty_print *pp, bool ignore_trailing) +{ + uvlong partial_file_pos = 0; + Range_decoder rdec; + int retval = 0; + bool first_member; + + if (!Rd_init(&rdec, infd)) { + show_error( "Not enough memory.", 0, false ); + cleanup_and_fail(1); + } + + for (first_member = true; ; first_member = false) { + int result, size; + unsigned dict_size; + File_header header; + LZ_decoder decoder; + + Rd_reset_member_position(&rdec); + size = Rd_read_data(&rdec, header, Fh_size); + if (Rd_finished(&rdec)) /* End Of File */ { + if (first_member || Fh_verify_prefix(header, size)) { + Pp_show_msg( pp, "File ends unexpectedly at member header." ); + retval = 2; + } else if (size > 0 && !show_trailing_data(header, size, pp, + true, ignore_trailing)) + retval = 2; + break; + } + if (!Fh_verify_magic(header)) { + if (first_member) { + show_file_error(pp->name, bad_magic_msg, 0); + retval = 2; + } else if (!show_trailing_data(header, size, pp, + false, ignore_trailing)) + retval = 2; + break; + } + if (!Fh_verify_version(header)) { + Pp_show_msg(pp, bad_version(Fh_version(header))); + retval = 2; + break; + } + dict_size = Fh_get_dict_size(header); + if (!isvalid_ds(dict_size)) { + Pp_show_msg(pp, bad_dict_msg); + retval = 2; + break; + } + + if (verbosity >= 2 || (verbosity == 1 && first_member)) { + Pp_show_msg(pp, 0); + show_header(dict_size); + } + + if (!LZd_init(&decoder, &rdec, dict_size, outfd)) { + Pp_show_msg( pp, "Not enough memory." ); + retval = 1; + break; + } + result = LZd_decode_member(&decoder, pp); + partial_file_pos += Rd_member_position(&rdec); + LZd_free(&decoder); + if (result != 0) { + if (verbosity >= 0 && result <= 2) { + Pp_show_msg(pp, 0); + fprintf(stderr, "%s: %s at pos %llud\n", + argv0, (result == 2? + "file ends unexpectedly": + "decoder error"), partial_file_pos); + } + retval = 2; + break; + } + if (verbosity >= 2) { + fputs("done\n", stderr); + Pp_reset(pp); + } + } + Rd_free(&rdec); + if (verbosity == 1 && retval == 0) + fputs("done\n", stderr); + return retval; +} + +void +signal_handler(int sig) +{ + USED(sig); + show_error("interrupt caught, quitting.", 0, false); + cleanup_and_fail(1); +} + +static void +set_signals(void) +{ +} + +void +show_error(char *msg, int, bool help) +{ + if (verbosity < 0) + return; + if (msg && msg[0]) + fprintf(stderr, "%s: %s: %r\n", argv0, msg); + if (help) + fprintf(stderr, "Try '%s --help' for more information.\n", + argv0); +} + +void +show_file_error(char *filename, char *msg, int errcode) +{ + if (verbosity < 0) + return; + fprintf(stderr, "%s: %s: %s", argv0, filename, msg); + if (errcode > 0) + fprintf(stderr, ": %r"); + fputc('\n', stderr); +} + +void +internal_error(char *msg) +{ + if (verbosity >= 0) + fprintf( stderr, "%s: internal error: %s\n", argv0, msg ); + exit(3); +} + +void +show_progress(uvlong partial_size, Matchfinder_base *m, + Pretty_print *p, uvlong cfile_size) +{ + static uvlong psize = 0, csize = 0; /* csize=file_size/100 */ + static Matchfinder_base *mb = 0; + static Pretty_print *pp = 0; + + if (verbosity < 2) + return; + if (m) { /* initialize static vars */ + csize = cfile_size; + psize = partial_size; + mb = m; + pp = p; + } + if (mb && pp) { + uvlong pos = psize + Mb_data_position(mb); + + if (csize > 0) + fprintf( stderr, "%4llud%%", pos / csize ); + fprintf( stderr, " %.1f MB\r", pos / 1000000.0 ); + Pp_reset(pp); + Pp_show_msg(pp, 0); /* restore cursor position */ + } +} + +/* + * Mapping from gzip/bzip2 style 1..9 compression modes to the corresponding + * LZMA compression modes. + */ +static Lzma_options option_mapping[] = { + { 1 << 16, 16 }, + { 1 << 20, 5 }, + { 3 << 19, 6 }, + { 1 << 21, 8 }, + { 3 << 20, 12 }, + { 1 << 22, 20 }, + { 1 << 23, 36 }, + { 1 << 24, 68 }, + { 3 << 23, 132 }, +// { 1 << 25, max_match_len }, // TODO + { 1 << 26, max_match_len }, +}; + +void +main(int argc, char *argv[]) +{ + int num_filenames, infd, i, retval = 0; + bool filenames_given = false, force = false, ignore_trailing = true, + recompress = false, + stdin_used = false, to_stdout = false, zero = false; + uvlong max_member_size = 0x0008000000000000ULL; + uvlong max_volume_size = 0x4000000000000000ULL; + uvlong member_size = max_member_size; + uvlong volume_size = 0; + char *default_output_filename = ""; + char **filenames = nil; + enum Mode program_mode = m_compress; + Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ + Pretty_print pp; + + CRC32_init(); + + ARGBEGIN { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + zero = (ARGC() == '0'); + encoder_options = option_mapping[ARGC() - '0']; + break; + case 'a': + ignore_trailing = false; + break; + case 'b': + member_size = getnum(EARGF(usage()), 100000, max_member_size); + break; + case 'c': + to_stdout = true; + break; + case 'd': + set_mode(&program_mode, m_decompress); + break; + case 'f': + force = true; + break; + case 'F': + recompress = true; + break; + case 'm': + encoder_options.match_len_limit = + getnum(EARGF(usage()), min_match_len_limit, max_match_len); + zero = false; + break; + case 'o': + default_output_filename = EARGF(usage()); + break; + case 'q': + verbosity = -1; + break; + case 's': + encoder_options.dict_size = get_dict_size(EARGF(usage())); + zero = false; + break; + case 'S': + volume_size = getnum(EARGF(usage()), 100000, max_volume_size); + break; + case 'v': + if (verbosity < 4) + ++verbosity; + break; + default: + usage(); + } ARGEND + + num_filenames = max(1, argc); + filenames = resize_buffer(filenames, num_filenames * sizeof filenames[0]); + filenames[0] = "-"; + for (i = 0; i < argc; ++i) { + filenames[i] = argv[i]; + if (strcmp(filenames[i], "-") != 0) + filenames_given = true; + } + + if (program_mode == m_compress) { + Dis_slots_init(); + Prob_prices_init(); + } + + if (!to_stdout && (filenames_given || default_output_filename[0])) + set_signals(); + + Pp_init(&pp, filenames, num_filenames, verbosity); + + output_filename = resize_buffer(output_filename, 1); + for (i = 0; i < num_filenames; ++i) { + char *input_filename = ""; + int tmp, eindex; + Dir in_stats; + Dir *in_statsp; + + output_filename[0] = 0; + if ( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) { + if (stdin_used) + continue; + else + stdin_used = true; + infd = 0; + if (to_stdout || !default_output_filename[0]) + outfd = 1; + else { + if (program_mode == m_compress) + set_c_outname(default_output_filename, + volume_size > 0); + else { + output_filename = resize_buffer(output_filename, + strlen(default_output_filename)+1); + strcpy(output_filename, + default_output_filename); + } + if (!open_outstream(force, true)) { + if (retval < 1) + retval = 1; + close(infd); + continue; + } + } + } else { + eindex = extension_index(input_filename = filenames[i]); + infd = open_instream2(input_filename, &in_stats, + program_mode, eindex, recompress, to_stdout); + if (infd < 0) { + if (retval < 1) + retval = 1; + continue; + } + if (to_stdout) + outfd = 1; + else { + if (program_mode == m_compress) + set_c_outname(input_filename, + volume_size > 0); + else + set_d_outname(input_filename, eindex); + if (!open_outstream(force, false)) { + if (retval < 1) + retval = 1; + close(infd); + continue; + } + } + } + + Pp_set_name(&pp, input_filename); + if (!check_tty(infd, program_mode)) { + if (retval < 1) + retval = 1; + cleanup_and_fail(retval); + } + + in_statsp = input_filename[0]? &in_stats: nil; + if (program_mode == m_compress) + tmp = compress(member_size, volume_size, infd, + &encoder_options, &pp, in_statsp, zero); + else + tmp = decompress(infd, &pp, ignore_trailing); + if (tmp > retval) + retval = tmp; + if (tmp) + cleanup_and_fail(retval); + + if (delete_output_on_interrupt) + close_and_set_permissions(in_statsp); + if (input_filename[0]) + close(infd); + } + if (outfd >= 0 && close(outfd) != 0) { + show_error("Can't close stdout", errno, false); + if (retval < 1) + retval = 1; + } + free(output_filename); + free(filenames); + exit(retval); +} diff --git a/sys/src/cmd/lzip/mkfile b/sys/src/cmd/lzip/mkfile new file mode 100644 index 0000000000..53f442cc9e --- /dev/null +++ b/sys/src/cmd/lzip/mkfile @@ -0,0 +1,21 @@ +# mkfile for lzip - LZMA lossless data compressor + /dev/null || + { + echo "$0: a POSIX shell is required to run the tests" + echo "Try bash -c \"$0 $1 $2\"" + exit 1 + } + +if [ -d tmp ] ; then rm -rf tmp ; fi +mkdir tmp +cd "${objdir}"/tmp || framework_failure + +cat "${testdir}"/test.txt > in || framework_failure +in_lz="${testdir}"/test.txt.lz +fail=0 +test_failed() { fail=1 ; printf " $1" ; [ -z "$2" ] || printf "($2)" ; } + +printf "testing clzip-%s..." "$2" + +"${LZIP}" -fkqm4 in +{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO +"${LZIP}" -fkqm274 in +{ [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO +for i in bad_size -1 0 4095 513MiB 1G 1T 1P 1E 1Z 1Y 10KB ; do + "${LZIP}" -fkqs $i in + { [ $? = 1 ] && [ ! -e in.lz ] ; } || test_failed $LINENO $i +done +"${LZIP}" -lq in +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -tq in +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -tq < in +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -cdq in +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -cdq < in +[ $? = 2 ] || test_failed $LINENO +# these are for code coverage +"${LZIP}" -lt "${in_lz}" 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -cdl "${in_lz}" > out 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -cdt "${in_lz}" > out 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -t -- nx_file 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --help > /dev/null || test_failed $LINENO +"${LZIP}" -n1 -V > /dev/null || test_failed $LINENO +"${LZIP}" -m 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -z 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --bad_option 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --t 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --test=2 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --output= 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" --output 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +printf "LZIP\001-.............................." | "${LZIP}" -t 2> /dev/null +printf "LZIP\002-.............................." | "${LZIP}" -t 2> /dev/null +printf "LZIP\001+.............................." | "${LZIP}" -t 2> /dev/null + +printf "\ntesting decompression..." + +"${LZIP}" -lq "${in_lz}" || test_failed $LINENO +"${LZIP}" -t "${in_lz}" || test_failed $LINENO +"${LZIP}" -cd "${in_lz}" > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO + +rm -f copy +cat "${in_lz}" > copy.lz || framework_failure +"${LZIP}" -dk copy.lz || test_failed $LINENO +cmp in copy || test_failed $LINENO +printf "to be overwritten" > copy || framework_failure +"${LZIP}" -d copy.lz 2> /dev/null +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -df copy.lz +{ [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; } || test_failed $LINENO + +printf "to be overwritten" > copy || framework_failure +"${LZIP}" -df -o copy < "${in_lz}" || test_failed $LINENO +cmp in copy || test_failed $LINENO + +rm -f copy +"${LZIP}" < in > anyothername || test_failed $LINENO +"${LZIP}" -dv --output copy - anyothername - < "${in_lz}" 2> /dev/null +{ [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; } || + test_failed $LINENO +rm -f copy anyothername.out + +"${LZIP}" -lq in "${in_lz}" +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -lq nx_file.lz "${in_lz}" +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -tq in "${in_lz}" +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -tq nx_file.lz "${in_lz}" +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -cdq in "${in_lz}" > copy +{ [ $? = 2 ] && cat copy in | cmp in - ; } || test_failed $LINENO +"${LZIP}" -cdq nx_file.lz "${in_lz}" > copy +{ [ $? = 1 ] && cmp in copy ; } || test_failed $LINENO +rm -f copy +cat "${in_lz}" > copy.lz || framework_failure +for i in 1 2 3 4 5 6 7 ; do + printf "g" >> copy.lz || framework_failure + "${LZIP}" -alvv copy.lz "${in_lz}" > /dev/null 2>&1 + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -atvvvv copy.lz "${in_lz}" 2> /dev/null + [ $? = 2 ] || test_failed $LINENO $i +done +"${LZIP}" -dq in copy.lz +{ [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; } || + test_failed $LINENO +"${LZIP}" -dq nx_file.lz copy.lz +{ [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e nx_file ] && cmp in copy ; } || + test_failed $LINENO + +cat in in > in2 || framework_failure +cat "${in_lz}" "${in_lz}" > in2.lz || framework_failure +"${LZIP}" -lq in2.lz || test_failed $LINENO +"${LZIP}" -t in2.lz || test_failed $LINENO +"${LZIP}" -cd in2.lz > copy2 || test_failed $LINENO +cmp in2 copy2 || test_failed $LINENO + +"${LZIP}" --output=copy2 < in2 || test_failed $LINENO +"${LZIP}" -lq copy2.lz || test_failed $LINENO +"${LZIP}" -t copy2.lz || test_failed $LINENO +"${LZIP}" -cd copy2.lz > copy2 || test_failed $LINENO +cmp in2 copy2 || test_failed $LINENO + +printf "\ngarbage" >> copy2.lz || framework_failure +"${LZIP}" -tvvvv copy2.lz 2> /dev/null || test_failed $LINENO +rm -f copy2 +"${LZIP}" -alq copy2.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -atq copy2.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -atq < copy2.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -adkq copy2.lz +{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO +"${LZIP}" -adkq -o copy2 < copy2.lz +{ [ $? = 2 ] && [ ! -e copy2 ] ; } || test_failed $LINENO +printf "to be overwritten" > copy2 || framework_failure +"${LZIP}" -df copy2.lz || test_failed $LINENO +cmp in2 copy2 || test_failed $LINENO + +printf "\ntesting compression..." + +"${LZIP}" -cf "${in_lz}" > out 2> /dev/null # /dev/null is a tty on OS/2 +[ $? = 1 ] || test_failed $LINENO +"${LZIP}" -cFvvm36 "${in_lz}" > out 2> /dev/null || test_failed $LINENO +"${LZIP}" -cd out | "${LZIP}" -d > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO + +for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do + "${LZIP}" -k -$i in || test_failed $LINENO $i + mv -f in.lz copy.lz || test_failed $LINENO $i + printf "garbage" >> copy.lz || framework_failure + "${LZIP}" -df copy.lz || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i +done + +for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do + "${LZIP}" -c -$i in > out || test_failed $LINENO $i + printf "g" >> out || framework_failure + "${LZIP}" -cd out > copy || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i +done + +for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do + "${LZIP}" -$i < in > out || test_failed $LINENO $i + "${LZIP}" -d < out > copy || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i +done + +for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do + "${LZIP}" -f -$i -o out < in || test_failed $LINENO $i + "${LZIP}" -df -o copy < out.lz || test_failed $LINENO $i + cmp in copy || test_failed $LINENO $i +done + +cat in in in in in in in in > in8 || framework_failure +"${LZIP}" -1s12 -S100k -o out < in8 || test_failed $LINENO +"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO +"${LZIP}" -cd out00001.lz out00002.lz | cmp in8 - || test_failed $LINENO +rm -f out00001.lz +"${LZIP}" -1ks4Ki -b100000 in8 || test_failed $LINENO +"${LZIP}" -t in8.lz || test_failed $LINENO +"${LZIP}" -cd in8.lz | cmp in8 - || test_failed $LINENO +rm -f in8 +"${LZIP}" -0 -S100k -o out < in8.lz || test_failed $LINENO +"${LZIP}" -t out00001.lz out00002.lz || test_failed $LINENO +"${LZIP}" -cd out00001.lz out00002.lz | cmp in8.lz - || test_failed $LINENO +rm -f out00001.lz out00002.lz +"${LZIP}" -0kF -b100k in8.lz || test_failed $LINENO +"${LZIP}" -t in8.lz.lz || test_failed $LINENO +"${LZIP}" -cd in8.lz.lz | cmp in8.lz - || test_failed $LINENO +rm -f in8.lz in8.lz.lz + +printf "\ntesting bad input..." + +cat "${in_lz}" "${in_lz}" "${in_lz}" > in3.lz || framework_failure +if dd if=in3.lz of=trunc.lz bs=14752 count=1 2> /dev/null && + [ -e trunc.lz ] && cmp in2.lz trunc.lz > /dev/null 2>&1 ; then + for i in 6 20 14734 14753 14754 14755 14756 14757 14758 ; do + dd if=in3.lz of=trunc.lz bs=$i count=1 2> /dev/null + "${LZIP}" -lq trunc.lz + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -t trunc.lz 2> /dev/null + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -tq < trunc.lz + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -cdq trunc.lz > out + [ $? = 2 ] || test_failed $LINENO $i + "${LZIP}" -dq < trunc.lz > out + [ $? = 2 ] || test_failed $LINENO $i + done +else + printf "\nwarning: skipping truncation test: 'dd' does not work on your system." +fi + +cat "${in_lz}" > ingin.lz || framework_failure +printf "g" >> ingin.lz || framework_failure +cat "${in_lz}" >> ingin.lz || framework_failure +"${LZIP}" -lq ingin.lz +[ $? = 2 ] || test_failed $LINENO +"${LZIP}" -t ingin.lz || test_failed $LINENO +"${LZIP}" -cd ingin.lz > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO +"${LZIP}" -t < ingin.lz || test_failed $LINENO +"${LZIP}" -d < ingin.lz > copy || test_failed $LINENO +cmp in copy || test_failed $LINENO + +echo +if [ ${fail} = 0 ] ; then + echo "tests completed successfully." + cd "${objdir}" && rm -r tmp +else + echo "tests failed." +fi +exit ${fail} diff --git a/sys/src/cmd/lzip/testsuite/test.txt b/sys/src/cmd/lzip/testsuite/test.txt new file mode 100644 index 0000000000..9196a3a97a --- /dev/null +++ b/sys/src/cmd/lzip/testsuite/test.txt @@ -0,0 +1,676 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. From 98744c801e88adcf868cbb9caa2e8b9a600ae84b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 1 Oct 2019 06:08:18 +0000 Subject: [PATCH 190/402] sys/src/cmd/ramcfs: import ramcfs from HARE (thanks Geoff Collyer) --- sys/src/cmd/ramcfs/bcache.c | 199 ++++++++ sys/src/cmd/ramcfs/bcache.h | 45 ++ sys/src/cmd/ramcfs/cformat.h | 75 +++ sys/src/cmd/ramcfs/cfs.c | 914 +++++++++++++++++++++++++++++++++++ sys/src/cmd/ramcfs/disk.c | 344 +++++++++++++ sys/src/cmd/ramcfs/disk.h | 24 + sys/src/cmd/ramcfs/file.c | 298 ++++++++++++ sys/src/cmd/ramcfs/file.h | 5 + sys/src/cmd/ramcfs/inode.c | 412 ++++++++++++++++ sys/src/cmd/ramcfs/inode.h | 60 +++ sys/src/cmd/ramcfs/lru.c | 75 +++ sys/src/cmd/ramcfs/lru.h | 15 + sys/src/cmd/ramcfs/mkfile | 41 ++ sys/src/cmd/ramcfs/notes | 21 + sys/src/cmd/ramcfs/stats.h | 26 + 15 files changed, 2554 insertions(+) create mode 100644 sys/src/cmd/ramcfs/bcache.c create mode 100644 sys/src/cmd/ramcfs/bcache.h create mode 100644 sys/src/cmd/ramcfs/cformat.h create mode 100644 sys/src/cmd/ramcfs/cfs.c create mode 100644 sys/src/cmd/ramcfs/disk.c create mode 100644 sys/src/cmd/ramcfs/disk.h create mode 100644 sys/src/cmd/ramcfs/file.c create mode 100644 sys/src/cmd/ramcfs/file.h create mode 100644 sys/src/cmd/ramcfs/inode.c create mode 100644 sys/src/cmd/ramcfs/inode.h create mode 100644 sys/src/cmd/ramcfs/lru.c create mode 100644 sys/src/cmd/ramcfs/lru.h create mode 100644 sys/src/cmd/ramcfs/mkfile create mode 100644 sys/src/cmd/ramcfs/notes create mode 100644 sys/src/cmd/ramcfs/stats.h diff --git a/sys/src/cmd/ramcfs/bcache.c b/sys/src/cmd/ramcfs/bcache.c new file mode 100644 index 0000000000..6f8935e290 --- /dev/null +++ b/sys/src/cmd/ramcfs/bcache.c @@ -0,0 +1,199 @@ +#include +#include +#include "cformat.h" +#include "lru.h" +#include "bcache.h" + +int +bcinit(Bcache *bc, char *mc, int bsize) +{ + Bbuf *b; + + /* + * allocate space for all buffers + * point all buffers into outer space + */ + bc->dfirst = 0; + bc->bsize = bsize; + bc->memcache = mc; + lruinit(bc); + for(b = bc->bb; b < &bc->bb[Nbcache]; b++){ + b->inuse = 0; + b->next = 0; + b->dirty = 0; + if(b->data == 0) + b->data = (char *)malloc(bc->bsize); + if(b->data == 0) + return -1; + lruadd(bc, b); + } + + return 0; +} + +/* + * Find a buffer for block b. If it's dirty, write it out. + */ +Bbuf * +bcfind(Bcache *bc, ulong bno) +{ + Bbuf *b; + + if(bno == Notabno) + error("bcfind: Notabno"); + bno &= ~Indbno; + + /* + * if we already have a buffer for this bno, use it + */ + for(b = bc->bb; b < &bc->bb[Nbcache]; b++) + if(b->inuse && b->bno==bno) + goto out; + + /* + * get least recently used block + */ + b = (Bbuf*)bc->lnext; +out: + /* + * if dirty, write it out + */ + if(b->dirty) + if(bcwrite(bc, b) < 0) + warning("writing dirty page"); + lruref(bc, b); + return b; +} + +/* + * allocate a buffer block for a block. it's guaranteed to be there till + * the next Nbcache bcread's. + */ +Bbuf * +bcalloc(Bcache *bc, ulong bno) +{ + Bbuf *b; + + b = bcfind(bc, bno); + bno &= ~Indbno; + b->bno = bno; + b->inuse = 1; + return b; +} + +/* + * read a block into a buffer cache. it's guaranteed to be there till + * the next Nbcache bcread's. + */ +Bbuf * +bcread(Bcache *bc, ulong bno) +{ + Bbuf *b; + + b = bcfind(bc, bno); + bno &= ~Indbno; + if(b->bno!=bno || !b->inuse) + /* + * read in the one we really want + */ + if(bread(bc, bno, b->data) < 0){ + b->inuse = 0; + return 0; + } + b->bno = bno; + b->inuse = 1; + return b; +} + +/* + * mark a page dirty, if it's already dirty force a write + * + * N.B: ordering is important. + */ +void +bcmark(Bcache *bc, Bbuf *b) +{ + lruref(bc, b); + + if(b->dirty){ + bcwrite(bc, b); + return; + } + + b->dirty = 1; + if(bc->dfirst) + bc->dlast->next = b; + else + bc->dfirst = b; + bc->dlast = b; +} + +/* + * write out a page (and all preceding dirty ones) + */ +int +bcwrite(Bcache *bc, Bbuf *b) +{ + Bbuf *nb; + + /* + * write out all preceding pages + */ + while(nb = bc->dfirst){ + if(bwrite(bc, nb->bno, nb->data) < 0) + return -1; + nb->dirty = 0; + bc->dfirst = nb->next; + nb->next = 0; + if(nb == b) + return 0; + } + + /* + * write out this page + */ + if(bwrite(bc, b->bno, b->data) < 0) + return -1; + b->dirty = 0; + b->next = 0; + return 0; +} + +/* + * write out all dirty pages (in order) + */ +int +bcsync(Bcache *bc) +{ + if(bc->dfirst) + return bcwrite(bc, bc->dlast); + return 0; +} + +/* + * read a block from memory cache + */ +int +bread(Bcache *bc, ulong bno, void *buf) +{ + uvlong x = (uvlong)bno * bc->bsize; + + if (x > cachesize - bc->bsize) + return -1; + memmove(buf, bc->memcache + x, bc->bsize); + return 0; +} + +/* + * write a block to memory cache + */ +int +bwrite(Bcache *bc, ulong bno, void *buf) +{ + uvlong x = (uvlong)bno * bc->bsize; + + if (x > cachesize - bc->bsize) + return -1; + memmove(bc->memcache + x, buf, bc->bsize); + return 0; +} diff --git a/sys/src/cmd/ramcfs/bcache.h b/sys/src/cmd/ramcfs/bcache.h new file mode 100644 index 0000000000..6e190e314b --- /dev/null +++ b/sys/src/cmd/ramcfs/bcache.h @@ -0,0 +1,45 @@ +typedef struct Bbuf Bbuf; +typedef struct Bcache Bcache; + +enum +{ + Nbcache= 32, /* number of blocks kept in pool */ +}; + +/* + * block cache descriptor + */ +struct Bbuf +{ + Lru; /* must be first in struct */ + ulong bno; + int inuse; + Bbuf *next; /* next in dirty list */ + int dirty; + char *data; +}; + +/* + * the buffer cache + */ +struct Bcache +{ + Lru; + int bsize; /* block size in bytes */ + char *memcache; /* memory cache base */ + Bbuf *dfirst; /* dirty list */ + Bbuf *dlast; + Bbuf bb[Nbcache]; +}; + +int bcinit(Bcache*, char*, int); +Bbuf* bcalloc(Bcache*, ulong); +Bbuf* bcread(Bcache*, ulong); +void bcmark(Bcache*, Bbuf*); +int bcwrite(Bcache*, Bbuf*); +int bcsync(Bcache*); +int bread(Bcache*, ulong, void*); +int bwrite(Bcache*, ulong, void*); +int bref(Bcache*, Bbuf*); +void error(char*, ...); +void warning(char*); diff --git a/sys/src/cmd/ramcfs/cformat.h b/sys/src/cmd/ramcfs/cformat.h new file mode 100644 index 0000000000..b69e3ee8bc --- /dev/null +++ b/sys/src/cmd/ramcfs/cformat.h @@ -0,0 +1,75 @@ +/* + * format of cache on disk + */ +typedef struct Dptr Dptr; +typedef struct Dahdr Dahdr; +typedef struct Dalloc Dalloc; +typedef struct Fphdr Fphdr; +typedef struct Fptr Fptr; +typedef struct Inode Inode; +typedef struct Dihdr Dihdr; +typedef struct Dinode Dinode; + +enum +{ + Amagic= 0xbebeefed, /* allocation block magic */ + Imagic= 0xbadc00ce, /* inode block magic */ + BtoUL= 8*sizeof(ulong),/* bits in a ulong */ + CACHENAMELEN= 128 +}; +#define Indbno 0x80000000 /* indirect block */ +#define Notabno 0xFFFFFFFF /* not a block number */ + +/* + * Allocation blocks at the begining of the disk. There are + * enough of these blocks to supply 1 bit for each block on the + * disk; + */ +struct Dahdr +{ + ulong magic; + ulong bsize; /* logical block size */ + char name[CACHENAMELEN]; + short nab; /* number of allocation blocks */ +}; +struct Dalloc +{ + Dahdr; + ulong bits[1]; +}; + +/* + * A pointer to disk data + */ +struct Dptr +{ + ulong fbno; /* file block number */ + ulong bno; /* disk block number */ + ushort start; /* offset into block of valid data */ + ushort end; /* offset into block after valid data */ +}; + +/* + * A file descriptor. + */ +struct Inode +{ + Qid qid; + vlong length; + Dptr ptr; /* pointer page */ + char inuse; +}; + +/* + * inode blocks (after allocation blocks) + */ +struct Dihdr +{ + ulong magic; + ulong nino; /* number of inodes */ +}; +struct Dinode +{ + Dihdr; + Inode inode[1]; +}; diff --git a/sys/src/cmd/ramcfs/cfs.c b/sys/src/cmd/ramcfs/cfs.c new file mode 100644 index 0000000000..96f07d05ae --- /dev/null +++ b/sys/src/cmd/ramcfs/cfs.c @@ -0,0 +1,914 @@ +#include +#include +#include +#include + +#include "cformat.h" +#include "lru.h" +#include "bcache.h" +#include "disk.h" +#include "inode.h" +#include "file.h" +#include "stats.h" + +enum +{ + Nfid= 10240, +}; + +/* maximum length of a file */ +enum { MAXLEN = ~0ULL >> 1 }; + +typedef struct Mfile Mfile; +typedef struct Ram Ram; +typedef struct P9fs P9fs; + +struct Mfile +{ + Qid qid; + char busy; +}; + +Mfile mfile[Nfid]; +Icache ic; +int debug, statson, noauth, openserver; +int readonly; /* flag: tree being cached is expected to not change */ + +struct P9fs +{ + int fd[2]; + Fcall rhdr; + Fcall thdr; + long len; + char *name; +}; + +P9fs c; /* client conversation */ +P9fs s; /* server conversation */ + +struct Cfsstat cfsstat, cfsprev; +char statbuf[2048]; +int statlen; + +#define MAXFDATA 8192 /* i/o size for read/write */ + +int messagesize = MAXFDATA+IOHDRSZ; + +uchar datasnd[MAXFDATA + IOHDRSZ]; +uchar datarcv[MAXFDATA + IOHDRSZ]; + +Qid rootqid; +Qid ctlqid = {0x5555555555555555LL, 0, 0}; + +ulong cachesize = 512 * 1024 * 1024; + +void rversion(void); +void rauth(Mfile*); +void rflush(void); +void rattach(Mfile*); +void rwalk(Mfile*); +void ropen(Mfile*); +void rcreate(Mfile*); +void rread(Mfile*); +void rwrite(Mfile*); +void rclunk(Mfile*); +void rremove(Mfile*); +void rstat(Mfile*); +void rwstat(Mfile*); +void error(char*, ...); +void warning(char*); +void mountinit(char*, char*); +void io(void); +void sendreply(char*); +void sendmsg(P9fs*, Fcall*); +void rcvmsg(P9fs*, Fcall*); +int delegate(void); +int askserver(void); +void cachesetup(int, char*, char*); +int ctltest(Mfile*); +void genstats(void); + +char *mname[]={ + [Tversion] "Tversion", + [Tauth] "Tauth", + [Tflush] "Tflush", + [Tattach] "Tattach", + [Twalk] "Twalk", + [Topen] "Topen", + [Tcreate] "Tcreate", + [Tclunk] "Tclunk", + [Tread] "Tread", + [Twrite] "Twrite", + [Tremove] "Tremove", + [Tstat] "Tstat", + [Twstat] "Twstat", + [Rversion] "Rversion", + [Rauth] "Rauth", + [Rerror] "Rerror", + [Rflush] "Rflush", + [Rattach] "Rattach", + [Rwalk] "Rwalk", + [Ropen] "Ropen", + [Rcreate] "Rcreate", + [Rclunk] "Rclunk", + [Rread] "Rread", + [Rwrite] "Rwrite", + [Rremove] "Rremove", + [Rstat] "Rstat", + [Rwstat] "Rwstat", + 0, +}; + +void +usage(void) +{ + fprint(2, "usage:\t%s -s [-dnrS] [-m size]\n", argv0); + fprint(2, "\t%s [-a netaddr | -F srv] [-dnrS] [-m size] [mntpt]\n", + argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + int std; + char *server, *mtpt; + + std = 0; + server = "tcp!pie"; + mtpt = "/n/ramcfs"; + + ARGBEGIN{ + case 'a': + server = EARGF(usage()); + break; + case 'd': + debug = 1; + break; + case 'F': + server = EARGF(usage()); + openserver = 1; + break; + case 'm': + cachesize = atoi(EARGF(usage())) * 1024 * 1024; + if (cachesize < 8 * 1024 * 1024 || + cachesize > 3750UL * 1024 * 1024) + sysfatal("implausible cache size %lud", cachesize); + break; + case 'n': + noauth = 1; + break; + case 'r': + readonly = 1; + break; + case 'S': + statson = 1; + break; + case 's': + std = 1; + break; + default: + usage(); + }ARGEND + if(argc && *argv) + mtpt = *argv; + + if(debug) + fmtinstall('F', fcallfmt); + + c.name = "client"; + s.name = "server"; + if(std){ + c.fd[0] = c.fd[1] = 1; + s.fd[0] = s.fd[1] = 0; + }else + mountinit(server, mtpt); + + cachesetup(1, nil, nil); + + switch(fork()){ + case 0: + io(); + exits(""); + case -1: + error("fork"); + default: + exits(""); + } +} + +void +cachesetup(int format, char *name, char *) +{ + int secsize; + int inodes; + int blocksize; + char *memcache; + + secsize = 512; /* only really matters for disks */ + blocksize = 4*1024; + inodes = 2*1024; + + memcache = malloc(cachesize); + if(memcache == nil) + error("can't allocate memory for cache: %r"); + + /* + * Always format. If we don't have a name, fall + * back to our old behavior of using "bootes" + */ + USED(format); + name = (name == nil? "bootes": name); + if(iformat(&ic, memcache, inodes, name, blocksize, secsize) < 0) + error("formatting failed"); +} + +void +mountinit(char *server, char *mountpoint) +{ + int err; + int p[2]; + + /* + * grab a channel and call up the file server + */ + if (openserver) { + s.fd[0] = open(server, ORDWR); + if(s.fd[0] < 0) + error("opening srv file %s: %r", server); + } else { + s.fd[0] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0); + if(s.fd[0] < 0) + error("dialing %s: %r", server); + } + s.fd[1] = s.fd[0]; + + /* + * mount onto name space + */ + if(pipe(p) < 0) + error("pipe failed"); + switch(fork()){ + case 0: + break; + default: + if (noauth) + err = mount(p[1], -1, mountpoint, MREPL|MCREATE|MCACHE, ""); + else + err = amount(p[1], mountpoint, MREPL|MCREATE|MCACHE, ""); + if (err < 0) + error("mount failed: %r"); + exits(0); + case -1: + error("fork failed\n"); +/*BUG: no wait!*/ + } + c.fd[0] = c.fd[1] = p[0]; +} + +void +io(void) +{ + int type; + Mfile *mf; + loop: + rcvmsg(&c, &c.thdr); + + type = c.thdr.type; + + if(statson){ + cfsstat.cm[type].n++; + cfsstat.cm[type].s = nsec(); + } + mf = &mfile[c.thdr.fid]; + switch(type){ + default: + error("type"); + break; + case Tversion: + rversion(); + break; + case Tauth: + mf = &mfile[c.thdr.afid]; + rauth(mf); + break; + case Tflush: + rflush(); + break; + case Tattach: + rattach(mf); + break; + case Twalk: + rwalk(mf); + break; + case Topen: + ropen(mf); + break; + case Tcreate: + rcreate(mf); + break; + case Tread: + rread(mf); + break; + case Twrite: + rwrite(mf); + break; + case Tclunk: + rclunk(mf); + break; + case Tremove: + rremove(mf); + break; + case Tstat: + rstat(mf); + break; + case Twstat: + rwstat(mf); + break; + } + if(statson){ + cfsstat.cm[type].t += nsec() -cfsstat.cm[type].s; + } + goto loop; +} + +void +rversion(void) +{ + if(messagesize > c.thdr.msize) + messagesize = c.thdr.msize; + c.thdr.msize = messagesize; /* set downstream size */ + delegate(); +} + +void +rauth(Mfile *mf) +{ + if(mf->busy) + error("auth to used channel"); + + if(delegate() == 0){ + mf->qid = s.rhdr.aqid; + mf->busy = 1; + } +} + +void +rflush(void) /* synchronous so easy */ +{ + sendreply(0); +} + +void +rattach(Mfile *mf) +{ + if(delegate() == 0){ + mf->qid = s.rhdr.qid; + mf->busy = 1; + if (statson == 1){ + statson++; + rootqid = mf->qid; + } + } +} + +void +rwalk(Mfile *mf) +{ + Mfile *nmf; + + nmf = nil; + if(statson + && mf->qid.type == rootqid.type && mf->qid.path == rootqid.path + && c.thdr.nwname == 1 && strcmp(c.thdr.wname[0], "cfsctl") == 0){ + /* This is the ctl file */ + nmf = &mfile[c.thdr.newfid]; + if(c.thdr.newfid != c.thdr.fid && nmf->busy) + error("clone to used channel"); + nmf = &mfile[c.thdr.newfid]; + nmf->qid = ctlqid; + nmf->busy = 1; + c.rhdr.nwqid = 1; + c.rhdr.wqid[0] = ctlqid; + sendreply(0); + return; + } + if(c.thdr.newfid != c.thdr.fid){ + if(c.thdr.newfid >= Nfid) + error("clone nfid out of range"); + nmf = &mfile[c.thdr.newfid]; + if(nmf->busy) + error("clone to used channel"); + nmf = &mfile[c.thdr.newfid]; + nmf->qid = mf->qid; + nmf->busy = 1; + mf = nmf; /* Walk mf */ + } + + if(delegate() < 0){ /* complete failure */ + if(nmf) + nmf->busy = 0; + return; + } + + if(s.rhdr.nwqid == c.thdr.nwname){ /* complete success */ + if(s.rhdr.nwqid > 0) + mf->qid = s.rhdr.wqid[s.rhdr.nwqid-1]; + return; + } + + /* partial success; release fid */ + if(nmf) + nmf->busy = 0; +} + +void +ropen(Mfile *mf) +{ + if(statson && ctltest(mf)){ + /* Opening ctl file */ + if(c.thdr.mode != OREAD){ + sendreply("does not exist"); + return; + } + c.rhdr.qid = ctlqid; + c.rhdr.iounit = 0; + sendreply(0); + genstats(); + return; + } + if(delegate() == 0){ + mf->qid = s.rhdr.qid; + if(c.thdr.mode & OTRUNC) + iget(&ic, mf->qid); + } +} + +void +rcreate(Mfile *mf) +{ + if(statson && ctltest(mf)){ + sendreply("exists"); + return; + } + if(delegate() == 0){ + mf->qid = s.rhdr.qid; + mf->qid.vers++; + } +} + +void +rclunk(Mfile *mf) +{ + if(!mf->busy){ + sendreply(0); + return; + } + mf->busy = 0; + delegate(); +} + +void +rremove(Mfile *mf) +{ + if(statson && ctltest(mf)){ + sendreply("not removed"); + return; + } + mf->busy = 0; + delegate(); +} + +void +rread(Mfile *mf) +{ + int cnt, done; + long n; + vlong off, first; + char *cp; + char data[MAXFDATA]; + Ibuf *b; + + off = c.thdr.offset; + first = off; + cnt = c.thdr.count; + + if(statson && ctltest(mf)){ + if(cnt > statlen-off) + c.rhdr.count = statlen-off; + else + c.rhdr.count = cnt; + if((int)c.rhdr.count < 0){ + sendreply("eof"); + return; + } + c.rhdr.data = statbuf + off; + sendreply(0); + return; + } + if(mf->qid.type & (QTDIR|QTAUTH)){ + delegate(); + if (statson) { + cfsstat.ndirread++; + if(c.rhdr.count > 0){ + cfsstat.bytesread += c.rhdr.count; + cfsstat.bytesfromdirs += c.rhdr.count; + } + } + return; + } + + b = iget(&ic, mf->qid); + if(b == 0){ + DPRINT(2, "delegating read\n"); + delegate(); + if (statson){ + cfsstat.ndelegateread++; + if(c.rhdr.count > 0){ + cfsstat.bytesread += c.rhdr.count; + cfsstat.bytesfromserver += c.rhdr.count; + } + } + return; + } + + cp = data; + done = 0; + while(cnt>0 && !done){ + if(off >= b->inode.length){ + DPRINT(2, "offset %lld greater than length %lld\n", + off, b->inode.length); + break; + } + n = fread(&ic, b, cp, off, cnt); + if(n <= 0){ + n = -n; + if(n==0 || n>cnt) + n = cnt; + DPRINT(2, + "fetch %ld bytes of data from server at offset %lld\n", + n, off); + s.thdr.type = c.thdr.type; + s.thdr.fid = c.thdr.fid; + s.thdr.tag = c.thdr.tag; + s.thdr.offset = off; + s.thdr.count = n; + if(statson) + cfsstat.ndelegateread++; + if(askserver() < 0){ + sendreply(s.rhdr.ename); + return; + } + if(s.rhdr.count != n) + done = 1; + n = s.rhdr.count; + if(n == 0){ + /* end of file */ + if(b->inode.length > off){ + DPRINT(2, "file %llud.%ld, length %lld\n", + b->inode.qid.path, + b->inode.qid.vers, off); + b->inode.length = off; + } + break; + } + memmove(cp, s.rhdr.data, n); + fwrite(&ic, b, cp, off, n); + if (statson){ + cfsstat.bytestocache += n; + cfsstat.bytesfromserver += n; + } + }else{ + DPRINT(2, "fetched %ld bytes from cache\n", n); + if(statson) + cfsstat.bytesfromcache += n; + } + cnt -= n; + off += n; + cp += n; + } + c.rhdr.data = data; + c.rhdr.count = off - first; + if(statson) + cfsstat.bytesread += c.rhdr.count; + sendreply(0); +} + +void +rwrite(Mfile *mf) +{ + Ibuf *b; + char buf[MAXFDATA]; + + if(statson && ctltest(mf)){ + sendreply("read only"); + return; + } + if(mf->qid.type & (QTDIR|QTAUTH)){ + delegate(); + if(statson && c.rhdr.count > 0) + cfsstat.byteswritten += c.rhdr.count; + return; + } + + memmove(buf, c.thdr.data, c.thdr.count); + if(delegate() < 0) + return; + + if(s.rhdr.count > 0) + cfsstat.byteswritten += s.rhdr.count; + /* don't modify our cache for append-only data; always read from server*/ + if(mf->qid.type & QTAPPEND) + return; + b = iget(&ic, mf->qid); + if(b == 0) + return; + if (b->inode.length < c.thdr.offset + s.rhdr.count) + b->inode.length = c.thdr.offset + s.rhdr.count; + mf->qid.vers++; + if (s.rhdr.count != c.thdr.count) + syslog(0, "cfslog", "rhdr.count %ud, thdr.count %ud\n", + s.rhdr.count, c.thdr.count); + if(fwrite(&ic, b, buf, c.thdr.offset, s.rhdr.count) == s.rhdr.count){ + iinc(&ic, b); + if(statson) + cfsstat.bytestocache += s.rhdr.count; + } +} + +void +rstat(Mfile *mf) +{ + Dir d; + + if(statson && ctltest(mf)){ + genstats(); + d.qid = ctlqid; + d.mode = 0444; + d.length = statlen; /* would be nice to do better */ + d.name = "cfsctl"; + d.uid = "none"; + d.gid = "none"; + d.muid = "none"; + d.atime = time(nil); + d.mtime = d.atime; + c.rhdr.nstat = convD2M(&d, c.rhdr.stat, + sizeof c.rhdr - (c.rhdr.stat - (uchar*)&c.rhdr)); + sendreply(0); + return; + } + if(delegate() == 0){ + Ibuf *b; + + convM2D(s.rhdr.stat, s.rhdr.nstat , &d, nil); + mf->qid = d.qid; + b = iget(&ic, mf->qid); + if(b) + b->inode.length = d.length; + } +} + +void +rwstat(Mfile *mf) +{ + Ibuf *b; + + if(statson && ctltest(mf)){ + sendreply("read only"); + return; + } + delegate(); + if(b = iget(&ic, mf->qid)) + b->inode.length = MAXLEN; +} + +void +error(char *fmt, ...) +{ + va_list arg; + static char buf[2048]; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%s: %s\n", argv0, buf); + exits("error"); +} + +void +warning(char *s) +{ + fprint(2, "%s: %s: %r\n", argv0, s); +} + +/* + * send a reply to the client + */ +void +sendreply(char *err) +{ + + if(err){ + c.rhdr.type = Rerror; + c.rhdr.ename = err; + }else{ + c.rhdr.type = c.thdr.type+1; + c.rhdr.fid = c.thdr.fid; + } + c.rhdr.tag = c.thdr.tag; + sendmsg(&c, &c.rhdr); +} + +/* + * send a request to the server, get the reply, and send that to + * the client + */ +int +delegate(void) +{ + int type; + + type = c.thdr.type; + if(statson){ + cfsstat.sm[type].n++; + cfsstat.sm[type].s = nsec(); + } + + sendmsg(&s, &c.thdr); + rcvmsg(&s, &s.rhdr); + + if(statson) + cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s; + + sendmsg(&c, &s.rhdr); + return c.thdr.type+1 == s.rhdr.type ? 0 : -1; +} + +/* + * send a request to the server and get a reply + */ +int +askserver(void) +{ + int type; + + s.thdr.tag = c.thdr.tag; + + type = s.thdr.type; + if(statson){ + cfsstat.sm[type].n++; + cfsstat.sm[type].s = nsec(); + } + + sendmsg(&s, &s.thdr); + rcvmsg(&s, &s.rhdr); + + if(statson) + cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s; + + return s.thdr.type+1 == s.rhdr.type ? 0 : -1; +} + +/* + * send/receive messages with logging + */ +void +sendmsg(P9fs *p, Fcall *f) +{ + DPRINT(2, "->%s: %F\n", p->name, f); + + p->len = convS2M(f, datasnd, messagesize); + if(p->len <= 0) + error("convS2M"); + if(write(p->fd[1], datasnd, p->len)!=p->len) + error("sendmsg"); +} + +void +dump(uchar *p, int len) +{ + fprint(2, "%d bytes", len); + while(len-- > 0) + fprint(2, " %.2ux", *p++); + fprint(2, "\n"); +} + +void +rcvmsg(P9fs *p, Fcall *f) +{ + int olen, rlen; + char buf[128]; + + olen = p->len; + p->len = read9pmsg(p->fd[0], datarcv, sizeof(datarcv)); + if(p->len <= 0){ + snprint(buf, sizeof buf, "read9pmsg(%d)->%ld: %r", + p->fd[0], p->len); + error(buf); + } + + if((rlen = convM2S(datarcv, p->len, f)) != p->len) + error("rcvmsg format error, expected length %d, got %d", + rlen, p->len); + if(f->fid >= Nfid){ + fprint(2, "<-%s: %d %s on %d\n", p->name, f->type, + mname[f->type]? mname[f->type]: "mystery", f->fid); + dump((uchar*)datasnd, olen); + dump((uchar*)datarcv, p->len); + error("rcvmsg fid out of range"); + } + DPRINT(2, "<-%s: %F\n", p->name, f); +} + +int +ctltest(Mfile *mf) +{ + return mf->busy && mf->qid.type == ctlqid.type && + mf->qid.path == ctlqid.path; +} + +void +genstats(void) +{ + int i; + char *p; + + p = statbuf; + + p += snprint(p, sizeof statbuf+statbuf-p, + " Client Server\n"); + p += snprint(p, sizeof statbuf+statbuf-p, + " #calls Δ ms/call Δ #calls Δ ms/call Δ\n"); + for (i = 0; i < nelem(cfsstat.cm); i++) + if(cfsstat.cm[i].n || cfsstat.sm[i].n) { + p += snprint(p, sizeof statbuf+statbuf-p, + "%7lud %7lud ", cfsstat.cm[i].n, + cfsstat.cm[i].n - cfsprev.cm[i].n); + if (cfsstat.cm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001*cfsstat.cm[i].t/ + cfsstat.cm[i].n); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + if(cfsstat.cm[i].n - cfsprev.cm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001* + (cfsstat.cm[i].t - cfsprev.cm[i].t)/ + (cfsstat.cm[i].n - cfsprev.cm[i].n)); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + p += snprint(p, sizeof statbuf+statbuf-p, + "%7lud %7lud ", cfsstat.sm[i].n, + cfsstat.sm[i].n - cfsprev.sm[i].n); + if (cfsstat.sm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001*cfsstat.sm[i].t/ + cfsstat.sm[i].n); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + if(cfsstat.sm[i].n - cfsprev.sm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001* + (cfsstat.sm[i].t - cfsprev.sm[i].t)/ + (cfsstat.sm[i].n - cfsprev.sm[i].n)); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + p += snprint(p, sizeof statbuf+statbuf-p, "%s\n", + mname[i]); + } + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndirread\n", + cfsstat.ndirread, cfsstat.ndirread - cfsprev.ndirread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelegateread\n", + cfsstat.ndelegateread, cfsstat.ndelegateread - + cfsprev.ndelegateread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ninsert\n", + cfsstat.ninsert, cfsstat.ninsert - cfsprev.ninsert); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelete\n", + cfsstat.ndelete, cfsstat.ndelete - cfsprev.ndelete); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud nupdate\n", + cfsstat.nupdate, cfsstat.nupdate - cfsprev.nupdate); + + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesread\n", + cfsstat.bytesread, cfsstat.bytesread - cfsprev.bytesread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud byteswritten\n", + cfsstat.byteswritten, cfsstat.byteswritten - + cfsprev.byteswritten); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromserver\n", + cfsstat.bytesfromserver, cfsstat.bytesfromserver - + cfsprev.bytesfromserver); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromdirs\n", + cfsstat.bytesfromdirs, cfsstat.bytesfromdirs - + cfsprev.bytesfromdirs); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromcache\n", + cfsstat.bytesfromcache, cfsstat.bytesfromcache - + cfsprev.bytesfromcache); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytestocache\n", + cfsstat.bytestocache, cfsstat.bytestocache - + cfsprev.bytestocache); + statlen = p - statbuf; + cfsprev = cfsstat; +} diff --git a/sys/src/cmd/ramcfs/disk.c b/sys/src/cmd/ramcfs/disk.c new file mode 100644 index 0000000000..320ad708ae --- /dev/null +++ b/sys/src/cmd/ramcfs/disk.c @@ -0,0 +1,344 @@ +#include +#include +#include "cformat.h" +#include "lru.h" +#include "bcache.h" +#include "disk.h" + +int icformat(Disk*, ulong); + +/* + * read in the disk structures, return -1 if the format + * is inconsistent. + */ +int +dinit(Disk *d, char *mc, int psize, char *expname) +{ + ulong i; + uvlong length; + char buf[1024]; + Bbuf *b; + Dalloc *ba; + + /* + * get disk size + */ + length = cachesize; + + /* + * read first physical block to get logical block size, # of inodes, + * and # of allocation blocks + */ + memmove(buf, mc, sizeof buf); + + ba = (Dalloc*)buf; + if(ba->bsize <= 0){ + fprint(2, "dinit: bsize 0x%lux<= 0\n", ba->bsize); + return -1; + } + if((ba->bsize % psize) != 0){ + fprint(2, "dinit: logical bsize (%lud) not multiple of physical (%ud)\n", + ba->bsize, psize); + return -1; + } + d->bsize = ba->bsize; + d->nb = length/d->bsize; + d->b2b = (d->bsize - sizeof(Dahdr))*8; + d->nab = (d->nb+d->b2b-1)/d->b2b; + d->p2b = d->bsize/sizeof(Dptr); + strncpy(d->name, ba->name, sizeof d->name); + + if (expname != nil && strncmp(d->name, expname, sizeof d->name) != 0) { + /* Mismatch with recorded name; fail here to force a format */ + fprint(2, "%s: name mismatch\n", argv0); + return -1; + } + + /* + * check allocation blocks for consistency + */ + if(bcinit(d, mc, d->bsize) < 0){ + fprint(2, "%s: dinit: couldn't init block cache\n", argv0); + return -1; + } + for(i = 0; i < d->nab; i++){ + b = bcread(d, i); + if(b == 0){ + perror("dinit: read"); + return -1; + } + ba = (Dalloc*)b->data; + if(ba->magic != Amagic){ + fprint(2, "dinit: bad magic in alloc block %uld\n", i); + return -1; + } + if(d->bsize != ba->bsize){ + fprint(2, "dinit: bad bsize in alloc block %uld\n", i); + return -1; + } + if(d->nab != ba->nab){ + fprint(2, "dinit: bad nab in alloc block %uld\n", i); + return -1; + } + if(strncmp(d->name, ba->name, sizeof(d->name))){ + fprint(2, "dinit: bad name in alloc block %uld\n", i); + return -1; + } + } + return 0; +} + +/* + * format the allocated memory as a cache + */ +int +dformat(Disk *d, char *mc, char *name, ulong bsize, ulong psize) +{ + int i; + uvlong length; + Bbuf *b; + Dalloc *ba; + Dptr dptr; + + fprint(2, "formatting memory\n"); + + /* + * calculate basic numbers + */ + length = cachesize; + d->bsize = bsize; + if((d->bsize % psize) != 0){ + fprint(2, "%s: logical bsize not multiple of physical\n", argv0); + return -1; + } + d->nb = length/d->bsize; + d->b2b = (d->bsize - sizeof(Dahdr))*8; + d->nab = (d->nb+d->b2b-1)/d->b2b; + d->p2b = d->bsize/sizeof(Dptr); + + /* + * init allocation blocks + */ + if(bcinit(d, mc, d->bsize) < 0) + return -1; + for(i = 0; i < d->nab; i++){ + b = bcalloc(d, i); + if(b == 0){ + perror("cfs: bcalloc"); + return -1; + } + memset(b->data, 0, d->bsize); + ba = (Dalloc*)b->data; + ba->magic = Amagic; + ba->bsize = d->bsize; + ba->nab = d->nab; + strncpy(ba->name, name, sizeof(ba->name)); + bcmark(d, b); + } + + /* + * allocate allocation blocks + */ + for(i = 0; i < d->nab; i++) + if(dalloc(d, &dptr) == Notabno){ + fprint(2, "can't allocate allocation blocks\n"); + return -1; + } + + return bcsync(d); +} + +/* + * allocate a block from a bit vector page + * + * a return value of Notabno means no blocks left + */ +static ulong +_balloc(Dalloc *ba, ulong max) +{ + int len; /* number of valid words */ + ulong i; /* bit position in long */ + ulong m; /* 1<bits, e = p + len; p < e; p++) + if(*p != 0xFFFFFFFF) + break; + if(p == e) + return Notabno; + + /* + * find the first 0 bit + */ + v = *p; + for(m = 1, i = 0; i < BtoUL; i++, m <<= 1) + if((m|v) != v) + break; + + /* + * calculate block number + */ + i += (p - ba->bits)*BtoUL; + if(i >= max) + return Notabno; + + /* + * set bit to 1 + */ + *p = v | m; + return i; +} + +/* + * allocate a block + * + * return Notabno if none left + */ +ulong +dalloc(Disk *d, Dptr *p) +{ + ulong bno, max, rv; + Bbuf *b; + Dalloc *ba; + + max = d->nb; + for(bno = 0; bno < d->nab; bno++){ + b = bcread(d, bno); + ba = (Dalloc*)b->data; + rv = _balloc(ba, max > d->b2b ? d->b2b : max); + if(rv != Notabno){ + rv = bno*d->b2b + rv; + if(p){ + p->start = p->end = 0; + p->bno = rv; + } + bcmark(d, b); + return rv; + } + max -= d->b2b; + } + if(p) + p->bno = Notabno; + return Notabno; +} + +/* + * allocate a block of pointers + */ +ulong +dpalloc(Disk *d, Dptr *p) +{ + Bbuf *b; + Dptr *sp, *ep; + + if(dalloc(d, p) == Notabno) + return Notabno; + + /* + * allocate the page and invalidate all the + * pointers + */ + b = bcalloc(d, p->bno); + if(b == 0) + return -1; + sp = (Dptr*)b->data; + for(ep = sp + d->p2b; sp < ep; sp++){ + sp->bno = Notabno; + sp->start = sp->end = 0; + } + p->bno |= Indbno; + p->start = 0; + p->end = d->bsize; + + /* + * mark the page as dirty + */ + bcmark(d, b); + return 0; +} + +/* + * free a block + */ +int +_bfree(Disk *d, ulong i) +{ + ulong bno, m; + ulong *p; + Bbuf *b; + Dalloc *ba; + + /* + * get correct allocation block + */ + bno = i/d->b2b; + if(bno >= d->nab) + return -1; + b = bcread(d, bno); + if(b == 0) + return -1; + ba = (Dalloc*)b->data; + + /* + * change bit + */ + i -= bno*d->b2b; + p = ba->bits + (i/BtoUL); + m = 1<<(i%BtoUL); + *p &= ~m; + bcmark(d, b); + + return 0; +} + +/* + * free a block (or blocks) + */ +int +dfree(Disk *d, Dptr *dp) +{ + ulong bno; + Dptr *sp, *ep; + Bbuf *b; + + bno = dp->bno; + dp->bno = Notabno; + + /* + * nothing to free + */ + if(bno == Notabno) + return 0; + + /* + * direct pointer + */ + if((bno & Indbno) == 0) + return _bfree(d, bno); + + /* + * first indirect page + */ + bno &= ~Indbno; + _bfree(d, bno); + + /* + * then all the pages it points to + * + * DANGER: this algorithm may fail if there are more + * allocation blocks than block buffers + */ + b = bcread(d, bno); + if(b == 0) + return -1; + sp = (Dptr*)b->data; + for(ep = sp + d->p2b; sp < ep; sp++) + if(dfree(d, sp) < 0) + return -1; + return 0; +} diff --git a/sys/src/cmd/ramcfs/disk.h b/sys/src/cmd/ramcfs/disk.h new file mode 100644 index 0000000000..e4e98a02c6 --- /dev/null +++ b/sys/src/cmd/ramcfs/disk.h @@ -0,0 +1,24 @@ +typedef struct Disk Disk; + +/* + * Reference to the disk (now memory cache) + */ +struct Disk +{ + Bcache; + ulong nb; /* number of blocks */ + ulong nab; /* number of allocation blocks */ + int b2b; /* allocation bits to a block */ + int p2b; /* Dptr's per page */ + char name[CACHENAMELEN]; +}; + +int dinit(Disk*, char*, int, char*); +int dformat(Disk*, char*, char*, ulong, ulong); +ulong dalloc(Disk*, Dptr*); +ulong dpalloc(Disk*, Dptr*); +int dfree(Disk*, Dptr*); + +extern int debug; + +#define DPRINT if(debug)fprint diff --git a/sys/src/cmd/ramcfs/file.c b/sys/src/cmd/ramcfs/file.c new file mode 100644 index 0000000000..457a434e69 --- /dev/null +++ b/sys/src/cmd/ramcfs/file.c @@ -0,0 +1,298 @@ +#include +#include +#include "cformat.h" +#include "lru.h" +#include "bcache.h" +#include "disk.h" +#include "inode.h" +#include "file.h" + +/* + * merge data with that which already exists in a block + * + * we allow only one range per block, always use the new + * data if the ranges don't overlap. + */ +void +fmerge(Dptr *p, char *to, char *from, int start, int len) +{ + int end; + + end = start + len; + memmove(to+start, from, end-start); + + /* + * if ranges do not overlap... + */ + if(start>p->end || p->start>end){ + /* + * just use the new data + */ + p->start = start; + p->end = end; + } else { + /* + * merge ranges + */ + if(start < p->start) + p->start = start; + if(end > p->end) + p->end = end; + } + +} + +/* + * write a block (or less) of data onto a disk, follow it with any necessary + * pointer writes. + * + * N.B. ordering is everything + */ +int +fbwrite(Icache *ic, Ibuf *b, char *a, ulong off, int len) +{ + int wrinode; + ulong fbno; + Bbuf *dbb; /* data block */ + Bbuf *ibb; /* indirect block */ + Dptr *p; + Dptr t; + + fbno = off / ic->bsize; + p = &b->inode.ptr; + ibb = 0; + wrinode = 0; + + /* + * are there any pages for this inode? + */ + if(p->bno == Notabno){ + wrinode = 1; + goto dowrite; + } + + /* + * is it an indirect block? + */ + if(p->bno & Indbno){ + ibb = bcread(ic, p->bno); + if(ibb == 0) + return -1; + p = (Dptr*)ibb->data; + p += fbno % ic->p2b; + goto dowrite; + } + + /* + * is it the wrong direct block? + */ + if((p->fbno%ic->p2b) != (fbno%ic->p2b)){ + /* + * yes, make an indirect block + */ + t = *p; + dpalloc(ic, p); + if(p->bno == Notabno){ + *p = t; + return -1; + } + ibb = bcalloc(ic, p->bno); + if(ibb == 0){ + *p = t; + return -1; + } + p = (Dptr*)ibb->data; + p += t.fbno % ic->p2b; + *p = t; + p = (Dptr*)ibb->data; + p += fbno % ic->p2b; + } + wrinode = 1; + +dowrite: + /* + * get the data block into the block cache + */ + if(p->bno == Notabno){ + /* + * create a new block + */ + dalloc(ic, p); + if(p->bno == Notabno) + return -1; /* no blocks left (maybe) */ + dbb = bcalloc(ic, p->bno); + } else { + /* + * use what's there + */ + dbb = bcread(ic, p->bno); + } + if(dbb == 0) + return -1; + + /* + * merge in the new data + */ + if(p->fbno != fbno){ + p->start = p->end = 0; + p->fbno = fbno; + } + fmerge(p, dbb->data, a, off % ic->bsize, len); + + /* + * write changed blocks back in the + * correct order + */ + bcmark(ic, dbb); + if(ibb) + bcmark(ic, ibb); + if(wrinode) + if(iwrite(ic, b) < 0) + return -1; + return len; +} + +/* + * write `n' bytes to the cache + * + * return number of bytes written + */ +long +fwrite(Icache *ic, Ibuf *b, char *a, ulong off, long n) +{ + int len; + long sofar; + + for(sofar = 0; sofar < n; sofar += len){ + len = ic->bsize - ((off+sofar)%ic->bsize); + if(len > n - sofar) + len = n - sofar; + if(fbwrite(ic, b, a+sofar, off+sofar, len) < 0) + return sofar; + } + return sofar; +} + +/* + * get a pointer to the next valid data at or after `off' + */ +Dptr * +fpget(Icache *ic, Ibuf *b, ulong off) +{ + ulong fbno; + long doff; + Bbuf *ibb; /* indirect block */ + Dptr *p, *p0, *pf; + + fbno = off / ic->bsize; + p = &b->inode.ptr; + + /* + * are there any pages for this inode? + */ + if(p->bno == Notabno) + return 0; + + /* + * if it's a direct block, life is easy? + */ + if(!(p->bno & Indbno)){ + /* + * a direct block, return p if it's at least past what we want + */ + if(p->fbno > fbno) + return p; + if(p->fbno < fbno) + return 0; + doff = off % ic->bsize; + if(doff>=p->start && doffend) + return p; + else + return 0; + } + + /* + * read the indirect block + */ + ibb = bcread(ic, p->bno); + if(ibb == 0) + return 0; + + /* + * find the next valid pointer + */ + p0 = (Dptr*)ibb->data; + pf = p0 + (fbno % ic->p2b); + if(pf->bno!=Notabno && pf->fbno==fbno){ + doff = off % ic->bsize; + if(doffend) + return pf; + } + for(p = pf+1; p < p0 + ic->p2b; p++){ + fbno++; + if(p->fbno==fbno && p->bno!=Notabno && p->startend) + return p; + } + for(p = p0; p < pf; p++){ + fbno++; + if(p->fbno==fbno && p->bno!=Notabno && p->startend) + return p; + } + return 0; +} + +/* + * read `n' bytes from the cache. + * + * if we hit a gap and we've read something, + * return number of bytes read so far. + * + * if we start with a gap, return minus the number of bytes + * to the next data. + * + * if there are no bytes cached, return 0. + */ +long +fread(Icache *ic, Ibuf *b, char *a, ulong off, long n) +{ + int len, start; + long sofar, gap; + Dptr *p; + Bbuf *bb; + + for(sofar = 0; sofar < n; sofar += len, off += len){ + /* + * get pointer to next data + */ + len = n - sofar; + p = fpget(ic, b, off); + + /* + * if no more data, return what we have so far + */ + if(p == 0) + return sofar; + + /* + * if there's a gap, return the size of the gap + */ + gap = (ic->bsize*p->fbno + p->start) - off; + if(gap>0) + if(sofar == 0) + return -gap; + else + return sofar; + + /* + * return what we have + */ + bb = bcread(ic, p->bno); + if(bb == 0) + return sofar; + start = p->start - gap; + if(p->end - start < len) + len = p->end - start; + memmove(a + sofar, bb->data + start, len); + } + return sofar; +} diff --git a/sys/src/cmd/ramcfs/file.h b/sys/src/cmd/ramcfs/file.h new file mode 100644 index 0000000000..244bca9304 --- /dev/null +++ b/sys/src/cmd/ramcfs/file.h @@ -0,0 +1,5 @@ +void fmerge(Dptr*, char*, char*, int, int); +int fbwrite(Icache*, Ibuf*, char*, ulong, int); +long fwrite(Icache*, Ibuf*, char*, ulong, long); +Dptr* fpget(Icache*, Ibuf*, ulong); +long fread(Icache*, Ibuf*, char*, ulong, long); diff --git a/sys/src/cmd/ramcfs/inode.c b/sys/src/cmd/ramcfs/inode.c new file mode 100644 index 0000000000..74d0325462 --- /dev/null +++ b/sys/src/cmd/ramcfs/inode.c @@ -0,0 +1,412 @@ +#include +#include +#include "cformat.h" +#include "lru.h" +#include "bcache.h" +#include "disk.h" +#include "inode.h" +#include "stats.h" + +extern int readonly; + +/* + * read the inode blocks and make sure they + * haven't been trashed. + * + * make the in-core table of qid to inode mappings. + * N.B. this is just an array. we need a linear search to find + * a particular inode. this could be done faster. + * + * nab is the first inode block. + */ +int +iinit(Icache *ic, char *mc, int psize, char* name) +{ + Ibuf *b; + Imap *m; + ulong ino; + Bbuf *bb; + Dinode *bi; + + /* + * get basic sizes and allocation info from disk + */ + if(dinit(ic, mc, psize, name) < 0) + return -1; + + /* + * read first inode block to get number of inodes + */ + bb = bcread(ic, ic->nab); + if(bb == 0){ + fprint(2, "iinit: can't read disk\n"); + return -1; + } + bi = (Dinode*)bb->data; + if(bi->nino==0 || bi->nino>2048){ + fprint(2, "iinit: bad nino\n"); + return -1; + } + ic->nino = bi->nino; + + /* + * set up sizing constants + */ + ic->i2b = (ic->bsize - sizeof(Dihdr))/sizeof(Inode); + ic->nib = (ic->nino + ic->i2b - 1)/ic->i2b; + + /* + * allocate the in-core qid/inode map, build it's lru + */ + if(ic->map) + free(ic->map); + ic->map = malloc(sizeof(Imap)*ic->nino); + if(ic->map == 0){ + fprint(2, "iinit: can't alloc map\n"); + return -1; + } + lruinit(&ic->mlru); + for(m = ic->map; m < &ic->map[ic->nino]; m++){ + m->inuse = 0; + m->b = 0; + lruadd(&ic->mlru, m); + } + + /* + * mark all cache buffers as empty, put them on the lru list + */ + lruinit(&ic->blru); + for(b = ic->ib; b < &ic->ib[Nicache]; b++){ + b->inuse = 0; + lruadd(&ic->blru, b); + } + + /* + * Read all inodes and + * build the in-core qid/inode map + */ + for(ino = 0; ino < ic->nino; ino++){ + b = iread(ic, ino); + if(b == 0){ + fprint(2, "iinit: can't read inode %ld\n", ino); + return -1; + } + if(b->inode.inuse){ + m = &ic->map[ino]; + m->inuse = 1; + m->qid = b->inode.qid; + lruref(&ic->mlru, m); + } + } + return 0; +} + +/* + * format the inode blocks + */ +int +iformat(Icache *ic, char *mc, ulong nino, char *name, int bsize, int psize) +{ + int nib; + ulong bno, i2b, i; + Bbuf *bb; + Dinode *bi; + + /* + * first format disk allocation + */ + if(dformat(ic, mc, name, bsize, psize) < 0) + return -1; + + fprint(2, "formatting inodes in memory\n"); + + i2b = (bsize - sizeof(Dihdr))/sizeof(Inode); + nib = (nino + i2b - 1)/i2b; + + for(bno = ic->nab; bno < ic->nab + nib; bno++){ + if(dalloc(ic, 0) == Notabno){ + fprint(2, "iformat: balloc failed\n"); + return -1; + } + bb = bcalloc(ic, bno); + if(bb == 0){ + fprint(2, "iformat: bcalloc failed\n"); + return -1; + } + bi = (Dinode*)bb->data; + bi->magic = Imagic; + bi->nino = nino; + for(i = 0; i < i2b; i++) + bi->inode[i].inuse = 0; + bcmark(ic, bb); + } + + bcsync(ic); + + return iinit(ic, mc, psize, name); +} + +/* + * allocate a cache buffer, use least recently used + */ +Ibuf* +ialloc(Icache *ic, ulong ino) +{ + Imap *m; + Ibuf *b; + + b = (Ibuf*)ic->blru.lnext; + if(b->inuse) + ic->map[b->ino].b = 0; + b->ino = ino; + b->inuse = 1; + m = &ic->map[ino]; + m->b = b; + return b; +} + +/* + * free a cache buffer + */ +void +ifree(Icache *ic, Ibuf *b) +{ + b->inuse = 0; + if(b->inuse) + ic->map[b->ino].b = 0; + lruderef(&ic->blru, b); +} + +/* + * get an inode into the cache. if no inode exists for this qid, create one + * from an unused qid/inode map. + */ +Ibuf * +iget(Icache *ic, Qid qid) +{ + Imap *m, *me; + Ibuf *b; + + /* + * find map entry with same qid.path + */ + for(m = ic->map, me = &ic->map[ic->nino]; m < me; m++) + if(m->inuse && m->qid.path==qid.path){ + if((m->qid.vers != qid.vers || qid.vers == 0) + && !readonly){ + /* + * our info is old or this is likely + * a synthetic file, so forget it + */ + DPRINT(2, "updating old file %llud.%lud\n", + qid.path, qid.vers); + m->qid = qid; + iupdate(ic, m - ic->map, qid); + } + break; + } + + /* + * if an already existing inode, just get it + */ + if(m != me) + return iread(ic, m - ic->map); + + /* + * create a new inode, throw out the least recently used inode + * if necessary + */ + m = (Imap*)ic->mlru.lnext; + if(m->inuse){ + DPRINT(2, "superceding file %llud.%ld by %llud.%ld\n", + m->qid.path, m->qid.vers, qid.path, qid.vers); + if(iremove(ic, m - ic->map) < 0) + return 0; + } + + if(statson) + cfsstat.ninsert++; + /* + * init inode and write to disk + */ + DPRINT(2, "new file %llud.%ld ino %ld\n", + qid.path, qid.vers, m - ic->map); + b = ialloc(ic, m - ic->map); + b->inode.inuse = m->inuse = 1; + b->inode.qid = qid; + b->inode.length = 0x7fffffffffffffffLL; + m->qid = qid; + b->inode.ptr.bno = Notabno; + iwrite(ic, b); + return b; +} + +/* + * read an inode into the cache + * + * ASSUMPTION: the inode is valid + */ +Ibuf* +iread(Icache *ic, ulong ino) +{ + Ibuf *b; + Imap *m; + ulong bno; + Bbuf *bb; + Dinode *bi; + + /* + * first see if we already have it in a cache entry + */ + m = &ic->map[ino]; + if(m->inuse && m->b){ + b = m->b; + goto out; + } + + /* + * read it + */ + b = ialloc(ic, ino); + bno = ic->nab + ino/ic->i2b; + bb = bcread(ic, bno); + if(bb == 0){ + ifree(ic, b); + return 0; + } + bi = (Dinode*)bb->data; + b->inode = bi->inode[ino % ic->i2b]; + + /* + * consistency check + */ + if(bi->nino!=ic->nino || bi->magic!=Imagic){ + fprint(2, "iread: inconsistent inode block\n"); + ifree(ic, b); + return 0; + } +out: + b->inuse = 1; + m->b = b; + if(b->inode.inuse) + lruref(&ic->mlru, m); + lruref(&ic->blru, b); + return b; +} + +/* + * write an inode back to disk + */ +int +iwrite(Icache *ic, Ibuf *b) +{ + ulong bno; + Bbuf *bb; + Dinode *bi; + + bno = ic->nab + b->ino/ic->i2b; + bb = bcread(ic, bno); + if(bb == 0) + return 0; + bi = (Dinode*)bb->data; + bi->inode[b->ino % ic->i2b] = b->inode; + bcmark(ic, bb); + lruref(&ic->mlru, &ic->map[b->ino]); + lruref(&ic->blru, b); + return 0; +} + +/* + * Forget what we know about an inode without removing it + * + * N.B: ordering of iwrite and dfree is important + */ +int +iupdate(Icache *ic, ulong ino, Qid qid) +{ + Ibuf *b; + Imap *m; + Dptr d; + + if(statson) + cfsstat.nupdate++; + b = iread(ic, ino); + if(b == 0) + return -1; + + /* + * update inode and map + */ + b->inode.qid = qid; + b->inode.length = 0x7fffffffffffffffLL; /* Set to maximum */ + m = &ic->map[ino]; + m->qid = qid; + + /* + * the free is not done if the write fails! + * this is important + */ + d = b->inode.ptr; + b->inode.ptr.bno = Notabno; + if(iwrite(ic, b) < 0) + return -1; + dfree(ic, &d); + return 0; +} + +/* + * remove an inode + * + * N.B: ordering of iwrite and dfree is important + */ +int +iremove(Icache *ic, ulong ino) +{ + Ibuf *b; + Imap *m; + + if(statson) + cfsstat.ndelete++; + m = &ic->map[ino]; + + /* + * read in inode + */ + b = iread(ic, ino); + if(b == 0) + return -1; + + /* + * mark it unused on disk + */ + b->inode.inuse = 0; + if(iwrite(ic, b) < 0) + return -1; + + /* + * throw out it's data pages + */ + dfree(ic, &b->inode.ptr); + + /* + * free the inode buffer + */ + ifree(ic, b); + + /* + * make map entry least recently used + */ + lruderef(&ic->mlru, m); + return 0; +} + +/* + * increment our version number + */ +void +iinc(Icache *ic, Ibuf *b) +{ + b->inode.qid.vers++; + ic->map[b->ino].qid = b->inode.qid; + iwrite(ic, b); +} diff --git a/sys/src/cmd/ramcfs/inode.h b/sys/src/cmd/ramcfs/inode.h new file mode 100644 index 0000000000..39c2a995a1 --- /dev/null +++ b/sys/src/cmd/ramcfs/inode.h @@ -0,0 +1,60 @@ +typedef struct Ibuf Ibuf; +typedef struct Imap Imap; +typedef struct Icache Icache; + +enum +{ + Nicache= 64, /* number of inodes kept in pool */ +}; + +/* + * a cached inode buffer + */ +struct Ibuf +{ + Lru; /* must be first in structure */ + int inuse; /* non-0 if in use */ + ulong ino; /* index into inode table */ + Inode inode; /* the inode contents */ +}; + +/* + * in-core qid to inode mapping + */ +struct Imap +{ + Lru; /* must be first in structure */ + Qid qid; + Ibuf *b; /* cache buffer */ + int inuse; /* non-0 if in use */ +}; + +/* + * the inode cache + */ +struct Icache +{ + Disk; + + int nino; /* number of inodes */ + ulong ib0; /* first inode block */ + int nib; /* number of inode blocks */ + int i2b; /* inodes to a block */ + + Ibuf ib[Nicache]; /* inode buffers */ + Lru blru; + + Imap *map; /* inode to qid mapping */ + Lru mlru; +}; + +Ibuf* ialloc(Icache*, ulong); +Ibuf* iget(Icache*, Qid); +Ibuf* iread(Icache*, ulong); +int iformat(Icache*, char*, ulong, char*, int, int); +int iinit(Icache*, char*, int, char*); +int iremove(Icache*, ulong); +int iupdate(Icache*, ulong, Qid); +int iwrite(Icache*, Ibuf*); +void ifree(Icache*, Ibuf*); +void iinc(Icache*, Ibuf*); diff --git a/sys/src/cmd/ramcfs/lru.c b/sys/src/cmd/ramcfs/lru.c new file mode 100644 index 0000000000..55f6c6e8b6 --- /dev/null +++ b/sys/src/cmd/ramcfs/lru.c @@ -0,0 +1,75 @@ +/* + * lru lists are circular with a list head + * pointing to the start and end of the list + */ +#include +#include "lru.h" + +/* + * Create an lru chain of buffers + */ +void +lruinit(Lru *h) +{ + h->lprev = h->lnext = h; +} + +/* + * Add a member to an lru chain + */ +void +lruadd(Lru *h, Lru *m) +{ + h->lprev->lnext = m; + m->lprev = h->lprev; + h->lprev = m; + m->lnext = h; +} + +/* + * Move to end of lru list + */ +void +lruref(Lru *h, Lru *m) +{ + if(h->lprev == m) + return; /* alread at end of list */ + + /* + * remove from list + */ + m->lprev->lnext = m->lnext; + m->lnext->lprev = m->lprev; + + /* + * add in at end + */ + h->lprev->lnext = m; + m->lprev = h->lprev; + h->lprev = m; + m->lnext = h; +} + +/* + * Move to head of lru list + */ +void +lruderef(Lru *h, Lru *m) +{ + if(h->lnext == m) + return; /* alread at head of list */ + + /* + * remove from list + */ + m->lprev->lnext = m->lnext; + m->lnext->lprev = m->lprev; + + /* + * add in at head + */ + h->lnext->lprev = m; + m->lnext = h->lnext; + h->lnext = m; + m->lprev = h; +} diff --git a/sys/src/cmd/ramcfs/lru.h b/sys/src/cmd/ramcfs/lru.h new file mode 100644 index 0000000000..b16f82e8c2 --- /dev/null +++ b/sys/src/cmd/ramcfs/lru.h @@ -0,0 +1,15 @@ +typedef struct Lruhead Lruhead; +typedef struct Lru Lru; + +struct Lru +{ + Lru *lprev; + Lru *lnext; +}; + +void lruinit(Lru*); +void lruadd(Lru*, Lru*); +void lruref(Lru*, Lru*); +void lruderef(Lru*, Lru*); + +extern ulong cachesize; diff --git a/sys/src/cmd/ramcfs/mkfile b/sys/src/cmd/ramcfs/mkfile new file mode 100644 index 0000000000..5ea5789de3 --- /dev/null +++ b/sys/src/cmd/ramcfs/mkfile @@ -0,0 +1,41 @@ + Date: Tue, 1 Oct 2019 04:15:26 +0000 Subject: [PATCH 191/402] sys/src/cmd/fscfs: import fscfs from HARE (thanks Geoff Collyer) --- sys/src/cmd/fscfs/cfs.c | 2043 ++++++++++++++++++++++++++++++++++++ sys/src/cmd/fscfs/dat.h | 162 +++ sys/src/cmd/fscfs/fns.h | 57 + sys/src/cmd/fscfs/messages | 40 + sys/src/cmd/fscfs/mkfile | 26 + sys/src/cmd/fscfs/notes | 94 ++ sys/src/cmd/fscfs/stats.h | 29 + 7 files changed, 2451 insertions(+) create mode 100644 sys/src/cmd/fscfs/cfs.c create mode 100644 sys/src/cmd/fscfs/dat.h create mode 100644 sys/src/cmd/fscfs/fns.h create mode 100644 sys/src/cmd/fscfs/messages create mode 100644 sys/src/cmd/fscfs/mkfile create mode 100644 sys/src/cmd/fscfs/notes create mode 100644 sys/src/cmd/fscfs/stats.h diff --git a/sys/src/cmd/fscfs/cfs.c b/sys/src/cmd/fscfs/cfs.c new file mode 100644 index 0000000000..57b8a91484 --- /dev/null +++ b/sys/src/cmd/fscfs/cfs.c @@ -0,0 +1,2043 @@ +#include +#include +#include +#include +#include + +/* + * to do: + * - concurrency? + * - only worthwhile with several connections, perhaps to several file servers + * - cache directories + * - message size (dynamic buffers) + * - more useful stats + * - notes + * - lru for sfids in paths (also correct ref counts for paths) + */ + +#include "dat.h" +#include "fns.h" +#include "stats.h" + +#define DPRINT if(debug)fprint + +/* maximum length of a file (used for unknown lengths) */ +enum { MAXLEN = ((uvlong)1<<63)-1 }; + +int debug, statson, noauth, openserver; + +#define MAXFDATA 8192 /* i/o size for read/write */ + +struct P9fs +{ + int fd[2]; + Fcall thdr; + Fcall rhdr; + uchar sndbuf[MAXFDATA+IOHDRSZ]; /* TO DO: dynamic */ + uchar rcvbuf[2][MAXFDATA + IOHDRSZ]; /* extra buffer to protect client data over server calls */ + int cb; /* current buffer */ + long len; + char *name; +}; + +P9fs c; /* client conversation */ +P9fs s; /* server conversation */ + +Host host[1]; /* clients, just the one for now */ + +Cfsstat cfsstat, cfsprev; +char statbuf[2048]; +int statlen; + +int messagesize = MAXFDATA+IOHDRSZ; /* must be the same for all connections */ + +Qid rootqid; +Qid ctlqid = {0x5555555555555555LL, 0, 0}; + +uint cachesize = 16 * 1024 * 1024; + +/* + * clients directly access directories, auth files, append-only files, exclusive-use files, and mount points + */ +#define isdirect(qid) (((qid).type & ~QTTMP) != QTFILE) + +static char Efidinuse[] = "fid in use"; +static char Ebadfid[] = "invalid fid"; +static char Enotdir[] = "not a directory"; +static char Enonexist[] = "file does not exist"; +static char Eexist[] = "file already exists"; +static char Eopened[] = "opened for I/O"; +static char Emode[] = "bad open mode"; +static char Eremoved[] = "file has been removed"; + +static SFid* freefids; +static u32int fidgen; + +static Data datalist; + +static Auth* authlist; + +void +usage(void) +{ + fprint(2, "usage: %s [-a netaddr | -F srv] [-dknS] [mntpt]\n", argv0); + threadexitsall("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + int std; + char *server, *mtpt; + + std = 0; + server = "net!$server"; + mtpt = "/n/remote"; + + ARGBEGIN{ + case 'a': + server = EARGF(usage()); + break; + case 'd': + debug = 1; + break; + case 'F': + server = EARGF(usage()); + openserver = 1; + break; + case 'm': + cachesize = atoi(EARGF(usage())) * 1024 * 1024; + if(cachesize < 8 * 1024 * 1024 || + cachesize > 3750UL * 1024 * 1024) + sysfatal("implausible cache size %ud", cachesize); + break; + case 'n': + noauth = 1; + break; + case 'S': + statson = 1; + break; + case 's': + std = 1; + break; + default: + usage(); + }ARGEND + if(argc && *argv) + mtpt = *argv; + + quotefmtinstall(); + if(debug){ + fmtinstall('F', fcallfmt); + fmtinstall('D', dirfmt); + fmtinstall('M', dirmodefmt); + } + + c.name = "client"; + s.name = "server"; + if(std){ + c.fd[0] = c.fd[1] = 1; + s.fd[0] = s.fd[1] = 0; + }else + mountinit(server, mtpt); + + switch(fork()){ + case 0: + io(); + threadexits(""); + case -1: + error("fork"); + default: + _exits(""); + } +} + +/* + * TO DO: need to use libthread variants + */ +void +mountinit(char *server, char *mountpoint) +{ + int err; + int p[2]; + + /* + * grab a channel and call up the file server + */ + if(openserver){ + s.fd[0] = open(server, ORDWR); + if(s.fd[0] < 0) + error("opening srv file %s: %r", server); + } else { + s.fd[0] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0); + if(s.fd[0] < 0) + error("dialing %s: %r", server); + } + s.fd[1] = s.fd[0]; + + /* + * mount onto name space + */ + if(pipe(p) < 0) + error("pipe failed"); + switch(fork()){ + case 0: + break; + default: + rfork(RFFDG); + close(p[0]); + if(noauth) + err = mount(p[1], -1, mountpoint, MREPL|MCREATE|MCACHE, ""); + else + err = amount(p[1], mountpoint, MREPL|MCREATE|MCACHE, ""); + if(err < 0) + error("mount failed: %r"); + _exits(0); + case -1: + error("fork failed\n"); +/*BUG: no wait!*/ + } + close(p[1]); + c.fd[0] = c.fd[1] = p[0]; +} + +void +io(void) +{ + Fcall *t; + + datainit(); + t = &c.thdr; + + loop: + rcvmsg(&c, t); + + if(statson){ + cfsstat.cm[t->type].n++; + cfsstat.cm[t->type].s = nsec(); + } + switch(t->type){ + default: + sendreply("invalid 9p operation"); + break; + case Tversion: + rversion(t); + break; + case Tauth: + rauth(t); + break; + case Tflush: + rflush(t); + break; + case Tattach: + rattach(t); + break; + case Twalk: + rwalk(t); + break; + case Topen: + ropen(t); + break; + case Tcreate: + rcreate(t); + break; + case Tread: + rread(t); + break; + case Twrite: + rwrite(t); + break; + case Tclunk: + rclunk(t); + break; + case Tremove: + rremove(t); + break; + case Tstat: + rstat(t); + break; + case Twstat: + rwstat(t); + break; + } + if(statson){ + cfsstat.cm[t->type].t += nsec() -cfsstat.cm[t->type].s; + } + goto loop; +} + +void +rversion(Fcall *t) +{ + if(messagesize > t->msize) + messagesize = t->msize; + t->msize = messagesize; /* set downstream size */ + delegate(t, nil, nil); +} + +void +rauth(Fcall *t) +{ + Fid *mf; + + mf = findfid(host, t->afid, 1); + if(mf == nil) + return; + mf->path = newpath(nil, "#auth", (Qid){0, 0, 0}); /* path name is never used */ + mf->opened = allocsfid(); /* newly allocated */ + if(delegate(t, mf, nil) == 0){ + mf->qid = s.rhdr.aqid; + mf->mode = ORDWR; + }else{ + freesfid(mf->opened); /* free, don't clunk: failed to establish */ + mf->opened = nil; + putfid(mf); + } +} + +void +rflush(Fcall*) /* synchronous so easy */ +{ + /*TO DO: need a tag hash to find requests, once auth is asynchronous */ + sendreply(0); +} + +void +rattach(Fcall *t) +{ + Fid *mf, *afid; + SFid *sfid; + + mf = findfid(host, t->fid, 1); + if(mf == nil) + return; + sfid = nil; + if(t->afid != NOFID){ + afid = findfid(host, t->afid, 0); + if(afid == nil) + return; + sfid = afid->opened; + if((afid->qid.type & QTAUTH) == 0 || sfid == nil){ + sendreply("bad auth file"); + return; + } + } + mf->path = newpath(nil, "", (Qid){0, 0, 0}); + mf->path->sfid = allocsfid(); /* newly allocated */ + if(delegate(t, mf, sfid) == 0){ + mf->qid = s.rhdr.qid; + mf->path->qid = mf->qid; + if(statson == 1){ + statson++; + rootqid = mf->qid; + } + }else{ + freesfid(mf->path->sfid); /* free, don't clunk: failed to establish */ + mf->path->sfid = nil; + putfid(mf); + } +} + +void +rwalk(Fcall *t) +{ + Fid *mf, *nmf; + SFid *sfid; + Path *p; + char *n; + int i; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(mf->path){ + DPRINT(2, "walk from %p %q + %d\n", mf, pathstr(mf->path), t->nwname); + } + nmf = nil; + if(t->newfid != t->fid){ + nmf = findfid(host, t->newfid, 1); + if(nmf == nil) + return; + nmf->qid = mf->qid; + if(nmf->path != nil) + freepath(nmf->path); + mf->path->ref++; + nmf->path = mf->path; + mf = nmf; /* Walk mf */ + } + + if(statson && + mf->qid.type == rootqid.type && mf->qid.path == rootqid.path && + t->nwname == 1 && strcmp(t->wname[0], "cfsctl") == 0){ + /* This is the ctl file */ + mf->qid = ctlqid; + c.rhdr.nwqid = 1; + c.rhdr.wqid[0] = ctlqid; + sendreply(0); + return; + } + + /* + * need this as an invariant, and it should always be true, because + * Twalk.fid should exist and thus have sfid. could compensate by + * rewalking from nearest parent with sfid (in the limit, root from attach) + */ + assert(mf->path->sfid != nil); + + if(t->nwname == 0){ + /* new local fid (if any) refers to existing path, shares its sfid via that path */ + c.rhdr.nwqid = 0; + sendreply(0); + return; + } + + /* t->nwname != 0 */ + + if(localwalk(mf, &c.thdr, &c.rhdr, &p)){ + /* it all worked or is known to fail (in all or in part) */ + if(c.rhdr.type == Rerror){ + DPRINT(2, "walk error: %q\n", c.rhdr.ename); + sendreply(c.rhdr.ename); + if(nmf != nil) + putfid(nmf); + return; + } + if(c.rhdr.nwqid != t->nwname){ + DPRINT(2, "partial walk, hit error\n"); + sendreply(0); + if(nmf != nil) + putfid(nmf); + return; + } + DPRINT(2, "seen it: %q %q\n", pathstr(p), p->inval); + if(p->sfid != nil){ + p->ref++; + freepath(mf->path); + mf->path = p; + if(c.rhdr.nwqid > 0) + mf->qid = c.rhdr.wqid[c.rhdr.nwqid-1]; + sendreply(0); + return; + } + /* know the path, but need a fid on the server */ + } + + /* walk to a new server fid (ie, server always sees fid != newfid) */ + sfid = allocsfid(); /* must release it, if walk doesn't work */ + + if(delegate(t, mf, sfid) < 0){ /* complete failure */ + if(t->nwname > 0){ /* cache first item's failure */ + DPRINT(2, "bad path: %q + %q -> %q\n", pathstr(mf->path), t->wname[0], s.rhdr.ename); + badpath(mf->path, t->wname[0], s.rhdr.ename); + } + if(nmf != nil) + putfid(nmf); + freesfid(sfid); /* no need to clunk it, since it hasn't been assigned */ + return; + } + + if(s.rhdr.nwqid == t->nwname){ /* complete success */ + for(i = 0; i < t->nwname; i++){ + n = t->wname[i]; + if(strcmp(n, "..") == 0){ + p = mf->path->parent; + if(p != nil){ /* otherwise at root, no change */ + p->ref++; + freepath(mf->path); + mf->path = p; + } + }else + mf->path = newpath(mf->path, n, s.rhdr.wqid[i]); + } + mf->qid = s.rhdr.wqid[s.rhdr.nwqid-1]; /* nwname != 0 (above) */ + if(mf->path->sfid != nil){ + /* shouldn't happen (otherwise we wouldn't walk, because localwalk would find it) */ + sysfatal("rwalk: unexpected sfid: %q -> %ud\n", pathstr(mf->path), mf->path->sfid->fid); + } + mf->path->sfid = sfid; + return; + } + + /* partial success; note success and failure, and release fid */ + p = mf->path; + for(i = 0; i < s.rhdr.nwqid; i++){ + n = t->wname[i]; + if(strcmp(n, "..") == 0){ + if(p->parent != nil) + p = p->parent; + }else + p = newpath(p, n, s.rhdr.wqid[i]); + } + n = t->wname[i]; + if(i == 0 || s.rhdr.wqid[i-1].type & QTDIR) + badpath(p, n, Enonexist); + if(nmf != nil) + putfid(nmf); + freesfid(sfid); +} + +int +localwalk(Fid *mf, Fcall *t, Fcall *r, Path **pp) +{ + Path *p, *q; + char *n, *err; + int i; + + *pp = nil; + if(t->nwname == 0) + return 0; /* clone */ + if(mf->path == nil) + return 0; + r->type = Rwalk; + r->nwqid = 0; + p = mf->path; + for(i = 0; i < t->nwname; i++){ + n = t->wname[i]; + if((err = p->inval) != nil) + goto Err; + if((p->qid.type & QTDIR) == 0){ + err = Enotdir; + goto Err; + } + if(strcmp(n, "..") == 0){ + if((q = p->parent) == nil) + q = p; + }else{ + for(q = p->child; q != nil; q = q->next){ + if(strcmp(n, q->name) == 0){ + if((err = q->inval) != nil) + goto Err; + break; + } + } + if(q == nil) + return 0; /* not found in cache, must try server */ + } + r->wqid[r->nwqid++] = q->qid; + p = q; + } + /* found them all: if p's not locally NOFID, link incoming fid to it as local value */ + *pp = p; + return 1; + +Err: + if(r->nwqid == 0){ + r->type = Rerror; + r->ename = err; + } + return 1; +} + +void +ropen(Fcall *t) +{ + Fid *mf; + SFid *sfid; + int omode; + File *file; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(mf->opened != nil){ + sendreply(Eopened); + return; + } + omode = openmode(t->mode); + if(omode < 0){ + sendreply(Emode); + return; + } + if(statson && ctltest(mf)){ + /* Opening ctl file */ + if(t->mode != OREAD){ + sendreply("permission denied"); + return; + } + mf->mode = OREAD; + c.rhdr.qid = ctlqid; + c.rhdr.iounit = 0; + sendreply(0); + genstats(); + return; + } + if(t->mode & (ORCLOSE|OTRUNC) || isdirect(mf->qid)){ + /* must have private sfid */ + DPRINT(2, "open dir/auth: %q\n", pathstr(mf->path)); + sfid = sfclone(mf->path->sfid); + if(delegate(t, mf, sfid) < 0){ + sfclunk(sfid); + return; + } + mf->qid = s.rhdr.qid; + /* don't currently need iounit */ + }else if((sfid = alreadyopen(mf, omode)) == nil){ + sfid = sfclone(mf->path->sfid); + DPRINT(2, "new open %q -> %ud\n", pathstr(mf->path), sfid->fid); + if(delegate(t, mf, sfid) < 0){ + sfclunk(sfid); + return; + } + if(mf->qid.type != s.rhdr.qid.type || mf->qid.path != s.rhdr.qid.path){ + /* file changed type or naming is volatile */ + print("file changed underfoot: %q %#ux %llud -> %#ux %llud\n", + pathstr(mf->path), mf->qid.type, mf->qid.path, s.rhdr.qid.type, s.rhdr.qid.path); + mf->path->qid = mf->qid; + fileinval(mf->path); + } + mf->qid = s.rhdr.qid; /* picks up vers */ + openfile(mf, omode, s.rhdr.iounit, sfid); + }else{ + DPRINT(2, "cached open %q -> %ud\n", pathstr(mf->path), sfid->fid); + c.rhdr.qid = mf->path->file->qid; + c.rhdr.iounit = mf->path->file->iounit; + sendreply(0); + } + mf->opened = sfid; + mf->mode = omode; + if(t->mode & OTRUNC && !(mf->qid.type & QTAPPEND)){ + file = mf->path->file; + if(file != nil){ + cacheinval(file); /* discard cached data */ + file->length = 0; + } + } +} + +void +rcreate(Fcall *t) +{ + Fid *mf; + SFid *sfid; + int omode; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(statson && ctltest(mf)){ + sendreply(Eexist); + return; + } + omode = openmode(t->mode); + if(omode < 0){ + sendreply(Emode); + return; + } + /* always write-through, and by definition can't exist and be open */ + sfid = sfclone(mf->path->sfid); + if(delegate(t, mf, sfid) == 0){ + mf->opened = sfid; + mf->mode = omode; + mf->qid = s.rhdr.qid; + mf->path = newpath(mf->path, t->name, mf->qid); + if(!(t->mode & ORCLOSE || isdirect(mf->qid))){ + /* can cache (if it's volatile, find out on subsequent open) */ + openfile(mf, omode, s.rhdr.iounit, sfid); + } + //mf->iounit = s.rhdr.iounit; + }else + sfclunk(sfid); +} + +void +rclunk(Fcall *t) +{ + Fid *mf; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(mf->opened != nil) + closefile(mf, 1, 0); + /* local clunk, not delegated */ + sendreply(0); + putfid(mf); +} + +void +rremove(Fcall *t) +{ + Fid *mf; + Path *p; + SFid *sfid; + File *file; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + /* invalidate path entry; discard file; discard any local fids in use */ + if(statson && ctltest(mf)){ + sendreply("not removed"); + return; + } + file = nil; + p = mf->path; + if(delegate(t, mf, nil) == 0){ + setinval(p, Eremoved); + file = p->file; + p->file = nil; + } + /* in any case, the fid was clunked: free the sfid */ + if(mf->opened == nil){ + sfid = p->sfid; + p->sfid = nil; + freesfid(sfid); + }else + closefile(mf, 0, 1); + putfid(mf); + if(file != nil) + putfile(file); +} + +void +rread(Fcall *t) +{ + Fid *mf; + int cnt, done; + long n; + vlong off, first; + char *cp; + File *file; + char data[MAXFDATA]; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + + off = t->offset; + cnt = t->count; + + if(statson && ctltest(mf)){ + if(cnt > statlen-off) + c.rhdr.count = statlen-off; + else + c.rhdr.count = cnt; + if((int)c.rhdr.count < 0){ + c.rhdr.count = 0; + sendreply(0); + return; + } + c.rhdr.data = statbuf + off; + sendreply(0); + return; + } + + if(mf->opened == nil || mf->mode == OWRITE){ + sendreply("not open for reading"); + return; + } + + file = mf->path->file; + if(isdirect(mf->qid) || file == nil){ + DPRINT(2, "delegating read\n"); + delegate(t, mf, nil); + if(statson){ + if(mf->qid.type & QTDIR) + cfsstat.ndirread++; + else + cfsstat.ndelegateread++; + if(s.rhdr.count > 0){ + cfsstat.bytesread += s.rhdr.count; + if(mf->qid.type & QTDIR) + cfsstat.bytesfromdirs += s.rhdr.count; + else + cfsstat.bytesfromserver += s.rhdr.count; + } + } + return; + } + + first = off; + cp = data; + done = 0; + while(cnt>0 && !done){ + if(off >= file->clength){ + DPRINT(2, "offset %lld >= length %lld\n", off, file->clength); + break; + } + n = cacheread(file, cp, off, cnt); + if(n <= 0){ + n = -n; + if(n==0 || n>cnt) + n = cnt; + DPRINT(2, "fetch %ld bytes of data from server at offset %lld\n", n, off); + s.thdr.tag = t->tag; + s.thdr.type = t->type; + s.thdr.fid = t->fid; + s.thdr.offset = off; + s.thdr.count = n; + if(statson) + cfsstat.ndelegateread++; + if(askserver(t, mf) < 0){ + sendreply(s.rhdr.ename); + return; + } + if(s.rhdr.count != n) + done = 1; + n = s.rhdr.count; + if(n == 0){ + /* end of file */ + if(file->clength > off){ + DPRINT(2, "file %llud.%ld, length %lld\n", + file->qid.path, + file->qid.vers, off); + file->clength = off; + } + break; + } + memmove(cp, s.rhdr.data, n); + cachewrite(file, cp, off, n); + if(statson){ + cfsstat.bytestocache += n; + cfsstat.bytesfromserver += n; + } + }else{ + DPRINT(2, "fetched %ld bytes from cache\n", n); + if(statson) + cfsstat.bytesfromcache += n; + } + cnt -= n; + off += n; + cp += n; + } + c.rhdr.data = data; + c.rhdr.count = off - first; + if(statson) + cfsstat.bytesread += c.rhdr.count; + sendreply(0); +} + +void +rwrite(Fcall *t) +{ + Fid *mf; + File *file; + u32int v1, v2, count; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(statson && ctltest(mf)){ + sendreply("read only"); + return; + } + if(mf->opened == nil || mf->mode == OREAD){ + sendreply("not open for writing"); + return; + } + file = mf->path->file; + if(isdirect(mf->qid) || file == nil){ + delegate(t, mf, nil); + if(statson && s.rhdr.count > 0) + cfsstat.byteswritten += s.rhdr.count; + return; + } + + /* add to local cache as write through */ + if(delegate(t, mf, nil) < 0) + return; + + count = s.rhdr.count; + cfsstat.byteswritten += count; + + v1 = mf->qid.vers + 1; + v2 = mf->path->qid.vers + 1; + if(v1 > v2) + v1 = v2; + mf->qid.vers = v1; + mf->path->qid.vers = v1; + file->qid.vers = v1; + if(file->clength < t->offset + count) + file->clength = t->offset + count; + cachewrite(file, t->data, t->offset, count); +} + +void +rstat(Fcall *t) +{ + Fid *mf; + Dir d; + uchar statbuf[256]; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(statson && ctltest(mf)){ + genstats(); + d.qid = ctlqid; + d.mode = 0444; + d.length = statlen; + d.name = "cfsctl"; + d.uid = "none"; + d.gid = "none"; + d.muid = "none"; + d.atime = time(nil); + d.mtime = d.atime; + c.rhdr.stat = statbuf; + c.rhdr.nstat = convD2M(&d, statbuf, sizeof(statbuf)); + sendreply(0); + return; + } + if(delegate(t, mf, nil) == 0){ + convM2D(s.rhdr.stat, s.rhdr.nstat , &d, nil); + //mf->qid = d.qid; + if(mf->path->file != nil) + copystat(mf->path->file, &d, 0); + } +} + +void +rwstat(Fcall *t) +{ + Fid *mf; + Path *p; + Dir *d; + int qt; + + mf = findfid(host, t->fid, 0); + if(mf == nil) + return; + if(statson && ctltest(mf)){ + sendreply("read only"); + return; + } + if(delegate(t, mf, nil) == 0){ + d = malloc(sizeof(*d)+t->nstat); + if(convM2D(t->stat, t->nstat, d, (char*)(d+1)) != 0){ + if(*d->name){ /* file renamed */ + p = mf->path; + free(p->name); + p->name = strdup(d->name); + } + if(d->mode != ~0){ + qt = d->mode>>24; + mf->qid.type = qt; + mf->path->qid.type = qt; + } + if(mf->path->file != nil) + copystat(mf->path->file, d, 1); + } + free(d); + } +} + +int +openmode(uint o) +{ + uint m; + + m = o & ~(OTRUNC|OCEXEC|ORCLOSE); + if(m > OEXEC) + return -1; + if(m == OEXEC) + m = OREAD; + if(o&OTRUNC && m == OREAD) + return -1; + return m; +} + +void +error(char *fmt, ...) +{ + va_list arg; + static char buf[2048]; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%s: %s\n", argv0, buf); + threadexitsall("error"); +} + +void +warning(char *s) +{ + fprint(2, "%s: %s: %r\n", argv0, s); +} + +/* + * send a reply to the client + */ +void +sendreply(char *err) +{ + if(err){ + c.rhdr.type = Rerror; + c.rhdr.ename = err; + }else{ + c.rhdr.type = c.thdr.type+1; + c.rhdr.fid = c.thdr.fid; + } + c.rhdr.tag = c.thdr.tag; + sendmsg(&c, &c.rhdr); +} + +/* + * local fids + */ +Fid* +findfid(Host *host, u32int fid, int mk) +{ + Fid *f, **l; + + if(fid == NOFID){ + sendreply(Ebadfid); + return nil; + } + l = &host->fids[fid & (FidHash-1)]; + for(f = *l; f != nil; f = f->next){ + if(f->fid == fid){ + if(mk){ + sendreply(Efidinuse); + return nil; + } + return f; + } + } + if(!mk){ + sendreply(Ebadfid); + return nil; + } + f = mallocz(sizeof(*f), 1); + f->fid = fid; + f->next = *l; + *l = f; + return f; +} + +void +putfid(Fid *f) +{ + Fid **l; + static Qid zeroqid; + + for(l = &host->fids[f->fid & (FidHash-1)]; *l != nil; l = &(*l)->next){ + if(*l == f){ + *l = f->next; + break; + } + } + if(f->opened != nil){ + sfclunk(f->opened); + f->opened = nil; + } + freepath(f->path); + /* poison values just in case */ + f->path = nil; + f->fid = NOFID; + f->qid = zeroqid; + free(f); +} + +/* + * return server fid for local fid + */ +u32int +mapfid(Fid *f) +{ + if(f->opened != nil){ + DPRINT(2, "mapfid: use open fid %ud -> %ud\n", f->fid, f->opened->fid); + return f->opened->fid; + } + if(f->path->sfid == nil) + sysfatal("mapfid: missing sfid for path %q\n", pathstr(f->path)); + return f->path->sfid->fid; +} + +/* + * send a request to the server, get the reply, + * and send that to the client + */ +int +delegate(Fcall *t, Fid *f1, SFid *f2) +{ + int type; + + type = t->type; + if(statson){ + cfsstat.sm[type].n++; + cfsstat.sm[type].s = nsec(); + } + + switch(type){ + case Tversion: + case Tflush: /* no fid */ + break; + case Tauth: /* afid */ + t->afid = mapfid(f1); + break; + case Tattach: /* fid, afid */ + t->fid = mapfid(f1); + if(f2 != nil) + t->afid = f2->fid; + else + t->afid = NOFID; + break; + case Twalk: /* fid, newfid */ + t->fid = mapfid(f1); + t->newfid = f2->fid; + break; + default: /* fid */ + if(f2 != nil) + t->fid = f2->fid; + else + t->fid = mapfid(f1); + break; + } + + sendmsg(&s, t); + rcvmsg(&s, &s.rhdr); + + if(statson) + cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s; + + sendmsg(&c, &s.rhdr); + return t->type+1 == s.rhdr.type? 0: -1; +} + +/* + * send an i/o request to the server and get a reply + */ +int +askserver(Fcall *t, Fid *f) +{ + int type; + + s.thdr.tag = t->tag; + + type = s.thdr.type; + if(statson){ + cfsstat.sm[type].n++; + cfsstat.sm[type].s = nsec(); + } + + s.thdr.fid = mapfid(f); + sendmsg(&s, &s.thdr); + rcvmsg(&s, &s.rhdr); + + if(statson) + cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s; + + return s.thdr.type+1 == s.rhdr.type ? 0 : -1; +} + +/* + * send/receive messages with logging + */ + +void +sendmsg(P9fs *p, Fcall *f) +{ + DPRINT(2, "->%s: %F\n", p->name, f); + + p->len = convS2M(f, p->sndbuf, messagesize); + if(p->len <= 0) + error("convS2M"); + if(write(p->fd[1], p->sndbuf, p->len)!=p->len) + error("sendmsg"); +} + +void +rcvmsg(P9fs *p, Fcall *f) +{ + int rlen; + char buf[128]; + + p->len = read9pmsg(p->fd[0], p->rcvbuf[p->cb], sizeof(p->rcvbuf[0])); + if(p->len <= 0){ + snprint(buf, sizeof buf, "read9pmsg(%d)->%ld: %r", + p->fd[0], p->len); + error(buf); + } + + if((rlen = convM2S(p->rcvbuf[p->cb], p->len, f)) != p->len) + error("rcvmsg format error, expected length %d, got %d", + rlen, p->len); + DPRINT(2, "<-%s: %F\n", p->name, f); + p->cb = (p->cb+1)%nelem(p->rcvbuf); +} + +void +dump(void *a, int len) +{ + uchar *p; + + p = a; + fprint(2, "%d bytes", len); + while(len-- > 0) + fprint(2, " %.2ux", *p++); + fprint(2, "\n"); +} + +/* + * requests (later, unused now) + */ + +void +readtmsgproc(void *a) +{ + //uint messagesize; + int n; + Req *r; + Channel *reqs; + + reqs = a; + for(;;){ + r = malloc(sizeof(*r)+messagesize); + r->msize = messagesize; + r->buf = (uchar*)(r+1); + n = read9pmsg(c.fd[0], r->buf, r->msize); + if(n <= 0){ + free(r); + sendp(reqs, nil); + threadexits(nil); + } + if(convM2S(r->buf, n, &r->t) != n){ + free(r); + error("convM2S error in readtmsgproc"); + } + sendp(reqs, r); + } +} + +void +readrmsgproc(void *a) +{ + //uint messagesize; + int n; + Fcall *r; + uchar *buf; + Channel *reps; + + reps = a; + for(;;){ + r = malloc(sizeof(*r)+messagesize); + buf = (uchar*)(r+1); + n = read9pmsg(c.fd[0], buf, messagesize); + if(n <= 0){ + free(r); + sendp(reps, nil); + threadexits(nil); + } + if(convM2S(buf, n, r) != n){ + free(r); + error("convM2S error in readtmsgproc"); + } + sendp(reps, r); + } +} + +void +freereq(Req *r) +{ + free(r); +} + +/* + * server fids +*/ + +SFid* +allocsfid(void) +{ + SFid *sf; + + sf = freefids; + if(sf != nil){ + freefids = sf->next; + sf->ref = 1; + return sf; + } + sf = mallocz(sizeof(*sf), 1); + sf->ref = 1; + sf->fid = ++fidgen; + return sf; +} + +void +freesfid(SFid *sf) +{ + if(--sf->ref != 0) + return; + /* leave sf->fid alone */ + sf->next = freefids; + freefids = sf; +} + +SFid* +sfclone(SFid *sf) +{ + Fcall t, r; + SFid *cf; + + cf = allocsfid(); + t.tag = c.thdr.tag; + t.type = Twalk; + t.fid = sf->fid; + t.newfid = cf->fid; + t.nwname = 0; + sendmsg(&s, &t); + rcvmsg(&s, &r); + if(r.type == Rerror){ + werrstr("%s", r.ename); + return nil; + } + assert(r.type == Rwalk); /* TO DO: out of order */ + return cf; +} + +Dir* +sfstat(Path *p, u32int tag) +{ + Fcall t, r; + Dir *d; + + assert(p->sfid != nil); + t.tag = tag; + t.type = Tstat; + t.fid = p->sfid->fid; + sendmsg(&s, &t); + rcvmsg(&s, &r); + if(r.type == Rerror){ + werrstr("%s", r.ename); + return nil; + } + d = malloc(sizeof(*d)+r.nstat); + if(convM2D(r.stat, r.nstat, d, (char*)(d+1)) == 0){ + free(d); + werrstr("invalid stat data"); + return nil; + } + return d; +} + +void +sfclunk(SFid *sf) +{ + Fcall t, r; + + if(sf->ref > 1) + return; + t.tag = c.thdr.tag; + t.type = Tclunk; + t.fid = sf->fid; + sendmsg(&s, &t); + rcvmsg(&s, &r); + /* don't care about result */ +} + +void +printpath(Path *p, int level) +{ + Path *q; + + for(int i = 0; i < level; i++) + print("\t"); + print("%q [%lud] %q\n", p->name, p->ref, p->inval?p->inval:""); + for(q = p->child; q != nil; q = q->next) + printpath(q, level+1); +} + +int +ctltest(Fid *mf) +{ + return mf->qid.type == ctlqid.type && mf->qid.path == ctlqid.path; +} + +char *mname[]={ + [Tversion] "Tversion", + [Tauth] "Tauth", + [Tflush] "Tflush", + [Tattach] "Tattach", + [Twalk] "Twalk", + [Topen] "Topen", + [Tcreate] "Tcreate", + [Tclunk] "Tclunk", + [Tread] "Tread", + [Twrite] "Twrite", + [Tremove] "Tremove", + [Tstat] "Tstat", + [Twstat] "Twstat", + [Rversion] "Rversion", + [Rauth] "Rauth", + [Rerror] "Rerror", + [Rflush] "Rflush", + [Rattach] "Rattach", + [Rwalk] "Rwalk", + [Ropen] "Ropen", + [Rcreate] "Rcreate", + [Rclunk] "Rclunk", + [Rread] "Rread", + [Rwrite] "Rwrite", + [Rremove] "Rremove", + [Rstat] "Rstat", + [Rwstat] "Rwstat", + 0, +}; + +void +genstats(void) +{ + int i; + char *p; + + p = statbuf; + + p += snprint(p, sizeof statbuf+statbuf-p, + " Client Server\n"); + p += snprint(p, sizeof statbuf+statbuf-p, + " #calls Δ ms/call Δ #calls Δ ms/call Δ\n"); + for(i = 0; i < nelem(cfsstat.cm); i++) + if(cfsstat.cm[i].n || cfsstat.sm[i].n){ + p += snprint(p, sizeof statbuf+statbuf-p, + "%7lud %7lud ", cfsstat.cm[i].n, + cfsstat.cm[i].n - cfsprev.cm[i].n); + if(cfsstat.cm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001*cfsstat.cm[i].t/ + cfsstat.cm[i].n); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + if(cfsstat.cm[i].n - cfsprev.cm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001* + (cfsstat.cm[i].t - cfsprev.cm[i].t)/ + (cfsstat.cm[i].n - cfsprev.cm[i].n)); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + p += snprint(p, sizeof statbuf+statbuf-p, + "%7lud %7lud ", cfsstat.sm[i].n, + cfsstat.sm[i].n - cfsprev.sm[i].n); + if(cfsstat.sm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001*cfsstat.sm[i].t/ + cfsstat.sm[i].n); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + if(cfsstat.sm[i].n - cfsprev.sm[i].n) + p += snprint(p, sizeof statbuf+statbuf-p, + "%7.3f ", 0.000001* + (cfsstat.sm[i].t - cfsprev.sm[i].t)/ + (cfsstat.sm[i].n - cfsprev.sm[i].n)); + else + p += snprint(p, sizeof statbuf+statbuf-p, + " "); + p += snprint(p, sizeof statbuf+statbuf-p, "%s\n", + mname[i]); + } + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndirread\n", + cfsstat.ndirread, cfsstat.ndirread - cfsprev.ndirread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelegateread\n", + cfsstat.ndelegateread, cfsstat.ndelegateread - + cfsprev.ndelegateread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ninsert\n", + cfsstat.ninsert, cfsstat.ninsert - cfsprev.ninsert); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelete\n", + cfsstat.ndelete, cfsstat.ndelete - cfsprev.ndelete); + p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud nupdate\n", + cfsstat.nupdate, cfsstat.nupdate - cfsprev.nupdate); + + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesread\n", + cfsstat.bytesread, cfsstat.bytesread - cfsprev.bytesread); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud byteswritten\n", + cfsstat.byteswritten, cfsstat.byteswritten - + cfsprev.byteswritten); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromserver\n", + cfsstat.bytesfromserver, cfsstat.bytesfromserver - + cfsprev.bytesfromserver); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromdirs\n", + cfsstat.bytesfromdirs, cfsstat.bytesfromdirs - + cfsprev.bytesfromdirs); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromcache\n", + cfsstat.bytesfromcache, cfsstat.bytesfromcache - + cfsprev.bytesfromcache); + p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytestocache\n", + cfsstat.bytestocache, cfsstat.bytestocache - + cfsprev.bytestocache); + statlen = p - statbuf; + cfsprev = cfsstat; +} + +/* + * paths + */ + +Path* +newpath(Path *parent, char *name, Qid qid) +{ + Path *p; + + if(parent != nil){ + for(p = parent->child; p != nil; p = p->next){ + if(strcmp(p->name, name) == 0){ + if(p->inval != nil){ + free(p->inval); + p->inval = nil; + } + p->qid = qid; + p->ref++; + return p; + } + } + } + p = mallocz(sizeof(*p), 1); + p->ref = 2; + if(name != nil) + p->name = strdup(name); + p->qid = qid; + p->parent = parent; + if(parent != nil){ + parent->ref++; + p->next = parent->child; + parent->child = p; + } + return p; +} + +void +setinval(Path *p, char *err) +{ + if(p->inval != nil){ + free(p->inval); + p->inval = nil; + } + if(err != nil) + p->inval = strdup(err); +} + +void +badpath(Path *parent, char *name, char *err) +{ + Path *p; + + for(p = parent->child; p != nil; p = p->next){ + if(strcmp(p->name, name) == 0){ + setinval(p, err); + return; + } + } + p = mallocz(sizeof(*p), 1); + p->ref = 2; + if(name != nil) + p->name = strdup(name); + p->inval = strdup(err); + p->parent = parent; + if(parent != nil){ + parent->ref++; + p->next = parent->child; + parent->child = p; + } +} + +void +fileinval(Path *p) +{ + if(p->file != nil){ + putfile(p->file); + p->file = nil; + } +} + +void +freepath(Path *p) +{ + Path *q, **r; + + while(p != nil && --p->ref == 0){ + if(p->child != nil) + error("freepath child"); + q = p->parent; + if(q != nil){ + for(r = &q->child; *r != nil; r = &(*r)->next){ + if(*r == p){ + *r = p->next; + break; + } + } + } + if(p->sfid != nil){ + /* TO DO: could queue these for a great clunking proc */ + sfclunk(p->sfid); + p->sfid = nil; + } + if(p->inval != nil) + free(p->inval); + if(p->file != nil) + putfile(p->file); + free(p->name); + free(p); + p = q; + } +} + +static char* +pathstr1(Path *p, char *ep) +{ + ep -= strlen(p->name); + memmove(ep, p->name, strlen(p->name)); + if(p->parent != nil){ + *--ep = '/'; + ep = pathstr1(p->parent, ep); + } + return ep; +} + +char* +pathstr(Path *p) +{ + static char buf[1000]; + return pathstr1(p, buf+sizeof(buf)-1); +} + +/* + * files + */ + +void +openfile(Fid *mf, int omode, u32int iounit, SFid *sfid) +{ + /* open mf and cache open File at p */ + Path *p; + File *file; + SFid *osfid; + + p = mf->path; + file = p->file; + if(file == nil){ + file = mallocz(sizeof(*file), 1); + file->ref = 1; + file->qid = mf->qid; /* TO DO: check for clone files */ + file->clength = MAXLEN; + p->file = file; + } + osfid = file->open[omode]; + if(osfid != nil){ + DPRINT(2, "openfile: existing sfid %ud open %d\n", osfid->fid, omode); + return; + } + DPRINT(2, "openfile: cached %ud for %q mode %d\n", sfid->fid, pathstr(p), omode); + sfid->ref++; + file->open[omode] = sfid; + if(file->iounit == 0) + file->iounit = iounit; /* BUG: might vary */ +} + +void +closefile(Fid *mf, int mustclunk, int removed) +{ + Path *p; + File *file; + SFid *sfid, *osfid; + + if((sfid = mf->opened) == nil) + return; + p = mf->path; + file = p->file; + if(file == nil){ /* TO DO: messy */ + mf->opened = nil; + if(sfid->ref == 1 && mustclunk) + sfclunk(sfid); + freesfid(sfid); + return; + } + osfid = file->open[mf->mode]; + if(osfid == sfid){ + if(removed || sfid->ref == 1) + file->open[mf->mode] = nil; + if(sfid->ref == 1){ + if(mustclunk) + sfclunk(sfid); + freesfid(sfid); + }else + sfid->ref--; + } + mf->opened = nil; +} + +SFid* +alreadyopen(Fid *mf, uint mode) +{ + File *file; + SFid *sfid; + + file = mf->path->file; + if(file == nil) + return nil; + sfid = file->open[mode&3]; + if(sfid == nil) + return nil; + DPRINT(2, "openfile: existing sfid %ud open %d\n", sfid->fid, mode&3); + sfid->ref++; + return sfid; +} + +void +copystat(File *file, Dir *d, int iswstat) +{ + if(d->length != ~(vlong)0){ + /* length change: discard cached data */ + if(iswstat && file->length < file->clength) + cacheinval(file); + file->length = d->length; + } + if(d->mode != ~0){ + file->mode = d->mode; + file->qid.type = d->mode>>24; + } + if(d->atime != ~0) + file->atime = d->atime; + if(d->mtime != ~0) + file->mtime = d->mtime; + if(*d->uid){ + freestr(file->uid); + file->uid = newstr(d->uid); + } + if(*d->gid){ + freestr(file->gid); + file->gid = newstr(d->gid); + } + if(*d->muid){ + freestr(file->muid); + file->muid = newstr(d->muid); + } +} + +void +putfile(File *f) +{ + int i; + SFid *sfid; + + if(--f->ref != 0) + return; + for(i = 0; i < nelem(f->open); i++){ + sfid = f->open[i]; + if(sfid != nil){ + f->open[i] = nil; + sfclunk(sfid); + freesfid(sfid); + } + } + freestr(f->uid); + freestr(f->gid); + freestr(f->muid); + cacheinval(f); + free(f->cached); + free(f); +} + +/* + * data + */ + +static int radix[] = {10, 12, 14}; +static uint range[] = {8, 32, 0}; +static uint cacheused; + +void +datainit(void) +{ + datalist.forw = datalist.back = &datalist; +} + +Data* +allocdata(File *file, uint n, uint nbytes) +{ + Data *d; + + while(cacheused+nbytes > cachesize && datalist.forw != datalist.back) + freedata(datalist.forw); + cacheused += nbytes; + d = mallocz(sizeof(*d), 0); + d->owner = file; + d->n = n; + d->base = malloc(nbytes); + d->size = nbytes; + d->min = 0; + d->max = 0; + d->forw = &datalist; + d->back = datalist.back; + d->back->forw = d; + datalist.back = d; + return d; +} + +void +freedata(Data *d) +{ + d->forw->back = d->back; + d->back->forw = d->forw; + cacheused -= d->size; + if(d->owner != nil) + d->owner->cached[d->n] = nil; + free(d->base); + free(d); +} + +/* + * move recently-used data to end + */ +void +usedata(Data *d) +{ + if(datalist.back == d) + return; /* already at end */ + + d->forw->back = d->back; + d->back->forw = d->forw; + + d->forw = &datalist; + d->back = datalist.back; + d->back->forw = d; + datalist.back = d; +} + +/* + * data cache + */ + +int +cacheread(File *file, void *buf, vlong offset, int nbytes) +{ + char *p; + Data *d; + int n, o; + + DPRINT(2, "file %lld length %lld\n", file->qid.path, file->clength); + p = buf; + while(nbytes > 0){ + d = finddata(file, offset, &o); + if(d == nil) + break; + if(o < d->min){ + if(p == (char*)buf) + return -(d->min-o); /* fill the gap */ + break; + }else if(o >= d->max) + break; + usedata(d); + /* o >= d->min && o < d->max */ + n = nbytes; + if(n > d->max-o) + n = d->max-o; + memmove(p, d->base+o, n); + p += n; + nbytes -= n; + offset += n; + } + return p-(char*)buf; +} + +void +cachewrite(File *file, void *buf, vlong offset, int nbytes) +{ + char *p; + Data *d; + int n, o; + + p = buf; + while(nbytes > 0){ + d = storedata(file, offset, &o); + if(d == nil) + break; + n = nbytes; + if(n > d->size-o) + n = d->size-o; + cachemerge(d, p, o, n); + p += n; + offset += n; + nbytes -= n; + } + if(offset > file->clength) + file->clength = offset; +} + +/* + * merge data in if it overlaps existing contents, + * or simply replace existing contents otherwise + */ +void +cachemerge(Data *p, char *from, int start, int len) +{ + int end; + + end = start + len; + memmove(p->base+start, from, len); + + if(start > p->max || p->min > end){ + p->min = start; + p->max = end; + }else{ + if(start < p->min) + p->min = start; + if(end > p->max) + p->max = end; + } +} + +void +cacheinval(File *file) +{ + Data *d; + int i; + + if(file->cached != nil){ + for(i = 0; i < file->ndata; i++){ + d = file->cached[i]; + if(d != nil){ + file->cached[i] = nil; + d->owner = nil; + freedata(d); + } + } + /* leave the array */ + } + file->clength = 0; +} + +Data* +finddata(File *file, uvlong offset, int *blkoff) +{ + int r, x; + uvlong base, o; + + x = 0; + base = 0; + for(r = 0; r < nelem(radix); r++){ + o = (offset - base) >> radix[r]; + DPRINT(2, "file %llud offset %llud x %d base %llud o %llud\n", file->qid.path, offset, x, base, o); + if(range[r] == 0 || o < range[r]){ + o += x; + if(o >= file->ndata) + break; + *blkoff = (offset-base) & ((1<cached[(int)o]; + } + base += range[r]<cached == nil){ + file->cached = mallocz(16*sizeof(*file->cached), 1); + file->ndata = 16; + } + x = 0; + base = 0; + for(r = 0; r < nelem(radix); r++){ + o = (offset - base) >> radix[r]; + DPRINT(2, "store file %llud offset %llud x %d base %llud o %llud\n", file->qid.path, offset, x, base, o); + if(range[r] == 0 || o < range[r]){ + o += x; + if(o >= file->ndata){ + if(o >= 512) + return nil; /* won't fit */ + v = (o+32+31)&~31; + file->cached = realloc(file->cached, v*sizeof(*file->cached)); + memset(file->cached+file->ndata, 0, (v-file->ndata)*sizeof(*file->cached)); + file->ndata = v; + } + size = 1 << radix[r]; + DPRINT(2, " -> %d %d\n", (int)o, size); + *blkoff = (offset-base) & (size-1); + p = &file->cached[(int)o]; + if(*p == nil) + *p = allocdata(file, (int)o, size); + else + usedata(*p); + return *p; + } + base += range[r]<>24) & 0xFF) | g; + } + return &stralloc.htab[h & Strhashmask]; +} + +String* +newstr(char *val) +{ + String *s, **l; + + //qlock(&stralloc); + for(l = hashslot(val); (s = *l) != nil; l = &s->next){ + if(strcmp(s->s, val) == 0){ + s->ref++; + //qunlock(&stralloc); + return s; + } + } + s = malloc(sizeof(*s)); + s->s = strdup(val); + s->len = strlen(s->s); + s->ref = 1; + s->next = *l; + *l = s; + //qunlock(&stralloc); + return s; +} + +String* +dupstr(String *s) +{ + s->ref++; + return s; +} + +void +freestr(String *s) +{ + String **l; + + if(s != nil && --s->ref == 0){ + //qlock(&stralloc); + for(l = hashslot(s->s); *l != nil; l = &(*l)->next){ + if(*l == s){ + *l = s->next; + break; + } + } + //qunlock(&stralloc); + free(s->s); + free(s); + } +} diff --git a/sys/src/cmd/fscfs/dat.h b/sys/src/cmd/fscfs/dat.h new file mode 100644 index 0000000000..aa2964400f --- /dev/null +++ b/sys/src/cmd/fscfs/dat.h @@ -0,0 +1,162 @@ +/* + * fscfs + */ + +typedef struct Attach Attach; +typedef struct Auth Auth; +typedef struct Data Data; +typedef struct Dref Dref; +typedef struct Fid Fid; +typedef struct File File; +typedef struct Host Host; +typedef struct Path Path; +typedef struct P9fs P9fs; +typedef struct Req Req; +typedef struct SFid SFid; +typedef struct String String; + +#pragma incomplete P9fs + +typedef u32int Tag; + +struct String +{ + Ref; + int len; + char* s; + String* next; /* hash chain */ +}; + +struct Dref +{ + int inuse; /* reference count locally */ + int faruse; /* remote references */ + Tag tag; /* remote object tag */ + Host* loc; /* location of object (nil if here) */ + Host* src; /* source of object reference (nil if here) */ + int depth; /* 0 if here or loc == src */ + int weight; /* proxy weight */ +}; + +enum{ + FidHash= 1<<8, +}; + +struct Attach +{ + /* parameters and result of a Tattach */ + u32int fid; + char* uname; + char* aname; + Path* root; /* qid from attach is root->qid, root->sfid is server fid */ + Attach* next; +}; + +struct Auth +{ + /* could probably use a Ref */ + SFid* afid; + char* uname; + char* aname; + char* error; + Auth* next; + int active; /* active until attached, with or without success */ + Req* pending; /* later Auth requests with same parameters, and flush requests */ +}; + +struct Host +{ + Ref; + + QLock; + int fd; /* link to host */ + char* name; /* symbolic name (mainly for diagnostics) */ + Fid* fids[FidHash]; /* fids active for this host */ + /* might need per-host auth/attach fid/afid for authentication? */ + /* implies separation of fid spaces, and thus separate Fids but not Files and Paths */ +}; + +struct Path +{ + Ref; + char* name; + Qid qid; + Path* parent; + Path* child; + Path* next; /* sibling */ + uint nxtime; /* zero (if exists) or last time we checked */ + char* inval; /* walk error if invalid */ + File* file; /* file data, if open */ + SFid* sfid; /* walked to this fid on server */ +}; + +struct Data +{ + /* cached portion of a file */ + uint min; /* offsets */ + uint max; + uint size; /* size of buffer (power of 2) */ + uchar* base; + + /* LRU stuff */ + Data* forw; + Data* back; + File* owner; + uint n; /* index in owner's cache */ +}; + +struct SFid +{ + Ref; /* by client fids */ + u32int fid; /* fid on server */ + SFid* next; /* on free or LRU list */ +}; + +struct Fid +{ + u32int fid; /* fid on Host */ + Qid qid; + Path* path; /* shared data about file */ + SFid* opened; /* server fid once opened */ + uint mode; /* open mode (OREAD, OWRITE, ORDWR) */ + Fid* next; /* in fid hash list */ +}; + +struct File +{ + Ref; + + SFid* open[3]; /* cached sfids: OREAD, OWRITE, ORDWR */ + + /* data from Dir */ + uint mode; /* permissions */ + uint atime; /* last read time */ + uint mtime; /* last write time */ + u64int length; /* file length from stat or 0 => use clength */ + String* uid; /* owner name */ + String* gid; /* group name */ + String* muid; /* last modifier name */ + + Qid qid; + u32int iounit; + u64int clength; /* known length in cache */ + uint ndata; /* size of cache array */ + Data** cached; + + /* Dref for local and remote references */ + /* possibly put expired ones on LRU? */ + File* next; +}; + +struct Req +{ + u32int tag; + Fcall t; + SFid* fid; /* also afid in Tauth */ + SFid* newfid; /* also afid in Tattach */ + Fcall r; + uchar* buf; + uint msize; + Req* flush; + Req* next; /* in tag list, or flush list of another Req */ +}; diff --git a/sys/src/cmd/fscfs/fns.h b/sys/src/cmd/fscfs/fns.h new file mode 100644 index 0000000000..968f7e75c7 --- /dev/null +++ b/sys/src/cmd/fscfs/fns.h @@ -0,0 +1,57 @@ +Data* allocdata(File*, uint, uint); +SFid* allocsfid(void); +SFid* alreadyopen(Fid*, uint); +int askserver(Fcall*, Fid*); +void badpath(Path*, char*, char*); +void cacheinval(File*); +void closefile(Fid*, int, int); +void cachemerge(Data*, char*, int, int); +void copystat(File*, Dir*, int); +int cacheread(File*, void*, vlong, int); +int ctltest(Fid*); +void cachewrite(File*, void*, vlong, int); +void datainit(void); +int delegate(Fcall*, Fid*, SFid*); +void dumpdata(Data*, int); +String* dupstr(String*); +void error(char*, ...); +void fileinval(Path*); +Data* finddata(File*, uvlong, int*); +Fid* findfid(Host*, u32int, int); +void freedata(Data*); +void freepath(Path*); +void freesfid(SFid*); +void freestr(String*); +void genstats(void); +void io(void); +int localwalk(Fid*, Fcall*, Fcall*, Path**); +void mountinit(char*, char*); +Path* newpath(Path*, char*, Qid); +String* newstr(char*); +void openfile(Fid*, int, u32int, SFid*); +int openmode(uint); +char* pathstr(Path*); +void printpath(Path*, int); +void putfid(Fid*); +void putfile(File*); +void rattach(Fcall*); +void rauth(Fcall*); +void rclunk(Fcall*); +void rcreate(Fcall*); +void rcvmsg(P9fs*, Fcall*); +void rflush(Fcall*); +void ropen(Fcall*); +void rread(Fcall*); +void rremove(Fcall*); +void rstat(Fcall*); +void rversion(Fcall*); +void rwalk(Fcall*); +void rwrite(Fcall*); +void rwstat(Fcall*); +void sendmsg(P9fs*, Fcall*); +void sendreply(char*); +void setinval(Path*, char*); +SFid* sfclone(SFid*); +void sfclunk(SFid*); +Data* storedata(File*, uvlong, int*); +void warning(char*); diff --git a/sys/src/cmd/fscfs/messages b/sys/src/cmd/fscfs/messages new file mode 100644 index 0000000000..e92dae1704 --- /dev/null +++ b/sys/src/cmd/fscfs/messages @@ -0,0 +1,40 @@ + size[4] Tversion tag[2] msize[4] version[s] + size[4] Rversion tag[2] msize[4] version[s] + + size[4] Tauth tag[2] afid[4] uname[s] aname[s] + size[4] Rauth tag[2] aqid[13] + + size[4] Rerror tag[2] ename[s] + + size[4] Tflush tag[2] oldtag[2] + size[4] Rflush tag[2] + + size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] + size[4] Rattach tag[2] qid[13] + + size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) + size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13]) + + size[4] Topen tag[2] fid[4] mode[1] + size[4] Ropen tag[2] qid[13] iounit[4] + + size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1] + size[4] Rcreate tag[2] qid[13] iounit[4] + + size[4] Tread tag[2] fid[4] offset[8] count[4] + size[4] Rread tag[2] count[4] data[count] + + size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] + size[4] Rwrite tag[2] count[4] + + size[4] Tclunk tag[2] fid[4] + size[4] Rclunk tag[2] + + size[4] Tremove tag[2] fid[4] + size[4] Rremove tag[2] + + size[4] Tstat tag[2] fid[4] + size[4] Rstat tag[2] stat[n] + + size[4] Twstat tag[2] fid[4] stat[n] + size[4] Rwstat tag[2] diff --git a/sys/src/cmd/fscfs/mkfile b/sys/src/cmd/fscfs/mkfile new file mode 100644 index 0000000000..3b6fac2a08 --- /dev/null +++ b/sys/src/cmd/fscfs/mkfile @@ -0,0 +1,26 @@ + R in order + +- could re-use tag of incoming op (probably assumes in order, or put client id in high-order bits) + +x String hash table + +- auth interaction, and attach + +- fid management different for input from clients and output to server + +- if any client has fid to file, server has fid to file +- if no client has fid to file, server might have fid to file (LRU) +- if any client has fid open, server has fid open (BUT: modes, auth) +- if no client has fid open, server will not have fid open (for now) + - OREAD, OWRITE, ORDWR, OEXEC(!) + - OTRUNC [if not QTAPPEND] + - OEXCL + - ORCLOSE + - OCEXEC (not in protocol) +- initially it's probably adequate to cache only OREAD + +fid walk +- Path has optional SFid +- root has SFid from Tattach + - must not be lost, in case of later attaches +- all local attach fids are bound to root.sfid +- if not localwalk, allocate SFid and walk that + - if walks to Path with SFid, clunk and substitute + (in non-concurrent system, can't happen? because localwalk would have returned it) + +attach and auth handling +- attach can't be done until successful Tauth +- Tauth just introduces a fid for Tread/Twrite[/Tclunk] + - need to assume that existing Attach with similar parameters is adequate authentication + (obviously wrong, because another incoming connection saying Tauth might not represent the + same principal. with one connection, it hardly matters, because if it's shared, + spoofing could occur by fid substitution if the connection can't be trusted. + also, in this particular application, it's usually safe to assume that every connection is either the + same principal or "none". trust lies in the authentication of the connection, and the associated "speaks for" + relationship.) + +- private sfid in ropen/rcreate for isdirect files; must clunk + +- Path's SFid is only walkable; Fid must have separate path to (possibly shared) SFid for IO + +- I/O fids should be shared (unless impossible) + - can't share QTEXCL, or QTDIR [offset clashes] + - for QTDIR, could read whole directory and cache that, with purely local fid, + or read and accumulate contents incrementally + - need a way to find the shared fid + - stored in File? as at present [one for each possible mode] + - map [hash] qid.path x (mode&3) x rclose -> SFid + - first open in given mode -> clone Path's SFid (as at present) + - have Fid.open: SFid -> shared fid once located? + - also private SFid when needed (eg, isdirect, ORCLOSE) + - Qid changes on open (eg, clone) + - might detect change of qid.path on first open and mark File as volatile + (enough to discard File reference from Path) diff --git a/sys/src/cmd/fscfs/stats.h b/sys/src/cmd/fscfs/stats.h new file mode 100644 index 0000000000..e5a2e74a3d --- /dev/null +++ b/sys/src/cmd/fscfs/stats.h @@ -0,0 +1,29 @@ +typedef struct Cfsmsg Cfsmsg; +typedef struct Cfsstat Cfsstat; + +struct Cfsmsg { + ulong n; /* number of messages (of some type) */ + vlong t; /* time spent in these messages */ + vlong s; /* start time of last call */ +}; + +struct Cfsstat { + Cfsmsg cm[128]; /* client messages */ + Cfsmsg sm[128]; /* server messages */ + + ulong ndirread; /* # of directory read ops */ + ulong ndelegateread; /* # of read ops delegated */ + ulong ninsert; /* # of cache insert ops */ + ulong ndelete; /* # of cache delete ops */ + ulong nupdate; /* # of cache update ops */ + + uvlong bytesread; /* # of bytes read by client */ + uvlong byteswritten; /* # of bytes written by client */ + uvlong bytesfromserver; /* # of bytes read from server */ + uvlong bytesfromdirs; /* # of directory bytes read from server */ + uvlong bytesfromcache; /* # of bytes read from cache */ + uvlong bytestocache; /* # of bytes written to cache */ +}; + +extern Cfsstat cfsstat, cfsprev; +extern int statson; From e99caa2df80a8e5011e177f4b8984d03813c2f55 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 12 Oct 2019 15:53:27 +0000 Subject: [PATCH 192/402] sys/src/cmd/fscfs: various fixes (thanks Richard Miller) --- sys/src/cmd/fscfs/cfs.c | 40 ++++++++++++++++++++++++++++++++++------ sys/src/cmd/fscfs/fns.h | 3 ++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/sys/src/cmd/fscfs/cfs.c b/sys/src/cmd/fscfs/cfs.c index 57b8a91484..8f2320d8aa 100644 --- a/sys/src/cmd/fscfs/cfs.c +++ b/sys/src/cmd/fscfs/cfs.c @@ -80,7 +80,7 @@ static Auth* authlist; void usage(void) { - fprint(2, "usage: %s [-a netaddr | -F srv] [-dknS] [mntpt]\n", argv0); + fprint(2, "usage: %s [-a netaddr | -F srv] [-dknS] [mntpt] [spec]\n", argv0); threadexitsall("usage"); } @@ -88,11 +88,12 @@ void threadmain(int argc, char *argv[]) { int std; - char *server, *mtpt; + char *server, *mtpt, *aname; std = 0; server = "net!$server"; mtpt = "/n/remote"; + aname = ""; ARGBEGIN{ case 'a': @@ -125,6 +126,8 @@ threadmain(int argc, char *argv[]) }ARGEND if(argc && *argv) mtpt = *argv; + if(argc > 1 && argv[1]) + aname = argv[1]; quotefmtinstall(); if(debug){ @@ -139,7 +142,7 @@ threadmain(int argc, char *argv[]) c.fd[0] = c.fd[1] = 1; s.fd[0] = s.fd[1] = 0; }else - mountinit(server, mtpt); + mountinit(server, mtpt, aname); switch(fork()){ case 0: @@ -156,7 +159,7 @@ threadmain(int argc, char *argv[]) * TO DO: need to use libthread variants */ void -mountinit(char *server, char *mountpoint) +mountinit(char *server, char *mountpoint, char *aname) { int err; int p[2]; @@ -187,9 +190,9 @@ mountinit(char *server, char *mountpoint) rfork(RFFDG); close(p[0]); if(noauth) - err = mount(p[1], -1, mountpoint, MREPL|MCREATE|MCACHE, ""); + err = mount(p[1], -1, mountpoint, MREPL|MCREATE|MCACHE, aname); else - err = amount(p[1], mountpoint, MREPL|MCREATE|MCACHE, ""); + err = amount(p[1], mountpoint, MREPL|MCREATE|MCACHE, aname); if(err < 0) error("mount failed: %r"); _exits(0); @@ -353,6 +356,10 @@ rwalk(Fcall *t) if(mf->path){ DPRINT(2, "walk from %p %q + %d\n", mf, pathstr(mf->path), t->nwname); } + if(mf->path->inval){ + sendreply(mf->path->inval); + return; + } nmf = nil; if(t->newfid != t->fid){ nmf = findfid(host, t->newfid, 1); @@ -908,6 +915,7 @@ rwstat(Fcall *t) p = mf->path; free(p->name); p->name = strdup(d->name); + freeinval(p); } if(d->mode != ~0){ qt = d->mode>>24; @@ -1497,6 +1505,26 @@ newpath(Path *parent, char *name, Qid qid) return p; } +void +freeinval(Path *p) +{ + Path *q, **r; + + for(r = &p->parent->child; (q = *r) != nil; r = &q->next){ + if(q == p) + continue; + if(strcmp(q->name, p->name) == 0 && q->inval != nil){ + if(q->ref > 1){ + *r = q->next; + q->next = p->next; + p->next = q; + } + freepath(q); + break; + } + } +} + void setinval(Path *p, char *err) { diff --git a/sys/src/cmd/fscfs/fns.h b/sys/src/cmd/fscfs/fns.h index 968f7e75c7..43ce44cde0 100644 --- a/sys/src/cmd/fscfs/fns.h +++ b/sys/src/cmd/fscfs/fns.h @@ -19,13 +19,14 @@ void fileinval(Path*); Data* finddata(File*, uvlong, int*); Fid* findfid(Host*, u32int, int); void freedata(Data*); +void freeinval(Path*); void freepath(Path*); void freesfid(SFid*); void freestr(String*); void genstats(void); void io(void); int localwalk(Fid*, Fcall*, Fcall*, Path**); -void mountinit(char*, char*); +void mountinit(char*, char*, char*); Path* newpath(Path*, char*, Qid); String* newstr(char*); void openfile(Fid*, int, u32int, SFid*); From dcd83318af4f47a7d7bdf0aa3f7955e7b2a1c567 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 21 Feb 2021 21:40:16 +0000 Subject: [PATCH 193/402] sys/src/cmd/dd: dd m modifier for megabytes to dd(1) (thanks Steve Simon) --- sys/src/cmd/dd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/src/cmd/dd.c b/sys/src/cmd/dd.c index 408d4d710f..cf002b5034 100644 --- a/sys/src/cmd/dd.c +++ b/sys/src/cmd/dd.c @@ -368,6 +368,10 @@ number(vlong big) for(;;) switch(*cs++) { + case 'm': + n *= 1024*1024; + continue; + case 'k': n *= 1024; continue; From db1e787b6b20c61c189c010ede74dca80a6dcedb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 21 Feb 2021 21:40:16 +0000 Subject: [PATCH 194/402] sys/src/cmd/sam: import wheel mouse support from plan9port (thanks Steve Simon) --- sys/src/cmd/samterm/main.c | 19 +++++++++++++++++++ sys/src/cmd/samterm/scroll.c | 18 +++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/sys/src/cmd/samterm/main.c b/sys/src/cmd/samterm/main.c index 59c9d56cbc..c416f40652 100644 --- a/sys/src/cmd/samterm/main.c +++ b/sys/src/cmd/samterm/main.c @@ -104,6 +104,10 @@ threadmain(int argc, char *argv[]) scroll(which, 3); else menu3hit(); + }else if((mousep->buttons&8)){ + scroll(which, 4); + }else if((mousep->buttons&16)){ + scroll(which, 5); } mouseunblock(); } @@ -432,6 +436,7 @@ flushtyping(int clearesc) #define PAGEUP Kpgup #define RIGHTARROW Kright #define SCROLLKEY Kdown +#define Kstx 0x02 int nontypingkey(int c) @@ -447,6 +452,7 @@ nontypingkey(int c) case PAGEUP: case RIGHTARROW: case SCROLLKEY: + case Kstx: return 1; } return 0; @@ -604,6 +610,19 @@ type(Flayer *l, int res) /* what a bloody mess this is */ } } } + }else if((mousep->buttons&8)){ + scroll(which, 4); + }else if((mousep->buttons&16)){ + scroll(which, 5); + }else if(c == Kstx){ + t = &cmd; + for(l=t->l; l->textfn==0; l++) + ; + current(l); + flushtyping(0); + a = t->rasp.nrunes; + flsetselect(l, a, a); + center(l, a); }else{ if(c==ESC && typeesc>=0){ l->p0 = typeesc; diff --git a/sys/src/cmd/samterm/scroll.c b/sys/src/cmd/samterm/scroll.c index f3a632cec5..579553d50e 100644 --- a/sys/src/cmd/samterm/scroll.c +++ b/sys/src/cmd/samterm/scroll.c @@ -120,7 +120,7 @@ scroll(Flayer *l, int but) draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min); do{ oin = in; - in = abs(x-mousep->xy.x)<=FLSCROLLWID/2; + in = (but>3) ||(but==2) || abs(x-mousep->xy.x)<=FLSCROLLWID/2; if(oin && !in) scrunmark(l, r); if(in){ @@ -131,9 +131,7 @@ scroll(Flayer *l, int but) my = s.min.y; if(my >= s.max.y) my = s.max.y; - if(!eqpt(mousep->xy, Pt(x, my))) - moveto(mousectl, Pt(x, my)); - if(but == 1){ + if(but == 1 || but == 4){ p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my)); rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); y = rt.min.y; @@ -141,7 +139,7 @@ scroll(Flayer *l, int but) y = my; if(y > s.max.y-2) y = s.max.y-2; - }else if(but == 3){ + }else if(but == 3 || but == 5){ p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); y = rt.min.y; @@ -152,19 +150,21 @@ scroll(Flayer *l, int but) scrmark(l, r); } } - }while(button(but)); + }while(but<3 && button(but)); if(in){ h = s.max.y-s.min.y; scrunmark(l, r); p0 = 0; - if(but == 1) + if(but == 1 || but == 4){ + but = 1; p0 = (long)(my-s.min.y)/l->f.font->height+1; - else if(but == 2){ + }else if(but == 2){ if(tot > 1024L*1024L) p0 = ((tot>>10)*(y-s.min.y)/h)<<10; else p0 = tot*(y-s.min.y)/h; - }else if(but == 3){ + }else if(but == 3 || but == 5){ + but = 3; p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); if(p0 > tot) p0 = tot; From 167f54569c7e88380d94bde481e1dad813006edb Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 31 Oct 2021 13:17:46 +0000 Subject: [PATCH 195/402] sys/src/cmd/sam: fix spurious overwrite message (thanks Russ Cox) --- sys/src/cmd/sam/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/sam/io.c b/sys/src/cmd/sam/io.c index 3fee95a056..f24389790d 100644 --- a/sys/src/cmd/sam/io.c +++ b/sys/src/cmd/sam/io.c @@ -63,7 +63,7 @@ writef(File *f) warn(Wnotnewline); closeio(n); if(f->name.s[0]==0 || samename){ - if(statfile(name, &dev, &qid, &mtime, 0, 0) > 0){ + if(statfile(genc, &dev, &qid, &mtime, 0, 0) > 0){ f->dev = dev; f->qidpath = qid; f->mtime = mtime; From e92e8c9134261bd79f5c365703d4fbd643963217 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 5 Jun 2022 15:22:46 +0000 Subject: [PATCH 196/402] sys/src/cmd: add the `walk` command, which walks a tree of files (thanks Ori Bernstein) --- sys/src/cmd/walk.c | 324 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 sys/src/cmd/walk.c diff --git a/sys/src/cmd/walk.c b/sys/src/cmd/walk.c new file mode 100644 index 0000000000..119350d212 --- /dev/null +++ b/sys/src/cmd/walk.c @@ -0,0 +1,324 @@ +#include +#include +#include +#include + +int Cflag = 0; +int uflag = 0; +String *stfmt; + +/* should turn these flags into a mask */ +int dflag = 1; +int fflag = 1; +int tflag = 0; +int xflag = 0; +long maxdepth = ~(1<<31); +long mindepth = 0; + +char *dotpath = "."; +Dir *dotdir = nil; + +Biobuf *bout; + +int seen(Dir*); + +void +warn(char *fmt, ...) +{ + va_list arg; + char buf[1024]; /* arbitrary */ + int n; + + if((n = snprint(buf, sizeof(buf), "%s: ", argv0)) < 0) + sysfatal("snprint: %r"); + va_start(arg, fmt); + vseprint(buf+n, buf+sizeof(buf), fmt, arg); + va_end(arg); + + Bflush(bout); + fprint(2, "%s\n", buf); +} + +void +dofile(char *path, Dir *f, int pathonly) +{ + char *p; + + if( + (f == dotdir) + || (tflag && ! (f->qid.type & QTTMP)) + || (xflag && ! (f->mode & DMEXEC)) + ) + return; + + for(p = s_to_c(stfmt); *p != '\0'; p++){ + switch(*p){ + case 'U': Bwrite(bout, f->uid, strlen(f->uid)); break; + case 'G': Bwrite(bout, f->gid, strlen(f->gid)); break; + case 'M': Bwrite(bout, f->muid, strlen(f->muid)); break; + case 'a': Bprint(bout, "%uld", f->atime); break; + case 'm': Bprint(bout, "%uld", f->mtime); break; + case 'n': Bwrite(bout, f->name, strlen(f->name)); break; + case 'p': + if(path != dotpath) + Bwrite(bout, path, strlen(path)); + if(! (f->qid.type & QTDIR) && !pathonly){ + if(path != dotpath) + Bputc(bout, '/'); + Bwrite(bout, f->name, strlen(f->name)); + } + break; + case 'q': Bprint(bout, "%ullx.%uld.%.2uhhx", f->qid.path, f->qid.vers, f->qid.type); break; + case 's': Bprint(bout, "%lld", f->length); break; + case 'x': Bprint(bout, "%ulo", f->mode); break; + + /* These two are slightly different, as they tell us about the fileserver instead of the file */ + case 'D': Bprint(bout, "%ud", f->dev); break; + case 'T': Bprint(bout, "%C", f->type); break; + default: + abort(); + } + + if(*(p+1) != '\0') + Bputc(bout, ' '); + } + + Bputc(bout, '\n'); + + if(uflag) + Bflush(bout); +} + +void +walk(char *path, Dir *cf, long depth) +{ + String *file; + Dir *dirs, *f, *fe; + int fd; + long n; + + if(cf == nil){ + warn("path: %s: %r", path); + return; + } + + if(depth >= maxdepth) + goto nodescend; + + if((fd = open(path, OREAD)) < 0){ + warn("couldn't open %s: %r", path); + return; + } + + while((n = dirread(fd, &dirs)) > 0){ + fe = dirs+n; + for(f = dirs; f < fe; f++){ + if(seen(f)) + continue; + if(! (f->qid.type & QTDIR)){ + if(fflag && depth >= mindepth) + dofile(path, f, 0); + } else if(strcmp(f->name, ".") == 0 || strcmp(f->name, "..") == 0){ + warn(". or .. named file: %s/%s", path, f->name); + } else{ + if(depth+1 > maxdepth){ + dofile(path, f, 0); + continue; + } else if(path == dotpath){ + if((file = s_new()) == nil) + sysfatal("s_new: %r"); + } else{ + if((file = s_copy(path)) == nil) + sysfatal("s_copy: %r"); + if(s_len(file) != 1 || *s_to_c(file) != '/') + s_putc(file, '/'); + } + s_append(file, f->name); + + walk(s_to_c(file), f, depth+1); + s_free(file); + } + } + free(dirs); + } + close(fd); + if(n < 0) + warn("%s: %r", path); + +nodescend: + depth--; + if(dflag && depth >= mindepth) + dofile(path, cf, 0); +} + +char* +slashslash(char *s) +{ + char *p, *q; + + for(p=q=s; *q; q++){ + if(q>s && *q=='/' && *(q-1)=='/') + continue; + if(p != q) + *p = *q; + p++; + } + do{ + *p-- = '\0'; + } while(p>s && *p=='/'); + + return s; +} + +long +estrtol(char *as, char **aas, int base) +{ + long n; + char *p; + + n = strtol(as, &p, base); + if(p == as || *p != '\0') + sysfatal("estrtol: bad input '%s'", as); + else if(aas != nil) + *aas = p; + + return n; +} + +void +elimdepth(char *p){ + char *q; + + if(strlen(p) == 0) + sysfatal("empty depth argument"); + + if(q = strchr(p, ',')){ + *q = '\0'; + if(p != q) + mindepth = estrtol(p, nil, 0); + p = q+1; + if(*p == '\0') + return; + } + + maxdepth = estrtol(p, nil, 0); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-udftx] [-n mind,maxd] [-e statfmt] [file ...]\n", argv0); + exits("usage"); +} + +/* + Last I checked (commit 3dd6a31881535615389c24ab9a139af2798c462c), + libString calls sysfatal when things go wrong; in my local + copy of libString, failed calls return nil and errstr is set. + + There are various nil checks in this code when calling libString + functions, but since they are a no-op and libString needs + a rework, I left them in - BurnZeZ +*/ + +void +main(int argc, char **argv) +{ + long i; + Dir *d; + + stfmt = nil; + ARGBEGIN{ + case 'C': Cflag++; break; /* undocumented; do not cleanname() the args */ + case 'u': uflag++; break; /* unbuffered output */ + + case 'd': dflag++; fflag = 0; break; /* only dirs */ + case 'f': fflag++; dflag = 0; break; /* only non-dirs */ + case 't': tflag++; break; /* only tmp files */ + case 'x': xflag++; break; /* only executable permission */ + + case 'n': elimdepth(EARGF(usage())); break; + case 'e': + if((stfmt = s_reset(stfmt)) == nil) + sysfatal("s_reset: %r"); + s_append(stfmt, EARGF(usage())); + i = strspn(s_to_c(stfmt), "UGMamnpqsxDT"); + if(i != s_len(stfmt)) + sysfatal("bad stfmt: %s", s_to_c(stfmt)); + break; + default: + usage(); + }ARGEND; + + if((bout = Bfdopen(1, OWRITE)) == nil) + sysfatal("Bfdopen: %r"); + if(stfmt == nil){ + if((stfmt = s_new()) == nil) + sysfatal("s_new: %r"); + s_putc(stfmt, 'p'); + s_terminate(stfmt); + } + if(maxdepth != ~(1<<31)) + maxdepth++; + if(argc == 0){ + dotdir = dirstat("."); + walk(dotpath, dotdir, 1); + } else for(i=0; iqid.type & QTDIR)){ + if(fflag && !seen(d) && mindepth < 1) + dofile(argv[i], d, 1); + } else + walk(argv[i], d, 1); + free(d); + } + Bterm(bout); + + exits(nil); +} + +/* below pilfered from /sys/src/cmd/du.c + * NOTE: I did not check for bugs */ + +#define NCACHE 256 /* must be power of two */ + +typedef struct +{ + Dir* cache; + int n; + int max; +} Cache; +Cache cache[NCACHE]; + +int +seen(Dir *dir) +{ + Dir *dp; + int i; + Cache *c; + + c = &cache[dir->qid.path&(NCACHE-1)]; + dp = c->cache; + for(i=0; in; i++, dp++) + if(dir->qid.path == dp->qid.path && + dir->type == dp->type && + dir->dev == dp->dev) + return 1; + if(c->n == c->max){ + if (c->max == 0) + c->max = 8; + else + c->max += c->max/2; + c->cache = realloc(c->cache, c->max*sizeof(Dir)); + if(c->cache == nil) + sysfatal("realloc: %r"); + } + c->cache[c->n++] = *dir; + return 0; +} From a1adaf2c06370d86623d39282f3b253cf6455ec6 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 5 Jun 2022 15:21:45 +0000 Subject: [PATCH 197/402] sys/src/cmd: import git (thanks Ori Bernstein) --- sys/lib/git/common.rc | 109 ++ sys/man/1/git | 654 ++++++++++++ sys/man/4/gitfs | 112 ++ sys/src/cmd/git/LICENSE | 19 + sys/src/cmd/git/README | 198 ++++ sys/src/cmd/git/add | 38 + sys/src/cmd/git/branch | 122 +++ sys/src/cmd/git/clone | 114 +++ sys/src/cmd/git/commit | 136 +++ sys/src/cmd/git/compat | 168 +++ sys/src/cmd/git/conf.c | 98 ++ sys/src/cmd/git/delta.c | 219 ++++ sys/src/cmd/git/diff | 47 + sys/src/cmd/git/export | 88 ++ sys/src/cmd/git/extra/gitls | 203 ++++ sys/src/cmd/git/extra/gitrules | 4 + sys/src/cmd/git/fs.c | 906 ++++++++++++++++ sys/src/cmd/git/get.c | 372 +++++++ sys/src/cmd/git/git.h | 326 ++++++ sys/src/cmd/git/import | 116 +++ sys/src/cmd/git/init | 39 + sys/src/cmd/git/log.c | 282 +++++ sys/src/cmd/git/merge | 46 + sys/src/cmd/git/mkfile | 57 ++ sys/src/cmd/git/objset.c | 67 ++ sys/src/cmd/git/ols.c | 170 +++ sys/src/cmd/git/pack.c | 1757 ++++++++++++++++++++++++++++++++ sys/src/cmd/git/proto.c | 514 ++++++++++ sys/src/cmd/git/pull | 73 ++ sys/src/cmd/git/push | 51 + sys/src/cmd/git/query.c | 199 ++++ sys/src/cmd/git/rebase | 92 ++ sys/src/cmd/git/ref.c | 567 +++++++++++ sys/src/cmd/git/repack.c | 85 ++ sys/src/cmd/git/revert | 22 + sys/src/cmd/git/rm | 3 + sys/src/cmd/git/save.c | 434 ++++++++ sys/src/cmd/git/send.c | 313 ++++++ sys/src/cmd/git/serve.c | 553 ++++++++++ sys/src/cmd/git/util.c | 393 +++++++ sys/src/cmd/git/walk.c | 331 ++++++ 41 files changed, 10097 insertions(+) create mode 100644 sys/lib/git/common.rc create mode 100644 sys/man/1/git create mode 100644 sys/man/4/gitfs create mode 100644 sys/src/cmd/git/LICENSE create mode 100644 sys/src/cmd/git/README create mode 100755 sys/src/cmd/git/add create mode 100755 sys/src/cmd/git/branch create mode 100755 sys/src/cmd/git/clone create mode 100644 sys/src/cmd/git/commit create mode 100755 sys/src/cmd/git/compat create mode 100644 sys/src/cmd/git/conf.c create mode 100644 sys/src/cmd/git/delta.c create mode 100644 sys/src/cmd/git/diff create mode 100755 sys/src/cmd/git/export create mode 100755 sys/src/cmd/git/extra/gitls create mode 100644 sys/src/cmd/git/extra/gitrules create mode 100644 sys/src/cmd/git/fs.c create mode 100644 sys/src/cmd/git/get.c create mode 100644 sys/src/cmd/git/git.h create mode 100755 sys/src/cmd/git/import create mode 100755 sys/src/cmd/git/init create mode 100644 sys/src/cmd/git/log.c create mode 100755 sys/src/cmd/git/merge create mode 100644 sys/src/cmd/git/mkfile create mode 100644 sys/src/cmd/git/objset.c create mode 100644 sys/src/cmd/git/ols.c create mode 100644 sys/src/cmd/git/pack.c create mode 100644 sys/src/cmd/git/proto.c create mode 100755 sys/src/cmd/git/pull create mode 100755 sys/src/cmd/git/push create mode 100644 sys/src/cmd/git/query.c create mode 100755 sys/src/cmd/git/rebase create mode 100644 sys/src/cmd/git/ref.c create mode 100644 sys/src/cmd/git/repack.c create mode 100644 sys/src/cmd/git/revert create mode 100755 sys/src/cmd/git/rm create mode 100644 sys/src/cmd/git/save.c create mode 100644 sys/src/cmd/git/send.c create mode 100644 sys/src/cmd/git/serve.c create mode 100644 sys/src/cmd/git/util.c create mode 100644 sys/src/cmd/git/walk.c diff --git a/sys/lib/git/common.rc b/sys/lib/git/common.rc new file mode 100644 index 0000000000..653d6bfb10 --- /dev/null +++ b/sys/lib/git/common.rc @@ -0,0 +1,109 @@ +nl=' +' + +fn die{ + >[1=2] echo $0: $* + exit $"* +} + +fn usage{ + >[1=2] echo -n 'usage:' $usage + exit 'usage' +} + +fn subst { + awk ' + BEGIN{ARGC=0} + {sub(ARGV[1], ARGV[2]); print} + ' $* +} + +fn drop { + awk ' + BEGIN{ARGC=0} + { + if(index($0, ARGV[1]) == 1) + $0=substr($0, length(ARGV[1])+1) + print + } + ' $* +} + +fn present { + if(~ $1 /dev/null && cmp $2 $3>/dev/null) + status=gone + if not if (~ $3 /dev/null && cmp $1 $2>/dev/null) + status=gone + if not + status=() +} + +fn whoami{ + name=`$nl{git/conf user.name} + email=`$nl{git/conf user.email} + if(test -f /adm/keys.who){ + if(~ $name '') + name=`$nl{awk -F'|' '$1=="'$user'" {x=$3} END{print x}' $tmp) + echo merge needed: $out >[1=2] + + if(present $ours $base $theirs){ + mv $tmp $out + git/add $out + } + if not { + rm -f $tmp $out + git/rm $out + } +}} + +fn gitup{ + gitroot=`{git/conf -r >[2]/dev/null} + if(~ $#gitroot 0) + die 'not a git repository' + gitfs=$gitroot/.git/fs + gitrel=`{pwd | drop $gitroot | sed 's@^/@@'} + if(~ $#gitrel 0) + gitrel='.' + cd $gitroot + startfs=() + if(! test -d $gitfs) + mkdir -p $gitfs + if(! test -e $gitfs/ctl) + startfs=true + if(! grep -s '^repo '$gitroot'$' $gitfs/ctl >[2]/dev/null) + startfs=true + if(~ $#startfs 1) + git/fs + if not + status='' +} diff --git a/sys/man/1/git b/sys/man/1/git new file mode 100644 index 0000000000..5f1e7cef69 --- /dev/null +++ b/sys/man/1/git @@ -0,0 +1,654 @@ +.TH GIT 1 +.SH NAME +git, git/conf, git/query, git/walk, git/clone, git/branch, +git/commit, git/diff, git/init, git/log, git/merge, git/push, +git/pull, git/rm, git/serve +\- Manage git repositories. + +.SH SYNOPSIS +.PP +.B git/add +[ +.B -r +] +.I path... +.PP +.B git/branch +[ +.B -admns +] +[ +.B -b +.I base +] +.I newbranch +.PP +.B git/clone +[ +.I remote +[ +.I local +] +] +.PP +.B git/commit +[ +.B -re +] +[ +.B -m msg +] +[ +.I file... +] +.PP +.B git/compat +.PP +.B git/conf +[ +.B -r +] +[ +.B -f +.I file +] +.I keys... +.PP +.B git/diff +[ +.B -c +.I branch +] +[ +.B -s +] +[ +.I file... +] +.PP +.B git/export +[ +.I commits... +] +.PP +.B git/import +[ +.I commits... +] +.PP +.B git/init +[ +.B -b +] +[ +.I dir +] +[ +.B -u +.I upstream +] +.PP +.B git/log +[ +.B -c +.I commit +.B | -e +.I expr +] +[ +.B -s +] +[ +.I files... +] +.PP +.B git/merge +.I theirs +.PP +.B git/rebase +[ +.B -ari +] +[ +.B onto +] +.PP +.B git/pull +[ +.B -fq +] +[ +.B -u +.I upstream +] +.PP +.B git/push +[ +.B -af +] +[ +.B -u +.I upstream +] +[ +.B -b +.I branch +] +[ +.B -r +.I branch +] +.PP +.B git/query +[ +.B -pcr +] +.I query +.PP +.B git/revert +[ +.B -c +.I commit +] +.I file... +.PP +.B git/rm +.I path... +.PP +.B git/serve +[ +.B -w +] +[ +.B -r +.I path +] +.PP +.B git/walk +[ +.B -qc +] +[ +.B -b +.I branch +] +[ +.B -f +.I filters +] +[ +.I [files...] +] + +.SH DESCRIPTION +.PP +Git is a distributed version control system. +This means that each repository contains a full copy of the history. +This history is then synced between computers as needed. + +.PP +These programs provide tools to manage and interoperate with +repositories hosted in git. + +.SH CONCEPTS + +Git stores snapshots of the working directory. +Files can either be in a tracked or untracked state. +Each commit takes the current version of all tracked files and +adds them to a new commit. + +This history is stored in the +.I .git +directory. +This suite of +.I git +tools provides a file interface to the +.I .git +directory mounted on +.I $repo/.git/fs. +Modifications to the repository are done directly to the +.I .git +directory, and are reflected in the file system interface. +This allows for easy scripting, without excessive complexity +in the file API. + +.SH COMMANDS + +.PP +.B Git/init +is used to create a new git repository, with no code or commits. +The repository is created in the current directory by default. +Passing a directory name will cause the repository to be created +there instead. +Passing the +.B -b +option will cause the repository to be initialized as a bare repository. +Passing the +.B -u +.I upstream +option will cause the upstream to be configured to +.I upstream. + +.PP +.B Git/clone +will take an existing repository, served over either the +.I git:// +or +.I ssh:// +protocols. +The first argument is the repository to clone. +The second argument, optionally, specifies the location to clone into. +If not specified, the repository will be cloned into the last path component +of the clone source, with the +.I .git +stripped off if present. + +.PP +.B Git/push +is used to push the current changes to a remote repository. +When no arguments are provided, the remote repository is taken from +the origin configured in +.I .git/config, +and only the changes on the current branch are pushed. +When passed the +.I -a +option, all branches are pushed. +When passed the +.I -u upstream +option, the changes are pushed to +.I upstream +instead of the configured origin. +When given the +.I -r +option, the branch is deleted from origin, instead of updated. + +.PP +.B Git/revert +restores the named files from HEAD. When passed the -c flag, restores files from +the named commit. + +.PP +.B Git/pull +behaves in a similar manner to git/push, however it gets changes from +the upstream repository. +After fetching, it checks out the changes into the working directory. +When passed the +.I -f +option, the update of the working copy is suppressed. +When passed the +.I -q +option, the listing of changes is silenced. +When passed the +.I -u upstream +option, the changes are pulled from +.I upstream +instead of the configured origin. +when passed the +.I -b branch +option, it only pulls changes related to +.IR branch . + +.PP +.B Git/serve +serves repositories using the +.I git:// +protocol over stdin. +By default, it serves them read-only. +The +.I -w +flag, it allows pushing into repositories. +The +.I -r +.B path +flag serves repositories relative to +.BR path . + +.PP +.B Git/fs +serves a file system on $repo/.git/fs. +For full documentation, see +.IR gitfs (4) + +.PP +.B Git/add +adds a file to the list of tracked files. When passed the +.I -r +flag, the file is removed from the list of tracked files. +The copy of the file in the repository is left untouched. +.PP +.B Git/rm +is an alias for +.IR git/add\ -r . + +.PP +.B Git/commit +creates a new commit consisting of all changes to the specified files. +By default, an editor is opened to prepare the commit message. +The +.I -m +flag supplies the commit message directly. +The +.I -r +flag revises the contents of the previous commit, reusing the message. +The +.I -e +flag opens an editor to finalize the commit message, regardless of +whether or not it was specified explicitly or reused. +To amend a commit message, +.I -r +can be used in conjuction with +.I -m +or +.IR -e . + +.PP +.B Git/branch +is used to list or switch branches. +When invoked with no arguments, it lists the current branch. +To list all branches, pass the +.I -a +option. +To switch between branches, pass a branch name. +When passed the +.I -n +option, the branch will be created, overwriting existing branch. +When passed the +.I -b base +option, the branch created is based off of +.I base +instead of +.I HEAD. +When passed the +.I -s +option, the branch is created but the files are not checked out. +When passed the +.I -d +option, the branch is deleted. +.PP +When switching branches, git/branch will refuse to clobber +modificiations. +Passing the +.I -m +option will cause git9 to attempt to merge the changes between +the branches. + +.PP +.B Git/log +shows a history of the current branch. +When passed a list of files, only commits affecting +those files are shown. +The +.I -c commit +option logs starting from the provided commit, instead of HEAD. +The +.I -s +option shows a summary of the commit, instead of the full message. +The +.I -e expr +option shows commits matching the query expression provided. +The expression is in the syntax of +.B git/query. + +.PP +.B Git/diff +shows the differences between the currently checked out code and +the +.I HEAD +commit. +When passed the +.I -c base +option, the diff is computed against +.I base +instead of +.I HEAD. +When passed the +.I -s +option, only the file statuses are +printed. + +.PP +.B Git/export +exports a list of commits in a format that +.B git/import +can apply. + +.PP +.B Git/import +imports a commit with message, author, and +date information. + +.PP +.B Git/merge +takes two branches and merges them filewise using +.I ape/diff3. +The next commit made will be a merge commmit. + +.PP +.B Git/rebase +takes one branch and moves it onto another. +On error, the remaining commits to rebase are +saved, and can be resumed once the conflict is +resolved using the +.I -r +option. +If the rebase is to be aborted, the +.I -a +option will clean up the in progress rebase +and reset the state of the branch. +The +.I -i +option will open an editor to modify the todo-list before the rebase +begins. + +.PP +The following rebase commands are supported: +.TP 10 +.B pick +Apply the commit. +.TP +.B reword +Apply the commit, then edit its commit message. +.TP +.B edit +Apply the commit, then exit to allow further changes. +.TP +.B squash +Fold the commit into the previous commit, then edit the combined +commit message. +.TP +.B fixup +Fold the commit into the previous commit, discarding its commit +message. +.TP +.B break +Exit to allow for manual edits or inspection before continuing. + +.PP +.B Git/conf +is a tool for querying the git configuration. +The configuration key is provided as a dotted string. Spaces +are accepted. For example, to find the URL of the origin +repository, one might pass +.I 'remote\ "origin".url'. +When given the +.I -r +option, the root of the current repository is printed. + +.B Git/query +takes an expression describing a commit, or set of commits, +and resolves it to a list of commits. +The +.I -r +option reverses the order of the commit list. +With the +.I -p +option, instead of printing the commit hashes, the full +path to their +.B git/fs +path is printed. With the +.I -c +option, the query must resolve to two commits. The blobs +that have changed in the commits are printed. + +.PP +.B Git/walk +provides a tool for walking the list of tracked objects and printing their status. +With no arguments, it prints a list of paths prefixed with the status character. +When given the +.I -c +character, only the paths are printed. +When given the +.I -q +option, all output is suppressed, and only the status is printed. +When given the +.I -f +option, the output is filtered by status code, and only matching items are printed. + +.PP +The status characters are as follows: +.TP +T +Tracked, not modified since last commit. +.TP +M +Modified since last commit. +.TP +R +This file will be gone in the next commit. +.TP +A +This file will be present in the next commit. + +.PP +.B Git/compat +spawns an rc subshell with a compatibility stub in +.IR $path . +This compatibility stub provides enough of the unix +.I git +commands to run tools like +.I go get +but not much more. + +.SH REF SYNTAX + +.PP +Refs are specified with a simple query syntax. +A bare hash always evaluates to itself. +Ref names are resolved to their hashes. +The +.B a ^ +suffix operator finds the parent of a commit. +The +.B a b @ +suffix operator finds the common ancestor of the previous two commits. +The +.B a .. b +or +.B a : b +operator finds all commits between +.B a +and +.B b. +Between is defined as the set of all commits which are reachable from +.B b +but not reachable from +.B a. + +.SH PROTOCOLS +.PP +Git9 supports URL schemes of the format +.BR transport://dial/repo/path . +The transport portion specifies the protocol to use. +If the transport portion is omitted, then the transport used is +.BR ssh . +The +.I dial +portion is either a plan 9 dial string, or a conventional +.I host:port +pair. +For the ssh protocol, it may also include a +.I user@ +prefix. +.I repo/path +portion is the path of the repository on the server. + +The supported transports are +.B ssh://, git://, hjgit://, gits://, http://, +and +.BR https . +Two of these are specific to git9: +.I gits:// +and +.IR hjgit:// . +Both are the +.I git:// +protocol, tunnelled over tls. +.I Hjgit:// +authenticates with the server using Plan 9 authentication, +using +.IR tlsclient\ -a . +Any of these protocol names may be prefixed with +.IR git+ , +for copy-paste compatibility with Unix git. + +.SH EXAMPLES + +.PP +In order to create a new repository, run +.B git/init: +.PP +.EX +git/init myrepo +.EE + +.PP +To clone an existing repository from a git server, run: +.PP +.EX +git/clone git://github.com/Harvey-OS/harvey +cd harvey +# edit files +git/commit foo.c +git/push +.EE + +.PP +To set a user and email for commits, run: +.PP +.EX +% mkdir $home/lib/git +% >$home/lib/git/config echo ' +[user] + name = Ori Bernstein + email = ori@eigenstate.org' +.EE + +.SH FILES +.TP +$repo/.git +The full git repository. +.TP +$repo/.git/config +The configuration file for a repository. +.TP +$home/lib/git/config +The user-wide configuration for git. +The contents of this file are used as fallbacks for the per-repository config. +.TP +/sys/lib/git/config +The system-wide configuration for git. +The contents of this file are used as fallbacks for the per-user config. + +.SH SEE ALSO +.IR replica (1), +.IR patch (1), +.IR gitfs (4), +.I diff3 + +.SH BUGS +.PP +Repositories with submodules are effectively read-only. +.PP +There are some missing commands, features, and tools. +.PP +git/compat only works within a git repository. diff --git a/sys/man/4/gitfs b/sys/man/4/gitfs new file mode 100644 index 0000000000..7ba097ad0c --- /dev/null +++ b/sys/man/4/gitfs @@ -0,0 +1,112 @@ +.TH GITFS 4 +.SH NAME +git/fs \- git file server + +.SH SYNOPSIS + +git/fs +[ +.B -d +] +[ +.B -m +.I mtpt +] + +.SH DESCRIPTION + +.PP +Git/fs serves a file system interface to a git repository in the +current directory. +This file system provides a read-only view into the repository contents. +By default, it is mounted on +.B $repo/.git/fs. +It does not cache mutable data, so any changes to the git repository will immediately be reflected in git/fs. + +.PP +Git/fs serves a few levels of hierarchy. +The top level contains the following files and directories: + +.TP +.B branch +Exposes branches. Branches are aliases for commit objects. + +.TP +.B object +Exposes all objects in the git repository. +Objects may be commits, trees, or blobs. + +.TP +.B HEAD +This is an alias for the current commit. + +.PP +Commits are also represented as small hierarchies. They contain +the following files: + +.TP +.B author +This is the author of the commit. +The contents of this file are free-form text, but conventionally +they take the form +.B Full Name + +.TP +.B hash +The commit id of the current branch + +.TP +.B msg +The full text of the commit message. + +.TP +.B parent +The list of parent commit ids of the current commit. +One parent is listed per line. + +.TP +.B tree +A directory containing the tree associated with the +commit. +The timestamp of the files contained within this +hierarchy are the same as the date of the commit. + +.PP +Trees are presented as directory listings, and blobs +as files. + +.SH FILES +.TP +.B .git +The git repository being expected. +.TP +.B .git/HEAD +A reference to the current HEAD. +Used to populate +.B $repo/.git/fs/HEAD +.TP +.git/config +The per-repository configuation for git tools. +.TP +.B $home/lib/git/config +The global configuration for git tools. + +.SH SOURCE +.TP +.B /sys/src/cmd/git/fs.c + +.SH "SEE ALSO" +.IR git (1) +.IR hg (1) +.IR hgfs (4) + +.SH BUGS +Symlinks are only partially supported. +Symlinks are treated as regular files when reading. +Modifying symlinks is unsupported. + +.PP +There is no way to inspect the raw objects. This is +a feature that would be useful for debugging. + + diff --git a/sys/src/cmd/git/LICENSE b/sys/src/cmd/git/LICENSE new file mode 100644 index 0000000000..b8852f1a37 --- /dev/null +++ b/sys/src/cmd/git/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019 Ori Bernstein + +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. diff --git a/sys/src/cmd/git/README b/sys/src/cmd/git/README new file mode 100644 index 0000000000..695d761cdb --- /dev/null +++ b/sys/src/cmd/git/README @@ -0,0 +1,198 @@ +Git for Plan 9: git/fs +====================== + +All commits in this repository were made with git9 running on 9front. + +About +----- + +Plan 9 is a non-posix system. Upstream git has been ported, but feels +distinctly un-plan9ish, and even in its native environment, has been +justifiably tarred and feathered for its user experience. + +Git/fs implements a git client for plan 9. The intent is to support +working with git repositories, without cloning the git interface +directly. + +Git/fs is my daily driver. It's solid, and works well for my needs. + +Getting Started +--------------- + +** USE THE VERSION THAT COMES WITH 9FRONT ** + +The version that comes with 9front is the most up to date +version out there. If you are on 9front, you do not need +this repository. + +If you are *NOT* on 9front: + +Install the appropriate patches to your system (listed below), +then: + +Get a bootstrap copy: + + % cd /tmp + % hget https://orib.dev/git/git9/HEAD/snap.tar.gz | tar xvz + % cd git9 + % mk all + % mk install + +Then get an updatable version from git: + + % cd $home/src + % git/clone gits://orib.dev/git9 + % cd git9 + % mk all + % mk install + +Configure your user name and email: + + % mkdir -p $home/lib/git + % echo ' + [user] + name=Ori Bernstein + email=ori@eigenstate.org + ' > $home/lib/git/config + +Read the docs: + + % man 1 git + % man 4 gitfs + +And start committing! + +Structure +--------- + +The git/fs program provides a file system mounted on $repo/.git/fs. +It provides a read-only view into the repository contents to allow +scripts to inspect the data. Surrounding scripts and binaries will +manipulate the repository contents directly. These changes will be +immediately mirrored in the file system. + +Scripts will generally mount git/fs as needed to do +their work, but if you want to browse the repository +manually, run it yourself. You'll get `$repo/.git/fs` mounted, +with the following contents: + + $repo/.git/fs/object: The objects in the repo. + $repo/.git/fs/branch: The branches in the repo. + $repo/.git/fs/ctl: A file showing the status of the repo. + Currently, it only shows the current branch. + $repo/.git/fs/HEAD An alias for the currently checked out + commit directory. + +Visible Differences +------------------- + +The most obvious difference is that Git's index is a bit boneheaded, so I'm +ignoring it. The index doesn't affect the wire protocol, so this +isn't an interoperability issue, unless you share the same physical +repository on both Plan 9 and Unix. If you do, expect them to disagree +about the files that have been modified in the working copy. + +In fact, the entire concept of the staging area has been dropped, as +it's both confusing and clunky. There are now only three states that +files can be in: 'untracked', 'dirty', and 'committed'. Tracking is +done with empty files under .git/index9/{removed,tracked}/path/to/file. + +It's implemented in Plan 9 flavor C, and provides tools for writing +repository contents, and a file system for read-only access, which +will mirror the current state of the repository. + +Installation +------------ + +Install with `mk install`. + +Examples +-------- + +Some usage examples: + + git/clone git://git.eigenstate.org/ori/mc.git + git/log + cd subdir/name + git/add foo.c + diff bar.c $repo/.git/fs/HEAD/ + git/commit foo.c + git/push + +Commits are presented as directories with the following +contents: + + author: A file containing the author name + hash: A file containing the commit hash + parent: A file containing the commit parents, one per line. + msg: A file containing the log message for that commit + tree: A directory containing a view of the repository. + +So, for example: + + % ls $repo/.git/fs/branch/heads/master + $repo/.git/fs/branch/heads/master/author + $repo/.git/fs/branch/heads/master/hash + $repo/.git/fs/branch/heads/master/msg + $repo/.git/fs/branch/heads/master/parent + $repo/.git/fs/branch/heads/master/tree + % cat $repo/.git/fs/branch/heads/master/hash + 7d539a7c08aba3f31b3913e0efef11c43ea9 + + # This is the same commit, with the same contents. + % ls $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef + $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef/author + $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef/hash + $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef/msg + $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef/parent + $repo/.git/fs/object/7d539a7c08aba3f31b3913e0efef11c43ea9f9ef/tree + + # what git/diff will hopefully do more concisely soon, filtering + # out the non-git files. + ape/diff -ur $repo/.git/fs/branch/heads/master/tree . + Only in .: .git + Only in .: debug + diff -ur $repo/.git/fs/branch/heads/master/tree/fold.myr ./fold.myr + --- $repo/.git/fs/branch/heads/master/tree/fold.myr Wed Dec 31 16:00:00 1969 + +++ ./fold.myr Mon Apr 1 21:39:06 2019 + @@ -6,6 +6,8 @@ + const foldexpr : (e : expr# -> std.option(constval)) + ;; + + +/* Look, diffing files just works, and I don't need any fancy glue! */ + + + const foldexpr = {e + match e + | &(`Eident &[.sc=`Sclassenum, .name=name, .ty=`Tyenum &(`Body enum)]): + Only in .: refs + + +The following utilities and binaries are provided: + + fs: The git filesystem. + fetch: The protocol bits for getting data from a git server. + send: The protocol bits for sending data to a git server. + save: The gnarly bits for storing the files for a commit. + conf: A program to extract information from a config file. + clone: Clones a repository. + commit: Commits a snapshot of the selected files. + log: Prints the contents of a commmit log. + add: Tells the repository to add a file to the next commit. + walk: `du`, but for git status. + ... and more + +Supported protocols: git:// and git+ssh://. If someone +implements others, I'll gladly accept patches. + +9legacy Notes +------------- + +To use git9 on 9legacy, these patches are necessary. + + - rc-line-split: implement delim{...} syntax for rc + - walk: port walk command to 9legacy. + - aux/getflags: 9front updated it with support for named args + +Additionally, git9 defaults to editing with hold(1). This command +is not present on 9legacy. Import it, or set $editor to your choice +of editor. diff --git a/sys/src/cmd/git/add b/sys/src/cmd/git/add new file mode 100755 index 0000000000..b980d7dc8b --- /dev/null +++ b/sys/src/cmd/git/add @@ -0,0 +1,38 @@ +#!/bin/rc -e +rfork ne +. /sys/lib/git/common.rc + +gitup + +flagfmt='r:remove'; args='file ...' +eval `''{aux/getflags $*} || exec aux/usage + +add='tracked' +del='removed' +if(~ $remove 1){ + add='removed' + del='tracked' +} +if(~ $#* 0) + exec aux/usage + +paths=`$nl{cleanname -d $gitrel $* | drop $gitroot} +if(~ $add tracked) + files=`$nl{walk -f ./$paths} +if not + files=`$nl{cd .git/index9/tracked/ && walk -f ./$paths} + +for(f in $files){ + if(! ~ `$nl{cleanname $f} .git/*){ + addpath=.git/index9/$add/$f + delpath=.git/index9/$del/$f + mkdir -p `$nl{basename -d $addpath} + mkdir -p `$nl{basename -d $delpath} + # We don't want a matching qid, so that + # git/walk doesn't think this came from + # a checkout. + echo -n > $addpath + rm -f $delpath + } +} +exit '' diff --git a/sys/src/cmd/git/branch b/sys/src/cmd/git/branch new file mode 100755 index 0000000000..01c41176bf --- /dev/null +++ b/sys/src/cmd/git/branch @@ -0,0 +1,122 @@ +#!/bin/rc -e +rfork en +. /sys/lib/git/common.rc + +gitup + +flagfmt='a:listall, b:baseref ref, d:delete, n:newbr, s:stay, m:merge' +args='[branch]' +eval `''{aux/getflags $*} || exec aux/usage + +modified=() +deleted=() + +if(~ $#* 0){ + if(~ $#listall 0) + awk '$1=="branch"{print $2}' < $gitfs/ctl + if not + cd .git/refs/ && walk -f heads remotes + exit +} +if(! ~ $#* 1) + exec aux/usage + +branch=$1 +if(~ $branch refs/heads/*) + new=$name +if not if(~ $branch heads/*) + new=refs/$branch +if not + new=refs/heads/$branch + +orig=`{git/query HEAD} +if (~ $#baseref 1) + base=`{git/query $baseref} || exit 'bad base' +if not if(~ $#newbr 0) + base=`{git/query $new} +if not + base=`{git/query HEAD} + +if(~ $#newbr 0){ + if(! ~ $#baseref 0) + die update would clobber $branch with $baseref + baseref=`$nl{echo -n $new | sed s@refs/heads/@refs/remotes/origin/@} + if(! test -e .git/$new) + if(! base=`{git/query $baseref}) + die could not find branch $branch +} +modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'} +deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'} + +# if we're not merging, don't clobber existing changes. +if(~ $#merge 0){ + if(! ~ $#modified 0 || ! ~ $#deleted 0){ + git/walk -fRMA $modified $deleted || + die 'uncommitted changes would be clobbered' + } +} +if(~ $delete 1){ + rm -f .git/$new + echo 'deleted branch' $new + exit +} +commit=`{git/query $base} || die 'branch does not exist:' $base +if(~ $new */*) + mkdir -p .git/`{basename -d $new} +if(! ~ $#stay 0){ + echo $commit > .git/$new + exit +} +basedir=`{git/query -p $base} +dirtypaths=() +if(! ~ $#modified 0 || ! ~ $#deleted 0) + dirtypaths=`$nl{git/walk -cfRMA $modified $deleted} +if(~ $#dirtypaths 0) + cleanpaths=($modified $deleted) +if not { + cleanpaths=() + for(p in $modified $deleted) + if(! ~ $p $dirtypaths) + cleanpaths=($cleanpaths $p) +} + +echo $commit > .git/$new +for(m in $cleanpaths){ + d=`$nl{basename -d $m} + mkdir -p $d + mkdir -p .git/index9/tracked/$d + # Modifications can turn a file into + # a directory, or vice versa, so we + # need to delete and copy the files + # over. + a=dir + b=dir + if(test -f $m) + a=file + if(test -f $basedir/tree/$m) + b=file + if(! ~ $a $b){ + rm -rf $m + rm -rf .git/index9/tracked/$m + } + if(~ $b file){ + cp -x -- $basedir/tree/$m $m + walk -eq $m > .git/index9/tracked/$m + touch $m + } +} + +for(ours in $dirtypaths){ + common=$gitfs/object/$orig/tree/$ours + theirs=$gitfs/object/$base/tree/$ours + merge1 $ours $ours $common $theirs +} + +if(! ~ $#deleted 0){ + rm -f $deleted + rm -f .git/index9/tracked/$deleted +} + +echo ref: $new > .git/HEAD +echo $new: `{git/query $new} +exit '' diff --git a/sys/src/cmd/git/clone b/sys/src/cmd/git/clone new file mode 100755 index 0000000000..93e7f0b974 --- /dev/null +++ b/sys/src/cmd/git/clone @@ -0,0 +1,114 @@ +#!/bin/rc +rfork en +. /sys/lib/git/common.rc + +flagfmt='d:debug, b:branch branch'; args='remote [local]' +eval `''{aux/getflags $*} || exec aux/usage +if(~ $debug 1) + debug=(-d) + +remote=`{echo $1 | sed 's@/*$@@'} +local=$2 + +if(~ $#remote 0) + exec aux/usage +if(~ $#local 0) + local=`{basename $remote .git} +if(~ $#branch 1) + branchflag=(-b $branch) + +if(test -e $local) + die 'repository already exists:' $local + +fn clone{ + flag +e + mkdir -p $local/.git + mkdir -p $local/.git/fs + mkdir -p $local/.git/objects/pack/ + mkdir -p $local/.git/refs/heads/ + + cd $local + + >>.git/config { + echo '[remote "origin"]' + echo ' url='$remote + } + {git/get $debug $branchflag $remote >[2=3] | awk ' + BEGIN{ + headref="" + if(ENVIRON["branch"] != "") + headref="refs/remotes/origin/"ENVIRON["branch"] + headhash="" + } + /^symref / && headref == "" { + if($2 == "HEAD"){ + gsub("^refs/heads", "refs/remotes/origin", $3) + gsub("^refs/tags", "refs/remotes/origin/tags", $3) + } + } + /^remote /{ + if($2=="HEAD"){ + headhash=$3 + }else if(match($2, "^refs/(heads|tags)/")){ + gsub("^refs/heads", "refs/remotes/origin", $2) + if($2 == headref || (headref == "" && $3 == headhash)) + headref=$2 + outfile = ".git/" $2 + outdir = outfile + gsub("/?[^/]*/?$", "", outdir) + system("mkdir -p "outdir) + print $3 > outfile + close(outfile) + } + } + END{ + if(headref != ""){ + remote = headref; + refdir = headref; + gsub("/?[^/]*/?$", "", refdir) + gsub("^refs/remotes/origin", "refs/heads", headref) + system("mkdir -p .git/"refdir); + system("cp .git/" remote " .git/" headref) + print "ref: " headref > ".git/HEAD" + }else if(headhash != ""){ + print "warning: detached head "headhash > "/fd/2" + print headhash > ".git/HEAD" + } + } + '} |[3] tr '\x0d' '\x0a' || die 'could not clone repository' + + tree=.git/fs/HEAD/tree + lbranch=`{git/branch} + rbranch=`{echo $lbranch | subst 'heads' 'remotes/origin'} + echo checking out repository... + if(test -f .git/refs/$rbranch){ + cp .git/refs/$rbranch .git/refs/$lbranch + git/fs + @ {builtin cd $tree && tar cif /fd/1 .} | @ {tar xf /fd/0} \ + || die 'checkout failed:' $status + for(f in `$nl{walk -f $tree | drop $tree}){ + idx=.git/index9/tracked/$f + mkdir -p `$nl{basename -d $idx} + walk -eq ./$f > $idx + } + } + if not{ + echo no default branch >[1=2] + echo check out your code with git/branch >[1=2] + } +} + +fn sigint { + echo cancelled clone $remote: cleaning $local >[1=2] + rm -rf $local + exit interrupted +} + +@{clone} +st=$status +if(! ~ $st ''){ + echo failed to clone $remote: cleaning $local >[1=2] + rm -rf $local + exit $st +} +exit '' diff --git a/sys/src/cmd/git/commit b/sys/src/cmd/git/commit new file mode 100644 index 0000000000..5b61fe1eb2 --- /dev/null +++ b/sys/src/cmd/git/commit @@ -0,0 +1,136 @@ +#!/bin/rc -e +rfork ne +. /sys/lib/git/common.rc + +fn findbranch{ + branch=`{git/branch} + if(test -e $gitfs/branch/$branch/tree){ + refpath=.git/refs/$branch + initial=false + } + if not if(test -e $gitfs/object/$branch/tree){ + refpath=.git/HEAD + initial=false + } + if not if(! test -e $gitfs/HEAD/tree){ + refpath=.git/refs/$branch + initial=true + } + if not + die 'invalid branch:' $branch +} + +# Remove commentary lines. +# Remove leading and trailing empty lines. +# Combine consecutive empty lines between paragraphs. +# Remove trailing spaces from lines. +# Ensure there's trailing newline. +fn cleanmsg{ + awk ' + /^[ ]*#/ {next} + /^[ ]*$/ {empty = 1; next} + + wet && empty {printf "\n"} + {wet = 1; empty = 0} + {sub(/[ ]+$/, ""); print $0} + ' +} + +fn editmsg{ + if(! test -s $msgfile.tmp){ + >$msgfile.tmp { + echo '# Author:' $name '<'$email'>' + echo '#' + for(p in $parents) + echo '# parent:' $p + git/walk -fAMR $files | subst '^' '# ' + echo '#' + echo '# Commit message:' + } + edit=1 + } + if(! ~ $#edit 0){ + giteditor=`{git/conf core.editor} + if(~ $#editor 0) + editor=$giteditor + if(~ $#editor 0) + editor=hold + $editor $msgfile.tmp + } + cleanmsg < $msgfile.tmp > $msgfile + if(! test -s $msgfile) + die 'empty commit message' +} + +fn parents{ + if(! ~ $#revise 0) + parents=`{cat $gitfs/HEAD/parent} + if not if(test -f .git/index9/merge-parents) + parents=`{cat .git/index9/merge-parents | sort | uniq} + if not if(~ $initial true) + parents=() + if not + parents=`{git/query $branch} +} + +fn commit{ + msg=`''{cat $msgfile} + if(! ~ $#parents 0) + pflags='-p'^$parents + hash=`{git/save -n $"name -e $"email -m $"msg $pflags $files || die $status} + rm -f .git/index9/merge-parents +} + +fn update{ + mkdir -p `{basename -d $refpath} + # Paranoia: let's not mangle the repo. + if(~ $#hash 0) + die 'botched commit' + echo $branch: $hash + echo $hash > $refpath + for(f in $files){ + if(test -e .git/index9/removed/$f || ! test -e $f){ + rm -f .git/index9/removed/$f + rm -f .git/index9/tracked/$f + } + if not{ + mkdir -p `{basename -d $f} + walk -eq $f > .git/index9/tracked/$f + } + } +} + +fn sigexit{ + if(~ ! $#msgfile 0) + rm -f $msgfile $msgfile.tmp +} + +gitup + +flagfmt='m:msg message, r:revise, e:edit'; args='[file ...]' +eval `''{aux/getflags $*} || exec aux/usage + +msgfile=/tmp/git-msg.$pid +if(~ $#msg 1) + echo $msg >$msgfile.tmp +if not if(~ $#revise 1){ + msg=1 + echo revising commit `{cat $gitfs/HEAD/hash} + cat $gitfs/HEAD/msg >$msgfile.tmp +} + +files=() +if(! ~ $#* 0) + files=`$nl{git/walk -c `$nl{cleanname -d $gitrel $*}} +if(~ $status '' || ~ $#files 0 && ! test -f .git/index9/merge-parents && ~ $#revise 0) + die 'nothing to commit' $status +@{ + flag e + + whoami + findbranch + parents + editmsg + commit + update +} || die 'could not commit:' $status +exit '' diff --git a/sys/src/cmd/git/compat b/sys/src/cmd/git/compat new file mode 100755 index 0000000000..25d14308fc --- /dev/null +++ b/sys/src/cmd/git/compat @@ -0,0 +1,168 @@ +#!/bin/rc + +rfork e + +opts=() +args=() + +fn cmd_init{ + while(~ $#* 0){ + switch($1){ + case --bare + opts=(-b) + case -- + # go likes to use these + case -* + die unknown command init $* + case * + args=($args $1) + } + shift + } + ls >[1=2] + git/init $opts $args +} + +fn cmd_clone{ + branch=() + while( ! ~ $#* 0){ + switch($1){ + case -b + branch=$2 + shift + case -- + # go likes to use these + case -* + die unknown command clone $* + case * + args=($args $1) + } + shift + } + git/clone $opts $args + if(~ $#branch 1) + git/branch -n -b $1 origin/$1 +} + +fn cmd_pull{ + if(~ $1 -*) + die unknown options for pull $* + git/pull +} + +fn cmd_fetch{ + while(~ $#* 0){ + switch($1){ + case --all + opts=($opts -a) + case -f + opts=($opts -u $2) + shift + case -- + # go likes to use these + case -* + die unknown command clone $* + case * + args=($args $1) + } + shift + } + git/pull -f $opts +} + + +fn cmd_checkout{ + if(~ $1 -*) + die unknown command pull $* + if(~ $#* 0) + die git checkout branch + git/branch $b +} + +fn cmd_submodule { + if(test -f .gitmodules) + die 'submodules unsupported' +} + +fn cmd_rev-parse{ + while(~ $1 -*){ + switch($1){ + case --git-dir + echo $gitroot/.git + shift + case --abbrev-ref + echo `{dcmd git9/branch | sed s@^heads/@@g} + shift + case * + dprint option $opt + } + shift + } +} + +fn cmd_show-ref{ + if(~ $1 -*) + die unknown command pull $* + filter=cat + if(~ $#* 0) + filter=cat + if not + filter='-e(^|/)'^$*^'$' + for(b in `$nl{cd $gitroot/.git/refs/ && walk -f}) + echo `{cat $gitroot/.git/refs/$b} refs/$b +} + +fn cmd_remote{ + if({! ~ $#* 3 && ! ~ $#* 4} || ! ~ $1 add) + die unimplemented remote cmd $* + name=$2 + url=$3 + if(~ $3 '--') + url=$4 + >>$gitroot/.git/config{ + echo '[remote "'$name'"]' + echo ' url='$url + } +} + +fn cmd_ls-remote{ + if(~ $1 -q) + shift + remote=`$nl{git/conf 'remote "'$1'".url'} + if(~ $#remote 0) + remote=$1 + git/get -l $remote | awk '/^remote/{print $3"\t"$2}' +} + +fn cmd_version{ + echo git version 2.2.0 +} + + +fn usage{ + echo 'git ' >[1=2] + exit usage +} + +fn die { + >[1=2] echo git $_cmdname: $* + exit $_cmdname: $* +} + +_cmdname=$1 +if(~ $0 *compat){ + ramfs -m /n/gitcompat + touch /n/gitcompat/git + bind $0 /n/gitcompat/git + path=( /n/gitcompat $path ) + exec rc +} + +if(! test -f '/env/fn#cmd_'$1) + die git $1: commmand not implemented +if(! ~ $1 init && ! ~ $1 clone) + gitroot=`{git/conf -r} || die repo + +echo $* >/tmp/gitlog +cmd_$1 $*(2-) +exit '' diff --git a/sys/src/cmd/git/conf.c b/sys/src/cmd/git/conf.c new file mode 100644 index 0000000000..63cf475d5f --- /dev/null +++ b/sys/src/cmd/git/conf.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "git.h" + +int findroot; +int showall; +int nfile; +char *file[32]; + +static int +showconf(char *cfg, char *sect, char *key) +{ + char *ln, *p; + Biobuf *f; + int foundsect, nsect, nkey, found; + + if((f = Bopen(cfg, OREAD)) == nil) + return 0; + + found = 0; + nsect = sect ? strlen(sect) : 0; + nkey = strlen(key); + foundsect = (sect == nil); + while((ln = Brdstr(f, '\n', 1)) != nil){ + p = strip(ln); + if(*p == '[' && sect){ + foundsect = strncmp(sect, ln, nsect) == 0; + }else if(foundsect && strncmp(p, key, nkey) == 0){ + p = strip(p + nkey); + if(*p != '=') + continue; + p = strip(p + 1); + print("%s\n", p); + found = 1; + if(!showall){ + free(ln); + goto done; + } + } + free(ln); + } +done: + return found; +} + + +void +usage(void) +{ + fprint(2, "usage: %s [-f file] [-r] keys..\n", argv0); + fprint(2, "\t-f: use file 'file' (default: .git/config)\n"); + fprint(2, "\t r: print repository root\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char repo[512], *p, *s; + int i, j; + + ARGBEGIN{ + case 'f': file[nfile++]=EARGF(usage()); break; + case 'r': findroot++; break; + case 'a': showall++; break; + default: usage(); break; + }ARGEND; + + if(findroot){ + if(findrepo(repo, sizeof(repo)) == -1) + sysfatal("%r"); + print("%s\n", repo); + exits(nil); + } + if(nfile == 0){ + file[nfile++] = ".git/config"; + if((p = getenv("home")) != nil) + file[nfile++] = smprint("%s/lib/git/config", p); + file[nfile++] = "/sys/lib/git/config"; + } + + for(i = 0; i < argc; i++){ + if((p = strchr(argv[i], '.')) == nil){ + s = nil; + p = argv[i]; + }else{ + *p = 0; + p++; + s = smprint("[%s]", argv[i]); + } + for(j = 0; j < nfile; j++) + if(showconf(file[j], s, p)) + break; + } + exits(nil); +} diff --git a/sys/src/cmd/git/delta.c b/sys/src/cmd/git/delta.c new file mode 100644 index 0000000000..32af58b64b --- /dev/null +++ b/sys/src/cmd/git/delta.c @@ -0,0 +1,219 @@ +#include +#include + +#include "git.h" + +enum { + Minchunk = 128, + Maxchunk = 8192, + Splitmask = (1<<8)-1, + +}; + +static u32int geartab[] = { + 0x67ed26b7, 0x32da500c, 0x53d0fee0, 0xce387dc7, 0xcd406d90, 0x2e83a4d4, 0x9fc9a38d, 0xb67259dc, + 0xca6b1722, 0x6d2ea08c, 0x235cea2e, 0x3149bb5f, 0x1beda787, 0x2a6b77d5, 0x2f22d9ac, 0x91fc0544, + 0xe413acfa, 0x5a30ff7a, 0xad6fdde0, 0x444fd0f5, 0x7ad87864, 0x58c5ff05, 0x8d2ec336, 0x2371f853, + 0x550f8572, 0x6aa448dd, 0x7c9ddbcf, 0x95221e14, 0x2a82ec33, 0xcbec5a78, 0xc6795a0d, 0x243995b7, + 0x1c909a2f, 0x4fded51c, 0x635d334b, 0x0e2b9999, 0x2702968d, 0x856de1d5, 0x3325d60e, 0xeb6a7502, + 0xec2a9844, 0x0905835a, 0xa1820375, 0xa4be5cab, 0x96a6c058, 0x2c2ccd70, 0xba40fce3, 0xd794c46b, + 0x8fbae83e, 0xc3aa7899, 0x3d3ff8ed, 0xa0d42b5b, 0x571c0c97, 0xd2811516, 0xf7e7b96c, 0x4fd2fcbd, + 0xe2fdec94, 0x282cc436, 0x78e8e95c, 0x80a3b613, 0xcfbee20c, 0xd4a32d1c, 0x2a12ff13, 0x6af82936, + 0xe5630258, 0x8efa6a98, 0x294fb2d1, 0xdeb57086, 0x5f0fddb3, 0xeceda7ce, 0x4c87305f, 0x3a6d3307, + 0xe22d2942, 0x9d060217, 0x1e42ed02, 0xb6f63b52, 0x4367f39f, 0x055cf262, 0x03a461b2, 0x5ef9e382, + 0x386bc03a, 0x2a1e79c7, 0xf1a0058b, 0xd4d2dea9, 0x56baf37d, 0x5daff6cc, 0xf03a951d, 0xaef7de45, + 0xa8f4581e, 0x3960b555, 0xffbfff6d, 0xbe702a23, 0x8f5b6d6f, 0x061739fb, 0x98696f47, 0x3fd596d4, + 0x151eac6b, 0xa9fcc4f5, 0x69181a12, 0x3ac5a107, 0xb5198fe7, 0x96bcb1da, 0x1b5ddf8e, 0xc757d650, + 0x65865c3a, 0x8fc0a41a, 0x87435536, 0x99eda6f2, 0x41874794, 0x29cff4e8, 0xb70efd9a, 0x3103f6e7, + 0x84d2453b, 0x15a450bd, 0x74f49af1, 0x60f664b1, 0xa1c86935, 0xfdafbce1, 0xe36353e3, 0x5d9ba739, + 0xbc0559ba, 0x708b0054, 0xd41d808c, 0xb2f31723, 0x9027c41f, 0xf136d165, 0xb5374b12, 0x9420a6ac, + 0x273958b6, 0xe6c2fad0, 0xebdc1f21, 0xfb33af8b, 0xc71c25cd, 0xe9a2d8e5, 0xbeb38a50, 0xbceb7cc2, + 0x4e4e73f0, 0xcd6c251d, 0xde4c032c, 0x4b04ac30, 0x725b8b21, 0x4eb8c33b, 0x20d07b75, 0x0567aa63, + 0xb56b2bb7, 0xc1f5fd3a, 0xcafd35ca, 0x470dd4da, 0xfe4f94cd, 0xfb8de424, 0xe8dbcf40, 0xfe50a37a, + 0x62db5b5d, 0xf32f4ab6, 0x2c4a8a51, 0x18473dc0, 0xfe0cbb6e, 0xfe399efd, 0xdf34ecc9, 0x6ccd5055, + 0x46097073, 0x139135c2, 0x721c76f6, 0x1c6a94b4, 0x6eee014d, 0x8a508e02, 0x3da538f5, 0x280d394f, + 0x5248a0c4, 0x3ce94c6c, 0x9a71ad3a, 0x8493dd05, 0xe43f0ab6, 0x18e4ed42, 0x6c5c0e09, 0x42b06ec9, + 0x8d330343, 0xa45b6f59, 0x2a573c0c, 0xd7fd3de6, 0xeedeab68, 0x5c84dafc, 0xbbd1b1a8, 0xa3ce1ad1, + 0x85b70bed, 0xb6add07f, 0xa531309c, 0x8f8ab852, 0x564de332, 0xeac9ed0c, 0x73da402c, 0x3ec52761, + 0x43af2f4d, 0xd6ff45c8, 0x4c367462, 0xd553bd6a, 0x44724855, 0x3b2aa728, 0x56e5eb65, 0xeaf16173, + 0x33fa42ff, 0xd714bb5d, 0xfbd0a3b9, 0xaf517134, 0x9416c8cd, 0x534cf94f, 0x548947c2, 0x34193569, + 0x32f4389a, 0xfe7028bc, 0xed73b1ed, 0x9db95770, 0x468e3922, 0x0440c3cd, 0x60059a62, 0x33504562, + 0x2b229fbd, 0x5174dca5, 0xf7028752, 0xd63c6aa8, 0x31276f38, 0x0646721c, 0xb0191da8, 0xe00e6de0, + 0x9eac1a6e, 0x9f7628a5, 0xed6c06ea, 0x0bb8af15, 0xf119fb12, 0x38693c1c, 0x732bc0fe, 0x84953275, + 0xb82ec888, 0x33a4f1b3, 0x3099835e, 0x028a8782, 0x5fdd51d7, 0xc6c717b3, 0xb06caf71, 0x17c8c111, + 0x61bad754, 0x9fd03061, 0xe09df1af, 0x3bc9eb73, 0x85878413, 0x9889aaf2, 0x3f5a9e46, 0x42c9f01f, + 0x9984a4f4, 0xd5de43cc, 0xd294daed, 0xbecba2d2, 0xf1f6e72c, 0x5551128a, 0x83af87e2, 0x6f0342ba, +}; + +static u64int +hash(void *p, int n) +{ + uchar buf[SHA1dlen]; + sha1((uchar*)p, n, buf, nil); + return GETBE64(buf); +} + +static void +addblk(Dtab *dt, void *buf, int len, int off, u64int h) +{ + int i, sz, probe; + Dblock *db; + + probe = h % dt->sz; + while(dt->b[probe].buf != nil){ + if(len == dt->b[probe].len && memcmp(buf, dt->b[probe].buf, len) == 0) + return; + probe = (probe + 1) % dt->sz; + } + assert(dt->b[probe].buf == nil); + dt->b[probe].buf = buf; + dt->b[probe].len = len; + dt->b[probe].off = off; + dt->b[probe].hash = h; + dt->nb++; + if(dt->sz < 2*dt->nb){ + sz = dt->sz; + db = dt->b; + dt->sz *= 2; + dt->nb = 0; + dt->b = eamalloc(dt->sz, sizeof(Dblock)); + for(i = 0; i < sz; i++) + if(db[i].buf != nil) + addblk(dt, db[i].buf, db[i].len, db[i].off, db[i].hash); + free(db); + } +} + +static Dblock* +lookup(Dtab *dt, uchar *p, int n) +{ + int probe; + u64int h; + + h = hash(p, n); + for(probe = h % dt->sz; dt->b[probe].buf != nil; probe = (probe + 1) % dt->sz){ + if(dt->b[probe].hash != h) + continue; + if(n != dt->b[probe].len) + continue; + if(memcmp(p, dt->b[probe].buf, n) != 0) + continue; + return &dt->b[probe]; + } + return nil; +} + +static int +nextblk(uchar *s, uchar *e) +{ + u32int gh; + uchar *p; + + if((e - s) < Minchunk) + return e - s; + p = s + Minchunk; + if((e - s) > Maxchunk) + e = s + Maxchunk; + gh = 0; + while(p != e){ + gh = (gh<<1) + geartab[*p++]; + if((gh & Splitmask) == 0) + break; + } + return p - s; +} + +void +dtinit(Dtab *dt, Object *obj) +{ + uchar *s, *e; + u64int h; + vlong n, o; + + o = 0; + s = (uchar*)obj->data; + e = s + obj->size; + dt->o = ref(obj); + dt->nb = 0; + dt->sz = 128; + dt->b = eamalloc(dt->sz, sizeof(Dblock)); + dt->base = (uchar*)obj->data; + dt->nbase = obj->size; + while(s != e){ + n = nextblk(s, e); + h = hash(s, n); + addblk(dt, s, n, o, h); + s += n; + o += n; + } +} + +void +dtclear(Dtab *dt) +{ + unref(dt->o); + free(dt->b); +} + +static int +emitdelta(Delta **pd, int *nd, int cpy, int off, int len) +{ + Delta *d; + + *nd += 1; + *pd = earealloc(*pd, *nd, sizeof(Delta)); + d = &(*pd)[*nd - 1]; + d->cpy = cpy; + d->off = off; + d->len = len; + return len; +} + +static int +stretch(Dtab *dt, Dblock *b, uchar *s, uchar *e, int n) +{ + uchar *p, *q, *eb; + + if(b == nil) + return n; + p = s + n; + q = dt->base + b->off + n; + eb = dt->base + dt->nbase; + while(n < (1<<24)-1){ + if(p == e || q == eb) + break; + if(*p != *q) + break; + p++; + q++; + n++; + } + return n; +} + +Delta* +deltify(Object *obj, Dtab *dt, int *pnd) +{ + Delta *d; + Dblock *b; + uchar *s, *e; + vlong n, o; + + o = 0; + d = nil; + s = (uchar*)obj->data; + e = s + obj->size; + *pnd = 0; + while(s != e){ + n = nextblk(s, e); + b = lookup(dt, s, n); + n = stretch(dt, b, s, e, n); + if(b != nil) + emitdelta(&d, pnd, 1, b->off, n); + else + emitdelta(&d, pnd, 0, o, n); + s += n; + o += n; + } + return d; +} diff --git a/sys/src/cmd/git/diff b/sys/src/cmd/git/diff new file mode 100644 index 0000000000..28e69d660c --- /dev/null +++ b/sys/src/cmd/git/diff @@ -0,0 +1,47 @@ +#!/bin/rc +rfork ne +. /sys/lib/git/common.rc + +gitup + +flagfmt='c:commit branch, s:summarize'; args='[file ...]' +eval `''{aux/getflags $*} || exec aux/usage + +if(~ $#commit 0) + commit=HEAD + +files=() +if(! ~ $#* 0) + files=`{cleanname -d $gitrel $*} + +branch=`{git/query -p $commit} +if(~ $summarize 1){ + git/walk -fMAR $files + exit +} + +fn lsdirty { + git/walk -c -fRMA $files + if(! ~ $commit HEAD) + git/query -c $commit HEAD | subst '^..' +} + +showed=() +mntgen /mnt/scratch +bind $branch/tree/ /mnt/scratch/a +bind . /mnt/scratch/b +for(f in `$nl{lsdirty | sort | uniq}){ + if(~ $#showed 0){ + echo diff `{git/query $commit} uncommitted + showed=1 + } + cd /mnt/scratch + a=a/$f + b=b/$f + if(! test -f a/$f) + a=/dev/null + if(! test -f b/$f) + b=/dev/null + diff -u $a $b +} +exit '' diff --git a/sys/src/cmd/git/export b/sys/src/cmd/git/export new file mode 100755 index 0000000000..2d7c068d35 --- /dev/null +++ b/sys/src/cmd/git/export @@ -0,0 +1,88 @@ +#!/bin/rc +rfork ne +. /sys/lib/git/common.rc + +patchname=/tmp/git.patchname.$pid +patchfile=/tmp/git.patchfile.$pid +fn sigexit{ + rm -f $patchname $patchfile +} + +gitup + +flagfmt='o:patchdir patchdir'; args='[query]' +eval `''{aux/getflags $*} || exec aux/usage + +if(~ $#patchdir 1 && ! test -d $patchdir) + mkdir -p $patchdir + +q=$* +if(~ $#q 0) + q=HEAD +commits=`{git/query $q || die $status} +n=1 +m=$#commits + + +# sleazy hack: we want to run +# under rfork m for the web ui, +# so don't error if we can't mount +mntgen /mnt/scratch >[2]/dev/null || status='' +for(c in $commits){ + cp=`{git/query -p $c} + pp=`{git/query -p $c'~'} + fc=`$nl{git/query -c $c~ $c | sed 's/^..//'} + + @{ + rfork n + cd /mnt/scratch + if(test -d $pp/tree) + bind $pp/tree a + if(test -d $cp/tree) + bind $cp/tree b + + echo From: `{cat $cp/author} + echo Date: `{date -uf'WW, DD MMM YYYY hh:mm:ss Z' `{walk -em $cp/author}} + <$cp/msg awk ' + NR == 1 { + n = ENVIRON["n"] + m = ENVIRON["m"] + msg=$0 + if(m > 1) + patch = sprintf("[PATCH %d/%d]", n, m) + else + patch = "[PATCH]" + printf "Subject: %s %s\n\n", patch, msg + + gsub("^[ ]|[ ]$", "", msg) + gsub("[^a-zA-Z0-9_]+", "-", msg) + printf "%.4d-%s.patch", n, msg >ENVIRON["patchname"] + next + } + { + print + }' + echo '---' + echo diff `{basename $pp} `{basename $cp} + for(f in $fc){ + a=a/$f + if(! test -e $a) + a=/dev/null + b=b/$f + if(! test -e $b) + b=/dev/null + ape/diff -urN $a $b + } + } >$patchfile + if(~ $#patchdir 0){ + cat $patchfile + ! ~ $n $m && echo + } + if not{ + f=$patchdir/`{cat $patchname} + mv $patchfile $f + echo $f + } + n=`{echo $n + 1 | bc} +} +exit '' diff --git a/sys/src/cmd/git/extra/gitls b/sys/src/cmd/git/extra/gitls new file mode 100755 index 0000000000..d9288c5134 --- /dev/null +++ b/sys/src/cmd/git/extra/gitls @@ -0,0 +1,203 @@ +#!/bin/rc -e + +cd $1 +shift + +rfork ne +nl=' +' + +fn htcat { + sed ' + s/&/\&/g; + s//\>/g; + s/"/\"/g; + s/''/\'/g + ' $* +} + +fn resolveref { + if(~ $refname HEAD) + echo $refname + if not if(test -d $gitfs/branch/$refname/tree) + echo branch/$refname + if not if(test -d $gitfs/object/$refname/tree) + echo object/$refname + if not + status='bad ref' +} + +fn repons { + mntgen + mntgen /mnt/mnt + bind /bin /mnt/bin + bind /tmp /mnt/tmp + bind -c /env /mnt/env + bind $1 /mnt/$repo + bind /mnt / + cd /mnt/$repo + git/fs + rfork m +} + + +fn prelude { + echo ' + + + + + + + + git webls + + + ' +} + +switch($1){ +case 'tar' + repo=$2 + refname=$3 + @{ + repons $2 + if(! ref=`{resolveref $refname}){ + echo 'invalid ref '$refname'' + exit + } + bind $gitfs/$ref/tree /mnt/$repo + cd /mnt + tar cz $repo + } + +case 'list' + rfork m + prelude + echo '

Repos

+
' + for(repo in `$nl{ls}){ + if(test -e $repo/.git/webpublish){ + echo '
'$repo'
' + echo '
' + if(test -f $repo/.git/desc) + htcat $repo/.git/desc + if not + echo 'code some guy wrote' + echo '
' + } + } + echo '
' + +case 'info' + repo=$2 + repodir=/mnt/$repo/.git + refname=$3 + @{ + repons $repo + if(! ref=`{resolveref $refname}){ + echo 'invalid ref '$refname'' + exit + } + cd $gitfs/$ref/tree + hash=`{cat $gitfs/$ref/hash} + + prelude $repo $ref $repo + echo '

Git: '$repo'

+

'$repo' @ '$hash' +

'
+	htcat $gitfs/object/$hash/msg
+	echo '	
+

Code

+

+ clone: git://orib.dev/'$repo', gits://orib.dev/'$repo'
+ push: hjgit://orib.dev/'$repo'
+ tar: snap.tar.gz
' + if(test -f $repodir/contact) + echo 'patches to: '^`$nl{cat $repodir/contact}^'
+

+
'
+	for(f in `$nl{ls}){
+		url=`$nl{echo -n $f/f.html | urlencode}
+		fname=`$nl{echo -n $f | htcat}
+		echo ''$fname''
+	}		
+	echo '
+

About This Repo

+
'
+	if(test -f $repodir/README)
+		htcat $repodir/README
+	if not if(test -f README)
+		htcat README
+	if not if (test -f README.md)
+		htcat README.md
+	if not if(test -f $repodir/desc)
+		htcat $repodir/desc
+	if not
+		echo 'this repo has no description'
+	echo '
+		
+ + + ' + } + +case 'view' + repo=$2 + repodir=/mnt/$repo/.git + refname=$3 + file=$4 + @{ + repons $repo + if(! ref=`{resolveref $refname}){ + echo 'invalid ref '$refname'' + exit + } + cd $gitfs/$ref/tree + if(~ $file '') + file='.' + hash=`{cat $gitfs/$ref/hash} + + prelude + echo '

Git: '$repo'

+

'$repo' @ '$hash' +

'
+	if(test -f $file){
+		htcat $file
+	}
+	if not if(test -d $file){
+		cd $file
+		for(f in `$nl{ls}){
+			url=`$nl{echo -n $f/f.html | urlencode}
+			fname=`$nl{echo -n $f | htcat}
+			echo ''$fname''
+		}
+	}
+	echo '	
+ + ' + } +} diff --git a/sys/src/cmd/git/extra/gitrules b/sys/src/cmd/git/extra/gitrules new file mode 100644 index 0000000000..d01c8b13e5 --- /dev/null +++ b/sys/src/cmd/git/extra/gitrules @@ -0,0 +1,4 @@ +/repos.html /bin/gitls /usr/git list +/([^'/]+)/([^'/]+)/info.html /bin/gitls /usr/git info '\1' '\2' +/([^'/]+)/([^'/]+)/snap.tar.gz /bin/gitls /usr/git tar '\1' '\2' +/([^'/]+)/([^'/]+)/(([^']+)/)?f.html /bin/gitls /usr/git view '\1' '\2' '\4' diff --git a/sys/src/cmd/git/fs.c b/sys/src/cmd/git/fs.c new file mode 100644 index 0000000000..7e6b4bf877 --- /dev/null +++ b/sys/src/cmd/git/fs.c @@ -0,0 +1,906 @@ +#include +#include +#include +#include +#include +#include <9p.h> + +#include "git.h" + +enum { + Qroot, + Qhead, + Qbranch, + Qcommit, + Qmsg, + Qparent, + Qtree, + Qcdata, + Qhash, + Qauthor, + Qcommitter, + Qobject, + Qctl, + Qmax, + Internal=1<<7, +}; + +typedef struct Gitaux Gitaux; +typedef struct Crumb Crumb; +typedef struct Cache Cache; +typedef struct Uqid Uqid; +struct Crumb { + char *name; + Object *obj; + Qid qid; + int mode; + vlong mtime; +}; + +struct Gitaux { + int ncrumb; + Crumb *crumb; + char *refpath; + int qdir; + + /* For listing object dir */ + Objlist *ols; + Object *olslast; +}; + +struct Uqid { + vlong uqid; + + vlong ppath; + vlong oid; + int t; + int idx; +}; + +struct Cache { + Uqid *cache; + int n; + int max; +}; + +char *qroot[] = { + "HEAD", + "branch", + "object", + "ctl", +}; + +#define Eperm "permission denied" +#define Eexist "does not exist" +#define E2long "path too long" +#define Enodir "not a directory" +#define Erepo "unable to read repo" +#define Eobject "invalid object" +#define Egreg "wat" +#define Ebadobj "invalid object" + +char gitdir[512]; +char *username; +char *groupname; +char *mntpt = ".git/fs"; +char **branches = nil; +Cache uqidcache[512]; +vlong nextqid = Qmax; + +static Object* walklink(Gitaux *, char *, int, int, int*); + +vlong +qpath(Crumb *p, int idx, vlong id, vlong t) +{ + int h, i; + vlong pp; + Cache *c; + Uqid *u; + + pp = p ? p->qid.path : 0; + h = (pp*333 + id*7 + t) & (nelem(uqidcache) - 1); + c = &uqidcache[h]; + u = c->cache; + for(i=0; i n ; i++){ + if(u->ppath == pp && u->oid == id && u->t == t && u->idx == idx) + return (u->uqid << 8) | t; + u++; + } + if(c->n == c->max){ + c->max += c->max/2 + 1; + c->cache = erealloc(c->cache, c->max*sizeof(Uqid)); + } + nextqid++; + c->cache[c->n] = (Uqid){nextqid, pp, id, t, idx}; + c->n++; + return (nextqid << 8) | t; +} + +static Crumb* +crumb(Gitaux *aux, int n) +{ + if(n < aux->ncrumb) + return &aux->crumb[aux->ncrumb - n - 1]; + return nil; +} + +static void +popcrumb(Gitaux *aux) +{ + Crumb *c; + + if(aux->ncrumb > 1){ + c = crumb(aux, 0); + free(c->name); + unref(c->obj); + aux->ncrumb--; + } +} + +static vlong +branchid(Gitaux *aux, char *path) +{ + int i; + + for(i = 0; branches[i]; i++) + if(strcmp(path, branches[i]) == 0) + goto found; + branches = realloc(branches, sizeof(char *)*(i + 2)); + branches[i] = estrdup(path); + branches[i + 1] = nil; + +found: + if(aux){ + if(aux->refpath) + free(aux->refpath); + aux->refpath = estrdup(branches[i]); + } + return i; +} + +static void +obj2dir(Dir *d, Crumb *c, Object *o, char *name) +{ + d->qid = c->qid; + d->atime = c->mtime; + d->mtime = c->mtime; + d->mode = c->mode; + d->name = estrdup9p(name); + d->uid = estrdup9p(username); + d->gid = estrdup9p(groupname); + d->muid = estrdup9p(username); + if(o->type == GBlob || o->type == GTag){ + d->qid.type = 0; + d->mode &= 0777; + d->length = o->size; + } + +} + +static int +rootgen(int i, Dir *d, void *p) +{ + Crumb *c; + + c = crumb(p, 0); + if (i >= nelem(qroot)) + return -1; + d->mode = 0555 | DMDIR; + d->name = estrdup9p(qroot[i]); + d->qid.vers = 0; + d->qid.type = strcmp(qroot[i], "ctl") == 0 ? 0 : QTDIR; + d->qid.path = qpath(nil, i, i, Qroot); + d->uid = estrdup9p(username); + d->gid = estrdup9p(groupname); + d->muid = estrdup9p(username); + d->mtime = c->mtime; + return 0; +} + +static int +branchgen(int i, Dir *d, void *p) +{ + Gitaux *aux; + Dir *refs; + Crumb *c; + int n; + + aux = p; + c = crumb(aux, 0); + refs = nil; + d->qid.vers = 0; + d->qid.type = QTDIR; + d->qid.path = qpath(c, i, branchid(aux, aux->refpath), Qbranch | Internal); + d->mode = 0555 | DMDIR; + d->uid = estrdup9p(username); + d->gid = estrdup9p(groupname); + d->muid = estrdup9p(username); + d->mtime = c->mtime; + d->atime = c->mtime; + if((n = slurpdir(aux->refpath, &refs)) < 0) + return -1; + if(i < n){ + d->name = estrdup9p(refs[i].name); + free(refs); + return 0; + }else{ + free(refs); + return -1; + } +} + +static int +gtreegen(int i, Dir *d, void *p) +{ + Object *o, *l, *e; + Gitaux *aux; + Crumb *c; + int m; + + aux = p; + c = crumb(aux, 0); + e = c->obj; + if(i >= e->tree->nent) + return -1; + m = e->tree->ent[i].mode; + if(e->tree->ent[i].ismod) + o = emptydir(); + else if((o = readobject(e->tree->ent[i].h)) == nil) + sysfatal("could not read object %H: %r", e->tree->ent[i].h); + if(e->tree->ent[i].islink) + if((l = walklink(aux, o->data, o->size, 0, &m)) != nil) + o = l; + d->qid.vers = 0; + d->qid.type = o->type == GTree ? QTDIR : 0; + d->qid.path = qpath(c, i, o->id, aux->qdir); + d->mode = m; + d->atime = c->mtime; + d->mtime = c->mtime; + d->uid = estrdup9p(username); + d->gid = estrdup9p(groupname); + d->muid = estrdup9p(username); + d->name = estrdup9p(e->tree->ent[i].name); + d->length = o->size; + return 0; +} + +static int +gcommitgen(int i, Dir *d, void *p) +{ + Object *o; + Crumb *c; + + c = crumb(p, 0); + o = c->obj; + d->uid = estrdup9p(username); + d->gid = estrdup9p(groupname); + d->muid = estrdup9p(username); + d->mode = 0444; + d->atime = o->commit->ctime; + d->mtime = o->commit->ctime; + d->qid.type = 0; + d->qid.vers = 0; + + switch(i){ + case 0: + d->mode = 0755 | DMDIR; + d->name = estrdup9p("tree"); + d->qid.type = QTDIR; + d->qid.path = qpath(c, i, o->id, Qtree); + break; + case 1: + d->name = estrdup9p("parent"); + d->qid.path = qpath(c, i, o->id, Qparent); + break; + case 2: + d->name = estrdup9p("msg"); + d->qid.path = qpath(c, i, o->id, Qmsg); + break; + case 3: + d->name = estrdup9p("hash"); + d->qid.path = qpath(c, i, o->id, Qhash); + break; + case 4: + d->name = estrdup9p("author"); + d->qid.path = qpath(c, i, o->id, Qauthor); + break; + default: + return -1; + } + return 0; +} + + +static int +objgen(int i, Dir *d, void *p) +{ + Gitaux *aux; + Object *o; + Crumb *c; + char name[64]; + Objlist *ols; + Hash h; + + aux = p; + c = crumb(aux, 0); + if(!aux->ols) + aux->ols = mkols(); + ols = aux->ols; + o = nil; + /* We tried to sent it, but it didn't fit */ + if(aux->olslast && ols->idx == i + 1){ + snprint(name, sizeof(name), "%H", aux->olslast->hash); + obj2dir(d, c, aux->olslast, name); + return 0; + } + while(ols->idx <= i){ + if(olsnext(ols, &h) == -1) + return -1; + if((o = readobject(h)) == nil){ + fprint(2, "corrupt object %H\n", h); + return -1; + } + } + if(o != nil){ + snprint(name, sizeof(name), "%H", o->hash); + obj2dir(d, c, o, name); + unref(aux->olslast); + aux->olslast = ref(o); + return 0; + } + return -1; +} + +static void +objread(Req *r, Gitaux *aux) +{ + Object *o; + + o = crumb(aux, 0)->obj; + switch(o->type){ + case GBlob: + readbuf(r, o->data, o->size); + break; + case GTag: + readbuf(r, o->data, o->size); + break; + case GTree: + dirread9p(r, gtreegen, aux); + break; + case GCommit: + dirread9p(r, gcommitgen, aux); + break; + default: + sysfatal("invalid object type %d", o->type); + } +} + +static void +readcommitparent(Req *r, Object *o) +{ + char *buf, *p, *e; + int i, n; + + /* 40 bytes per hash, 1 per nl, 1 for terminator */ + n = o->commit->nparent * (40 + 1) + 1; + buf = emalloc(n); + p = buf; + e = buf + n; + for (i = 0; i < o->commit->nparent; i++) + p = seprint(p, e, "%H\n", o->commit->parent[i]); + readbuf(r, buf, p - buf); + free(buf); +} + +static void +gitattach(Req *r) +{ + Gitaux *aux; + Dir *d; + + if((d = dirstat(".git")) == nil) + sysfatal("git/fs: %r"); + if(getwd(gitdir, sizeof(gitdir)) == nil) + sysfatal("getwd: %r"); + aux = emalloc(sizeof(Gitaux)); + aux->crumb = emalloc(sizeof(Crumb)); + aux->crumb[0].qid = (Qid){Qroot, 0, QTDIR}; + aux->crumb[0].obj = nil; + aux->crumb[0].mode = DMDIR | 0555; + aux->crumb[0].mtime = d->mtime; + aux->crumb[0].name = estrdup("/"); + aux->ncrumb = 1; + r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; + r->fid->qid = r->ofcall.qid; + r->fid->aux = aux; + respond(r, nil); +} + +static Object* +walklink(Gitaux *aux, char *link, int nlink, int ndotdot, int *mode) +{ + char *p, *e, *path; + Object *o, *n; + int i; + + path = emalloc(nlink + 1); + memcpy(path, link, nlink); + cleanname(path); + + o = crumb(aux, ndotdot)->obj; + assert(o->type == GTree); + for(p = path; *p; p = e){ + n = nil; + e = p + strcspn(p, "/"); + if(*e == '/') + *e++ = '\0'; + /* + * cleanname guarantees these show up at the start of the name, + * which allows trimming them from the end of the trail of crumbs + * instead of needing to keep track of full parentage. + */ + if(strcmp(p, "..") == 0) + n = crumb(aux, ++ndotdot)->obj; + else if(o->type == GTree) + for(i = 0; i < o->tree->nent; i++) + if(strcmp(o->tree->ent[i].name, p) == 0){ + *mode = o->tree->ent[i].mode; + n = readobject(o->tree->ent[i].h); + break; + } + o = n; + if(o == nil) + break; + } + free(path); + return o; +} + +static char * +objwalk1(Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir, Gitaux *aux) +{ + Object *w, *l; + char *e; + int i, m; + + w = nil; + e = nil; + if(!o) + return Eexist; + if(o->type == GTree){ + q->type = 0; + for(i = 0; i < o->tree->nent; i++){ + if(strcmp(o->tree->ent[i].name, name) != 0) + continue; + m = o->tree->ent[i].mode; + w = readobject(o->tree->ent[i].h); + if(!w && o->tree->ent[i].ismod) + w = emptydir(); + if(w && o->tree->ent[i].islink) + if((l = walklink(aux, w->data, w->size, 1, &m)) != nil) + w = l; + if(!w) + return Ebadobj; + q->type = (w->type == GTree) ? QTDIR : 0; + q->path = qpath(c, i, w->id, qdir); + c->mode = m; + c->mode |= (w->type == GTree) ? DMDIR|0755 : 0644; + c->obj = w; + break; + } + if(!w) + e = Eexist; + }else if(o->type == GCommit){ + q->type = 0; + c->mtime = o->commit->mtime; + c->mode = 0644; + assert(qdir == Qcommit || qdir == Qobject || qdir == Qtree || qdir == Qhead || qdir == Qcommitter); + if(strcmp(name, "msg") == 0) + q->path = qpath(p, 0, o->id, Qmsg); + else if(strcmp(name, "parent") == 0) + q->path = qpath(p, 1, o->id, Qparent); + else if(strcmp(name, "hash") == 0) + q->path = qpath(p, 2, o->id, Qhash); + else if(strcmp(name, "author") == 0) + q->path = qpath(p, 3, o->id, Qauthor); + else if(strcmp(name, "committer") == 0) + q->path = qpath(p, 3, o->id, Qcommitter); + else if(strcmp(name, "tree") == 0){ + q->type = QTDIR; + q->path = qpath(p, 4, o->id, Qtree); + unref(c->obj); + c->mode = DMDIR | 0755; + c->obj = readobject(o->commit->tree); + if(c->obj == nil) + sysfatal("could not read object %H: %r", o->commit->tree); + } + else + e = Eexist; + }else if(o->type == GTag){ + e = "tag walk unimplemented"; + } + return e; +} + +static Object * +readref(char *pathstr) +{ + char buf[128], path[128], *p, *e; + Hash h; + int n, f; + + snprint(path, sizeof(path), "%s", pathstr); + while(1){ + if((f = open(path, OREAD)) == -1) + return nil; + if((n = readn(f, buf, sizeof(buf) - 1)) == -1) + return nil; + close(f); + buf[n] = 0; + if(strncmp(buf, "ref:", 4) != 0) + break; + + p = buf + 4; + while(isspace(*p)) + p++; + if((e = strchr(p, '\n')) != nil) + *e = 0; + snprint(path, sizeof(path), ".git/%s", p); + } + + if(hparse(&h, buf) == -1) + return nil; + + return readobject(h); +} + +static char* +gitwalk1(Fid *fid, char *name, Qid *q) +{ + char path[128]; + Gitaux *aux; + Crumb *c, *o; + char *e; + Dir *d; + Hash h; + + e = nil; + aux = fid->aux; + + q->vers = 0; + if(strcmp(name, "..") == 0){ + popcrumb(aux); + c = crumb(aux, 0); + *q = c->qid; + fid->qid = *q; + return nil; + } + + aux->crumb = realloc(aux->crumb, (aux->ncrumb + 1) * sizeof(Crumb)); + aux->ncrumb++; + c = crumb(aux, 0); + o = crumb(aux, 1); + memset(c, 0, sizeof(Crumb)); + c->mode = o->mode; + c->mtime = o->mtime; + c->obj = o->obj ? ref(o->obj) : nil; + + switch(QDIR(&fid->qid)){ + case Qroot: + if(strcmp(name, "HEAD") == 0){ + *q = (Qid){Qhead, 0, QTDIR}; + c->mode = DMDIR | 0555; + c->obj = readref(".git/HEAD"); + }else if(strcmp(name, "object") == 0){ + *q = (Qid){Qobject, 0, QTDIR}; + c->mode = DMDIR | 0555; + }else if(strcmp(name, "branch") == 0){ + *q = (Qid){Qbranch, 0, QTDIR}; + aux->refpath = estrdup(".git/refs/"); + c->mode = DMDIR | 0555; + }else if(strcmp(name, "ctl") == 0){ + *q = (Qid){Qctl, 0, 0}; + c->mode = 0644; + }else{ + e = Eexist; + } + break; + case Qbranch: + if(strcmp(aux->refpath, ".git/refs/heads") == 0 && strcmp(name, "HEAD") == 0) + snprint(path, sizeof(path), ".git/HEAD"); + else + snprint(path, sizeof(path), "%s/%s", aux->refpath, name); + q->type = QTDIR; + d = dirstat(path); + if(d && d->qid.type == QTDIR) + q->path = qpath(o, Qbranch, branchid(aux, path), Qbranch); + else if(d && (c->obj = readref(path)) != nil) + q->path = qpath(o, Qbranch, c->obj->id, Qcommit); + else + e = Eexist; + free(d); + break; + case Qobject: + if(c->obj){ + e = objwalk1(q, o->obj, o, c, name, Qobject, aux); + }else{ + if(hparse(&h, name) == -1) + return Eobject; + if((c->obj = readobject(h)) == nil) + return Eobject; + if(c->obj->type == GBlob || c->obj->type == GTag){ + c->mode = 0644; + q->type = 0; + }else{ + c->mode = DMDIR | 0755; + q->type = QTDIR; + } + q->path = qpath(o, Qobject, c->obj->id, Qobject); + q->vers = 0; + } + break; + case Qhead: + e = objwalk1(q, o->obj, o, c, name, Qhead, aux); + break; + case Qcommit: + e = objwalk1(q, o->obj, o, c, name, Qcommit, aux); + break; + case Qtree: + e = objwalk1(q, o->obj, o, c, name, Qtree, aux); + break; + case Qparent: + case Qmsg: + case Qcdata: + case Qhash: + case Qauthor: + case Qcommitter: + case Qctl: + return Enodir; + default: + return Egreg; + } + + c->name = estrdup(name); + c->qid = *q; + fid->qid = *q; + return e; +} + +static char* +gitclone(Fid *o, Fid *n) +{ + Gitaux *aux, *oaux; + int i; + + oaux = o->aux; + aux = emalloc(sizeof(Gitaux)); + aux->ncrumb = oaux->ncrumb; + aux->crumb = eamalloc(oaux->ncrumb, sizeof(Crumb)); + for(i = 0; i < aux->ncrumb; i++){ + aux->crumb[i] = oaux->crumb[i]; + aux->crumb[i].name = estrdup(oaux->crumb[i].name); + if(aux->crumb[i].obj) + aux->crumb[i].obj = ref(oaux->crumb[i].obj); + } + if(oaux->refpath) + aux->refpath = strdup(oaux->refpath); + aux->qdir = oaux->qdir; + n->aux = aux; + return nil; +} + +static void +gitdestroyfid(Fid *f) +{ + Gitaux *aux; + int i; + + if((aux = f->aux) == nil) + return; + for(i = 0; i < aux->ncrumb; i++){ + if(aux->crumb[i].obj) + unref(aux->crumb[i].obj); + free(aux->crumb[i].name); + } + olsfree(aux->ols); + free(aux->refpath); + free(aux->crumb); + free(aux); +} + +static char * +readctl(Req *r) +{ + char data[1024], ref[512], *s, *e; + int fd, n; + + if((fd = open(".git/HEAD", OREAD)) == -1) + return Erepo; + /* empty HEAD is invalid */ + if((n = readn(fd, ref, sizeof(ref) - 1)) <= 0) + return Erepo; + close(fd); + + s = ref; + ref[n] = 0; + if(strncmp(s, "ref:", 4) == 0) + s += 4; + while(*s == ' ' || *s == '\t') + s++; + if((e = strchr(s, '\n')) != nil) + *e = 0; + if(strstr(s, "refs/") == s) + s += strlen("refs/"); + + snprint(data, sizeof(data), "branch %s\nrepo %s\n", s, gitdir); + readstr(r, data); + return nil; +} + +static void +gitread(Req *r) +{ + char buf[256], *e; + Gitaux *aux; + Object *o; + Qid *q; + + aux = r->fid->aux; + q = &r->fid->qid; + o = crumb(aux, 0)->obj; + e = nil; + + switch(QDIR(q)){ + case Qroot: + dirread9p(r, rootgen, aux); + break; + case Qbranch: + if(o) + objread(r, aux); + else + dirread9p(r, branchgen, aux); + break; + case Qobject: + if(o) + objread(r, aux); + else + dirread9p(r, objgen, aux); + break; + case Qmsg: + readbuf(r, o->commit->msg, o->commit->nmsg); + break; + case Qparent: + readcommitparent(r, o); + break; + case Qhash: + snprint(buf, sizeof(buf), "%H\n", o->hash); + readstr(r, buf); + break; + case Qauthor: + snprint(buf, sizeof(buf), "%s\n", o->commit->author); + readstr(r, buf); + break; + case Qcommitter: + snprint(buf, sizeof(buf), "%s\n", o->commit->committer); + readstr(r, buf); + break; + case Qctl: + e = readctl(r); + break; + case Qhead: + /* Empty repositories have no HEAD */ + if(o == nil) + r->ofcall.count = 0; + else + objread(r, aux); + break; + case Qcommit: + case Qtree: + case Qcdata: + objread(r, aux); + break; + default: + e = Egreg; + } + respond(r, e); +} + +static void +gitopen(Req *r) +{ + Gitaux *aux; + Crumb *c; + + aux = r->fid->aux; + c = crumb(aux, 0); + switch(r->ifcall.mode&3){ + default: + respond(r, "botched mode"); + break; + case OWRITE: + respond(r, Eperm); + break; + case OREAD: + case ORDWR: + respond(r, nil); + break; + case OEXEC: + if((c->mode & 0111) == 0) + respond(r, Eperm); + else + respond(r, nil); + break; + } +} + +static void +gitstat(Req *r) +{ + Gitaux *aux; + Crumb *c; + + aux = r->fid->aux; + c = crumb(aux, 0); + r->d.uid = estrdup9p(username); + r->d.gid = estrdup9p(groupname); + r->d.muid = estrdup9p(username); + r->d.qid = r->fid->qid; + r->d.mtime = c->mtime; + r->d.atime = c->mtime; + r->d.mode = c->mode; + if(c->obj) + obj2dir(&r->d, c, c->obj, c->name); + else + r->d.name = estrdup9p(c->name); + respond(r, nil); +} + +Srv gitsrv = { + .attach=gitattach, + .walk1=gitwalk1, + .clone=gitclone, + .open=gitopen, + .read=gitread, + .stat=gitstat, + .destroyfid=gitdestroyfid, +}; + +void +usage(void) +{ + fprint(2, "usage: %s [-d]\n", argv0); + fprint(2, "\t-d: debug\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Dir *d; + + gitinit(); + ARGBEGIN{ + case 'd': + chatty9p++; + break; + case 'm': + mntpt = EARGF(usage()); + break; + default: + usage(); + break; + }ARGEND; + if(argc != 0) + usage(); + + if((d = dirstat(".git")) == nil) + sysfatal("dirstat .git: %r"); + username = strdup(d->uid); + groupname = strdup(d->gid); + free(d); + + branches = emalloc(sizeof(char*)); + branches[0] = nil; + postmountsrv(&gitsrv, nil, mntpt, MCREATE); + exits(nil); +} diff --git a/sys/src/cmd/git/get.c b/sys/src/cmd/git/get.c new file mode 100644 index 0000000000..95dfe106ed --- /dev/null +++ b/sys/src/cmd/git/get.c @@ -0,0 +1,372 @@ +#include +#include + +#include "git.h" + +char *fetchbranch; +char *upstream = "origin"; +int listonly; + +int +resolveremote(Hash *h, char *ref) +{ + char buf[128], *s; + int r, f; + + ref = strip(ref); + if((r = hparse(h, ref)) != -1) + return r; + /* Slightly special handling: translate remote refs to local ones. */ + if(strcmp(ref, "HEAD") == 0){ + snprint(buf, sizeof(buf), ".git/HEAD"); + }else if(strstr(ref, "refs/heads") == ref){ + ref += strlen("refs/heads"); + snprint(buf, sizeof(buf), ".git/refs/remotes/%s/%s", upstream, ref); + }else if(strstr(ref, "refs/tags") == ref){ + ref += strlen("refs/tags"); + snprint(buf, sizeof(buf), ".git/refs/tags/%s/%s", upstream, ref); + }else{ + return -1; + } + + r = -1; + s = strip(buf); + if((f = open(s, OREAD)) == -1) + return -1; + if(readn(f, buf, sizeof(buf)) >= 40) + r = hparse(h, buf); + close(f); + + if(r == -1 && strstr(buf, "ref:") == buf) + return resolveremote(h, buf + strlen("ref:")); + return r; +} + +int +rename(char *pack, char *idx, Hash h) +{ + char name[128]; + Dir st; + + nulldir(&st); + st.name = name; + snprint(name, sizeof(name), "%H.pack", h); + if(access(name, AEXIST) == 0) + fprint(2, "warning, pack %s already fetched\n", name); + else if(dirwstat(pack, &st) == -1) + return -1; + snprint(name, sizeof(name), "%H.idx", h); + if(access(name, AEXIST) == 0) + fprint(2, "warning, pack %s already indexed\n", name); + else if(dirwstat(idx, &st) == -1) + return -1; + return 0; +} + +int +checkhash(int fd, vlong sz, Hash *hcomp) +{ + DigestState *st; + Hash hexpect; + char buf[Pktmax]; + vlong n, r; + int nr; + + if(sz < 28){ + werrstr("undersize packfile"); + return -1; + } + + st = nil; + n = 0; + while(n != sz - 20){ + nr = sizeof(buf); + if(sz - n - 20 < sizeof(buf)) + nr = sz - n - 20; + r = readn(fd, buf, nr); + if(r != nr) + return -1; + st = sha1((uchar*)buf, nr, nil, st); + n += r; + } + sha1(nil, 0, hcomp->h, st); + if(readn(fd, hexpect.h, sizeof(hexpect.h)) != sizeof(hexpect.h)) + sysfatal("truncated packfile"); + if(!hasheq(hcomp, &hexpect)){ + werrstr("bad hash: %H != %H", *hcomp, hexpect); + return -1; + } + return 0; +} + +int +mkoutpath(char *path) +{ + char s[128]; + char *p; + int fd; + + snprint(s, sizeof(s), "%s", path); + for(p=strchr(s+1, '/'); p; p=strchr(p+1, '/')){ + *p = 0; + if(access(s, AEXIST) != 0){ + fd = create(s, OREAD, DMDIR | 0775); + if(fd == -1) + return -1; + close(fd); + } + *p = '/'; + } + return 0; +} + +int +branchmatch(char *br, char *pat) +{ + char name[128]; + + if(strstr(pat, "refs/heads") == pat) + snprint(name, sizeof(name), "%s", pat); + else if(strstr(pat, "heads")) + snprint(name, sizeof(name), "refs/%s", pat); + else + snprint(name, sizeof(name), "refs/heads/%s", pat); + return strcmp(br, name) == 0; +} + +char * +matchcap(char *s, char *cap, int full) +{ + if(strncmp(s, cap, strlen(cap)) == 0) + if(!full || strlen(s) == strlen(cap)) + return s + strlen(cap); + return nil; +} + +void +handlecaps(char *caps) +{ + char *p, *n, *c, *r; + + for(p = caps; p != nil; p = n){ + n = strchr(p, ' '); + if(n != nil) + *n++ = 0; + if((c = matchcap(p, "symref=", 0)) != nil){ + if((r = strchr(c, ':')) != nil){ + *r++ = '\0'; + print("symref %s %s\n", c, r); + } + } + } +} + +void +fail(char *pack, char *idx, char *msg, ...) +{ + char buf[ERRMAX]; + va_list ap; + + va_start(ap, msg); + snprint(buf, sizeof(buf), msg, ap); + va_end(ap); + + remove(pack); + remove(idx); + fprint(2, "%s", buf); + exits(buf); +} + +int +fetchpack(Conn *c) +{ + char buf[Pktmax], *sp[3], *ep; + char *packtmp, *idxtmp, **ref; + Hash h, *have, *want; + int nref, refsz, first; + int i, n, l, req, pfd; + vlong packsz; + Objset hadobj; + Object *o; + + nref = 0; + refsz = 16; + first = 1; + have = eamalloc(refsz, sizeof(have[0])); + want = eamalloc(refsz, sizeof(want[0])); + ref = eamalloc(refsz, sizeof(ref[0])); + while(1){ + n = readpkt(c, buf, sizeof(buf)); + if(n == -1) + return -1; + if(n == 0) + break; + if(strncmp(buf, "ERR ", 4) == 0) + sysfatal("%s", buf + 4); + + if(first && n > strlen(buf)) + handlecaps(buf + strlen(buf) + 1); + first = 0; + + getfields(buf, sp, nelem(sp), 1, " \t\n\r"); + if(strstr(sp[1], "^{}")) + continue; + if(fetchbranch && !branchmatch(sp[1], fetchbranch)) + continue; + if(refsz == nref + 1){ + refsz *= 2; + have = earealloc(have, refsz, sizeof(have[0])); + want = earealloc(want, refsz, sizeof(want[0])); + ref = earealloc(ref, refsz, sizeof(ref[0])); + } + if(hparse(&want[nref], sp[0]) == -1) + sysfatal("invalid hash %s", sp[0]); + if (resolveremote(&have[nref], sp[1]) == -1) + memset(&have[nref], 0, sizeof(have[nref])); + ref[nref] = estrdup(sp[1]); + nref++; + } + if(listonly){ + flushpkt(c); + goto showrefs; + } + + if(writephase(c) == -1) + sysfatal("write: %r"); + req = 0; + for(i = 0; i < nref; i++){ + if(hasheq(&have[i], &want[i])) + continue; + if((o = readobject(want[i])) != nil){ + unref(o); + continue; + } + n = snprint(buf, sizeof(buf), "want %H\n", want[i]); + if(writepkt(c, buf, n) == -1) + sysfatal("could not send want for %H", want[i]); + req = 1; + } + flushpkt(c); + osinit(&hadobj); + for(i = 0; i < nref; i++){ + if(hasheq(&have[i], &Zhash) || oshas(&hadobj, have[i])) + continue; + if((o = readobject(have[i])) == nil) + sysfatal("missing object we should have: %H", have[i]); + osadd(&hadobj, o); + unref(o); + n = snprint(buf, sizeof(buf), "have %H\n", have[i]); + if(writepkt(c, buf, n + 1) == -1) + sysfatal("could not send have for %H", have[i]); + } + osclear(&hadobj); + if(!req) + flushpkt(c); + + n = snprint(buf, sizeof(buf), "done\n"); + if(writepkt(c, buf, n) == -1) + sysfatal("write: %r"); + if(!req) + goto showrefs; + if(readphase(c) == -1) + sysfatal("read: %r"); + if((n = readpkt(c, buf, sizeof(buf))) == -1) + sysfatal("read: %r"); + buf[n] = 0; + + if((packtmp = smprint(".git/objects/pack/fetch.%d.pack", getpid())) == nil) + sysfatal("smprint: %r"); + if((idxtmp = smprint(".git/objects/pack/fetch.%d.idx", getpid())) == nil) + sysfatal("smprint: %r"); + if(mkoutpath(packtmp) == -1) + sysfatal("could not create %s: %r", packtmp); + if((pfd = create(packtmp, ORDWR, 0664)) == -1) + sysfatal("could not create %s: %r", packtmp); + + fprint(2, "fetching...\n"); + /* + * Work around torvalds git bug: we get duplicate have lines + * somtimes, even though the protocol is supposed to start the + * pack file immediately. + * + * Skip ahead until we read 'PACK' off the wire + */ + while(1){ + if(readn(c->rfd, buf, 4) != 4) + sysfatal("fetch packfile: short read"); + buf[4] = 0; + if(strncmp(buf, "PACK", 4) == 0) + break; + l = strtol(buf, &ep, 16); + if(l == 0 || ep != buf + 4) + sysfatal("fetch packfile: junk pktline"); + if(readn(c->rfd, buf, l) != l) + sysfatal("fetch packfile: short read"); + } + if(write(pfd, "PACK", 4) != 4) + sysfatal("write pack header: %r"); + packsz = 4; + while(1){ + n = read(c->rfd, buf, sizeof buf); + if(n == 0) + break; + if(n == -1 || write(pfd, buf, n) != n) + sysfatal("fetch packfile: %r"); + packsz += n; + } + + closeconn(c); + if(seek(pfd, 0, 0) == -1) + fail(packtmp, idxtmp, "packfile seek: %r"); + if(checkhash(pfd, packsz, &h) == -1) + fail(packtmp, idxtmp, "corrupt packfile: %r"); + close(pfd); + if(indexpack(packtmp, idxtmp, h) == -1) + fail(packtmp, idxtmp, "could not index fetched pack: %r"); + if(rename(packtmp, idxtmp, h) == -1) + fail(packtmp, idxtmp, "could not rename indexed pack: %r"); + +showrefs: + for(i = 0; i < nref; i++){ + print("remote %s %H local %H\n", ref[i], want[i], have[i]); + free(ref[i]); + } + free(ref); + free(want); + free(have); + return 0; +} + +void +usage(void) +{ + fprint(2, "usage: %s [-dl] [-b br] [-u upstream] remote\n", argv0); + fprint(2, "\t-b br: only fetch matching branch 'br'\n"); + fprint(2, "remote: fetch from this repository\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Conn c; + + ARGBEGIN{ + case 'b': fetchbranch=EARGF(usage()); break; + case 'u': upstream=EARGF(usage()); break; + case 'd': chattygit++; break; + case 'l': listonly++; break; + default: usage(); break; + }ARGEND; + + gitinit(); + if(argc != 1) + usage(); + + if(gitconnect(&c, argv[0], "upload") == -1) + sysfatal("could not dial %s: %r", argv[0]); + if(fetchpack(&c) == -1) + sysfatal("fetch failed: %r"); + closeconn(&c); + exits(nil); +} diff --git a/sys/src/cmd/git/git.h b/sys/src/cmd/git/git.h new file mode 100644 index 0000000000..4e74333c50 --- /dev/null +++ b/sys/src/cmd/git/git.h @@ -0,0 +1,326 @@ +#include +#include +#include +#include +#include + +typedef struct Capset Capset; +typedef struct Conn Conn; +typedef struct Hash Hash; +typedef struct Delta Delta; +typedef struct Cinfo Cinfo; +typedef struct Tinfo Tinfo; +typedef struct Object Object; +typedef struct Objset Objset; +typedef struct Pack Pack; +typedef struct Buf Buf; +typedef struct Dirent Dirent; +typedef struct Idxent Idxent; +typedef struct Objlist Objlist; +typedef struct Dtab Dtab; +typedef struct Dblock Dblock; +typedef struct Objq Objq; +typedef struct Qelt Qelt; + +enum { + Pathmax = 512, + Npackcache = 32, + Hashsz = 20, + Pktmax = 65536, + KiB = 1024, + MiB = 1024*KiB, +}; + +enum { + GNone = 0, + GCommit = 1, + GTree = 2, + GBlob = 3, + GTag = 4, + GOdelta = 6, + GRdelta = 7, +}; + +enum { + Cloaded = 1 << 0, + Cidx = 1 << 1, + Ccache = 1 << 2, + Cexist = 1 << 3, + Cparsed = 1 << 5, + Cthin = 1 << 6, +}; + +enum { + ConnGit, + ConnGit9, + ConnSsh, + ConnHttp, +}; + +struct Objlist { + int idx; + + int fd; + int state; + int stage; + + Dir *top; + int ntop; + int topidx; + Dir *loose; + int nloose; + int looseidx; + Dir *pack; + int npack; + int packidx; + int nent; + int entidx; +}; + +struct Hash { + uchar h[20]; +}; + +struct Conn { + int type; + int rfd; + int wfd; + + /* only used by http */ + int cfd; + char *url; /* note, first GET uses a different url */ + char *dir; + char *direction; +}; + +struct Dirent { + char *name; + int mode; + Hash h; + char ismod; + char islink; +}; + +struct Object { + /* Git data */ + Hash hash; + int type; + + /* Cache */ + int id; + int flag; + int refs; + Object *next; + Object *prev; + + /* For indexing */ + vlong off; + vlong len; + u32int crc; + + /* Everything below here gets cleared */ + char *all; + char *data; + /* size excludes header */ + vlong size; + + /* Significant win on memory use */ + union { + Cinfo *commit; + Tinfo *tree; + }; +}; + +struct Tinfo { + /* Tree */ + Dirent *ent; + int nent; +}; + +struct Cinfo { + /* Commit */ + Hash *parent; + int nparent; + Hash tree; + char *author; + char *committer; + char *msg; + int nmsg; + vlong ctime; + vlong mtime; +}; + +struct Objset { + Object **obj; + int nobj; + int sz; +}; + +struct Qelt { + Object *o; + vlong ctime; + int color; +}; + +struct Objq { + Qelt *heap; + int nheap; + int heapsz; +}; + +struct Dtab { + Object *o; + uchar *base; + int nbase; + Dblock *b; + int nb; + int sz; +}; + +struct Dblock { + uchar *buf; + int len; + int off; + u64int hash; +}; + +struct Delta { + int cpy; + int off; + int len; +}; + + +#define GETBE16(b)\ + ((((b)[0] & 0xFFul) << 8) | \ + (((b)[1] & 0xFFul) << 0)) + +#define GETBE32(b)\ + ((((b)[0] & 0xFFul) << 24) | \ + (((b)[1] & 0xFFul) << 16) | \ + (((b)[2] & 0xFFul) << 8) | \ + (((b)[3] & 0xFFul) << 0)) +#define GETBE64(b)\ + ((((b)[0] & 0xFFull) << 56) | \ + (((b)[1] & 0xFFull) << 48) | \ + (((b)[2] & 0xFFull) << 40) | \ + (((b)[3] & 0xFFull) << 32) | \ + (((b)[4] & 0xFFull) << 24) | \ + (((b)[5] & 0xFFull) << 16) | \ + (((b)[6] & 0xFFull) << 8) | \ + (((b)[7] & 0xFFull) << 0)) + +#define PUTBE16(b, n)\ + do{ \ + (b)[0] = (n) >> 8; \ + (b)[1] = (n) >> 0; \ + } while(0) + +#define PUTBE32(b, n)\ + do{ \ + (b)[0] = (n) >> 24; \ + (b)[1] = (n) >> 16; \ + (b)[2] = (n) >> 8; \ + (b)[3] = (n) >> 0; \ + } while(0) + +#define PUTBE64(b, n)\ + do{ \ + (b)[0] = (n) >> 56; \ + (b)[1] = (n) >> 48; \ + (b)[2] = (n) >> 40; \ + (b)[3] = (n) >> 32; \ + (b)[4] = (n) >> 24; \ + (b)[5] = (n) >> 16; \ + (b)[6] = (n) >> 8; \ + (b)[7] = (n) >> 0; \ + } while(0) + +#define QDIR(qid) ((int)(qid)->path & (0xff)) +#define isblank(c) \ + (((c) != '\n') && isspace(c)) + +extern Reprog *authorpat; +extern Objset objcache; +extern vlong cachemax; +extern Hash Zhash; +extern int chattygit; +extern int interactive; + +#pragma varargck type "H" Hash +#pragma varargck type "T" int +#pragma varargck type "O" Object* +#pragma varargck type "Q" Qid +int Hfmt(Fmt*); +int Tfmt(Fmt*); +int Ofmt(Fmt*); +int Qfmt(Fmt*); + +void gitinit(void); + +/* object io */ +int resolverefs(Hash **, char *); +int resolveref(Hash *, char *); +int listrefs(Hash **, char ***); +Object *ancestor(Object *, Object *); +int findtwixt(Hash *, int, Hash *, int, Object ***, int *); +Object *readobject(Hash); +Object *clearedobject(Hash, int); +void parseobject(Object *); +int indexpack(char *, char *, Hash); +int writepack(int, Hash*, int, Hash*, int, Hash*); +int hasheq(Hash *, Hash *); +Object *ref(Object *); +void unref(Object *); +void cache(Object *); +Object *emptydir(void); + +/* object sets */ +void osinit(Objset *); +void osclear(Objset *); +void osadd(Objset *, Object *); +int oshas(Objset *, Hash); +Object *osfind(Objset *, Hash); + +/* object listing */ +Objlist *mkols(void); +int olsnext(Objlist *, Hash *); +void olsfree(Objlist *); + +/* util functions */ +#define dprint(lvl, ...) \ + if(chattygit >= lvl) _dprint(__VA_ARGS__) +void _dprint(char *, ...); +void *eamalloc(ulong, ulong); +void *emalloc(ulong); +void *earealloc(void *, ulong, ulong); +void *erealloc(void *, ulong); +char *estrdup(char *); +int slurpdir(char *, Dir **); +int hparse(Hash *, char *); +int hassuffix(char *, char *); +int swapsuffix(char *, int, char *, char *, char *); +char *strip(char *); +int findrepo(char *, int); +int showprogress(int, int); + +/* packing */ +void dtinit(Dtab *, Object*); +void dtclear(Dtab*); +Delta* deltify(Object*, Dtab*, int*); + +/* proto handling */ +int readpkt(Conn*, char*, int); +int writepkt(Conn*, char*, int); +int flushpkt(Conn*); +void initconn(Conn*, int, int); +int gitconnect(Conn *, char *, char *); +int readphase(Conn *); +int writephase(Conn *); +void closeconn(Conn *); + +/* queues */ +void qinit(Objq*); +void qclear(Objq*); +void qput(Objq*, Object*, int); +int qpop(Objq*, Qelt*); diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import new file mode 100755 index 0000000000..7ba7d0e48a --- /dev/null +++ b/sys/src/cmd/git/import @@ -0,0 +1,116 @@ +#!/bin/rc +rfork ne +. /sys/lib/git/common.rc + +diffpath=/tmp/gitimport.$pid.diff +fn sigexit { + rm -f $diffpath +} + + +fn apply @{ + git/fs + amail='' + aname='' + msg='' + whoami + parents='-p'^`{git/query HEAD} + branch=`{git/branch} + if(test -e $gitfs/branch/$branch/tree) + refpath=.git/refs/$branch + if not if(test -e $gitfs/object/$branch/tree) + refpath=.git/HEAD + if not + die 'invalid branch:' $branch + awk ' + BEGIN{ + state="headers" + } + state=="headers" && /^From:/ { + sub(/^From:[ \t]*/, "", $0); + aname=$0; + amail=$0; + sub(/[ \t]*<.*$/, "", aname); + sub(/^[^<]*[^>]*$/, "", amail); + } + state=="headers" && /^Date:/{ + sub(/^Date:[ \t]*/, "", $0) + date=$0 + } + state=="headers" && /^Subject:/{ + sub(/^Subject:[ \t]*(\[[^\]]*\][ \t]*)*/, "", $0); + gotmsg = 1 + print > "/env/msg" + } + state=="headers" && /^$/ { + state="body" + } + (state=="headers" || state=="body") && (/^diff / || /^---( |$)/){ + state="diff" + } + state=="body" && /^[ ]*$/ { + empty=1 + next + } + state=="body" { + if(empty) + printf "\n" > "/env/msg" + empty=0 + sub(/[ ]+$/, "") + print > "/env/msg" + } + state=="diff" { + print > ENVIRON["diffpath"] + } + END{ + if(state != "diff") + exit("malformed patch: " state); + if(aname == "" || amail == "" || date == "" || gotmsg == "") + exit("missing headers"); + printf "%s", aname > "/env/aname" + printf "%s", amail > "/env/amail" + printf "%s", date > "/env/date" + } + ' || die 'could not import:' $status + + # force re-reading env + rc -c ' + echo applying $msg | sed 1q + date=`{seconds $date} + if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep ''^patching file'' | sed ''s/^patching file `(.*)''''/\1/''}) + die ''patch failed'' + for(f in $files){ + if(test -e $f) + git/add $f + if not + git/add -r $f + } + git/walk -fRMA $files + if(~ $#nocommit 0){ + if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $date $parents $files}) + echo $hash > $refpath + } + status='''' + ' +} + +gitup + +flagfmt='n:nocommit'; args='file ...' +eval `''{aux/getflags $*} || exec aux/usage + +patches=(/fd/0) +if(! ~ $#* 0) + patches=$* +for(p in $patches){ + # upas serves the decoded header and body separately, + # so we cat them together when applying a upas message. + # + # this allows mime-encoded or line-wrapped patches. + if(test -d $p && test -f $p/header && test -f $p/body) + {{cat $p/header; echo; cat $p/body} | apply} || die $status + if not + apply < $p || die $status +} +exit '' diff --git a/sys/src/cmd/git/init b/sys/src/cmd/git/init new file mode 100755 index 0000000000..50fa0270a4 --- /dev/null +++ b/sys/src/cmd/git/init @@ -0,0 +1,39 @@ +#!/bin/rc -e +rfork ne +. /sys/lib/git/common.rc + +flagfmt='u:upstream upstream,b:branch branch'; args='name' +eval `''{aux/getflags $*} || exec aux/usage + +dir=$1 +if(~ $#dir 0) + dir=. +if(~ $#branch 0) + branch=front +if(test -e $dir/.git) + die $dir/.git already exists +name=`{basename `{cleanname -d `{pwd} $dir}} +if(~ $#upstream 0){ + upstream=`{git/conf 'defaults "origin".baseurl'} + if(! ~ $#upstream 0) + upstream=$upstream/$name +} + +mkdir -p $dir/.git/refs/^(heads remotes) +mkdir -p $dir/.git/^(fs objects) +>$dir/.git/config { + echo '[core]' + echo ' repositoryformatversion = p9.0' + if(! ~ $#upstream 0){ + echo '[remote "origin"]' + echo ' url = '$upstream + } + echo '[branch "'$branch'"]' + echo ' remote = origin' +} + +>$dir/.git/HEAD { + echo ref: refs/heads/$branch +} + +exit '' diff --git a/sys/src/cmd/git/log.c b/sys/src/cmd/git/log.c new file mode 100644 index 0000000000..f6d5f4a4e9 --- /dev/null +++ b/sys/src/cmd/git/log.c @@ -0,0 +1,282 @@ +#include +#include +#include "git.h" + +typedef struct Pfilt Pfilt; +struct Pfilt { + char *elt; + int show; + Pfilt *sub; + int nsub; +}; + +Biobuf *out; +char *queryexpr; +char *commitid; +int shortlog; + +Objset done; +Objq objq; +Pfilt *pathfilt; + +void +filteradd(Pfilt *pf, char *path) +{ + char *p, *e; + int i; + + if((e = strchr(path, '/')) != nil) + p = smprint("%.*s", (int)(e - path), path); + else + p = strdup(path); + + while(e != nil && *e == '/') + e++; + for(i = 0; i < pf->nsub; i++){ + if(strcmp(pf->sub[i].elt, p) == 0){ + pf->sub[i].show = pf->sub[i].show || (e == nil); + if(e != nil) + filteradd(&pf->sub[i], e); + free(p); + return; + } + } + pf->sub = earealloc(pf->sub, pf->nsub+1, sizeof(Pfilt)); + pf->sub[pf->nsub].elt = p; + pf->sub[pf->nsub].show = (e == nil); + pf->sub[pf->nsub].nsub = 0; + pf->sub[pf->nsub].sub = nil; + if(e != nil) + filteradd(&pf->sub[pf->nsub], e); + pf->nsub++; +} + +Hash +lookup(Pfilt *pf, Object *o) +{ + int i; + + for(i = 0; i < o->tree->nent; i++) + if(strcmp(o->tree->ent[i].name, pf->elt) == 0) + return o->tree->ent[i].h; + return Zhash; +} + +int +filtermatch1(Pfilt *pf, Object *t, Object *pt) +{ + Object *a, *b; + Hash ha, hb; + int i, r; + + if(pf->show) + return 1; + if(t->type != pt->type) + return 1; + if(t->type != GTree) + return 0; + + for(i = 0; i < pf->nsub; i++){ + ha = lookup(&pf->sub[i], t); + hb = lookup(&pf->sub[i], pt); + if(hasheq(&ha, &hb)) + continue; + if(hasheq(&ha, &Zhash) || hasheq(&hb, &Zhash)) + return 1; + if((a = readobject(ha)) == nil) + sysfatal("read %H: %r", ha); + if((b = readobject(hb)) == nil) + sysfatal("read %H: %r", hb); + r = filtermatch1(&pf->sub[i], a, b); + unref(a); + unref(b); + if(r) + return 1; + } + return 0; +} + +int +filtermatch(Object *o) +{ + Object *t, *p, *pt; + int i, r; + + if(pathfilt == nil) + return 1; + if((t = readobject(o->commit->tree)) == nil) + sysfatal("read %H: %r", o->commit->tree); + for(i = 0; i < o->commit->nparent; i++){ + if((p = readobject(o->commit->parent[i])) == nil) + sysfatal("read %H: %r", o->commit->parent[i]); + if((pt = readobject(p->commit->tree)) == nil) + sysfatal("read %H: %r", o->commit->tree); + r = filtermatch1(pathfilt, t, pt); + unref(p); + unref(pt); + if(r) + return 1; + } + return o->commit->nparent == 0; +} + + +static char* +nextline(char *p, char *e) +{ + for(; p != e; p++) + if(*p == '\n') + break; + return p; +} + +static void +show(Object *o) +{ + Tm tm; + char *p, *q, *e; + + assert(o->type == GCommit); + if(!filtermatch(o)) + return; + + if(shortlog){ + p = o->commit->msg; + e = p + o->commit->nmsg; + q = nextline(p, e); + Bprint(out, "%H ", o->hash); + Bwrite(out, p, q - p); + Bputc(out, '\n'); + }else{ + Bprint(out, "Hash:\t%H\n", o->hash); + Bprint(out, "Author:\t%s\n", o->commit->author); + if(o->commit->committer != nil + && strcmp(o->commit->author, o->commit->committer) != 0) + Bprint(out, "Committer:\t%s\n", o->commit->committer); + Bprint(out, "Date:\t%s\n", ctime(o->commit->mtime)); + Bprint(out, "\n"); + p = o->commit->msg; + e = p + o->commit->nmsg; + for(; p != e; p = q){ + q = nextline(p, e); + Bputc(out, '\t'); + Bwrite(out, p, q - p); + Bputc(out, '\n'); + if(q != e) + q++; + } + Bprint(out, "\n"); + } + Bflush(out); +} + +static void +showquery(char *q) +{ + Object *o; + Hash *h; + int n, i; + + if((n = resolverefs(&h, q)) == -1) + sysfatal("resolve: %r"); + for(i = 0; i < n; i++){ + if((o = readobject(h[i])) == nil) + sysfatal("read %H: %r", h[i]); + show(o); + unref(o); + } + exits(nil); +} + +static void +showcommits(char *c) +{ + Object *o, *p; + Qelt e; + int i; + Hash h; + + if(c == nil) + c = "HEAD"; + if(resolveref(&h, c) == -1) + sysfatal("resolve %s: %r", c); + if((o = readobject(h)) == nil) + sysfatal("load %H: %r", h); + qinit(&objq); + osinit(&done); + qput(&objq, o, 0); + while(qpop(&objq, &e)){ + show(e.o); + for(i = 0; i < e.o->commit->nparent; i++){ + if(oshas(&done, e.o->commit->parent[i])) + continue; + if((p = readobject(e.o->commit->parent[i])) == nil) + sysfatal("load %H: %r", o->commit->parent[i]); + osadd(&done, p); + qput(&objq, p, 0); + } + unref(e.o); + } +} + +static void +usage(void) +{ + fprint(2, "usage: %s [-s] [-e expr | -c commit] files..\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char path[1024], repo[1024], *p, *r; + int i, nrepo; + + ARGBEGIN{ + case 'e': + queryexpr = EARGF(usage()); + break; + case 'c': + commitid = EARGF(usage()); + break; + case 's': + shortlog++; + break; + default: + usage(); + break; + }ARGEND; + + if(findrepo(repo, sizeof(repo)) == -1) + sysfatal("find root: %r"); + nrepo = strlen(repo); + if(argc != 0){ + if(getwd(path, sizeof(path)) == nil) + sysfatal("getwd: %r"); + if(strncmp(path, repo, nrepo) != 0) + sysfatal("path shifted??"); + p = path + nrepo; + pathfilt = emalloc(sizeof(Pfilt)); + for(i = 0; i < argc; i++){ + if(*argv[i] == '/'){ + if(strncmp(argv[i], repo, nrepo) != 0) + continue; + r = smprint("./%s", argv[i]+nrepo); + }else + r = smprint("./%s/%s", p, argv[i]); + cleanname(r); + filteradd(pathfilt, r); + free(r); + } + } + if(chdir(repo) == -1) + sysfatal("chdir: %r"); + + gitinit(); + out = Bfdopen(1, OWRITE); + if(queryexpr != nil) + showquery(queryexpr); + else + showcommits(commitid); + exits(nil); +} diff --git a/sys/src/cmd/git/merge b/sys/src/cmd/git/merge new file mode 100755 index 0000000000..051e224834 --- /dev/null +++ b/sys/src/cmd/git/merge @@ -0,0 +1,46 @@ +#!/bin/rc -e +rfork ne +. /sys/lib/git/common.rc + +fn merge{ + ourbr=$gitfs/object/$1/tree + basebr=$gitfs/object/$2/tree + theirbr=$gitfs/object/$3/tree + + all=`$nl{{git/query -c $1 $2; git/query -c $2 $3} | sed 's/^..//' | sort | uniq} + for(f in $all){ + ours=$ourbr/$f + base=$basebr/$f + theirs=$theirbr/$f + merge1 ./$f $ours $base $theirs + } +} + +gitup + +flagfmt=''; args='theirs' +eval `''{aux/getflags $*} || exec aux/usage + +if(! ~ $#* 1) + exec aux/usage + +theirs=`{git/query $1} +ours=`{git/query HEAD} +base=`{git/query $theirs ^ ' ' ^ $ours ^ '@'} + +if(~ $base $theirs) + die 'nothing to merge, doofus' +if(! git/walk -q) + die 'dirty work tree, refusing to merge' +if(~ $base $ours){ + >[1=2] echo 'fast forwarding...' + echo $theirs > .git/refs/`{git/branch} + git/revert . + exit '' +} +echo $ours >> .git/index9/merge-parents +echo $theirs >> .git/index9/merge-parents + +merge $ours $base $theirs +>[1=2] echo 'merge complete: remember to commit' +exit '' diff --git a/sys/src/cmd/git/mkfile b/sys/src/cmd/git/mkfile new file mode 100644 index 0000000000..e8df434ff3 --- /dev/null +++ b/sys/src/cmd/git/mkfile @@ -0,0 +1,57 @@ + +#include + +#include "git.h" + +void +osinit(Objset *s) +{ + s->sz = 16; + s->nobj = 0; + s->obj = eamalloc(s->sz, sizeof(Hash)); +} + +void +osclear(Objset *s) +{ + free(s->obj); +} + +void +osadd(Objset *s, Object *o) +{ + u32int probe; + Object **obj; + int i, sz; + + probe = GETBE32(o->hash.h) % s->sz; + while(s->obj[probe]){ + if(hasheq(&s->obj[probe]->hash, &o->hash)){ + s->obj[probe] = o; + return; + } + probe = (probe + 1) % s->sz; + } + assert(s->obj[probe] == nil); + s->obj[probe] = o; + s->nobj++; + if(s->sz < 2*s->nobj){ + sz = s->sz; + obj = s->obj; + + s->sz *= 2; + s->nobj = 0; + s->obj = eamalloc(s->sz, sizeof(Hash)); + for(i = 0; i < sz; i++) + if(obj[i]) + osadd(s, obj[i]); + free(obj); + } +} + +Object* +osfind(Objset *s, Hash h) +{ + u32int probe; + + for(probe = GETBE32(h.h) % s->sz; s->obj[probe]; probe = (probe + 1) % s->sz) + if(hasheq(&s->obj[probe]->hash, &h)) + return s->obj[probe]; + return 0; +} + +int +oshas(Objset *s, Hash h) +{ + return osfind(s, h) != nil; +} diff --git a/sys/src/cmd/git/ols.c b/sys/src/cmd/git/ols.c new file mode 100644 index 0000000000..3b77d3741d --- /dev/null +++ b/sys/src/cmd/git/ols.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include "git.h" + +enum { + Sinit, + Siter, +}; + +static int +crackidx(char *path, int *np) +{ + int fd; + char buf[4]; + + if((fd = open(path, OREAD)) == -1) + return -1; + if(seek(fd, 8 + 255*4, 0) == -1) + return -1; + if(readn(fd, buf, sizeof(buf)) != sizeof(buf)) + return -1; + *np = GETBE32(buf); + return fd; +} + +int +isloosedir(char *s) +{ + return strlen(s) == 2 && isxdigit(s[0]) && isxdigit(s[1]); +} + +int +endswith(char *n, char *s) +{ + int nn, ns; + + nn = strlen(n); + ns = strlen(s); + return nn > ns && strcmp(n + nn - ns, s) == 0; +} + +int +olsreadpacked(Objlist *ols, Hash *h) +{ + char *p; + int i, j; + + i = ols->packidx; + j = ols->entidx; + + if(ols->state == Siter) + goto step; + for(i = 0; i < ols->npack; i++){ + if(!endswith(ols->pack[i].name, ".idx")) + continue; + if((p = smprint(".git/objects/pack/%s", ols->pack[i].name)) == nil) + sysfatal("smprint: %r"); + ols->fd = crackidx(p, &ols->nent); + free(p); + if(ols->fd == -1) + continue; + j = 0; + while(j < ols->nent){ + if(readn(ols->fd, h->h, sizeof(h->h)) != sizeof(h->h)) + continue; + ols->state = Siter; + ols->packidx = i; + ols->entidx = j; + return 0; +step: + j++; + } + close(ols->fd); + } + ols->state = Sinit; + return -1; +} + + +int +olsreadloose(Objlist *ols, Hash *h) +{ + char buf[64], *p; + int i, j, n; + + i = ols->topidx; + j = ols->looseidx; + if(ols->state == Siter) + goto step; + for(i = 0; i < ols->ntop; i++){ + if(!isloosedir(ols->top[i].name)) + continue; + if((p = smprint(".git/objects/%s", ols->top[i].name)) == nil) + sysfatal("smprint: %r"); + ols->fd = open(p, OREAD); + free(p); + if(ols->fd == -1) + continue; + while((ols->nloose = dirread(ols->fd, &ols->loose)) > 0){ + j = 0; + while(j < ols->nloose){ + n = snprint(buf, sizeof(buf), "%s%s", ols->top[i].name, ols->loose[j].name); + if(n >= sizeof(buf)) + goto step; + if(hparse(h, buf) == -1) + goto step; + ols->state = Siter; + ols->topidx = i; + ols->looseidx = j; + return 0; +step: + j++; + } + free(ols->loose); + ols->loose = nil; + } + close(ols->fd); + ols->fd = -1; + } + ols->state = Sinit; + return -1; +} + +Objlist* +mkols(void) +{ + Objlist *ols; + + ols = emalloc(sizeof(Objlist)); + if((ols->ntop = slurpdir(".git/objects", &ols->top)) == -1) + sysfatal("read top level: %r"); + if((ols->npack = slurpdir(".git/objects/pack", &ols->pack)) == -1) + ols->pack = nil; + ols->fd = -1; + return ols; +} + +void +olsfree(Objlist *ols) +{ + if(ols == nil) + return; + if(ols->fd != -1) + close(ols->fd); + free(ols->top); + free(ols->loose); + free(ols->pack); + free(ols); +} + +int +olsnext(Objlist *ols, Hash *h) +{ + if(ols->stage == 0){ + if(olsreadloose(ols, h) != -1){ + ols->idx++; + return 0; + } + ols->stage++; + } + if(ols->stage == 1){ + if(olsreadpacked(ols, h) != -1){ + ols->idx++; + return 0; + } + ols->stage++; + } + return -1; +} diff --git a/sys/src/cmd/git/pack.c b/sys/src/cmd/git/pack.c new file mode 100644 index 0000000000..34431730f4 --- /dev/null +++ b/sys/src/cmd/git/pack.c @@ -0,0 +1,1757 @@ +#include +#include +#include + +#include "git.h" + +typedef struct Buf Buf; +typedef struct Metavec Metavec; +typedef struct Meta Meta; +typedef struct Compout Compout; +typedef struct Packf Packf; + +#define max(x, y) ((x) > (y) ? (x) : (y)) + +struct Metavec { + Meta **meta; + int nmeta; + int metasz; +}; + +struct Meta { + Object *obj; + char *path; + vlong mtime; + + /* The best delta we picked */ + Meta *head; + Meta *prev; + Delta *delta; + int ndelta; + int nchain; + + /* Only used for delta window */ + Dtab dtab; + + /* Only used for writing offset deltas */ + vlong off; +}; + +struct Compout { + Biobuf *bfd; + DigestState *st; +}; + +struct Buf { + int len; + int sz; + int off; + char *data; +}; + +struct Packf { + char path[128]; + char *idx; + vlong nidx; + + int refs; + Biobuf *pack; + vlong opentm; +}; + +static int readpacked(Biobuf *, Object *, int); +static Object *readidxobject(Biobuf *, Hash, int); + +Objset objcache; +Object *lruhead; +Object *lrutail; +vlong ncache; +vlong cachemax = 512*MiB; +Packf *packf; +int npackf; +int openpacks; +int gitdirmode = -1; + +static void +clear(Object *o) +{ + if(!o) + return; + + assert(o->refs == 0); + assert((o->flag & Ccache) == 0); + assert(o->flag & Cloaded); + switch(o->type){ + case GCommit: + if(!o->commit) + break; + free(o->commit->parent); + free(o->commit->author); + free(o->commit->committer); + free(o->commit); + o->commit = nil; + break; + case GTree: + if(!o->tree) + break; + free(o->tree->ent); + free(o->tree); + o->tree = nil; + break; + default: + break; + } + + free(o->all); + o->all = nil; + o->data = nil; + o->flag &= ~(Cloaded|Cparsed); +} + +void +unref(Object *o) +{ + if(!o) + return; + o->refs--; + if(o->refs == 0) + clear(o); +} + +Object* +ref(Object *o) +{ + o->refs++; + return o; +} + +void +cache(Object *o) +{ + Object *p; + + if(o == lruhead) + return; + if(o == lrutail) + lrutail = lrutail->prev; + if(!(o->flag & Cexist)){ + osadd(&objcache, o); + o->id = objcache.nobj; + o->flag |= Cexist; + } + if(o->prev != nil) + o->prev->next = o->next; + if(o->next != nil) + o->next->prev = o->prev; + if(lrutail == o){ + lrutail = o->prev; + if(lrutail != nil) + lrutail->next = nil; + }else if(lrutail == nil) + lrutail = o; + if(lruhead) + lruhead->prev = o; + o->next = lruhead; + o->prev = nil; + lruhead = o; + + if(!(o->flag & Ccache)){ + o->flag |= Ccache; + ref(o); + ncache += o->size; + } + while(ncache > cachemax && lrutail != nil){ + p = lrutail; + lrutail = p->prev; + if(lrutail != nil) + lrutail->next = nil; + p->flag &= ~Ccache; + p->prev = nil; + p->next = nil; + ncache -= p->size; + unref(p); + } +} + +static int +loadpack(Packf *pf, char *name) +{ + char buf[128]; + int i, ifd; + Dir *d; + + memset(pf, 0, sizeof(Packf)); + snprint(buf, sizeof(buf), ".git/objects/pack/%s.idx", name); + snprint(pf->path, sizeof(pf->path), ".git/objects/pack/%s.pack", name); + /* + * if we already have the pack open, just + * steal the loaded info + */ + for(i = 0; i < npackf; i++){ + if(strcmp(pf->path, packf[i].path) == 0){ + pf->pack = packf[i].pack; + pf->idx = packf[i].idx; + pf->nidx = packf[i].nidx; + packf[i].idx = nil; + packf[i].pack = nil; + return 0; + } + } + if((ifd = open(buf, OREAD)) == -1) + return -1; + if((d = dirfstat(ifd)) == nil){ + close(ifd); + return -1; + } + pf->nidx = d->length; + pf->idx = emalloc(pf->nidx); + if(readn(ifd, pf->idx, pf->nidx) != pf->nidx){ + close(ifd); + free(pf->idx); + free(d); + return -1; + } + close(ifd); + free(d); + return 0; +} + +static void +refreshpacks(void) +{ + Packf *pf, *new; + int i, n, l, nnew; + Dir *d; + + if((n = slurpdir(".git/objects/pack", &d)) == -1) + return; + nnew = 0; + new = eamalloc(n, sizeof(Packf)); + for(i = 0; i < n; i++){ + l = strlen(d[i].name); + if(l > 4 && strcmp(d[i].name + l - 4, ".idx") != 0) + continue; + d[i].name[l - 4] = 0; + if(loadpack(&new[nnew], d[i].name) != -1) + nnew++; + } + for(i = 0; i < npackf; i++){ + pf = &packf[i]; + free(pf->idx); + if(pf->pack != nil) + Bterm(pf->pack); + } + free(packf); + packf = new; + npackf = nnew; + free(d); +} + +static Biobuf* +openpack(Packf *pf) +{ + vlong t; + int i, best; + + if(pf->pack != nil){ + pf->refs++; + return pf->pack; + } + /* + * If we've got more packs open + * than we want cached, try to + * free up the oldest ones. + * + * If we can't find a slot, this + * isn't fatal; we can just use + * another fd. + */ + while(openpacks >= Npackcache){ + t = (1ull<<62)-1; + best = -1; + for(i = 0; i < npackf; i++){ + if(&packf[i] != pf + && packf[i].pack != nil + && packf[i].opentm < t + && packf[i].refs == 0){ + t = packf[i].opentm; + best = i; + } + } + if(best == -1){ + fprint(2, "no available pack slots\n"); + break; + } + Bterm(packf[best].pack); + packf[best].pack = nil; + openpacks--; + } + openpacks++; + pf->opentm = nsec(); + pf->refs++; + if((pf->pack = Bopen(pf->path, OREAD)) == nil) + return nil; + return pf->pack; +} + +static void +closepack(Packf *pf) +{ + pf->refs--; +} + +static u32int +crc32(u32int crc, char *b, int nb) +{ + static u32int crctab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, + 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, + 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, + 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, + 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, + 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, + 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, + 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, + 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, + 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, + 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, + 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, + 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, + 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, + 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, + 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, + 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, + 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, + 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, + 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }; + int i; + + crc ^= 0xFFFFFFFF; + for(i = 0; i < nb; i++) + crc = (crc >> 8) ^ crctab[(crc ^ b[i]) & 0xFF]; + return crc ^ 0xFFFFFFFF; +} + +int +bappend(void *p, void *src, int len) +{ + Buf *b = p; + char *n; + + while(b->len + len >= b->sz){ + b->sz = b->sz*2 + 64; + n = realloc(b->data, b->sz); + if(n == nil) + return -1; + b->data = n; + } + memmove(b->data + b->len, src, len); + b->len += len; + return len; +} + +int +breadc(void *p) +{ + return Bgetc(p); +} + +int +bdecompress(Buf *d, Biobuf *b, vlong *csz) +{ + vlong o; + + o = Boffset(b); + if(inflatezlib(d, bappend, b, breadc) == -1 || d->data == nil){ + free(d->data); + return -1; + } + if (csz) + *csz = Boffset(b) - o; + return d->len; +} + +int +decompress(void **p, Biobuf *b, vlong *csz) +{ + Buf d = {.len=0, .data=nil, .sz=0}; + + if(bdecompress(&d, b, csz) == -1){ + free(d.data); + return -1; + } + *p = d.data; + return d.len; +} + +static vlong +readvint(char *p, char **pp) +{ + int s, c; + vlong n; + + s = 0; + n = 0; + do { + c = *p++; + n |= (c & 0x7f) << s; + s += 7; + } while (c & 0x80 && s < 63); + *pp = p; + + return n; +} + +static int +applydelta(Object *dst, Object *base, char *d, int nd) +{ + char *r, *b, *ed, *er; + int n, nr, c; + vlong o, l; + + ed = d + nd; + b = base->data; + n = readvint(d, &d); + if(n != base->size){ + werrstr("mismatched source size"); + return -1; + } + + nr = readvint(d, &d); + r = emalloc(nr + 64); + n = snprint(r, 64, "%T %d", base->type, nr) + 1; + dst->all = r; + dst->type = base->type; + dst->data = r + n; + dst->size = nr; + er = dst->data + nr; + r = dst->data; + + while(d != ed){ + c = *d++; + /* copy from base */ + if(c & 0x80){ + o = 0; + l = 0; + /* Offset in base */ + if(d != ed && (c & 0x01)) o |= (*d++ << 0) & 0x000000ff; + if(d != ed && (c & 0x02)) o |= (*d++ << 8) & 0x0000ff00; + if(d != ed && (c & 0x04)) o |= (*d++ << 16) & 0x00ff0000; + if(d != ed && (c & 0x08)) o |= (*d++ << 24) & 0xff000000; + + /* Length to copy */ + if(d != ed && (c & 0x10)) l |= (*d++ << 0) & 0x0000ff; + if(d != ed && (c & 0x20)) l |= (*d++ << 8) & 0x00ff00; + if(d != ed && (c & 0x40)) l |= (*d++ << 16) & 0xff0000; + if(l == 0) l = 0x10000; + + if(o + l > base->size){ + werrstr("garbled delta: out of bounds copy"); + return -1; + } + memmove(r, b + o, l); + r += l; + /* inline data */ + }else{ + if(c > ed - d){ + werrstr("garbled delta: write past object"); + return -1; + } + memmove(r, d, c); + d += c; + r += c; + } + } + if(r != er){ + werrstr("truncated delta"); + return -1; + } + + return nr; +} + +static int +readrdelta(Biobuf *f, Object *o, int nd, int flag) +{ + Object *b; + Hash h; + char *d; + int n; + + d = nil; + if(Bread(f, h.h, sizeof(h.h)) != sizeof(h.h)) + goto error; + if(hasheq(&o->hash, &h)) + goto error; + if((n = decompress(&d, f, nil)) == -1) + goto error; + o->len = Boffset(f) - o->off; + if(d == nil || n != nd) + goto error; + if((b = readidxobject(f, h, flag|Cthin)) == nil) + goto error; + if(applydelta(o, b, d, n) == -1) + goto error; + free(d); + return 0; +error: + free(d); + return -1; +} + +static int +readodelta(Biobuf *f, Object *o, vlong nd, vlong p, int flag) +{ + Object b; + char *d; + vlong r; + int c, n; + + d = nil; + if((c = Bgetc(f)) == -1) + return -1; + r = c & 0x7f; + while(c & 0x80 && r < (1ULL<<56)){ + if((c = Bgetc(f)) == -1) + return -1; + r = ((r + 1)<<7) | (c & 0x7f); + } + + if(r > p || r >= (1ULL<<56)){ + werrstr("junk offset -%lld (from %lld)", r, p); + goto error; + } + if((n = decompress(&d, f, nil)) == -1) + goto error; + o->len = Boffset(f) - o->off; + if(d == nil || n != nd) + goto error; + if(Bseek(f, p - r, 0) == -1) + goto error; + memset(&b, 0, sizeof(Object)); + if(readpacked(f, &b, flag) == -1) + goto error; + if(applydelta(o, &b, d, nd) == -1) + goto error; + clear(&b); + free(d); + return 0; +error: + free(d); + return -1; +} + +static int +readpacked(Biobuf *f, Object *o, int flag) +{ + int c, s, n; + vlong l, p; + int t; + Buf b; + + p = Boffset(f); + c = Bgetc(f); + if(c == -1) + return -1; + l = c & 0xf; + s = 4; + t = (c >> 4) & 0x7; + if(!t){ + werrstr("unknown type for byte %x at %lld", c, p); + return -1; + } + while(c & 0x80){ + if((c = Bgetc(f)) == -1) + return -1; + l |= (c & 0x7f) << s; + s += 7; + } + if(l >= (1ULL << 32)){ + werrstr("object too big"); + return -1; + } + switch(t){ + default: + werrstr("invalid object at %lld", Boffset(f)); + return -1; + case GCommit: + case GTree: + case GTag: + case GBlob: + b.sz = 64 + l; + b.data = emalloc(b.sz); + n = snprint(b.data, 64, "%T %lld", t, l) + 1; + b.len = n; + if(bdecompress(&b, f, nil) == -1){ + free(b.data); + return -1; + } + o->len = Boffset(f) - o->off; + o->type = t; + o->all = b.data; + o->data = b.data + n; + o->size = b.len - n; + break; + case GOdelta: + if(readodelta(f, o, l, p, flag) == -1) + return -1; + break; + case GRdelta: + if(readrdelta(f, o, l, flag) == -1) + return -1; + break; + } + o->flag |= Cloaded|flag; + return 0; +} + +static int +readloose(Biobuf *f, Object *o, int flag) +{ + struct { char *tag; int type; } *p, types[] = { + {"blob", GBlob}, + {"tree", GTree}, + {"commit", GCommit}, + {"tag", GTag}, + {nil}, + }; + char *d, *s, *e; + vlong sz, n; + int l; + + n = decompress(&d, f, nil); + if(n == -1) + return -1; + + s = d; + o->type = GNone; + for(p = types; p->tag; p++){ + l = strlen(p->tag); + if(strncmp(s, p->tag, l) == 0){ + s += l; + o->type = p->type; + while(!isspace(*s)) + s++; + break; + } + } + if(o->type == GNone){ + free(o->data); + return -1; + } + sz = strtol(s, &e, 0); + if(e == s || *e++ != 0){ + werrstr("malformed object header"); + goto error; + } + if(sz != n - (e - d)){ + werrstr("mismatched sizes"); + goto error; + } + o->size = sz; + o->data = e; + o->all = d; + o->flag |= Cloaded|flag; + return 0; + +error: + free(d); + return -1; +} + +vlong +searchindex(char *idx, int nidx, Hash h) +{ + int lo, hi, hidx, i, r, nent; + vlong o, oo; + void *s; + + o = 8; + if(nidx < 8 + 256*4) + return -1; + /* + * Read the fanout table. The fanout table + * contains 256 entries, corresponsding to + * the first byte of the hash. Each entry + * is a 4 byte big endian integer, containing + * the total number of entries with a leading + * byte <= the table index, allowing us to + * rapidly do a binary search on them. + */ + if (h.h[0] == 0){ + lo = 0; + hi = GETBE32(idx + o); + } else { + o += h.h[0]*4 - 4; + lo = GETBE32(idx + o); + hi = GETBE32(idx + o + 4); + } + if(hi == lo) + goto notfound; + nent=GETBE32(idx + 8 + 255*4); + + /* + * Now that we know the range of hashes that the + * entry may exist in, search them + */ + r = -1; + hidx = -1; + o = 8 + 256*4; + while(lo < hi){ + hidx = (hi + lo)/2; + s = idx + o + hidx*sizeof(h.h); + r = memcmp(h.h, s, sizeof(h.h)); + if(r < 0) + hi = hidx; + else if(r > 0) + lo = hidx + 1; + else + break; + } + if(r != 0) + goto notfound; + + /* + * We found the entry. If it's 32 bits, then we + * can just return the oset, otherwise the 32 + * bit entry contains the oset to the 64 bit + * entry. + */ + oo = 8; /* Header */ + oo += 256*4; /* Fanout table */ + oo += Hashsz*nent; /* Hashes */ + oo += 4*nent; /* Checksums */ + oo += 4*hidx; /* Offset offset */ + if(oo < 0 || oo + 4 > nidx) + goto err; + i = GETBE32(idx + oo); + o = i & 0xffffffffULL; + /* + * Large offsets (i.e. 64-bit) are encoded as an index + * into the next table with the MSB bit set. + */ + if(o & (1ull << 31)){ + o &= 0x7fffffffULL; + oo = 8; /* Header */ + oo += 256*4; /* Fanout table */ + oo += Hashsz*nent; /* Hashes */ + oo += 4*nent; /* Checksums */ + oo += 4*nent; /* 32-bit Offsets */ + oo += 8*o; /* 64-bit Offset offset */ + if(oo < 0 || oo + 8 >= nidx) + goto err; + o = GETBE64(idx + oo); + } + return o; + +err: + werrstr("out of bounds read"); + return -1; +notfound: + werrstr("not present"); + return -1; +} + +/* + * Scans for non-empty word, copying it into buf. + * Strips off word, leading, and trailing space + * from input. + * + * Returns -1 on empty string or error, leaving + * input unmodified. + */ +static int +scanword(char **str, int *nstr, char *buf, int nbuf) +{ + char *p; + int n, r; + + r = -1; + p = *str; + n = *nstr; + while(n && isblank(*p)){ + n--; + p++; + } + + for(; n && *p && !isspace(*p); p++, n--){ + r = 0; + *buf++ = *p; + nbuf--; + if(nbuf == 0) + return -1; + } + while(n && isblank(*p)){ + n--; + p++; + } + *buf = 0; + *str = p; + *nstr = n; + return r; +} + +static void +nextline(char **str, int *nstr) +{ + char *s; + + if((s = strchr(*str, '\n')) != nil){ + *nstr -= s - *str + 1; + *str = s + 1; + } +} + +static int +parseauthor(char **str, int *nstr, char **name, vlong *time) +{ + char buf[128]; + Resub m[4]; + char *p; + int n, nm; + + if((p = strchr(*str, '\n')) == nil) + sysfatal("malformed author line"); + n = p - *str; + if(n >= sizeof(buf)) + sysfatal("overlong author line"); + memset(m, 0, sizeof(m)); + snprint(buf, n + 1, *str); + *str = p; + *nstr -= n; + + if(!regexec(authorpat, buf, m, nelem(m))) + sysfatal("invalid author line %s", buf); + nm = m[1].ep - m[1].sp; + *name = emalloc(nm + 1); + memcpy(*name, m[1].sp, nm); + buf[nm] = 0; + + nm = m[2].ep - m[2].sp; + memcpy(buf, m[2].sp, nm); + buf[nm] = 0; + *time = atoll(buf); + return 0; +} + +static void +parsecommit(Object *o) +{ + char *p, *t, buf[128]; + int np; + + p = o->data; + np = o->size; + o->commit = emalloc(sizeof(Cinfo)); + while(1){ + if(scanword(&p, &np, buf, sizeof(buf)) == -1) + break; + if(strcmp(buf, "tree") == 0){ + if(scanword(&p, &np, buf, sizeof(buf)) == -1) + sysfatal("invalid commit: tree missing"); + if(hparse(&o->commit->tree, buf) == -1) + sysfatal("invalid commit: garbled tree"); + }else if(strcmp(buf, "parent") == 0){ + if(scanword(&p, &np, buf, sizeof(buf)) == -1) + sysfatal("invalid commit: missing parent"); + o->commit->parent = realloc(o->commit->parent, ++o->commit->nparent * sizeof(Hash)); + if(!o->commit->parent) + sysfatal("unable to malloc: %r"); + if(hparse(&o->commit->parent[o->commit->nparent - 1], buf) == -1) + sysfatal("invalid commit: garbled parent"); + }else if(strcmp(buf, "author") == 0){ + parseauthor(&p, &np, &o->commit->author, &o->commit->mtime); + }else if(strcmp(buf, "committer") == 0){ + parseauthor(&p, &np, &o->commit->committer, &o->commit->ctime); + }else if(strcmp(buf, "gpgsig") == 0){ + /* just drop it */ + if((t = strstr(p, "-----END PGP SIGNATURE-----")) == nil) + sysfatal("malformed gpg signature"); + np -= t - p; + p = t; + } + nextline(&p, &np); + } + while (np && isspace(*p)) { + p++; + np--; + } + o->commit->msg = p; + o->commit->nmsg = np; +} + +static void +parsetree(Object *o) +{ + int m, a, entsz, nent; + Dirent *t, *ent; + char *p, *ep; + + p = o->data; + ep = p + o->size; + + nent = 0; + entsz = 16; + ent = eamalloc(entsz, sizeof(Dirent)); + o->tree = emalloc(sizeof(Tinfo)); + while(p != ep){ + if(nent == entsz){ + entsz *= 2; + ent = earealloc(ent, entsz, sizeof(Dirent)); + } + t = &ent[nent++]; + m = strtol(p, &p, 8); + if(*p != ' ') + sysfatal("malformed tree %H: *p=(%d) %c\n", o->hash, *p, *p); + p++; + /* + * only the stored permissions for the user + * are relevant; git fills group and world + * bits with whatever -- so to serve with + * useful permissions, replicate the mode + * of the git repo dir. + */ + a = (m & 0777)>>6; + t->mode = ((a<<6)|(a<<3)|a) & gitdirmode; + t->ismod = 0; + t->islink = 0; + if(m == 0160000){ + t->mode |= DMDIR; + t->ismod = 1; + }else if(m == 0120000){ + t->mode = 0; + t->islink = 1; + } + if(m & 0040000) + t->mode |= DMDIR; + t->name = p; + p = memchr(p, 0, ep - p); + if(*p++ != 0 || ep - p < sizeof(t->h.h)) + sysfatal("malformed tree %H, remaining %d (%s)", o->hash, (int)(ep - p), p); + memcpy(t->h.h, p, sizeof(t->h.h)); + p += sizeof(t->h.h); + } + o->tree->ent = ent; + o->tree->nent = nent; +} + +static void +parsetag(Object *) +{ +} + +void +parseobject(Object *o) +{ + if(o->flag & Cparsed) + return; + switch(o->type){ + case GTree: parsetree(o); break; + case GCommit: parsecommit(o); break; + case GTag: parsetag(o); break; + default: break; + } + o->flag |= Cparsed; +} + +static Object* +readidxobject(Biobuf *idx, Hash h, int flag) +{ + char path[Pathmax], hbuf[41]; + Object *obj, *new; + int i, r, retried; + Biobuf *f; + vlong o; + + if((obj = osfind(&objcache, h)) != nil){ + if(flag & Cidx){ + /* + * If we're indexing, we need to be careful + * to only return objects within this pack, + * so if the objects exist outside the pack, + * we don't index the wrong copy. + */ + if(!(obj->flag & Cidx)) + return nil; + if(obj->flag & Cloaded) + return obj; + o = Boffset(idx); + if(Bseek(idx, obj->off, 0) == -1) + return nil; + if(readpacked(idx, obj, flag) == -1) + return nil; + if(Bseek(idx, o, 0) == -1) + sysfatal("could not restore offset"); + cache(obj); + return obj; + } + if(obj->flag & Cloaded) + return obj; + } + if(flag & Cthin) + flag &= ~Cidx; + if(flag & Cidx) + return nil; + new = nil; + if(obj == nil){ + new = emalloc(sizeof(Object)); + new->id = objcache.nobj + 1; + new->hash = h; + obj = new; + } + + o = -1; + retried = 0; +retry: + for(i = 0; i < npackf; i++){ + o = searchindex(packf[i].idx, packf[i].nidx, h); + if(o != -1){ + if((f = openpack(&packf[i])) == nil) + goto error; + if((r = Bseek(f, o, 0)) != -1) + r = readpacked(f, obj, flag); + closepack(&packf[i]); + if(r == -1) + goto error; + parseobject(obj); + cache(obj); + return obj; + } + } + + snprint(hbuf, sizeof(hbuf), "%H", h); + snprint(path, sizeof(path), ".git/objects/%c%c/%s", hbuf[0], hbuf[1], hbuf + 2); + if((f = Bopen(path, OREAD)) != nil){ + if(readloose(f, obj, flag) == -1) + goto errorf; + Bterm(f); + parseobject(obj); + cache(obj); + return obj; + } + + if(o == -1){ + if(retried) + goto error; + retried = 1; + refreshpacks(); + goto retry; + } +errorf: + Bterm(f); +error: + free(new); + return nil; +} + +/* + * Loads and returns a cached object. + */ +Object* +readobject(Hash h) +{ + Object *o; + Dir *d; + + if(gitdirmode == -1){ + if((d = dirstat(".git")) == nil) + sysfatal("stat .git: %r"); + gitdirmode = d->mode & 0777; + free(d); + } + if((o = readidxobject(nil, h, 0)) == nil) + return nil; + parseobject(o); + ref(o); + return o; +} + +/* + * Creates and returns a cached, cleared object + * that will get loaded some other time. Useful + * for performance if need to mark that a blob + * exists, but we don't care about its contents. + * + * The refcount of the returned object is 0, so + * it doesn't need to be unrefed. + */ +Object* +clearedobject(Hash h, int type) +{ + Object *o; + + if((o = osfind(&objcache, h)) != nil) + return o; + + o = emalloc(sizeof(Object)); + o->hash = h; + o->type = type; + osadd(&objcache, o); + o->id = objcache.nobj; + o->flag |= Cexist; + return o; +} + +int +objcmp(void *pa, void *pb) +{ + Object *a, *b; + + a = *(Object**)pa; + b = *(Object**)pb; + return memcmp(a->hash.h, b->hash.h, sizeof(a->hash.h)); +} + +static int +hwrite(Biobuf *b, void *buf, int len, DigestState **st) +{ + *st = sha1(buf, len, nil, *st); + return Bwrite(b, buf, len); +} + +static u32int +objectcrc(Biobuf *f, Object *o) +{ + char buf[8096]; + int n, r; + + o->crc = 0; + Bseek(f, o->off, 0); + for(n = o->len; n > 0; n -= r){ + r = Bread(f, buf, n > sizeof(buf) ? sizeof(buf) : n); + if(r == -1) + return -1; + if(r == 0) + return 0; + o->crc = crc32(o->crc, buf, r); + } + return 0; +} + +int +indexpack(char *pack, char *idx, Hash ph) +{ + char hdr[4*3], buf[8]; + int nobj, npct, nvalid, nbig; + int i, n, pct; + Object *o, **obj; + DigestState *st; + char *valid; + Biobuf *f; + Hash h; + int c; + + if((f = Bopen(pack, OREAD)) == nil) + return -1; + if(Bread(f, hdr, sizeof(hdr)) != sizeof(hdr)){ + werrstr("short read on header"); + return -1; + } + if(memcmp(hdr, "PACK\0\0\0\2", 8) != 0){ + werrstr("invalid header"); + return -1; + } + + pct = 0; + npct = 0; + nvalid = 0; + nobj = GETBE32(hdr + 8); + obj = eamalloc(nobj, sizeof(Object*)); + valid = eamalloc(nobj, sizeof(char)); + if(interactive) + fprint(2, "indexing %d objects: 0%%", nobj); + while(nvalid != nobj){ + n = 0; + for(i = 0; i < nobj; i++){ + if(valid[i]){ + n++; + continue; + } + pct = showprogress((npct*100)/nobj, pct); + if(obj[i] == nil){ + o = emalloc(sizeof(Object)); + o->off = Boffset(f); + obj[i] = o; + } + o = obj[i]; + /* + * We can seek around when packing delta chains. + * Be extra careful while we don't know where all + * the objects start. + */ + Bseek(f, o->off, 0); + if(readpacked(f, o, Cidx) == -1) + continue; + sha1((uchar*)o->all, o->size + strlen(o->all) + 1, o->hash.h, nil); + valid[i] = 1; + cache(o); + npct++; + n++; + if(objectcrc(f, o) == -1) + return -1; + } + if(n == nvalid){ + sysfatal("fix point reached too early: %d/%d: %r", nvalid, nobj); + goto error; + } + nvalid = n; + } + if(interactive) + fprint(2, "\b\b\b\b100%%\n"); + Bterm(f); + + st = nil; + qsort(obj, nobj, sizeof(Object*), objcmp); + if((f = Bopen(idx, OWRITE)) == nil) + return -1; + if(hwrite(f, "\xfftOc\x00\x00\x00\x02", 8, &st) != 8) + goto error; + /* fanout table */ + c = 0; + for(i = 0; i < 256; i++){ + while(c < nobj && (obj[c]->hash.h[0] & 0xff) <= i) + c++; + PUTBE32(buf, c); + if(hwrite(f, buf, 4, &st) == -1) + goto error; + } + for(i = 0; i < nobj; i++){ + o = obj[i]; + if(hwrite(f, o->hash.h, sizeof(o->hash.h), &st) == -1) + goto error; + } + + for(i = 0; i < nobj; i++){ + PUTBE32(buf, obj[i]->crc); + if(hwrite(f, buf, 4, &st) == -1) + goto error; + } + + nbig = 0; + for(i = 0; i < nobj; i++){ + if(obj[i]->off < (1ull<<31)) + PUTBE32(buf, obj[i]->off); + else{ + PUTBE32(buf, (1ull << 31) | nbig); + nbig++; + } + if(hwrite(f, buf, 4, &st) == -1) + goto error; + } + for(i = 0; i < nobj; i++){ + if(obj[i]->off >= (1ull<<31)){ + PUTBE64(buf, obj[i]->off); + if(hwrite(f, buf, 8, &st) == -1) + goto error; + } + } + if(hwrite(f, ph.h, sizeof(ph.h), &st) == -1) + goto error; + sha1(nil, 0, h.h, st); + Bwrite(f, h.h, sizeof(h.h)); + + free(obj); + free(valid); + Bterm(f); + return 0; + +error: + free(obj); + free(valid); + Bterm(f); + return -1; +} + +static int +deltaordercmp(void *pa, void *pb) +{ + Meta *a, *b; + int cmp; + + a = *(Meta**)pa; + b = *(Meta**)pb; + if(a->obj->type != b->obj->type) + return a->obj->type - b->obj->type; + cmp = strcmp(a->path, b->path); + if(cmp != 0) + return cmp; + if(a->mtime != b->mtime) + return a->mtime - b->mtime; + return memcmp(a->obj->hash.h, b->obj->hash.h, sizeof(a->obj->hash.h)); +} + +static int +writeordercmp(void *pa, void *pb) +{ + Meta *a, *b, *ahd, *bhd; + + a = *(Meta**)pa; + b = *(Meta**)pb; + ahd = (a->head == nil) ? a : a->head; + bhd = (b->head == nil) ? b : b->head; + if(ahd->mtime != bhd->mtime) + return bhd->mtime - ahd->mtime; + if(ahd != bhd) + return (uintptr)bhd - (uintptr)ahd; + if(a->nchain != b->nchain) + return a->nchain - b->nchain; + return a->mtime - b->mtime; +} + +static void +addmeta(Metavec *v, Objset *has, Object *o, char *path, vlong mtime) +{ + Meta *m; + + if(oshas(has, o->hash)) + return; + osadd(has, o); + if(v == nil) + return; + m = emalloc(sizeof(Meta)); + m->obj = o; + m->path = estrdup(path); + m->mtime = mtime; + + if(v->nmeta == v->metasz){ + v->metasz = 2*v->metasz; + v->meta = earealloc(v->meta, v->metasz, sizeof(Meta*)); + } + v->meta[v->nmeta++] = m; +} + +static void +freemeta(Meta *m) +{ + free(m->delta); + free(m->path); + free(m); +} + +static int +loadtree(Metavec *v, Objset *has, Hash tree, char *dpath, vlong mtime) +{ + Object *t, *o; + Dirent *e; + char *p; + int i, k; + + if(oshas(has, tree)) + return 0; + if((t = readobject(tree)) == nil) + return -1; + if(t->type != GTree){ + fprint(2, "load: %H: not tree\n", t->hash); + unref(t); + return 0; + } + addmeta(v, has, t, dpath, mtime); + for(i = 0; i < t->tree->nent; i++){ + e = &t->tree->ent[i]; + if(oshas(has, e->h)) + continue; + if(e->ismod) + continue; + k = (e->mode & DMDIR) ? GTree : GBlob; + o = clearedobject(e->h, k); + p = smprint("%s/%s", dpath, e->name); + if(k == GBlob) + addmeta(v, has, o, p, mtime); + else if(loadtree(v, has, e->h, p, mtime) == -1){ + free(p); + return -1; + } + free(p); + } + unref(t); + return 0; +} + +static int +loadcommit(Metavec *v, Objset *has, Hash h) +{ + Object *c; + int r; + + if(osfind(has, h)) + return 0; + if((c = readobject(h)) == nil) + return -1; + if(c->type != GCommit){ + fprint(2, "load: %H: not commit\n", c->hash); + unref(c); + return 0; + } + addmeta(v, has, c, "", c->commit->ctime); + r = loadtree(v, has, c->commit->tree, "", c->commit->ctime); + unref(c); + return r; +} + +static int +readmeta(Hash *theirs, int ntheirs, Hash *ours, int nours, Meta ***m) +{ + Object **obj; + Objset has; + int i, nobj; + Metavec v; + + *m = nil; + osinit(&has); + v.nmeta = 0; + v.metasz = 64; + v.meta = eamalloc(v.metasz, sizeof(Meta*)); + if(findtwixt(theirs, ntheirs, ours, nours, &obj, &nobj) == -1) + sysfatal("load twixt: %r"); + + if(nobj == 0) + return 0; + for(i = 0; i < nours; i++) + if(!hasheq(&ours[i], &Zhash)) + if(loadcommit(nil, &has, ours[i]) == -1) + goto out; + for(i = 0; i < nobj; i++) + if(loadcommit(&v, &has, obj[i]->hash) == -1) + goto out; + osclear(&has); + *m = v.meta; + return v.nmeta; +out: + osclear(&has); + free(v.meta); + return -1; +} + +static int +deltasz(Delta *d, int nd) +{ + int i, sz; + sz = 32; + for(i = 0; i < nd; i++) + sz += d[i].cpy ? 7 : d[i].len + 1; + return sz; +} + +static void +pickdeltas(Meta **meta, int nmeta) +{ + Meta *m, *p; + Object *o; + Delta *d; + int i, j, nd, sz, pct, best; + + pct = 0; + dprint(1, "picking deltas\n"); + if(interactive) + fprint(2, "deltifying %d objects: 0%%", nmeta); + qsort(meta, nmeta, sizeof(Meta*), deltaordercmp); + for(i = 0; i < nmeta; i++){ + m = meta[i]; + pct = showprogress((i*100) / nmeta, pct); + m->delta = nil; + m->ndelta = 0; + if(m->obj->type == GCommit || m->obj->type == GTag) + continue; + if((o = readobject(m->obj->hash)) == nil) + sysfatal("readobject %H: %r", m->obj->hash); + dtinit(&m->dtab, o); + if(i >= 11) + dtclear(&meta[i-11]->dtab); + best = o->size; + for(j = max(0, i - 10); j < i; j++){ + p = meta[j]; + /* long chains make unpacking slow */ + if(p->nchain >= 128 || p->obj->type != o->type) + continue; + d = deltify(o, &p->dtab, &nd); + sz = deltasz(d, nd); + if(sz + 32 < best){ + /* + * if we already picked a best delta, + * replace it. + */ + free(m->delta); + best = sz; + m->delta = d; + m->ndelta = nd; + m->nchain = p->nchain + 1; + m->prev = p; + m->head = p->head; + if(m->head == nil) + m->head = p; + }else + free(d); + } + unref(o); + } + for(i = max(0, nmeta - 10); i < nmeta; i++) + dtclear(&meta[i]->dtab); + if(interactive) + fprint(2, "\b\b\b\b100%%\n"); +} + +static int +compread(void *p, void *dst, int n) +{ + Buf *b; + + b = p; + if(n > b->sz - b->off) + n = b->sz - b->off; + memcpy(dst, b->data + b->off, n); + b->off += n; + return n; +} + +static int +compwrite(void *p, void *buf, int n) +{ + return hwrite(((Compout *)p)->bfd, buf, n, &((Compout*)p)->st); +} + +static int +hcompress(Biobuf *bfd, void *buf, int sz, DigestState **st) +{ + int r; + Buf b ={ + .off=0, + .data=buf, + .sz=sz, + }; + Compout o = { + .bfd = bfd, + .st = *st, + }; + + r = deflatezlib(&o, compwrite, &b, compread, 6, 0); + *st = o.st; + return r; +} + +static void +append(char **p, int *len, int *sz, void *seg, int nseg) +{ + if(*len + nseg >= *sz){ + while(*len + nseg >= *sz) + *sz += *sz/2; + *p = erealloc(*p, *sz); + } + memcpy(*p + *len, seg, nseg); + *len += nseg; +} + +static int +encodedelta(Meta *m, Object *o, Object *b, void **pp) +{ + char *p, *bp, buf[16]; + int len, sz, n, i, j; + Delta *d; + + sz = 128; + len = 0; + p = emalloc(sz); + + /* base object size */ + buf[0] = b->size & 0x7f; + n = b->size >> 7; + for(i = 1; n > 0; i++){ + buf[i - 1] |= 0x80; + buf[i] = n & 0x7f; + n >>= 7; + } + append(&p, &len, &sz, buf, i); + + /* target object size */ + buf[0] = o->size & 0x7f; + n = o->size >> 7; + for(i = 1; n > 0; i++){ + buf[i - 1] |= 0x80; + buf[i] = n & 0x7f; + n >>= 7; + } + append(&p, &len, &sz, buf, i); + for(j = 0; j < m->ndelta; j++){ + d = &m->delta[j]; + if(d->cpy){ + n = d->off; + bp = buf + 1; + buf[0] = 0x81; + buf[1] = 0x00; + for(i = 0; i < sizeof(buf); i++) { + buf[0] |= 1<>= 8; + if(n == 0) + break; + } + + n = d->len; + if(n != 0x10000) { + buf[0] |= 0x1<<4; + for(i = 0; i < sizeof(buf)-4 && n > 0; i++){ + buf[0] |= 1<<(i + 4); + *bp++ = n & 0xff; + n >>= 8; + } + } + append(&p, &len, &sz, buf, bp - buf); + }else{ + n = 0; + while(n != d->len){ + buf[0] = (d->len - n < 127) ? d->len - n : 127; + append(&p, &len, &sz, buf, 1); + append(&p, &len, &sz, o->data + d->off + n, buf[0]); + n += buf[0]; + } + } + } + *pp = p; + return len; +} + +static int +packhdr(char *hdr, int ty, int len) +{ + int i; + + hdr[0] = ty << 4; + hdr[0] |= len & 0xf; + len >>= 4; + for(i = 1; len != 0; i++){ + hdr[i-1] |= 0x80; + hdr[i] = len & 0x7f; + len >>= 7; + } + return i; +} + +static int +packoff(char *hdr, vlong off) +{ + int i, j; + char rbuf[8]; + + rbuf[0] = off & 0x7f; + for(i = 1; (off >>= 7) != 0; i++) + rbuf[i] = (--off & 0x7f)|0x80; + + j = 0; + while(i > 0) + hdr[j++] = rbuf[--i]; + return j; +} + +static int +genpack(int fd, Meta **meta, int nmeta, Hash *h, int odelta) +{ + int i, nh, nd, res, pct, ret; + DigestState *st; + Biobuf *bfd; + Meta *m; + Object *o, *po, *b; + char *p, buf[32]; + + st = nil; + ret = -1; + pct = 0; + dprint(1, "generating pack\n"); + if((fd = dup(fd, -1)) == -1) + return -1; + if((bfd = Bfdopen(fd, OWRITE)) == nil) + return -1; + if(hwrite(bfd, "PACK", 4, &st) == -1) + return -1; + PUTBE32(buf, 2); + if(hwrite(bfd, buf, 4, &st) == -1) + return -1; + PUTBE32(buf, nmeta); + if(hwrite(bfd, buf, 4, &st) == -1) + return -1; + qsort(meta, nmeta, sizeof(Meta*), writeordercmp); + if(interactive) + fprint(2, "writing %d objects: 0%%", nmeta); + for(i = 0; i < nmeta; i++){ + pct = showprogress((i*100)/nmeta, pct); + m = meta[i]; + m->off = Boffset(bfd); + if(m->off == -1) + goto error; + if((o = readobject(m->obj->hash)) == nil) + return -1; + if(m->delta == nil){ + nh = packhdr(buf, o->type, o->size); + if(hwrite(bfd, buf, nh, &st) == -1) + goto error; + if(hcompress(bfd, o->data, o->size, &st) == -1) + goto error; + }else{ + if((b = readobject(m->prev->obj->hash)) == nil) + goto error; + nd = encodedelta(m, o, b, &p); + unref(b); + if(odelta && m->prev->off != 0){ + nh = 0; + nh += packhdr(buf, GOdelta, nd); + nh += packoff(buf+nh, m->off - m->prev->off); + if(hwrite(bfd, buf, nh, &st) == -1) + goto error; + }else{ + nh = packhdr(buf, GRdelta, nd); + po = m->prev->obj; + if(hwrite(bfd, buf, nh, &st) == -1) + goto error; + if(hwrite(bfd, po->hash.h, sizeof(po->hash.h), &st) == -1) + goto error; + } + res = hcompress(bfd, p, nd, &st); + free(p); + if(res == -1) + goto error; + } + unref(o); + } + if(interactive) + fprint(2, "\b\b\b\b100%%\n"); + sha1(nil, 0, h->h, st); + if(Bwrite(bfd, h->h, sizeof(h->h)) == -1) + goto error; + ret = 0; +error: + if(Bterm(bfd) == -1) + return -1; + return ret; +} + +int +writepack(int fd, Hash *theirs, int ntheirs, Hash *ours, int nours, Hash *h) +{ + Meta **meta; + int i, r, nmeta; + + if((nmeta = readmeta(theirs, ntheirs, ours, nours, &meta)) == -1) + return -1; + pickdeltas(meta, nmeta); + r = genpack(fd, meta, nmeta, h, 0); + for(i = 0; i < nmeta; i++) + freemeta(meta[i]); + free(meta); + return r; +} diff --git a/sys/src/cmd/git/proto.c b/sys/src/cmd/git/proto.c new file mode 100644 index 0000000000..05d72cc49b --- /dev/null +++ b/sys/src/cmd/git/proto.c @@ -0,0 +1,514 @@ +#include +#include +#include + +#include "git.h" + +#define Useragent "useragent git/2.24.1" +#define Contenthdr "headers Content-Type: application/x-git-%s-pack-request" +#define Accepthdr "headers Accept: application/x-git-%s-pack-result" + +enum { + Nproto = 16, + Nport = 16, + Nhost = 256, + Npath = 128, + Nrepo = 64, + Nbranch = 32, +}; + +void +tracepkt(int v, char *pfx, char *b, int n) +{ + char *f; + int o, i; + + if(chattygit < v) + return; + o = 0; + f = emalloc(n*4 + 1); + for(i = 0; i < n; i++){ + if(isprint(b[i])){ + f[o++] = b[i]; + continue; + } + f[o++] = '\\'; + switch(b[i]){ + case '\\': f[o++] = '\\'; break; + case '\n': f[o++] = 'n'; break; + case '\r': f[o++] = 'r'; break; + case '\v': f[o++] = 'v'; break; + case '\0': f[o++] = '0'; break; + default: + f[o++] = 'x'; + f[o++] = "0123456789abcdef"[(b[i]>>4)&0xf]; + f[o++] = "0123456789abcdef"[(b[i]>>0)&0xf]; + break; + } + } + f[o] = '\0'; + fprint(2, "%s %04x:\t%s\n", pfx, n, f); + free(f); +} + +int +readpkt(Conn *c, char *buf, int nbuf) +{ + char len[5]; + char *e; + int n; + + if(readn(c->rfd, len, 4) == -1) + return -1; + len[4] = 0; + n = strtol(len, &e, 16); + if(n == 0){ + dprint(1, "=r=> 0000\n"); + return 0; + } + if(e != len + 4 || n <= 4) + sysfatal("pktline: bad length '%s'", len); + n -= 4; + if(n >= nbuf) + sysfatal("pktline: undersize buffer"); + if(readn(c->rfd, buf, n) != n) + return -1; + buf[n] = 0; + tracepkt(1, "=r=>", buf, n); + return n; +} + +int +writepkt(Conn *c, char *buf, int nbuf) +{ + char len[5]; + + + snprint(len, sizeof(len), "%04x", nbuf + 4); + if(write(c->wfd, len, 4) != 4) + return -1; + if(write(c->wfd, buf, nbuf) != nbuf) + return -1; + tracepkt(1, "<=w=", buf, nbuf); + return 0; +} + +int +flushpkt(Conn *c) +{ + dprint(1, "<=w= 0000\n"); + return write(c->wfd, "0000", 4); +} + +static void +grab(char *dst, int n, char *p, char *e) +{ + int l; + + l = e - p; + if(l >= n) + sysfatal("overlong component"); + memcpy(dst, p, l); + dst[l] = 0; +} + +static int +parseuri(char *uri, char *proto, char *host, char *port, char *path, char *repo) +{ + char *s, *p, *q; + int n, hasport; + print("uri: \"%s\"\n", uri); + + p = strstr(uri, "://"); + if(p == nil) + snprint(proto, Nproto, "ssh"); + else if(strncmp(uri, "git+", 4) == 0) + grab(proto, Nproto, uri + 4, p); + else + grab(proto, Nproto, uri, p); + *port = 0; + hasport = 1; + if(strcmp(proto, "git") == 0) + snprint(port, Nport, "9418"); + else if(strncmp(proto, "https", 5) == 0) + snprint(port, Nport, "443"); + else if(strncmp(proto, "http", 4) == 0) + snprint(port, Nport, "80"); + else if(strncmp(proto, "hjgit", 5) == 0) + snprint(port, Nport, "17021"); + else if(strncmp(proto, "gits", 5) == 0) + snprint(port, Nport, "9419"); + else + hasport = 0; + s = (p != nil) ? p + 3 : uri; + p = nil; + if(!hasport){ + p = strstr(s, ":"); + if(p != nil) + p++; + } + if(p == nil) + p = strstr(s, "/"); + if(p == nil || strlen(p) == 1){ + werrstr("missing path"); + return -1; + } + + q = memchr(s, ':', p - s); + if(q){ + grab(host, Nhost, s, q); + grab(port, Nport, q + 1, p); + }else{ + grab(host, Nhost, s, p); + } + + snprint(path, Npath, "%s", p); + if((q = strrchr(p, '/')) != nil) + p = q + 1; + if(strlen(p) == 0){ + werrstr("missing repository in uri"); + return -1; + } + n = strlen(p); + if(hassuffix(p, ".git")) + n -= 4; + grab(repo, Nrepo, p, p + n); + return 0; +} + +static int +webclone(Conn *c, char *url) +{ + char buf[16]; + int n, conn; + + if((c->cfd = open("/mnt/web/clone", ORDWR)) < 0) + goto err; + if((n = read(c->cfd, buf, sizeof(buf)-1)) == -1) + goto err; + buf[n] = 0; + conn = atoi(buf); + + /* github will behave differently based on useragent */ + if(write(c->cfd, Useragent, sizeof(Useragent)) == -1) + return -1; + dprint(1, "open url %s\n", url); + if(fprint(c->cfd, "url %s", url) == -1) + goto err; + free(c->dir); + c->dir = smprint("/mnt/web/%d", conn); + return 0; +err: + if(c->cfd != -1) + close(c->cfd); + return -1; +} + +static int +webopen(Conn *c, char *file, int mode) +{ + char path[128]; + int fd; + + snprint(path, sizeof(path), "%s/%s", c->dir, file); + if((fd = open(path, mode)) == -1) + return -1; + return fd; +} + +static int +issmarthttp(Conn *c, char *direction) +{ + char buf[Pktmax+1], svc[128]; + int fd, n; + + if((fd = webopen(c, "contenttype", OREAD)) == -1) + return -1; + n = readn(fd, buf, sizeof(buf) - 1); + close(fd); + if(n == -1) + return -1; + buf[n] = '\0'; + snprint(svc, sizeof(svc), "application/x-git-%s-pack-advertisement", direction); + if(strcmp(svc, buf) != 0){ + werrstr("dumb http protocol not supported"); + return -1; + } + + if((n = readpkt(c, buf, sizeof(buf))) == -1) + sysfatal("http read: %r"); + buf[n] = 0; + snprint(svc, sizeof(svc), "# service=git-%s-pack\n", direction); + if(strncmp(svc, buf, n) != 0){ + werrstr("invalid initial packet line"); + return -1; + } + if(readpkt(c, buf, sizeof(buf)) != 0){ + werrstr("protocol garble: expected flushpkt"); + return -1; + } + return 0; +} + +static int +dialhttp(Conn *c, char *host, char *port, char *path, char *direction) +{ + char *geturl, *suff, *hsep, *psep; + + suff = ""; + hsep = ""; + psep = ""; + if(port && strlen(port) != 0) + hsep = ":"; + if(path && path[0] != '/') + psep = "/"; + memset(c, 0, sizeof(*c)); + geturl = smprint("https://%s%s%s%s%s%s/info/refs?service=git-%s-pack", host, hsep, port, psep, path, suff, direction); + c->type = ConnHttp; + c->url = smprint("https://%s%s%s%s%s%s/git-%s-pack", host, hsep, port, psep, path, suff, direction); + c->cfd = webclone(c, geturl); + free(geturl); + if(c->cfd == -1) + return -1; + c->rfd = webopen(c, "body", OREAD); + c->wfd = -1; + if(c->rfd == -1) + return -1; + if(issmarthttp(c, direction) == -1) + return -1; + c->direction = estrdup(direction); + return 0; +} + +static int +dialssh(Conn *c, char *host, char *, char *path, char *direction) +{ + int pid, pfd[2]; + char cmd[64]; + + if(pipe(pfd) == -1) + sysfatal("unable to open pipe: %r"); + pid = fork(); + if(pid == -1) + sysfatal("unable to fork"); + if(pid == 0){ + close(pfd[1]); + dup(pfd[0], 0); + dup(pfd[0], 1); + snprint(cmd, sizeof(cmd), "git-%s-pack", direction); + dprint(1, "exec ssh '%s' '%s' %s\n", host, cmd, path); + execl("/bin/ssh", "ssh", host, cmd, path, nil); + sysfatal("exec: %r"); + } + close(pfd[0]); + c->type = ConnSsh; + c->rfd = pfd[1]; + c->wfd = dup(pfd[1], -1); + return 0; +} + +static int +githandshake(Conn *c, char *host, char *path, char *direction) +{ + char *p, *e, cmd[512]; + + p = cmd; + e = cmd + sizeof(cmd); + p = seprint(p, e - 1, "git-%s-pack %s", direction, path); + if(host != nil) + p = seprint(p + 1, e, "host=%s", host); + if(writepkt(c, cmd, p - cmd + 1) == -1){ + fprint(2, "failed to write message\n"); + closeconn(c); + return -1; + } + return 0; +} + +static int +dialhjgit(Conn *c, char *host, char *port, char *path, char *direction, int auth) +{ + char *ds; + int pid, pfd[2]; + + if((ds = netmkaddr(host, "tcp", port)) == nil) + return -1; + if(pipe(pfd) == -1) + sysfatal("unable to open pipe: %r"); + pid = fork(); + if(pid == -1) + sysfatal("unable to fork"); + if(pid == 0){ + close(pfd[1]); + dup(pfd[0], 0); + dup(pfd[0], 1); + dprint(1, "exec tlsclient -a %s\n", ds); + if(auth) + execl("/bin/tlsclient", "tlsclient", "-a", ds, nil); + else + execl("/bin/tlsclient", "tlsclient", ds, nil); + sysfatal("exec: %r"); + } + close(pfd[0]); + c->type = ConnGit9; + c->rfd = pfd[1]; + c->wfd = dup(pfd[1], -1); + return githandshake(c, host, path, direction); +} + +void +initconn(Conn *c, int rd, int wr) +{ + c->type = ConnGit; + c->rfd = rd; + c->wfd = wr; +} + +static int +dialgit(Conn *c, char *host, char *port, char *path, char *direction) +{ + char *ds; + int fd; + + if((ds = netmkaddr(host, "tcp", port)) == nil) + return -1; + dprint(1, "dial %s git-%s-pack %s\n", ds, direction, path); + fd = dial(ds, nil, nil, nil); + if(fd == -1) + return -1; + c->type = ConnGit; + c->rfd = fd; + c->wfd = dup(fd, -1); + return githandshake(c, host, path, direction); +} + +static int +servelocal(Conn *c, char *path, char *direction) +{ + int pid, pfd[2]; + + if(pipe(pfd) == -1) + sysfatal("unable to open pipe: %r"); + pid = fork(); + if(pid == -1) + sysfatal("unable to fork"); + if(pid == 0){ + close(pfd[1]); + dup(pfd[0], 0); + dup(pfd[0], 1); + execl("/bin/git/serve", "serve", "-w", nil); + sysfatal("exec: %r"); + } + close(pfd[0]); + c->type = ConnGit; + c->rfd = pfd[1]; + c->wfd = dup(pfd[1], -1); + return githandshake(c, nil, path, direction); +} + +static int +localrepo(char *uri, char *path, int npath) +{ + int fd; + + snprint(path, npath, "%s/.git/../", uri); + fd = open(path, OREAD); + if(fd < 0) + return -1; + if(fd2path(fd, path, npath) != 0){ + close(fd); + return -1; + } + close(fd); + return 0; +} + +int +gitconnect(Conn *c, char *uri, char *direction) +{ + char proto[Nproto], host[Nhost], port[Nport]; + char repo[Nrepo], path[Npath]; + + memset(c, 0, sizeof(Conn)); + c->rfd = c->wfd = c->cfd = -1; + + if(localrepo(uri, path, sizeof(path)) == 0) + return servelocal(c, path, direction); + + if(parseuri(uri, proto, host, port, path, repo) == -1){ + werrstr("bad uri %s", uri); + return -1; + } + if(strcmp(proto, "ssh") == 0) + return dialssh(c, host, port, path, direction); + else if(strcmp(proto, "git") == 0) + return dialgit(c, host, port, path, direction); + else if(strcmp(proto, "hjgit") == 0) + return dialhjgit(c, host, port, path, direction, 1); + else if(strcmp(proto, "gits") == 0) + return dialhjgit(c, host, port, path, direction, 0); + else if(strcmp(proto, "http") == 0 || strcmp(proto, "https") == 0) + return dialhttp(c, host, port, path, direction); + werrstr("unknown protocol %s", proto); + return -1; +} + +int +writephase(Conn *c) +{ + char hdr[128]; + int n; + + dprint(1, "start write phase\n"); + if(c->type != ConnHttp) + return 0; + + if(c->wfd != -1) + close(c->wfd); + if(c->cfd != -1) + close(c->cfd); + if((c->cfd = webclone(c, c->url)) == -1) + return -1; + n = snprint(hdr, sizeof(hdr), Contenthdr, c->direction); + if(write(c->cfd, hdr, n) == -1) + return -1; + n = snprint(hdr, sizeof(hdr), Accepthdr, c->direction); + if(write(c->cfd, hdr, n) == -1) + return -1; + if((c->wfd = webopen(c, "postbody", OWRITE)) == -1) + return -1; + c->rfd = -1; + return 0; +} + +int +readphase(Conn *c) +{ + dprint(1, "start read phase\n"); + if(c->type != ConnHttp) + return 0; + if(close(c->wfd) == -1) + return -1; + if((c->rfd = webopen(c, "body", OREAD)) == -1) + return -1; + c->wfd = -1; + return 0; +} + +void +closeconn(Conn *c) +{ + close(c->rfd); + close(c->wfd); + switch(c->type){ + case ConnGit: + break; + case ConnGit9: + case ConnSsh: + free(wait()); + break; + case ConnHttp: + close(c->cfd); + break; + } +} diff --git a/sys/src/cmd/git/pull b/sys/src/cmd/git/pull new file mode 100755 index 0000000000..13db8151b9 --- /dev/null +++ b/sys/src/cmd/git/pull @@ -0,0 +1,73 @@ +#!/bin/rc -e +rfork en +. /sys/lib/git/common.rc + +fn update{ + upstream=$1 + url=$2 + dir=$3 + dflag=() + if(! ~ $#debug 0) + dflag='-d' + {git/get $dflag -u $upstream $url >[2=3] || die $status} | awk ' + /^remote/{ + if($2=="HEAD") + next + ref=$2 + hash=$3 + gsub("^refs/heads", "refs/remotes/'$upstream'", ref) + outfile = ".git/"ref + system("mkdir -p `{basename -d "outfile"}"); + print hash > outfile; + close(outfile); + } + ' |[3] tr '\x0d' '\x0a' +} + +gitup + +flagfmt='d:debug, q:quiet, f:fetchonly, + u:upstream upstream' +args='' +eval `''{aux/getflags $*} || exec aux/usage + +if(~ $#upstream 0) + upstream=origin +remote=`$nl{git/conf 'remote "'$upstream'".url'} +if(~ $#remote 0){ + remote=$upstream + upstream=THEM +} + +update $upstream $remote +if (~ $fetchonly 1) + exit + +local=`{git/branch} +remote=`{git/branch | subst '^(refs/)?heads' 'remotes/'$upstream} + +# we have local commits, but the remote hasn't changed. +# in this case, we want to keep the local commits untouched. +if(~ `{git/query HEAD $remote @} `{git/query $remote}){ + echo 'up to date' >[1=2] + exit +} +# The remote repository and our HEAD have diverged: we +# need to merge. +if(! ~ `{git/query HEAD $remote @} `{git/query HEAD}){ + >[1=2]{ + echo ours: `{git/query HEAD} + echo theirs: `{git/query $remote} + echo common: `{git/query HEAD $remote @} + echo git/merge $remote + } + exit diverged +} +# The remote is directly ahead of the local, and we have +# no local commits that need merging. +if(~ $#quiet 0) + git/log -s -e $local'..'$remote +echo +echo $remote':' `{git/query $local} '=>' `{git/query $remote} +git/branch -mnb $remote $local +exit '' diff --git a/sys/src/cmd/git/push b/sys/src/cmd/git/push new file mode 100755 index 0000000000..ee05d952ac --- /dev/null +++ b/sys/src/cmd/git/push @@ -0,0 +1,51 @@ +#!/bin/rc -e +rfork en +. /sys/lib/git/common.rc + +gitup + +flagfmt='a:pushall, b:branch branch, f:force, d:debug, + r:remove remove, u:upstream upstream' args='' +eval `''{aux/getflags $*} || exec aux/usage +if(! ~ $#* 0) + exec aux/usage + +if(~ $pushall 1) + branch=`$nl{cd .git/refs/heads && walk -f} +if(~ $#branch 0) + branch=`{git/branch} +if(~ $#branch 0) + die 'no branches' +if(~ $force 1) + force=-f +if(~ $debug 1) + debug='-d' + +if(~ $#upstream 0) + upstream=origin + +remotes=`$nl{git/conf -a 'remote "'$upstream'".url'} +if(~ $#remotes 0) + remotes=$upstream +branch=-b^$branch +if(! ~ $#remove 0) + remove=-r^$remove +for(remote in $remotes){ + updates=`$nl{git/send $debug $force $branch $remove $remote} || die $status + for(ln in $updates){ + u=`{echo $ln} + refpath=`{echo $u(2) | subst '^refs/heads/' '.git/refs/remotes/'$upstream'/'} + switch($u(1)){ + case update; + mkdir -p `{basename -d $refpath} + echo $u(4) > $refpath + echo $u(2)^':' $u(3) '=>' $u(4) + case delete; + echo $u(2)^': removed' + rm -f $refpath + case uptodate; + echo $u(2)^': up to date' + } + } +} +exit '' diff --git a/sys/src/cmd/git/query.c b/sys/src/cmd/git/query.c new file mode 100644 index 0000000000..40020eafc6 --- /dev/null +++ b/sys/src/cmd/git/query.c @@ -0,0 +1,199 @@ +#include +#include + +#include "git.h" + +#pragma varargck type "P" void + +int fullpath; +int changes; +int reverse; +char *path[128]; +int npath; + +int +Pfmt(Fmt *f) +{ + int i, n; + + n = 0; + for(i = 0; i < npath; i++) + n += fmtprint(f, "%s/", path[i]); + return n; +} + +void +showdir(Hash dh, char *dname, char m) +{ + Dirent *p, *e; + Object *d; + + + path[npath++] = dname; + if((d = readobject(dh)) == nil) + sysfatal("bad hash %H", dh); + assert(d->type == GTree); + p = d->tree->ent; + e = p + d->tree->nent; + for(; p != e; p++){ + if(p->ismod) + continue; + if(p->mode & DMDIR) + showdir(p->h, p->name, m); + else + print("%c %P%s\n", m, p->name); + } + print("%c %P\n", m); + unref(d); + npath--; +} + +void +show(Dirent *e, char m) +{ + if(e->mode & DMDIR) + showdir(e->h, e->name, m); + else + print("%c %P%s\n", m, e->name); +} + +void +difftrees(Object *a, Object *b) +{ + Dirent *ap, *bp, *ae, *be; + int c; + + ap = ae = nil; + bp = be = nil; + if(a != nil){ + if(a->type != GTree) + return; + ap = a->tree->ent; + ae = ap + a->tree->nent; + } + if(b != nil){ + if(b->type != GTree) + return; + bp = b->tree->ent; + be = bp + b->tree->nent; + } + while(ap != ae && bp != be){ + c = strcmp(ap->name, bp->name); + if(c == 0){ + if(ap->mode == bp->mode && hasheq(&ap->h, &bp->h)) + goto next; + if(ap->mode != bp->mode) + print("! %P%s\n", ap->name); + else if(!(ap->mode & DMDIR) || !(bp->mode & DMDIR)) + print("@ %P%s\n", ap->name); + if((ap->mode & DMDIR) && (bp->mode & DMDIR)){ + if(npath >= nelem(path)) + sysfatal("path too deep"); + path[npath++] = ap->name; + if((a = readobject(ap->h)) == nil) + sysfatal("bad hash %H", ap->h); + if((b = readobject(bp->h)) == nil) + sysfatal("bad hash %H", bp->h); + difftrees(a, b); + unref(a); + unref(b); + npath--; + } +next: + ap++; + bp++; + }else if(c < 0) { + show(ap, '-'); + ap++; + }else if(c > 0){ + show(bp, '+'); + bp++; + } + } + for(; ap != ae; ap++) + show(ap, '-'); + for(; bp != be; bp++) + show(bp, '+'); +} + +void +diffcommits(Hash ah, Hash bh) +{ + Object *a, *b, *at, *bt; + + at = nil; + bt = nil; + if(!hasheq(&ah, &Zhash) && (a = readobject(ah)) != nil){ + if(a->type != GCommit) + sysfatal("not commit: %H", ah); + if((at = readobject(a->commit->tree)) == nil) + sysfatal("bad hash %H", a->commit->tree); + unref(a); + } + if(!hasheq(&bh, &Zhash) && (b = readobject(bh)) != nil){ + if(b->type != GCommit) + sysfatal("not commit: %H", ah); + if((bt = readobject(b->commit->tree)) == nil) + sysfatal("bad hash %H", b->commit->tree); + unref(b); + } + difftrees(at, bt); + unref(at); + unref(bt); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-pcr] query\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int i, j, n; + Hash *h; + char *p, *e, *s, *objpfx; + char query[2048], repo[512]; + + ARGBEGIN{ + case 'd': chattygit++; break; + case 'p': fullpath++; break; + case 'c': changes++; break; + case 'r': reverse ^= 1; break; + default: usage(); break; + }ARGEND; + + gitinit(); + fmtinstall('P', Pfmt); + + if(argc == 0) + usage(); + if(findrepo(repo, sizeof(repo)) == -1) + sysfatal("find root: %r"); + if(chdir(repo) == -1) + sysfatal("chdir: %r"); + if((objpfx = smprint("%s/.git/fs/object/", repo)) == nil) + sysfatal("smprint: %r"); + s = ""; + p = query; + e = query + nelem(query); + for(i = 0; i < argc; i++){ + p = seprint(p, e, "%s%s", s, argv[i]); + s = " "; + } + if((n = resolverefs(&h, query)) == -1) + sysfatal("resolve: %r"); + if(changes){ + if(n != 2) + sysfatal("diff: need 2 commits, got %d", n); + diffcommits(h[0], h[1]); + }else{ + p = (fullpath ? objpfx : ""); + for(j = 0; j < n; j++) + print("%s%H\n", p, h[reverse ? n - 1 - j : j]); + } + exits(nil); +} + diff --git a/sys/src/cmd/git/rebase b/sys/src/cmd/git/rebase new file mode 100755 index 0000000000..395f3e6936 --- /dev/null +++ b/sys/src/cmd/git/rebase @@ -0,0 +1,92 @@ +#!/bin/rc + +. /sys/lib/git/common.rc +gitup + +flagfmt='a:abort, r:resume, i:interactive'; args='onto' +eval `''{aux/getflags $*} || exec aux/usage + +tmp=_rebase.working +if(! git/walk -q) + die dirty working tree +if(~ $#abort 1){ + if(! test -f .git/rebase.todo) + die no rebase to abort + src=`{cat .git/rebase.src} + rm -f .git/rebase.^(src todo) + git/branch $src + git/branch -d $tmp + exit +} +if(test -f .git/rebase.todo){ + if(~ $#resume 0) + die rebase in progress + if(! ~ $#* 0) + exec aux/usage + src=`{cat .git/rebase.src} +} +if not{ + if(! ~ $#* 1) + exec aux/usage + src=`{git/branch} + dst=`{git/query $1} + echo $src > .git/rebase.src + git/log -se $dst' '$src' @ .. '$src | sed 's/^/pick /' >.git/rebase.todo + if(! ~ $#interactive 0){ + giteditor=`{git/conf core.editor} + if(~ $#editor 0) + editor=$giteditor + if(~ $#editor 0) + editor=hold + $editor .git/rebase.todo + } + git/branch -nb $dst $tmp +} +todo=`$nl{cat .git/rebase.todo} + +fn sigexit { + s=$status + if(!) + echo 'fix and git/rebase -r' + >.git/rebase.todo for(i in $todo) + echo $i + status=$s +} + +flag e + + +while(! ~ $#todo 0){ + item=`{echo $todo(1)} + todo=$todo(2-) + echo $item + c=$item(2) + switch($item(1)){ + case p pick + git/export $c | git/import + case r reword + git/export $c | git/import + git/commit -re + case e edit + git/export $c | git/import + echo 'stopped for edit, resume with git/rebase -r' + exit + case s squash + git/export $c | git/import -n + msg=`''{cat $gitfs/HEAD/msg; echo; cat $gitfs/object/$c/msg} + git/commit -rem $msg . + case f fixup + git/export $c | git/import -n + git/commit -r . + case b break + echo 'stopped, resume with git/rebase -r' + exit + case '#'* '' + case * + die 'unknown command '''^$item(1)^'''' + } +} + +fn sigexit +git/branch -nb $tmp $src +git/branch -d $tmp +rm .git/rebase.todo .git/rebase.src diff --git a/sys/src/cmd/git/ref.c b/sys/src/cmd/git/ref.c new file mode 100644 index 0000000000..11eea7a077 --- /dev/null +++ b/sys/src/cmd/git/ref.c @@ -0,0 +1,567 @@ +#include +#include +#include + +#include "git.h" + +typedef struct Eval Eval; + +enum { + Blank, + Keep, + Drop, + Skip, +}; + +struct Eval { + char *str; + char *p; + Object **stk; + int nstk; + int stksz; +}; + +static char *colors[] = { +[Keep] "keep", +[Drop] "drop", +[Blank] "blank", +[Skip] "skip", +}; + +static Object zcommit = { + .type=GCommit +}; + +void +eatspace(Eval *ev) +{ + while(isspace(ev->p[0])) + ev->p++; +} + +void +push(Eval *ev, Object *o) +{ + if(ev->nstk == ev->stksz){ + ev->stksz = 2*ev->stksz + 1; + ev->stk = erealloc(ev->stk, ev->stksz*sizeof(Object*)); + } + ev->stk[ev->nstk++] = o; +} + +Object* +pop(Eval *ev) +{ + if(ev->nstk == 0) + sysfatal("stack underflow"); + return ev->stk[--ev->nstk]; +} + +Object* +peek(Eval *ev) +{ + if(ev->nstk == 0) + sysfatal("stack underflow"); + return ev->stk[ev->nstk - 1]; +} + +int +isword(char e) +{ + return isalnum(e) || e == '/' || e == '-' || e == '_' || e == '.'; +} + +int +word(Eval *ev, char *b, int nb) +{ + char *p, *e; + int n; + + p = ev->p; + for(e = p; isword(*e) && strncmp(e, "..", 2) != 0; e++) + /* nothing */; + /* 1 for nul terminator */ + n = e - p + 1; + if(n >= nb) + n = nb; + snprint(b, n, "%s", p); + ev->p = e; + return n > 0; +} + +int +take(Eval *ev, char *m) +{ + int l; + + l = strlen(m); + if(strncmp(ev->p, m, l) != 0) + return 0; + ev->p += l; + return 1; +} + +static int +paint(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres, int ancestor) +{ + Qelt e; + Objq objq; + Objset keep, drop, skip; + Object *o, *c; + int i, nskip; + + osinit(&keep); + osinit(&drop); + osinit(&skip); + qinit(&objq); + nskip = 0; + + for(i = 0; i < nhead; i++){ + if((o = readobject(head[i])) == nil){ + fprint(2, "warning: %H does not point at commit\n", o->hash); + werrstr("read head %H: %r", head[i]); + return -1; + } + if(o->type != GCommit){ + fprint(2, "warning: %H does not point at commit\n", o->hash); + unref(o); + continue; + } + dprint(1, "init: keep %H\n", o->hash); + qput(&objq, o, Keep); + unref(o); + } + for(i = 0; i < ntail; i++){ + if((o = readobject(tail[i])) == nil){ + werrstr("read tail %H: %r", tail[i]); + return -1; + } + if(o->type != GCommit){ + fprint(2, "warning: %H does not point at commit\n", o->hash); + unref(o); + continue; + } + dprint(1, "init: drop %H\n", o->hash); + qput(&objq, o, Drop); + unref(o); + } + + dprint(1, "finding twixt commits\n"); + while(nskip != objq.nheap && qpop(&objq, &e)){ + if(e.color == Skip) + nskip--; + if(oshas(&skip, e.o->hash)) + continue; + switch(e.color){ + case Keep: + if(oshas(&keep, e.o->hash)) + continue; + if(oshas(&drop, e.o->hash)) + e.color = Skip; + osadd(&keep, e.o); + break; + case Drop: + if(oshas(&drop, e.o->hash)) + continue; + if(oshas(&keep, e.o->hash)) + e.color = Skip; + osadd(&drop, e.o); + break; + case Skip: + osadd(&skip, e.o); + break; + } + o = readobject(e.o->hash); + for(i = 0; i < o->commit->nparent; i++){ + if((c = readobject(e.o->commit->parent[i])) == nil) + goto error; + if(c->type != GCommit){ + fprint(2, "warning: %H does not point at commit\n", c->hash); + unref(c); + continue; + } + dprint(2, "\tenqueue: %s %H\n", colors[e.color], c->hash); + qput(&objq, c, e.color); + unref(c); + if(e.color == Skip) + nskip++; + } + unref(o); + } + if(ancestor){ + dprint(1, "found ancestor\n"); + o = nil; + for(i = 0; i < keep.sz; i++){ + o = keep.obj[i]; + if(o != nil && oshas(&drop, o->hash) && !oshas(&skip, o->hash)) + break; + } + if(i == keep.sz){ + *nres = 0; + *res = nil; + }else{ + *nres = 1; + *res = eamalloc(1, sizeof(Object*)); + (*res)[0] = o; + } + }else{ + dprint(1, "found twixt\n"); + *res = eamalloc(keep.nobj, sizeof(Object*)); + *nres = 0; + for(i = 0; i < keep.sz; i++){ + o = keep.obj[i]; + if(o != nil && !oshas(&drop, o->hash) && !oshas(&skip, o->hash)){ + (*res)[*nres] = o; + (*nres)++; + } + } + } + osclear(&keep); + osclear(&drop); + osclear(&skip); + return 0; +error: + dprint(1, "twixt error: %r\n"); + free(objq.heap); + return -1; +} + +int +findtwixt(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres) +{ + return paint(head, nhead, tail, ntail, res, nres, 0); +} + +Object* +ancestor(Object *a, Object *b) +{ + Object **o, *r; + int n; + + if(paint(&a->hash, 1, &b->hash, 1, &o, &n, 1) == -1 || n == 0) + return nil; + r = ref(o[0]); + free(o); + return r; +} + +int +lca(Eval *ev) +{ + Object *a, *b, **o; + int n; + + if(ev->nstk < 2){ + werrstr("ancestor needs 2 objects"); + return -1; + } + n = 0; + b = pop(ev); + a = pop(ev); + paint(&a->hash, 1, &b->hash, 1, &o, &n, 1); + if(n == 0) + return -1; + push(ev, *o); + free(o); + return 0; +} + +static int +parent(Eval *ev) +{ + Object *o, *p; + + o = pop(ev); + /* Special case: first commit has no parent. */ + if(o->commit->nparent == 0) + p = emptydir(); + else if ((p = readobject(o->commit->parent[0])) == nil){ + werrstr("no parent for %H", o->hash); + return -1; + } + + push(ev, p); + return 0; +} + +static int +unwind(Eval *ev, Object **obj, int *idx, int nobj, Object **p, Objset *set, int keep) +{ + int i; + + for(i = nobj; i >= 0; i--){ + idx[i]++; + if(keep && !oshas(set, obj[i]->hash)){ + push(ev, obj[i]); + osadd(set, obj[i]); + }else{ + osadd(set, obj[i]); + } + if(idx[i] < obj[i]->commit->nparent){ + *p = obj[i]; + return i; + } + unref(obj[i]); + } + return -1; +} + +static int +range(Eval *ev) +{ + Object *a, *b, *p, *q, **all; + int nall, *idx; + Objset keep, skip; + + b = pop(ev); + a = pop(ev); + if(hasheq(&b->hash, &Zhash)) + b = &zcommit; + if(hasheq(&a->hash, &Zhash)) + a = &zcommit; + if(a->type != GCommit || b->type != GCommit){ + werrstr("non-commit object in range"); + return -1; + } + + p = b; + all = nil; + idx = nil; + nall = 0; + osinit(&keep); + osinit(&skip); + osadd(&keep, a); + while(1){ + all = earealloc(all, (nall + 1), sizeof(Object*)); + idx = earealloc(idx, (nall + 1), sizeof(int)); + all[nall] = p; + idx[nall] = 0; + if(p == a || p->commit->nparent == 0 && a == &zcommit){ + if((nall = unwind(ev, all, idx, nall, &p, &keep, 1)) == -1) + break; + }else if(p->commit->nparent == 0){ + if((nall = unwind(ev, all, idx, nall, &p, &skip, 0)) == -1) + break; + }else if(oshas(&keep, p->hash)){ + if((nall = unwind(ev, all, idx, nall, &p, &keep, 1)) == -1) + break; + }else if(oshas(&skip, p->hash)) + if((nall = unwind(ev, all, idx, nall, &p, &skip, 0)) == -1) + break; + if(p->commit->nparent == 0) + break; + if((q = readobject(p->commit->parent[idx[nall]])) == nil){ + werrstr("bad commit %H", p->commit->parent[idx[nall]]); + goto error; + } + if(q->type != GCommit){ + werrstr("not commit: %H", q->hash); + goto error; + } + p = q; + nall++; + } + free(all); + return 0; +error: + free(all); + return -1; +} + +int +readref(Hash *h, char *ref) +{ + static char *try[] = {"", "refs/", "refs/heads/", "refs/remotes/", "refs/tags/", nil}; + char buf[256], s[256], **pfx; + int r, f, n; + + /* TODO: support hash prefixes */ + if((r = hparse(h, ref)) != -1) + return r; + if(strcmp(ref, "HEAD") == 0){ + snprint(buf, sizeof(buf), ".git/HEAD"); + if((f = open(buf, OREAD)) == -1) + return -1; + if((n = readn(f, s, sizeof(s) - 1))== -1) + return -1; + s[n] = 0; + strip(s); + r = hparse(h, s); + goto found; + } + for(pfx = try; *pfx; pfx++){ + snprint(buf, sizeof(buf), ".git/%s%s", *pfx, ref); + if((f = open(buf, OREAD)) == -1) + continue; + if((n = readn(f, s, sizeof(s) - 1)) == -1) + continue; + s[n] = 0; + strip(s); + r = hparse(h, s); + close(f); + goto found; + } + return -1; + +found: + if(r == -1 && strstr(s, "ref: ") == s) + r = readref(h, s + strlen("ref: ")); + return r; +} + +int +evalpostfix(Eval *ev) +{ + char name[256]; + Object *o; + Hash h; + + eatspace(ev); + if(!word(ev, name, sizeof(name))){ + werrstr("expected name in expression"); + return -1; + } + if(readref(&h, name) == -1){ + werrstr("invalid ref %s", name); + return -1; + } + if(hasheq(&h, &Zhash)) + o = &zcommit; + else if((o = readobject(h)) == nil){ + werrstr("invalid ref %s (hash %H)", name, h); + return -1; + } + push(ev, o); + + while(1){ + eatspace(ev); + switch(ev->p[0]){ + case '^': + case '~': + ev->p++; + if(parent(ev) == -1) + return -1; + break; + case '@': + ev->p++; + if(lca(ev) == -1) + return -1; + break; + default: + goto done; + break; + } + } +done: + return 0; +} + +int +evalexpr(Eval *ev, char *ref) +{ + memset(ev, 0, sizeof(*ev)); + ev->str = ref; + ev->p = ref; + + while(1){ + if(evalpostfix(ev) == -1) + return -1; + if(ev->p[0] == '\0') + return 0; + else if(take(ev, ":") || take(ev, "..")){ + if(evalpostfix(ev) == -1) + return -1; + if(ev->p[0] != '\0'){ + werrstr("junk at end of expression"); + return -1; + } + return range(ev); + } + } +} + +int +resolverefs(Hash **r, char *ref) +{ + Eval ev; + Hash *h; + int i; + + if(evalexpr(&ev, ref) == -1){ + free(ev.stk); + return -1; + } + h = eamalloc(ev.nstk, sizeof(Hash)); + for(i = 0; i < ev.nstk; i++) + h[i] = ev.stk[i]->hash; + *r = h; + free(ev.stk); + return ev.nstk; +} + +int +resolveref(Hash *r, char *ref) +{ + Eval ev; + + if(evalexpr(&ev, ref) == -1){ + free(ev.stk); + return -1; + } + if(ev.nstk != 1){ + werrstr("ambiguous ref expr"); + free(ev.stk); + return -1; + } + *r = ev.stk[0]->hash; + free(ev.stk); + return 0; +} + +int +readrefdir(Hash **refs, char ***names, int *nrefs, char *dpath, char *dname) +{ + Dir *d, *e, *dir; + char *path, *name, *sep; + int ndir; + + if((ndir = slurpdir(dpath, &dir)) == -1) + return -1; + sep = (*dname == '\0') ? "" : "/"; + e = dir + ndir; + for(d = dir; d != e; d++){ + path = smprint("%s/%s", dpath, d->name); + name = smprint("%s%s%s", dname, sep, d->name); + if(d->mode & DMDIR) { + if(readrefdir(refs, names, nrefs, path, name) == -1) + goto noref; + }else{ + *refs = erealloc(*refs, (*nrefs + 1)*sizeof(Hash)); + *names = erealloc(*names, (*nrefs + 1)*sizeof(char*)); + if(resolveref(&(*refs)[*nrefs], name) == -1) + goto noref; + (*names)[*nrefs] = name; + *nrefs += 1; + goto next; + } +noref: free(name); +next: free(path); + } + free(dir); + return 0; +} + +int +listrefs(Hash **refs, char ***names) +{ + int nrefs; + + *refs = nil; + *names = nil; + nrefs = 0; + if(readrefdir(refs, names, &nrefs, ".git/refs", "") == -1){ + free(*refs); + return -1; + } + return nrefs; +} diff --git a/sys/src/cmd/git/repack.c b/sys/src/cmd/git/repack.c new file mode 100644 index 0000000000..601231b015 --- /dev/null +++ b/sys/src/cmd/git/repack.c @@ -0,0 +1,85 @@ +#include +#include + +#include "git.h" + +#define TMPPATH(suff) (".git/objects/pack/repack."suff) + +int +cleanup(Hash h) +{ + char newpfx[42], dpath[256], fpath[256]; + int i, j, nd; + Dir *d; + + snprint(newpfx, sizeof(newpfx), "%H.", h); + for(i = 0; i < 256; i++){ + snprint(dpath, sizeof(dpath), ".git/objects/%02x", i); + if((nd = slurpdir(dpath, &d)) == -1) + continue; + for(j = 0; j < nd; j++){ + snprint(fpath, sizeof(fpath), ".git/objects/%02x/%s", i, d[j].name); + remove(fpath); + } + remove(dpath); + free(d); + } + snprint(dpath, sizeof(dpath), ".git/objects/pack"); + if((nd = slurpdir(dpath, &d)) == -1) + return -1; + for(i = 0; i < nd; i++){ + if(strncmp(d[i].name, newpfx, strlen(newpfx)) == 0) + continue; + snprint(fpath, sizeof(fpath), ".git/objects/pack/%s", d[i].name); + remove(fpath); + } + return 0; +} + +void +usage(void) +{ + fprint(2, "usage: %s [-d]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char path[128], **names; + int fd, nrefs; + Hash *refs, h; + Dir rn; + + ARGBEGIN{ + case 'd': + chattygit++; + break; + default: + usage(); + }ARGEND; + + gitinit(); + refs = nil; + if((nrefs = listrefs(&refs, &names)) == -1) + sysfatal("load refs: %r"); + if((fd = create(TMPPATH("pack.tmp"), OWRITE, 0644)) == -1) + sysfatal("open %s: %r", TMPPATH("pack.tmp")); + if(writepack(fd, refs, nrefs, nil, 0, &h) == -1) + sysfatal("writepack: %r"); + if(indexpack(TMPPATH("pack.tmp"), TMPPATH("idx.tmp"), h) == -1) + sysfatal("indexpack: %r"); + close(fd); + + nulldir(&rn); + rn.name = path; + snprint(path, sizeof(path), "%H.pack", h); + if(dirwstat(TMPPATH("pack.tmp"), &rn) == -1) + sysfatal("rename pack: %r"); + snprint(path, sizeof(path), "%H.idx", h); + if(dirwstat(TMPPATH("idx.tmp"), &rn) == -1) + sysfatal("rename pack: %r"); + if(cleanup(h) == -1) + sysfatal("cleanup: %r"); + exits(nil); +} diff --git a/sys/src/cmd/git/revert b/sys/src/cmd/git/revert new file mode 100644 index 0000000000..1adb0d2e60 --- /dev/null +++ b/sys/src/cmd/git/revert @@ -0,0 +1,22 @@ +#!/bin/rc +rfork en +. /sys/lib/git/common.rc + +gitup + +flagfmt='c:query query' args='file ...' +if (! eval `''{aux/getflags $*} || ~ $#* 0) + exec aux/usage + +commit=$gitfs/HEAD +if(~ $#query 1) + commit=`{git/query -p $query} + +files=`$nl{cleanname -d $gitrel $* | drop $gitroot} +for(f in `$nl{cd $commit/tree/ && walk -f ./$files}){ + mkdir -p `{basename -d $f} + cp -x -- $commit/tree/$f $f + touch $f + git/add $f +} +exit '' diff --git a/sys/src/cmd/git/rm b/sys/src/cmd/git/rm new file mode 100755 index 0000000000..deaf3ae5a4 --- /dev/null +++ b/sys/src/cmd/git/rm @@ -0,0 +1,3 @@ +#!/bin/rc -e + +exec git/add -r $* diff --git a/sys/src/cmd/git/save.c b/sys/src/cmd/git/save.c new file mode 100644 index 0000000000..08a1a50cf1 --- /dev/null +++ b/sys/src/cmd/git/save.c @@ -0,0 +1,434 @@ +#include +#include +#include "git.h" + +typedef struct Objbuf Objbuf; +struct Objbuf { + int off; + char *hdr; + int nhdr; + char *dat; + int ndat; +}; +enum { + Maxparents = 16, +}; + +char *authorname; +char *authoremail; +char *committername; +char *committeremail; +char *commitmsg; +Hash parents[Maxparents]; +int nparents; + +int +gitmode(Dirent *e) +{ + if(e->islink) + return 0120000; + else if(e->ismod) + return 0160000; + else if(e->mode & DMDIR) + return 0040000; + else if(e->mode & 0111) + return 0100755; + else + return 0100644; +} + +int +entcmp(void *pa, void *pb) +{ + char abuf[256], bbuf[256], *ae, *be; + Dirent *a, *b; + + a = pa; + b = pb; + /* + * If the files have the same name, they're equal. + * Otherwise, If they're trees, they sort as thoug + * there was a trailing slash. + * + * Wat. + */ + if(strcmp(a->name, b->name) == 0) + return 0; + + ae = seprint(abuf, abuf + sizeof(abuf) - 1, a->name); + be = seprint(bbuf, bbuf + sizeof(bbuf) - 1, b->name); + if(a->mode & DMDIR) + *ae = '/'; + if(b->mode & DMDIR) + *be = '/'; + return strcmp(abuf, bbuf); +} + +static int +bwrite(void *p, void *buf, int nbuf) +{ + return Bwrite(p, buf, nbuf); +} + +static int +objbytes(void *p, void *buf, int nbuf) +{ + Objbuf *b; + int r, n, o; + char *s; + + b = p; + n = 0; + if(b->off < b->nhdr){ + r = b->nhdr - b->off; + r = (nbuf < r) ? nbuf : r; + memcpy(buf, b->hdr, r); + b->off += r; + nbuf -= r; + n += r; + } + if(b->off < b->ndat + b->nhdr){ + s = buf; + o = b->off - b->nhdr; + r = b->ndat - o; + r = (nbuf < r) ? nbuf : r; + memcpy(s + n, b->dat + o, r); + b->off += r; + n += r; + } + return n; +} + +void +writeobj(Hash *h, char *hdr, int nhdr, char *dat, int ndat) +{ + Objbuf b = {.off=0, .hdr=hdr, .nhdr=nhdr, .dat=dat, .ndat=ndat}; + char s[64], o[256]; + SHA1state *st; + Biobuf *f; + int fd; + + st = sha1((uchar*)hdr, nhdr, nil, nil); + st = sha1((uchar*)dat, ndat, nil, st); + sha1(nil, 0, h->h, st); + + snprint(s, sizeof(s), "%H", *h); + fd = create(".git/objects", OREAD, DMDIR|0755); + close(fd); + snprint(o, sizeof(o), ".git/objects/%c%c", s[0], s[1]); + fd = create(o, OREAD, DMDIR | 0755); + close(fd); + snprint(o, sizeof(o), ".git/objects/%c%c/%s", s[0], s[1], s + 2); + if(readobject(*h) == nil){ + if((f = Bopen(o, OWRITE)) == nil) + sysfatal("could not open %s: %r", o); + if(deflatezlib(f, bwrite, &b, objbytes, 9, 0) == -1) + sysfatal("could not write %s: %r", o); + Bterm(f); + } +} + +int +writetree(Dirent *ent, int nent, Hash *h) +{ + char *t, *txt, *etxt, hdr[128]; + int nhdr, n; + Dirent *d, *p; + + t = emalloc((16+256+20) * nent); + txt = t; + etxt = t + (16+256+20) * nent; + + /* sqeeze out deleted entries */ + n = 0; + p = ent; + for(d = ent; d != ent + nent; d++) + if(d->name) + p[n++] = *d; + nent = n; + + qsort(ent, nent, sizeof(Dirent), entcmp); + for(d = ent; d != ent + nent; d++){ + if(strlen(d->name) >= 255) + sysfatal("overly long filename: %s", d->name); + t = seprint(t, etxt, "%o %s", gitmode(d), d->name) + 1; + memcpy(t, d->h.h, sizeof(d->h.h)); + t += sizeof(d->h.h); + } + nhdr = snprint(hdr, sizeof(hdr), "%T %lld", GTree, (vlong)(t - txt)) + 1; + writeobj(h, hdr, nhdr, txt, t - txt); + free(txt); + return nent; +} + +void +blobify(Dir *d, char *path, int *mode, Hash *bh) +{ + char h[64], *buf; + int f, nh; + + if((d->mode & DMDIR) != 0) + sysfatal("not file: %s", path); + *mode = d->mode; + nh = snprint(h, sizeof(h), "%T %lld", GBlob, d->length) + 1; + if((f = open(path, OREAD)) == -1) + sysfatal("could not open %s: %r", path); + buf = emalloc(d->length); + if(readn(f, buf, d->length) != d->length) + sysfatal("could not read blob %s: %r", path); + writeobj(bh, h, nh, buf, d->length); + free(buf); + close(f); +} + +int +tracked(char *path) +{ + char ipath[256]; + Dir *d; + + /* Explicitly removed. */ + snprint(ipath, sizeof(ipath), ".git/index9/removed/%s", path); + if(strstr(cleanname(ipath), ".git/index9/removed") != ipath) + sysfatal("path %s leaves index", ipath); + d = dirstat(ipath); + if(d != nil && d->qid.type != QTDIR){ + free(d); + return 0; + } + + /* Explicitly added. */ + snprint(ipath, sizeof(ipath), ".git/index9/tracked/%s", path); + if(strstr(cleanname(ipath), ".git/index9/tracked") != ipath) + sysfatal("path %s leaves index", ipath); + if(access(ipath, AEXIST) == 0) + return 1; + + return 0; +} + +int +pathelt(char *buf, int nbuf, char *p, int *isdir) +{ + char *b; + + b = buf; + if(*p == '/') + p++; + while(*p && *p != '/' && b != buf + nbuf) + *b++ = *p++; + *b = '\0'; + *isdir = (*p == '/'); + return b - buf; +} + +Dirent* +dirent(Dirent **ent, int *nent, char *name) +{ + Dirent *d; + + for(d = *ent; d != *ent + *nent; d++) + if(d->name && strcmp(d->name, name) == 0) + return d; + *nent += 1; + *ent = erealloc(*ent, *nent * sizeof(Dirent)); + d = *ent + (*nent - 1); + memset(d, 0, sizeof(*d)); + d->name = estrdup(name); + return d; +} + +int +treeify(Object *t, char **path, char **epath, int off, Hash *h) +{ + int r, n, ne, nsub, nent, isdir; + char **p, **ep; + char elt[256]; + Object **sub; + Dirent *e, *ent; + Dir *d; + + r = -1; + nsub = 0; + nent = t->tree->nent; + ent = eamalloc(nent, sizeof(*ent)); + sub = eamalloc((epath - path), sizeof(Object*)); + memcpy(ent, t->tree->ent, nent*sizeof(*ent)); + for(p = path; p != epath; p = ep){ + ne = pathelt(elt, sizeof(elt), *p + off, &isdir); + for(ep = p; ep != epath; ep++){ + if(strncmp(elt, *ep + off, ne) != 0) + break; + if((*ep)[off+ne] != '\0' && (*ep)[off+ne] != '/') + break; + } + e = dirent(&ent, &nent, elt); + if(e->islink) + sysfatal("symlinks may not be modified: %s", *path); + if(e->ismod) + sysfatal("submodules may not be modified: %s", *path); + if(isdir){ + e->mode = DMDIR | 0755; + sub[nsub] = readobject(e->h); + if(sub[nsub] == nil || sub[nsub]->type != GTree) + sub[nsub] = emptydir(); + /* + * if after processing deletions, a tree is empty, + * mark it for removal from the parent. + * + * Note, it is still written to the object store, + * but this is fine -- and ensures that an empty + * repository will continue to work. + */ + n = treeify(sub[nsub], p, ep, off + ne + 1, &e->h); + if(n == 0) + e->name = nil; + else if(n == -1) + goto err; + }else{ + d = dirstat(*p); + if(d != nil && tracked(*p)) + blobify(d, *p, &e->mode, &e->h); + else + e->name = nil; + free(d); + } + } + if(nent == 0){ + werrstr("%.*s: empty directory", off, *path); + goto err; + } + + r = writetree(ent, nent, h); +err: + free(sub); + return r; +} + + +void +mkcommit(Hash *c, vlong date, Hash tree) +{ + char *s, h[64]; + int ns, nh, i; + Fmt f; + + fmtstrinit(&f); + fmtprint(&f, "tree %H\n", tree); + for(i = 0; i < nparents; i++) + fmtprint(&f, "parent %H\n", parents[i]); + fmtprint(&f, "author %s <%s> %lld +0000\n", authorname, authoremail, date); + fmtprint(&f, "committer %s <%s> %lld +0000\n", committername, committeremail, date); + fmtprint(&f, "\n"); + fmtprint(&f, "%s", commitmsg); + s = fmtstrflush(&f); + + ns = strlen(s); + nh = snprint(h, sizeof(h), "%T %d", GCommit, ns) + 1; + writeobj(c, h, nh, s, ns); + free(s); +} + +Object* +findroot(void) +{ + Object *t, *c; + Hash h; + + if(resolveref(&h, "HEAD") == -1) + return emptydir(); + if((c = readobject(h)) == nil || c->type != GCommit) + sysfatal("could not read HEAD %H", h); + if((t = readobject(c->commit->tree)) == nil) + sysfatal("could not read tree for commit %H", h); + return t; +} + +void +usage(void) +{ + fprint(2, "usage: %s -n name -e email -m message -d date [files...]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Hash th, ch; + char *dstr, cwd[1024]; + int i, r, ncwd; + vlong date; + Object *t; + + gitinit(); + if(access(".git", AEXIST) != 0) + sysfatal("could not find git repo: %r"); + if(getwd(cwd, sizeof(cwd)) == nil) + sysfatal("getcwd: %r"); + dstr = nil; + date = time(nil); + ncwd = strlen(cwd); + + ARGBEGIN{ + case 'm': + commitmsg = EARGF(usage()); + break; + case 'n': + authorname = EARGF(usage()); + break; + case 'e': + authoremail = EARGF(usage()); + break; + case 'N': + committername = EARGF(usage()); + break; + case 'E': + committeremail = EARGF(usage()); + break; + case 'd': + dstr = EARGF(usage()); + break; + case 'p': + if(nparents >= Maxparents) + sysfatal("too many parents"); + if(resolveref(&parents[nparents++], EARGF(usage())) == -1) + sysfatal("invalid parent: %r"); + break; + default: + usage(); + break; + }ARGEND; + + if(commitmsg == nil) + sysfatal("missing message"); + if(authorname == nil) + sysfatal("missing name"); + if(authoremail == nil) + sysfatal("missing email"); + if((committername == nil) != (committeremail == nil)) + sysfatal("partially specified committer"); + if(committername == nil && committeremail == nil){ + committername = authorname; + committeremail = authoremail; + } + if(dstr){ + date=strtoll(dstr, &dstr, 10); + if(strlen(dstr) != 0) + sysfatal("could not parse date %s", dstr); + } + for(i = 0; i < argc; i++){ + cleanname(argv[i]); + if(*argv[i] == '/' && strncmp(argv[i], cwd, ncwd) == 0) + argv[i] += ncwd; + while(*argv[i] == '/') + argv[i]++; + } + + t = findroot(); + r = treeify(t, argv, argv + argc, 0, &th); + if(r == -1) + sysfatal("could not commit: %r\n"); + mkcommit(&ch, date, th); + print("%H\n", ch); + exits(nil); +} diff --git a/sys/src/cmd/git/send.c b/sys/src/cmd/git/send.c new file mode 100644 index 0000000000..1188a71fa7 --- /dev/null +++ b/sys/src/cmd/git/send.c @@ -0,0 +1,313 @@ +#include +#include + +#include "git.h" + +typedef struct Capset Capset; +typedef struct Map Map; + +struct Capset { + int sideband; + int sideband64k; + int report; +}; + +struct Map { + char *ref; + Hash ours; + Hash theirs; +}; + +int sendall; +int force; +int nbranch; +char **branch; +char *removed[128]; +int nremoved; +int npacked; +int nsent; + +int +findref(char **r, int nr, char *ref) +{ + int i; + for(i = 0; i < nr; i++) + if(strcmp(r[i], ref) == 0) + return i; + return -1; +} + +int +findkey(Map *m, int nm, char *ref) +{ + int i; + for(i = 0; i < nm; i++) + if(strcmp(m[i].ref, ref) == 0) + return i; + return -1; +} + +int +readours(Hash **tailp, char ***refp) +{ + int nu, i, idx; + char *r, *pfx, **ref; + Hash *tail; + + if(sendall) + return listrefs(tailp, refp); + nu = 0; + tail = eamalloc((nremoved + nbranch), sizeof(Hash)); + ref = eamalloc((nremoved + nbranch), sizeof(char*)); + for(i = 0; i < nbranch; i++){ + ref[nu] = estrdup(branch[i]); + if(resolveref(&tail[nu], branch[i]) == -1) + sysfatal("broken branch %s", branch[i]); + nu++; + } + for(i = 0; i < nremoved; i++){ + pfx = "refs/heads/"; + if(strstr(removed[i], "heads/") == removed[i]) + pfx = "refs/"; + if(strstr(removed[i], "refs/heads/") == removed[i]) + pfx = ""; + if((r = smprint("%s%s", pfx, removed[i])) == nil) + sysfatal("smprint: %r"); + if((idx = findref(ref, nu, r)) == -1) + idx = nu++; + assert(idx < nremoved + nbranch); + memcpy(&tail[idx], &Zhash, sizeof(Hash)); + free(r); + } + dprint(1, "nu: %d\n", nu); + for(i = 0; i < nu; i++) + dprint(1, "update: %H %s\n", tail[i], ref[i]); + *tailp = tail; + *refp = ref; + return nu; +} + +char * +matchcap(char *s, char *cap, int full) +{ + if(strncmp(s, cap, strlen(cap)) == 0) + if(!full || strlen(s) == strlen(cap)) + return s + strlen(cap); + return nil; +} + +void +parsecaps(char *caps, Capset *cs) +{ + char *p, *n; + + for(p = caps; p != nil; p = n){ + n = strchr(p, ' '); + if(n != nil) + *n++ = 0; + if(matchcap(p, "report-status", 1) != nil) + cs->report = 1; + if(matchcap(p, "side-band", 1) != nil) + cs->sideband = 1; + if(matchcap(p, "side-band-64k", 1) != nil) + cs->sideband64k = 1; + } +} + +int +sendpack(Conn *c) +{ + int i, n, idx, nsp, send, first; + int nours, ntheirs, nmap; + char buf[Pktmax], *sp[3]; + Hash h, *theirs, *ours; + Object *a, *b, *p, *o; + char **refs; + Capset cs; + Map *map, *m; + + first = 1; + memset(&cs, 0, sizeof(Capset)); + nours = readours(&ours, &refs); + theirs = nil; + ntheirs = 0; + nmap = nours; + map = eamalloc(nmap, sizeof(Map)); + for(i = 0; i < nmap; i++){ + map[i].theirs = Zhash; + map[i].ours = ours[i]; + map[i].ref = refs[i]; + } + while(1){ + n = readpkt(c, buf, sizeof(buf)); + if(n == -1) + return -1; + if(n == 0) + break; + if(first && n > strlen(buf)) + parsecaps(buf + strlen(buf) + 1, &cs); + first = 0; + if(strncmp(buf, "ERR ", 4) == 0) + sysfatal("%s", buf + 4); + + if(getfields(buf, sp, nelem(sp), 1, " \t\r\n") != 2) + sysfatal("invalid ref line %.*s", utfnlen(buf, n), buf); + theirs = earealloc(theirs, ntheirs+1, sizeof(Hash)); + if(hparse(&theirs[ntheirs], sp[0]) == -1) + sysfatal("invalid hash %s", sp[0]); + if((idx = findkey(map, nmap, sp[1])) != -1) + map[idx].theirs = theirs[ntheirs]; + /* + * we only keep their ref if we can read the object to add it + * to our reachability; otherwise, discard it; we only care + * that we don't have it, so we can tell whether we need to + * bail out of pushing. + */ + if((o = readobject(theirs[ntheirs])) != nil){ + ntheirs++; + unref(o); + } + } + + if(writephase(c) == -1) + return -1; + send = 0; + if(force) + send=1; + for(i = 0; i < nmap; i++){ + m = &map[i]; + a = readobject(m->theirs); + if(hasheq(&m->ours, &Zhash)) + b = nil; + else + b = readobject(m->ours); + p = nil; + if(a != nil && b != nil) + p = ancestor(a, b); + if(!force && !hasheq(&m->theirs, &Zhash) && (a == nil || p != a)){ + fprint(2, "remote has diverged\n"); + werrstr("remote diverged"); + flushpkt(c); + return -1; + } + unref(a); + unref(b); + unref(p); + if(hasheq(&m->theirs, &m->ours)){ + print("uptodate %s\n", m->ref); + continue; + } + print("update %s %H %H\n", m->ref, m->theirs, m->ours); + n = snprint(buf, sizeof(buf), "%H %H %s", m->theirs, m->ours, m->ref); + + /* + * Workaround for github. + * + * Github will accept the pack but fail to update the references + * if we don't have capabilities advertised. Report-status seems + * harmless to add, so we add it. + * + * Github doesn't advertise any capabilities, so we can't check + * for compatibility. We just need to add it blindly. + */ + if(i == 0 && cs.report){ + buf[n++] = '\0'; + n += snprint(buf + n, sizeof(buf) - n, " report-status"); + } + if(writepkt(c, buf, n) == -1) + sysfatal("unable to send update pkt"); + send = 1; + } + flushpkt(c); + if(!send){ + fprint(2, "nothing to send\n"); + return 0; + } + + if(writepack(c->wfd, ours, nours, theirs, ntheirs, &h) == -1) + return -1; + if(!cs.report) + return 0; + + if(readphase(c) == -1) + return -1; + /* We asked for a status report, may as well use it. */ + while((n = readpkt(c, buf, sizeof(buf))) > 0){ + buf[n] = 0; + if(chattygit) + fprint(2, "done sending pack, status %s\n", buf); + nsp = getfields(buf, sp, nelem(sp), 1, " \t\n\r"); + if(nsp < 2) + continue; + if(nsp < 3) + sp[2] = ""; + /* + * Only report errors; successes will be reported by + * surrounding scripts. + */ + if(strcmp(sp[0], "unpack") == 0 && strcmp(sp[1], "ok") != 0) + fprint(2, "unpack %s\n", sp[1]); + else if(strcmp(sp[0], "ng") == 0) + fprint(2, "failed update: %s\n", sp[1]); + else + continue; + return -1; + } + return 0; +} + +void +usage(void) +{ + fprint(2, "usage: %s remote [reponame]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *br; + Conn c; + + ARGBEGIN{ + default: + usage(); + break; + case 'd': + chattygit++; + break; + case 'f': + force++; + break; + case 'r': + if(nremoved == nelem(removed)) + sysfatal("too many deleted branches"); + removed[nremoved++] = EARGF(usage()); + break; + case 'a': + sendall++; + break; + case 'b': + br = EARGF(usage()); + if(strncmp(br, "refs/heads/", strlen("refs/heads/")) == 0) + br = smprint("%s", br); + else if(strncmp(br, "heads/", strlen("heads/")) == 0) + br = smprint("refs/%s", br); + else + br = smprint("refs/heads/%s", br); + branch = erealloc(branch, (nbranch + 1)*sizeof(char*)); + branch[nbranch] = br; + nbranch++; + break; + }ARGEND; + + gitinit(); + if(argc != 1) + usage(); + if(gitconnect(&c, argv[0], "receive") == -1) + sysfatal("git connect: %s: %r", argv[0]); + if(sendpack(&c) == -1) + sysfatal("send failed: %r"); + closeconn(&c); + exits(nil); +} diff --git a/sys/src/cmd/git/serve.c b/sys/src/cmd/git/serve.c new file mode 100644 index 0000000000..895c6f5e0e --- /dev/null +++ b/sys/src/cmd/git/serve.c @@ -0,0 +1,553 @@ +#include +#include +#include +#include + +#include "git.h" + +char *pathpfx = nil; +int allowwrite; + +int +fmtpkt(Conn *c, char *fmt, ...) +{ + char pkt[Pktmax]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprint(pkt, sizeof(pkt), fmt, ap); + n = writepkt(c, pkt, n); + va_end(ap); + return n; +} + +int +showrefs(Conn *c) +{ + int i, ret, nrefs; + Hash head, *refs; + char **names; + + ret = -1; + nrefs = 0; + refs = nil; + names = nil; + if(resolveref(&head, "HEAD") != -1) + if(fmtpkt(c, "%H HEAD\n", head) == -1) + goto error; + + if((nrefs = listrefs(&refs, &names)) == -1) + sysfatal("listrefs: %r"); + for(i = 0; i < nrefs; i++){ + if(strncmp(names[i], "heads/", strlen("heads/")) != 0) + continue; + if(fmtpkt(c, "%H refs/%s\n", refs[i], names[i]) == -1) + goto error; + } + if(flushpkt(c) == -1) + goto error; + ret = 0; +error: + for(i = 0; i < nrefs; i++) + free(names[i]); + free(names); + free(refs); + return ret; +} + +int +servnegotiate(Conn *c, Hash **head, int *nhead, Hash **tail, int *ntail) +{ + char pkt[Pktmax]; + int n, acked; + Object *o; + Hash h; + + if(showrefs(c) == -1) + return -1; + + *head = nil; + *tail = nil; + *nhead = 0; + *ntail = 0; + while(1){ + if((n = readpkt(c, pkt, sizeof(pkt))) == -1) + goto error; + if(n == 0) + break; + if(strncmp(pkt, "want ", 5) != 0){ + werrstr(" protocol garble %s", pkt); + goto error; + } + if(hparse(&h, &pkt[5]) == -1){ + werrstr(" garbled want"); + goto error; + } + if((o = readobject(h)) == nil){ + werrstr("requested nonexistent object"); + goto error; + } + unref(o); + *head = erealloc(*head, (*nhead + 1)*sizeof(Hash)); + (*head)[*nhead] = h; + *nhead += 1; + } + + acked = 0; + while(1){ + if((n = readpkt(c, pkt, sizeof(pkt))) == -1) + goto error; + if(strncmp(pkt, "done", 4) == 0) + break; + if(n == 0){ + if(!acked && fmtpkt(c, "NAK") == -1) + goto error; + } + if(strncmp(pkt, "have ", 5) != 0){ + werrstr(" protocol garble %s", pkt); + goto error; + } + if(hparse(&h, &pkt[5]) == -1){ + werrstr(" garbled have"); + goto error; + } + if((o = readobject(h)) == nil) + continue; + if(!acked){ + if(fmtpkt(c, "ACK %H", h) == -1) + goto error; + acked = 1; + } + unref(o); + *tail = erealloc(*tail, (*ntail + 1)*sizeof(Hash)); + (*tail)[*ntail] = h; + *ntail += 1; + } + if(!acked && fmtpkt(c, "NAK\n") == -1) + goto error; + return 0; +error: + fmtpkt(c, "ERR %r\n"); + free(*head); + free(*tail); + return -1; +} + +int +servpack(Conn *c) +{ + Hash *head, *tail, h; + int nhead, ntail; + + dprint(1, "negotiating pack\n"); + if(servnegotiate(c, &head, &nhead, &tail, &ntail) == -1) + sysfatal("negotiate: %r"); + dprint(1, "writing pack\n"); + if(writepack(c->wfd, head, nhead, tail, ntail, &h) == -1) + sysfatal("send: %r"); + return 0; +} + +int +validref(char *s) +{ + if(strncmp(s, "refs/", 5) != 0) + return 0; + for(; *s != '\0'; s++) + if(!isalnum(*s) && strchr("/-_.", *s) == nil) + return 0; + return 1; +} + +int +recvnegotiate(Conn *c, Hash **cur, Hash **upd, char ***ref, int *nupd) +{ + char pkt[Pktmax], *sp[4]; + Hash old, new; + int n, i; + + if(showrefs(c) == -1) + return -1; + *cur = nil; + *upd = nil; + *ref = nil; + *nupd = 0; + while(1){ + if((n = readpkt(c, pkt, sizeof(pkt))) == -1) + goto error; + if(n == 0) + break; + if(getfields(pkt, sp, nelem(sp), 1, " \t\n\r") != 3){ + fmtpkt(c, "ERR protocol garble %s\n", pkt); + goto error; + } + if(hparse(&old, sp[0]) == -1){ + fmtpkt(c, "ERR bad old hash %s\n", sp[0]); + goto error; + } + if(hparse(&new, sp[1]) == -1){ + fmtpkt(c, "ERR bad new hash %s\n", sp[1]); + goto error; + } + if(!validref(sp[2])){ + fmtpkt(c, "ERR invalid ref %s\n", sp[2]); + goto error; + } + *cur = erealloc(*cur, (*nupd + 1)*sizeof(Hash)); + *upd = erealloc(*upd, (*nupd + 1)*sizeof(Hash)); + *ref = erealloc(*ref, (*nupd + 1)*sizeof(Hash)); + (*cur)[*nupd] = old; + (*upd)[*nupd] = new; + (*ref)[*nupd] = estrdup(sp[2]); + *nupd += 1; + } + return 0; +error: + free(*cur); + free(*upd); + for(i = 0; i < *nupd; i++) + free((*ref)[i]); + free(*ref); + return -1; +} + +int +rename(char *pack, char *idx, Hash h) +{ + char name[128], path[196]; + Dir st; + + nulldir(&st); + st.name = name; + snprint(name, sizeof(name), "%H.pack", h); + snprint(path, sizeof(path), ".git/objects/pack/%s", name); + if(access(path, AEXIST) == 0) + fprint(2, "warning, pack %s already pushed\n", name); + else if(dirwstat(pack, &st) == -1) + return -1; + snprint(name, sizeof(name), "%H.idx", h); + snprint(path, sizeof(path), ".git/objects/pack/%s", name); + if(access(path, AEXIST) == 0) + fprint(2, "warning, pack %s already indexed\n", name); + else if(dirwstat(idx, &st) == -1) + return -1; + return 0; +} + +int +checkhash(int fd, vlong sz, Hash *hcomp) +{ + DigestState *st; + Hash hexpect; + char buf[Pktmax]; + vlong n, r; + int nr; + + if(sz < 28){ + werrstr("undersize packfile"); + return -1; + } + + st = nil; + n = 0; + if(seek(fd, 0, 0) == -1) + sysfatal("packfile seek: %r"); + while(n != sz - 20){ + nr = sizeof(buf); + if(sz - n - 20 < sizeof(buf)) + nr = sz - n - 20; + r = readn(fd, buf, nr); + if(r != nr){ + werrstr("short read"); + return -1; + } + st = sha1((uchar*)buf, nr, nil, st); + n += r; + } + sha1(nil, 0, hcomp->h, st); + if(readn(fd, hexpect.h, sizeof(hexpect.h)) != sizeof(hexpect.h)) + sysfatal("truncated packfile"); + if(!hasheq(hcomp, &hexpect)){ + werrstr("bad hash: %H != %H", *hcomp, hexpect); + return -1; + } + return 0; +} + +int +mkdir(char *dir) +{ + char buf[ERRMAX]; + int f; + + if(access(dir, AEXIST) == 0) + return 0; + if((f = create(dir, OREAD, DMDIR | 0755)) == -1){ + rerrstr(buf, sizeof(buf)); + if(strstr(buf, "exist") == nil) + return -1; + } + close(f); + return 0; +} + +int +updatepack(Conn *c) +{ + char buf[Pktmax], packtmp[128], idxtmp[128], ebuf[ERRMAX]; + int n, pfd, packsz; + Hash h; + + /* make sure the needed dirs exist */ + if(mkdir(".git/objects") == -1) + return -1; + if(mkdir(".git/objects/pack") == -1) + return -1; + if(mkdir(".git/refs") == -1) + return -1; + if(mkdir(".git/refs/heads") == -1) + return -1; + snprint(packtmp, sizeof(packtmp), ".git/objects/pack/recv-%d.pack.tmp", getpid()); + snprint(idxtmp, sizeof(idxtmp), ".git/objects/pack/recv-%d.idx.tmp", getpid()); + if((pfd = create(packtmp, ORDWR, 0644)) == -1) + return -1; + packsz = 0; + while(1){ + n = read(c->rfd, buf, sizeof(buf)); + if(n == 0) + break; + if(n == -1){ + rerrstr(ebuf, sizeof(ebuf)); + if(strstr(ebuf, "hungup") == nil) + return -1; + break; + } + if(write(pfd, buf, n) != n) + return -1; + packsz += n; + } + if(checkhash(pfd, packsz, &h) == -1){ + dprint(1, "hash mismatch\n"); + goto error1; + } + if(indexpack(packtmp, idxtmp, h) == -1){ + dprint(1, "indexing failed: %r\n"); + goto error1; + } + if(rename(packtmp, idxtmp, h) == -1){ + dprint(1, "rename failed: %r\n"); + goto error2; + } + return 0; + +error2: remove(idxtmp); +error1: remove(packtmp); + return -1; +} + +int +lockrepo(void) +{ + int fd, i; + + for(i = 0; i < 10; i++) { + if((fd = create(".git/_lock", ORCLOSE|ORDWR|OTRUNC|OEXCL, 0644))!= -1) + return fd; + sleep(250); + } + return -1; +} + +int +updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd) +{ + char refpath[512], buf[128]; + int i, newidx, hadref, fd, ret, lockfd; + vlong newtm; + Object *o; + Hash h; + + ret = -1; + hadref = 0; + newidx = -1; + /* + * Date of Magna Carta. + * Wrong because it was computed using + * the proleptic gregorian calendar. + */ + newtm = -23811206400; + if((lockfd = lockrepo()) == -1){ + snprint(buf, sizeof(buf), "repo locked\n"); + return -1; + } + for(i = 0; i < nupd; i++){ + if(resolveref(&h, ref[i]) == 0){ + hadref = 1; + if(!hasheq(&h, &cur[i])){ + snprint(buf, sizeof(buf), "old ref changed: %s", ref[i]); + goto error; + } + } + if(snprint(refpath, sizeof(refpath), ".git/%s", ref[i]) == sizeof(refpath)){ + snprint(buf, sizeof(buf), "ref path too long: %s", ref[i]); + goto error; + } + if(hasheq(&upd[i], &Zhash)){ + remove(refpath); + continue; + } + if((o = readobject(upd[i])) == nil){ + snprint(buf, sizeof(buf), "update to nonexistent hash %H", upd[i]); + goto error; + } + if(o->type != GCommit){ + snprint(buf, sizeof(buf), "not commit: %H", upd[i]); + goto error; + } + if(o->commit->mtime > newtm){ + newtm = o->commit->mtime; + newidx = i; + } + unref(o); + if((fd = create(refpath, OWRITE|OTRUNC, 0644)) == -1){ + snprint(buf, sizeof(buf), "open ref: %r"); + goto error; + } + if(fprint(fd, "%H", upd[i]) == -1){ + snprint(buf, sizeof(buf), "upate ref: %r"); + close(fd); + goto error; + } + close(fd); + } + /* + * Heuristic: + * If there are no valid refs, and HEAD is invalid, then + * pick the ref with the newest commits as the default + * branch. + * + * Several people have been caught out by pushing to + * a repo where HEAD named differently from what got + * pushed, and this is going to be more of a footgun + * when 'master', 'main', and 'front' are all in active + * use. This should make us pick a useful default in + * those cases, instead of silently failing. + */ + if(resolveref(&h, "HEAD") == -1 && hadref == 0 && newidx != -1){ + if((fd = create(".git/HEAD", OWRITE|OTRUNC, 0644)) == -1){ + snprint(buf, sizeof(buf), "open HEAD: %r"); + goto error; + } + if(fprint(fd, "ref: %s", ref[0]) == -1){ + snprint(buf, sizeof(buf), "write HEAD ref: %r"); + goto error; + } + close(fd); + } + ret = 0; +error: + fmtpkt(c, "ERR %s", buf); + close(lockfd); + werrstr(buf); + return ret; +} + +int +recvpack(Conn *c) +{ + Hash *cur, *upd; + char **ref; + int nupd; + + if(recvnegotiate(c, &cur, &upd, &ref, &nupd) == -1) + sysfatal("negotiate refs: %r"); + if(nupd != 0 && updatepack(c) == -1) + sysfatal("update pack: %r"); + if(nupd != 0 && updaterefs(c, cur, upd, ref, nupd) == -1) + sysfatal("update refs: %r"); + return 0; +} + +char* +parsecmd(char *buf, char *cmd, int ncmd) +{ + int i; + char *p; + + for(p = buf, i = 0; *p && i < ncmd - 1; i++, p++){ + if(*p == ' ' || *p == '\t'){ + cmd[i] = 0; + break; + } + cmd[i] = *p; + } + while(*p == ' ' || *p == '\t') + p++; + return p; +} + +void +usage(void) +{ + fprint(2, "usage: %s [-dw] [-r rel]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *repo, cmd[32], buf[512]; + Conn c; + + ARGBEGIN{ + case 'd': + chattygit++; + break; + case 'r': + pathpfx = EARGF(usage()); + if(*pathpfx != '/') + sysfatal("path prefix must begin with '/'"); + break; + case 'w': + allowwrite++; + break; + default: + usage(); + break; + }ARGEND; + + gitinit(); + interactive = 0; + if(rfork(RFNAMEG) == -1) + sysfatal("rfork: %r"); + if(pathpfx != nil){ + if(bind(pathpfx, "/", MREPL) == -1) + sysfatal("bind: %r"); + } + if(rfork(RFNOMNT) == -1) + sysfatal("rfork: %r"); + + initconn(&c, 0, 1); + if(readpkt(&c, buf, sizeof(buf)) == -1) + sysfatal("readpkt: %r"); + repo = parsecmd(buf, cmd, sizeof(cmd)); + cleanname(repo); + if(strncmp(repo, "../", 3) == 0) + sysfatal("invalid path %s\n", repo); + if(bind(repo, "/", MREPL) == -1){ + fmtpkt(&c, "ERR no repo %r\n"); + sysfatal("enter %s: %r", repo); + } + if(chdir("/") == -1) + sysfatal("chdir: %r"); + if(access(".git", AREAD) == -1) + sysfatal("no git repository"); + if(strcmp(cmd, "git-receive-pack") == 0 && allowwrite) + recvpack(&c); + else if(strcmp(cmd, "git-upload-pack") == 0) + servpack(&c); + else + sysfatal("unsupported command '%s'", cmd); + exits(nil); +} diff --git a/sys/src/cmd/git/util.c b/sys/src/cmd/git/util.c new file mode 100644 index 0000000000..1d2398a7eb --- /dev/null +++ b/sys/src/cmd/git/util.c @@ -0,0 +1,393 @@ +#include +#include +#include + +#include "git.h" + +Reprog *authorpat; +Hash Zhash; + +int chattygit; +int interactive = 1; + +Object* +emptydir(void) +{ + static Object *e; + + if(e != nil) + return ref(e); + e = emalloc(sizeof(Object)); + e->hash = Zhash; + e->type = GTree; + e->tree = emalloc(sizeof(Tinfo)); + e->tree->ent = nil; + e->tree->nent = 0; + e->flag |= Cloaded|Cparsed; + e->off = -1; + ref(e); + cache(e); + return e; +} + +int +hasheq(Hash *a, Hash *b) +{ + return memcmp(a->h, b->h, sizeof(a->h)) == 0; +} + +static int +charval(int c, int *err) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + *err = 1; + return -1; +} + +void * +emalloc(ulong n) +{ + void *v; + + v = mallocz(n, 1); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +void * +eamalloc(ulong n, ulong sz) +{ + uvlong na; + void *v; + + na = (uvlong)n*(uvlong)sz; + if(na >= (1ULL<<30)) + sysfatal("alloc: overflow"); + v = mallocz(na, 1); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +void * +erealloc(void *p, ulong n) +{ + void *v; + + v = realloc(p, n); + if(v == nil) + sysfatal("realloc: %r"); + setmalloctag(v, getcallerpc(&p)); + return v; +} + +void * +earealloc(void *p, ulong n, ulong sz) +{ + uvlong na; + void *v; + + na = (uvlong)n*(uvlong)sz; + if(na >= (1ULL<<30)) + sysfatal("alloc: overflow"); + v = realloc(p, na); + if(v == nil) + sysfatal("realloc: %r"); + setmalloctag(v, getcallerpc(&p)); + return v; +} + +char* +estrdup(char *s) +{ + s = strdup(s); + if(s == nil) + sysfatal("strdup: %r"); + setmalloctag(s, getcallerpc(&s)); + return s; +} + +int +Hfmt(Fmt *fmt) +{ + Hash h; + int i, n, l; + char c0, c1; + + l = 0; + h = va_arg(fmt->args, Hash); + for(i = 0; i < sizeof h.h; i++){ + n = (h.h[i] >> 4) & 0xf; + c0 = (n >= 10) ? n-10 + 'a' : n + '0'; + n = h.h[i] & 0xf; + c1 = (n >= 10) ? n-10 + 'a' : n + '0'; + l += fmtprint(fmt, "%c%c", c0, c1); + } + return l; +} + +int +Tfmt(Fmt *fmt) +{ + int t; + int l; + + t = va_arg(fmt->args, int); + switch(t){ + case GNone: l = fmtprint(fmt, "none"); break; + case GCommit: l = fmtprint(fmt, "commit"); break; + case GTree: l = fmtprint(fmt, "tree"); break; + case GBlob: l = fmtprint(fmt, "blob"); break; + case GTag: l = fmtprint(fmt, "tag"); break; + case GOdelta: l = fmtprint(fmt, "odelta"); break; + case GRdelta: l = fmtprint(fmt, "gdelta"); break; + default: l = fmtprint(fmt, "?%d?", t); break; + } + return l; +} + +int +Ofmt(Fmt *fmt) +{ + Object *o; + int l; + + o = va_arg(fmt->args, Object *); + print("== %H (%T) ==\n", o->hash, o->type); + switch(o->type){ + case GTree: + l = fmtprint(fmt, "tree\n"); + break; + case GBlob: + l = fmtprint(fmt, "blob %s\n", o->data); + break; + case GCommit: + l = fmtprint(fmt, "commit\n"); + break; + case GTag: + l = fmtprint(fmt, "tag\n"); + break; + default: + l = fmtprint(fmt, "invalid: %d\n", o->type); + break; + } + return l; +} + +int +Qfmt(Fmt *fmt) +{ + Qid q; + + q = va_arg(fmt->args, Qid); + return fmtprint(fmt, "Qid{path=0x%llx(dir:%d,obj:%lld), vers=%ld, type=%d}", + q.path, QDIR(&q), (q.path >> 8), q.vers, q.type); +} + +void +gitinit(void) +{ + fmtinstall('H', Hfmt); + fmtinstall('T', Tfmt); + fmtinstall('O', Ofmt); + fmtinstall('Q', Qfmt); + inflateinit(); + deflateinit(); + authorpat = regcomp("[\t ]*(.*)[\t ]+([0-9]+)[\t ]+([\\-+]?[0-9]+)"); + osinit(&objcache); +} + +int +hparse(Hash *h, char *b) +{ + int i, err; + + err = 0; + for(i = 0; i < sizeof(h->h); i++){ + err = 0; + h->h[i] = 0; + h->h[i] |= ((charval(b[2*i], &err) & 0xf) << 4); + h->h[i] |= ((charval(b[2*i+1], &err)& 0xf) << 0); + if(err){ + werrstr("invalid hash"); + return -1; + } + } + return 0; +} + +int +slurpdir(char *p, Dir **d) +{ + int r, f; + + if((f = open(p, OREAD)) == -1) + return -1; + r = dirreadall(f, d); + close(f); + return r; +} + +int +hassuffix(char *base, char *suf) +{ + int nb, ns; + + nb = strlen(base); + ns = strlen(suf); + if(ns <= nb && strcmp(base + (nb - ns), suf) == 0) + return 1; + return 0; +} + +int +swapsuffix(char *dst, int dstsz, char *base, char *oldsuf, char *suf) +{ + int bl, ol, sl, l; + + bl = strlen(base); + ol = strlen(oldsuf); + sl = strlen(suf); + l = bl + sl - ol; + if(l + 1 > dstsz || ol > bl) + return -1; + memmove(dst, base, bl - ol); + memmove(dst + bl - ol, suf, sl); + dst[l] = 0; + return l; +} + +char * +strip(char *s) +{ + char *e; + + while(isspace(*s)) + s++; + e = s + strlen(s); + while(e > s && isspace(*--e)) + *e = 0; + return s; +} + +void +_dprint(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprint(2, fmt, ap); + va_end(ap); +} + +/* Finds the directory containing the git repo. */ +int +findrepo(char *buf, int nbuf) +{ + char *p, *suff; + + suff = "/.git/HEAD"; + if(getwd(buf, nbuf - strlen(suff) - 1) == nil) + return -1; + + for(p = buf + strlen(buf); p != nil; p = strrchr(buf, '/')){ + strcpy(p, suff); + if(access(buf, AEXIST) == 0){ + p[p == buf] = '\0'; + return 0; + } + *p = '\0'; + } + werrstr("not a git repository"); + return -1; +} + +int +showprogress(int x, int pct) +{ + if(!interactive) + return 0; + if(x > pct){ + pct = x; + fprint(2, "\b\b\b\b%3d%%", pct); + } + return pct; +} + +void +qinit(Objq *q) +{ + memset(q, 0, sizeof(Objq)); + q->nheap = 0; + q->heapsz = 8; + q->heap = eamalloc(q->heapsz, sizeof(Qelt)); +} + +void +qclear(Objq *q) +{ + free(q->heap); +} + +void +qput(Objq *q, Object *o, int color) +{ + Qelt t; + int i; + + if(q->nheap == q->heapsz){ + q->heapsz *= 2; + q->heap = earealloc(q->heap, q->heapsz, sizeof(Qelt)); + } + q->heap[q->nheap].o = o; + q->heap[q->nheap].color = color; + q->heap[q->nheap].ctime = o->commit->ctime; + for(i = q->nheap; i > 0; i = (i-1)/2){ + if(q->heap[i].ctime < q->heap[(i-1)/2].ctime) + break; + t = q->heap[i]; + q->heap[i] = q->heap[(i-1)/2]; + q->heap[(i-1)/2] = t; + } + q->nheap++; +} + +int +qpop(Objq *q, Qelt *e) +{ + int i, l, r, m; + Qelt t; + + if(q->nheap == 0) + return 0; + *e = q->heap[0]; + if(--q->nheap == 0) + return 1; + + i = 0; + q->heap[0] = q->heap[q->nheap]; + while(1){ + m = i; + l = 2*i+1; + r = 2*i+2; + if(l < q->nheap && q->heap[m].ctime < q->heap[l].ctime) + m = l; + if(r < q->nheap && q->heap[m].ctime < q->heap[r].ctime) + m = r; + if(m == i) + break; + t = q->heap[m]; + q->heap[m] = q->heap[i]; + q->heap[i] = t; + i = m; + } + return 1; +} diff --git a/sys/src/cmd/git/walk.c b/sys/src/cmd/git/walk.c new file mode 100644 index 0000000000..50a227e21b --- /dev/null +++ b/sys/src/cmd/git/walk.c @@ -0,0 +1,331 @@ +#include +#include +#include "git.h" + +#define NCACHE 4096 +#define TDIR ".git/index9/tracked" +#define RDIR ".git/index9/removed" +#define HDIR ".git/fs/HEAD/tree" +typedef struct Cache Cache; +typedef struct Wres Wres; +struct Cache { + Dir* cache; + int n; + int max; +}; + +struct Wres { + char **path; + int npath; + int pathsz; +}; + +enum { + Rflg = 1 << 0, + Mflg = 1 << 1, + Aflg = 1 << 2, + Tflg = 1 << 3, +}; + +Cache seencache[NCACHE]; +int quiet; +int printflg; +char *rstr = "R "; +char *tstr = "T "; +char *mstr = "M "; +char *astr = "A "; + +int +seen(Dir *dir) +{ + Dir *dp; + int i; + Cache *c; + + c = &seencache[dir->qid.path&(NCACHE-1)]; + dp = c->cache; + for(i=0; in; i++, dp++) + if(dir->qid.path == dp->qid.path && + dir->type == dp->type && + dir->dev == dp->dev) + return 1; + if(c->n == c->max){ + if (c->max == 0) + c->max = 8; + else + c->max += c->max/2; + c->cache = realloc(c->cache, c->max*sizeof(Dir)); + if(c->cache == nil) + sysfatal("realloc: %r"); + } + c->cache[c->n++] = *dir; + return 0; +} + +void +grow(Wres *r) +{ + if(r->npath == r->pathsz){ + r->pathsz = 2*r->pathsz + 1; + r->path = erealloc(r->path, r->pathsz * sizeof(char*)); + } +} + +int +readpaths(Wres *r, char *pfx, char *dir) +{ + char *f, *sub, *full, *sep; + Dir *d; + int fd, ret, i, n; + + d = nil; + ret = -1; + sep = ""; + if(dir[0] != 0) + sep = "/"; + if((full = smprint("%s/%s", pfx, dir)) == nil) + sysfatal("smprint: %r"); + if((fd = open(full, OREAD)) < 0) + goto error; + while((n = dirread(fd, &d)) > 0){ + for(i = 0; i < n; i++){ + if(seen(&d[i])) + continue; + if(d[i].qid.type & QTDIR){ + if((sub = smprint("%s%s%s", dir, sep, d[i].name)) == nil) + sysfatal("smprint: %r"); + if(readpaths(r, pfx, sub) == -1){ + free(sub); + goto error; + } + free(sub); + }else{ + grow(r); + if((f = smprint("%s%s%s", dir, sep, d[i].name)) == nil) + sysfatal("smprint: %r"); + r->path[r->npath++] = f; + } + } + free(d); + } + ret = r->npath; +error: + close(fd); + free(full); + return ret; +} + +int +cmp(void *pa, void *pb) +{ + return strcmp(*(char **)pa, *(char **)pb); +} + +void +dedup(Wres *r) +{ + int i, o; + + if(r->npath <= 1) + return; + o = 0; + qsort(r->path, r->npath, sizeof(r->path[0]), cmp); + for(i = 1; i < r->npath; i++) + if(strcmp(r->path[o], r->path[i]) != 0) + r->path[++o] = r->path[i]; + r->npath = o + 1; +} + +int +sameqid(Dir *d, char *qf) +{ + char indexqid[64], fileqid[64], *p; + int fd, n; + + if(!d) + return 0; + if((fd = open(qf, OREAD)) == -1) + return 0; + if((n = readn(fd, indexqid, sizeof(indexqid) - 1)) == -1) + return 0; + indexqid[n] = 0; + close(fd); + if((p = strpbrk(indexqid, " \t\n\r")) != nil) + *p = 0; + + snprint(fileqid, sizeof(fileqid), "%ullx.%uld.%.2uhhx", + d->qid.path, d->qid.vers, d->qid.type); + + if(strcmp(indexqid, fileqid) == 0) + return 1; + return 0; +} + +void +writeqid(Dir *d, char *qf) +{ + int fd; + + if((fd = create(qf, OWRITE, 0666)) == -1) + return; + fprint(fd, "%ullx.%uld.%.2uhhx\n", + d->qid.path, d->qid.vers, d->qid.type); + close(fd); +} + +int +samedata(char *pa, char *pb) +{ + char ba[32*1024], bb[32*1024]; + int fa, fb, na, nb, same; + + same = 0; + fa = open(pa, OREAD); + fb = open(pb, OREAD); + if(fa == -1 || fb == -1){ + goto mismatch; + } + while(1){ + if((na = readn(fa, ba, sizeof(ba))) == -1) + goto mismatch; + if((nb = readn(fb, bb, sizeof(bb))) == -1) + goto mismatch; + if(na != nb) + goto mismatch; + if(na == 0) + break; + if(memcmp(ba, bb, na) != 0) + goto mismatch; + } + same = 1; +mismatch: + if(fa != -1) + close(fa); + if(fb != -1) + close(fb); + return same; +} + +void +usage(void) +{ + fprint(2, "usage: %s [-qbc] [-f filt] [paths...]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *rpath, *tpath, *bpath, buf[8], repo[512]; + char *p, *e; + int i, dirty; + Wres r; + Dir *d; + + ARGBEGIN{ + case 'q': + quiet++; + break; + case 'c': + rstr = ""; + tstr = ""; + mstr = ""; + astr = ""; + break; + case 'f': + for(p = EARGF(usage()); *p; p++) + switch(*p){ + case 'T': printflg |= Tflg; break; + case 'A': printflg |= Aflg; break; + case 'M': printflg |= Mflg; break; + case 'R': printflg |= Rflg; break; + default: usage(); break; + } + break; + default: + usage(); + }ARGEND + + if(findrepo(repo, sizeof(repo)) == -1) + sysfatal("find root: %r"); + if(chdir(repo) == -1) + sysfatal("chdir: %r"); + if(access(".git/fs/ctl", AEXIST) != 0) + sysfatal("no running git/fs"); + dirty = 0; + memset(&r, 0, sizeof(r)); + if(printflg == 0) + printflg = Tflg | Aflg | Mflg | Rflg; + if(argc == 0){ + if(access(TDIR, AEXIST) == 0 && readpaths(&r, TDIR, "") == -1) + sysfatal("read tracked: %r"); + if(access(RDIR, AEXIST) == 0 && readpaths(&r, RDIR, "") == -1) + sysfatal("read removed: %r"); + }else{ + for(i = 0; i < argc; i++){ + tpath = smprint(TDIR"/%s", argv[i]); + rpath = smprint(RDIR"/%s", argv[i]); + if((d = dirstat(tpath)) == nil && (d = dirstat(rpath)) == nil) + goto nextarg; + if(d->mode & DMDIR){ + readpaths(&r, TDIR, argv[i]); + readpaths(&r, RDIR, argv[i]); + }else{ + grow(&r); + r.path[r.npath++] = estrdup(argv[i]); + } +nextarg: + free(tpath); + free(rpath); + free(d); + } + } + dedup(&r); + + for(i = 0; i < r.npath; i++){ + p = r.path[i]; + d = dirstat(p); + if(d && d->mode & DMDIR) + goto next; + rpath = smprint(RDIR"/%s", p); + tpath = smprint(TDIR"/%s", p); + bpath = smprint(HDIR"/%s", p); + /* Fast path: we don't want to force access to the rpath. */ + if(d && sameqid(d, tpath)) { + if(!quiet && (printflg & Tflg)) + print("%s%s\n", tstr, p); + }else{ + if(d == nil || access(rpath, AEXIST) == 0){ + dirty |= Rflg; + if(!quiet && (printflg & Rflg)) + print("%s%s\n", rstr, p); + }else if(access(bpath, AEXIST) == -1) { + dirty |= Aflg; + if(!quiet && (printflg & Aflg)) + print("%s%s\n", astr, p); + }else if(samedata(p, bpath)){ + if(!quiet && (printflg & Tflg)) + print("%s%s\n", tstr, p); + writeqid(d, tpath); + }else{ + dirty |= Mflg; + if(!quiet && (printflg & Mflg)) + print("%s%s\n", mstr, p); + } + } + free(rpath); + free(tpath); + free(bpath); +next: + free(d); + } + if(!dirty) + exits(nil); + + p = buf; + e = buf + sizeof(buf); + for(i = 0; (1 << i) != Tflg; i++) + if(dirty & (1 << i)) + p = seprint(p, e, "%c", "DMAT"[i]); + exits(buf); +} From 39d3f0eadd02ab1afadfcba5e3199f3fdaf92cd5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 5 Jun 2022 14:48:29 +0000 Subject: [PATCH 198/402] dist/replica: add /sys/lib/git directory to plan9.proto --- dist/replica/plan9.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist/replica/plan9.proto b/dist/replica/plan9.proto index b24dfbf477..821b091012 100644 --- a/dist/replica/plan9.proto +++ b/dist/replica/plan9.proto @@ -105,6 +105,8 @@ sys - sys sys + - sys sys ghostscript - sys sys + - sys sys + git - sys sys + + - sys sys kbmap - sys sys + - sys sys lex - sys sys From d8bbca04d5efebb50ec2c41852e3ebebbba5aae4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:37 +0000 Subject: [PATCH 199/402] sys/src/libthread: port threadspawn and threadspawnl functions from plan9port --- sys/include/thread.h | 2 ++ sys/man/2/thread | 16 +++++++++ sys/src/libthread/exec.c | 60 ++++++++++++++++++++++++++++++++++ sys/src/libthread/threadimpl.h | 9 +++++ 4 files changed, 87 insertions(+) diff --git a/sys/include/thread.h b/sys/include/thread.h index f67012f772..57bff0a32e 100644 --- a/sys/include/thread.h +++ b/sys/include/thread.h @@ -98,6 +98,8 @@ void threadkill(int); /* kill thread */ void threadkillgrp(int); /* kill threads in group */ void threadmain(int argc, char *argv[]); void threadnonotes(void); +int threadspawn(int[3], char*, char*[]); +int threadspawnl(int[3], char*, ...); int threadnotify(int (*f)(void*, char*), int in); int threadid(void); int threadpid(int); diff --git a/sys/man/2/thread b/sys/man/2/thread index b06e31b964..6d42ac3b51 100644 --- a/sys/man/2/thread +++ b/sys/man/2/thread @@ -41,6 +41,8 @@ threadid, threadpid, threadsetgrp, threadsetname, +threadspawn, +threadspawnl, threadwaitchan, yield \- thread and proc management .SH SYNOPSIS @@ -128,6 +130,8 @@ int chanprint(Channel *c, char *fmt, ...) int chanclose(Channel *c); int chanclosing(Channel *c); .XX +int threadspawnl(int fd[3], char *file, ...) +int threadspawn(int fd[3], char *file, char *args[]) void procexecl(Channel *cpid, char *file, ...) void procexec(Channel *cpid, char *file, char *args[]) Channel* threadwaitchan(void) @@ -237,6 +241,7 @@ Calls that do this are .IR procexec , .IR procexecl , .IR threadexits , +.IR threadspawn , .IR alt , .IR send , and @@ -362,6 +367,17 @@ must exist; .I procexec(l) mount pipes there. .PP +.I Threadspawnl +and +.I threadspawn +are like +.I threadexecl +and +.I threadexec +but do not replace the current thread. +They return the pid of the invoked program on success, or +\-1 on error. +.PP .I Threadwaitchan returns a channel of pointers to .B Waitmsg diff --git a/sys/src/libthread/exec.c b/sys/src/libthread/exec.c index b93eeb28fa..f1ccab53a0 100644 --- a/sys/src/libthread/exec.c +++ b/sys/src/libthread/exec.c @@ -78,3 +78,63 @@ procexecl(Channel *pidc, char *f, ...) procexec(pidc, f, &f+1); } +static void +execproc(void *v) +{ + Execjob *e; + + e = v; + rfork(RFFDG); + dup(e->fd[0], 0); + dup(e->fd[1], 1); + dup(e->fd[2], 2); + procexec(e->c, e->cmd, e->argv); + threadexits(nil); +} + +int +threadspawn(int fd[3], char *cmd, char *argv[]) +{ + int pid; + Execjob e; + + e.fd = fd; + e.cmd = cmd; + e.argv = argv; + e.c = chancreate(sizeof(void*), 0); + proccreate(execproc, &e, 65536); + close(fd[0]); + close(fd[1]); + close(fd[2]); + pid = recvul(e.c); + chanfree(e.c); + return pid; +} + +int +threadspawnl(int fd[3], char *cmd, ...) +{ + char **argv, *s; + int n, pid; + va_list arg; + + va_start(arg, cmd); + for(n=0; va_arg(arg, char*) != nil; n++) + ; + n++; + va_end(arg); + + argv = malloc(n*sizeof(argv[0])); + if(argv == nil) + return -1; + + va_start(arg, cmd); + for(n=0; (s=va_arg(arg, char*)) != nil; n++) + argv[n] = s; + argv[n] = 0; + va_end(arg); + + pid = threadspawn(fd, cmd, argv); + free(argv); + return pid; +} diff --git a/sys/src/libthread/threadimpl.h b/sys/src/libthread/threadimpl.h index fc3168f538..d85be2a1b6 100644 --- a/sys/src/libthread/threadimpl.h +++ b/sys/src/libthread/threadimpl.h @@ -24,6 +24,7 @@ typedef struct Rgrp Rgrp; typedef struct Tqueue Tqueue; typedef struct Thread Thread; typedef struct Execargs Execargs; +typedef struct Execjob Execjob; typedef struct Proc Proc; /* must match list in sched.c */ @@ -101,6 +102,14 @@ struct Execargs int fd[2]; }; +struct Execjob +{ + int *fd; + char *cmd; + char **argv; + Channel *c; +}; + struct Proc { Lock lock; From 47a5609604a0abb14e44f432802079bacec849b3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 26 May 2021 19:44:24 +0000 Subject: [PATCH 200/402] sys/src/libdynld: import libdynld from Inferno (thanks Charles Forsyth) --- sys/include/ape/dynld.h | 49 ++++++ sys/include/dynld.h | 41 +++++ sys/man/2/dynld | 287 +++++++++++++++++++++++++++++++ sys/src/libdynld/NOTICE | 28 +++ sys/src/libdynld/dynld-386.c | 43 +++++ sys/src/libdynld/dynld-68000.c | 23 +++ sys/src/libdynld/dynld-amd64.c | 23 +++ sys/src/libdynld/dynld-arm.c | 45 +++++ sys/src/libdynld/dynld-arm64.c | 23 +++ sys/src/libdynld/dynld-mips.c | 23 +++ sys/src/libdynld/dynld-mips64.c | 23 +++ sys/src/libdynld/dynld-power.c | 66 +++++++ sys/src/libdynld/dynld-power64.c | 23 +++ sys/src/libdynld/dynld-riscv.c | 23 +++ sys/src/libdynld/dynld-riscv64.c | 23 +++ sys/src/libdynld/dynld-sparc.c | 21 +++ sys/src/libdynld/dynld-spim.c | 23 +++ sys/src/libdynld/dynld-spim64.c | 23 +++ sys/src/libdynld/dynld.c | 259 ++++++++++++++++++++++++++++ sys/src/libdynld/dynloadfd.c | 36 ++++ sys/src/libdynld/mkfile | 10 ++ sys/src/mkfile | 1 + 22 files changed, 1116 insertions(+) create mode 100644 sys/include/ape/dynld.h create mode 100644 sys/include/dynld.h create mode 100644 sys/man/2/dynld create mode 100644 sys/src/libdynld/NOTICE create mode 100644 sys/src/libdynld/dynld-386.c create mode 100644 sys/src/libdynld/dynld-68000.c create mode 100644 sys/src/libdynld/dynld-amd64.c create mode 100644 sys/src/libdynld/dynld-arm.c create mode 100644 sys/src/libdynld/dynld-arm64.c create mode 100644 sys/src/libdynld/dynld-mips.c create mode 100644 sys/src/libdynld/dynld-mips64.c create mode 100644 sys/src/libdynld/dynld-power.c create mode 100644 sys/src/libdynld/dynld-power64.c create mode 100644 sys/src/libdynld/dynld-riscv.c create mode 100644 sys/src/libdynld/dynld-riscv64.c create mode 100644 sys/src/libdynld/dynld-sparc.c create mode 100644 sys/src/libdynld/dynld-spim.c create mode 100644 sys/src/libdynld/dynld-spim64.c create mode 100644 sys/src/libdynld/dynld.c create mode 100644 sys/src/libdynld/dynloadfd.c create mode 100644 sys/src/libdynld/mkfile diff --git a/sys/include/ape/dynld.h b/sys/include/ape/dynld.h new file mode 100644 index 0000000000..03261d331e --- /dev/null +++ b/sys/include/ape/dynld.h @@ -0,0 +1,49 @@ +#ifndef __DYNLD_H +#define __DYNLD_H +#if !defined(_PLAN9_SOURCE) + This header file is an extension to ANSI/POSIX +#endif + +#pragma src "/sys/src/ape/lib/dynld" +#pragma lib "/$M/lib/ape/libdynld.a" + +typedef struct Dynobj Dynobj; +typedef struct Dynsym Dynsym; + +struct Dynobj +{ + unsigned long size; /* total size in bytes */ + unsigned long text; /* bytes of text */ + unsigned long data; /* bytes of data */ + unsigned long bss; /* bytes of bss */ + unsigned char* base; /* start of text, data, bss */ + int nexport; + Dynsym* export; /* export table */ + int nimport; + Dynsym** import; /* import table */ +}; + +/* + * this structure is known to the linkers + */ +struct Dynsym +{ + unsigned long sig; + unsigned long addr; + char *name; +}; + +extern Dynsym* dynfindsym(char*, Dynsym*, int); +extern void dynfreeimport(Dynobj*); +extern void* dynimport(Dynobj*, char*, unsigned long); +extern int dynloadable(void*, long (*r)(void*,void*,long), long long(*sk)(void*,long long,int)); +extern Dynobj* dynloadfd(int, Dynsym*, int, unsigned long); +extern Dynobj* dynloadgen(void*, long (*r)(void*,void*,long), long long (*s)(void*,long long,int), void (*e)(char*), Dynsym*, int, unsigned long); +extern long dynmagic(void); +extern void dynobjfree(Dynobj*); +extern char* dynreloc(unsigned char*, unsigned long, int, Dynsym**, int); +extern int dyntabsize(Dynsym*); + +extern Dynsym _exporttab[]; /* created by linker -x (when desired) */ + +#endif diff --git a/sys/include/dynld.h b/sys/include/dynld.h new file mode 100644 index 0000000000..eeac1c2aad --- /dev/null +++ b/sys/include/dynld.h @@ -0,0 +1,41 @@ +#pragma src "/sys/src/libdynld" +#pragma lib "libdynld.a" + +typedef struct Dynobj Dynobj; +typedef struct Dynsym Dynsym; + +struct Dynobj +{ + ulong size; /* total size in bytes */ + ulong text; /* bytes of text */ + ulong data; /* bytes of data */ + ulong bss; /* bytes of bss */ + uchar* base; /* start of text, data, bss */ + int nexport; + Dynsym* export; /* export table */ + int nimport; + Dynsym** import; /* import table */ +}; + +/* + * this structure is known to the linkers + */ +struct Dynsym +{ + ulong sig; + ulong addr; + char *name; +}; + +extern Dynsym* dynfindsym(char*, Dynsym*, int); +extern void dynfreeimport(Dynobj*); +extern void* dynimport(Dynobj*, char*, ulong); +extern int dynloadable(void*, long (*r)(void*,void*,long), vlong(*sk)(void*,vlong,int)); +extern Dynobj* dynloadfd(int, Dynsym*, int, ulong); +extern Dynobj* dynloadgen(void*, long (*r)(void*,void*,long), vlong (*s)(void*,vlong,int), void (*e)(char*), Dynsym*, int, ulong); +extern long dynmagic(void); +extern void dynobjfree(Dynobj*); +extern char* dynreloc(uchar*, ulong, int, Dynsym**, int); +extern int dyntabsize(Dynsym*); + +extern Dynsym _exporttab[]; /* created by linker -x (when desired) */ diff --git a/sys/man/2/dynld b/sys/man/2/dynld new file mode 100644 index 0000000000..89773339ad --- /dev/null +++ b/sys/man/2/dynld @@ -0,0 +1,287 @@ +.TH DYNLD 2 +.SH NAME +dynfindsym, dynfreeimport, dynloadfd, dynloadgen, dynobjfree, dyntabsize \- load object file dynamically +.SH SYNOPSIS +.B #include +.br +.B #include +.br +.B #include +.PP +.ta \w'\fLDynsym*** 'u +.B +Dynsym* dynfindsym(char *name, Dynsym *syms, int nsym) +.PP +.B +Dynobj* dynloadfd(int fd, Dynsym *exports, int nexport, +.br +.B + ulong maxsize) +.PP +.B +Dynobj* dynloadgen(void *file, long (*read)(void*,void*,long), +.br +.B + vlong (*seek)(void*,vlong,int), void (*err)(char*), +.br +.B + Dynsym *exports, int nexport, ulong maxsize) +.PP +.B +void* dynimport(Dynobj *o, char *name, ulong sig) +.PP +.B +void dynfreeimport(Dynobj *o) +.PP +.B +void dynobjfree(Dynobj *o) +.PP +.B +int dyntabsize(Dynsym *t) +.PP +.B +extern Dynsym _exporttab[]; +.DT +.SH DESCRIPTION +These functions allow a process to load further code and data +into the currently executing image. +A dynamically-loadable file, called a +.I module +here, is a variant of the +.IR a.out (10.6) +executable format with some extra components. +The loader for the architecture +(see +.IR 8l (1)) +creates a module file from component object file(s) when given the +.B -u +option. +A module contains text and data sections, an import table, an export table, +and relocation data. +The import table lists the symbols the module needs from the loading program; +the export table lists symbols the module provides when loaded. +A program that loads a module provides a table of its own symbols to match +the symbols in the module's import table. +.PP +A symbol entry in a symbol table names a global function or data item, and has an associated +.I signature +value representing the type of the corresponding function or data in the source code. +The +.B Dynsym +structure defines a symbol: +.IP +.EX +typedef struct { + ulong sig; + ulong addr; + char* name; +} Dynsym; +.EE +.PP +The structure is known to the loaders +.IR 8l (1). +.I Name +is the linkage name of the function or data. +.I Addr +is its address, which is relative to the start of the module before loading, +and an address in the current address space after loading. +The signature +.I sig +is the value produced by the C compiler's +.B signof +operator applied to the type. +Symbol tables must be sorted by +.IR name . +.PP +An executable that wishes to load modules will normally be linked using the +.B -x +option to the appropriate loader +.IR 8l (1). +The resulting executable contains an export table +.B _exporttab +that lists all the exported symbols of the program (by default, all external symbols). +A nil name marks the end of the table. +See +.IR 8l (1) +for details. +The table can be given to the functions below to allow a loaded module +to access those symbols. +.PP +A loaded module is described by a +.B Dynobj +structure: +.IP +.EX +typedef struct { + ulong size; /* total size in bytes */ + ulong text; /* bytes of text */ + ulong data; /* bytes of data */ + ulong bss; /* bytes of bss */ + uchar* base; /* start of text, data, bss */ + int nexport; + Dynsym* export; /* export table */ + int nimport; + Dynsym** import; /* import table */ +} Dynobj; +.EE +.PP +Several fields give sizes of the module's components, as noted in comments above. +.I Base +gives the address at which the module has been loaded. +All its internal +references have been adjusted where needed to reflect its current address. +.I Export +points to a symbol table listing the symbols exported by the module; +.I nexport +gives the table's length. +.I Import +points to a list of symbols imported by the module; +note that each entry actually points to an entry in a symbol table +provided by the program that loaded the module (see below). +.I Nimport +gives the import table's length. +If the import table is not required, call +.I dynfreeimport +on the module pointer to free it. +.PP +.I Dynfindysm +looks up the entry for the given +.I name +in symbol table +.I syms +(of length +.IR nsym ). +It returns a pointer to the entry if found; nil otherwise. +The symbol table must be sorted by name in ascending order. +.PP +.I Dyntabsize +returns the length of symbol table +.IR t , +defined to be the number of +.B Dynsym +values starting at +.I t +that have non-nil +.I name +fields. +It is used to find the length of +.BR _exporttab . +.PP +.I Dynloadfd +loads a module from the file open for reading on +.IR fd , +and returns the resulting module pointer on success, +or nil on error. +If +.I maxsize +is non-zero +the size of the dynamically-loaded module's code and data +is limited to +.I maxsize +bytes. +.I Exports +is an array of +.I nexport +symbols in the current program that can be imported by the current module. +It uses +.IR read (2) +and +.IR seek (2) +to access +.IR fd , +and calls +.I werrstr +(see +.IR errstr (2)) +to set the error string if necessary. +.PP +.I Dynloadgen +is a more general function that can load a module from an +arbitrary source, not just an open file descriptor. +(In particular, it can be +called by the kernel using functions internal to the kernel +instead of making system calls.) +.IR Exports , +.I nexport +and +.I maxsize +are just as for +.IR dynloadfd . +.I File +is a pointer to a structure defined by the caller that represents the file +containing the module. +It is passed to +.I read +and +.IR seek . +.I Read +is invoked as +.BI (*read)( file , buf ,\ \fInbytes\fP)\fR.\fP +.I Read +should read +.I nbytes +of data from +.I file +into +.I buf +and return the number of bytes transferred. +It should return -1 on error. +.I Seek +is invoked as +.BI (*seek)( file , n ,\ \fItype\fP) +where +.I n +and +.I type +are just as for +.IR seek (2); +it should seek to the requested offset in +.IR file , +or return -1 on error. +.I Dynloadgen +returns a pointer to the loaded module on success. +On error, +it returns nil after calling its +.I err +parameter to set the error string. +.PP +.I Dynimport +returns a pointer to the value of the symbol +.I name +in loaded module +.IR o , +or +.I nil +if +.I o +does not export a symbol with the given +.IR name . +If +.I sig +is non-zero, the exported symbol's signature must equal +.IR sig , +or +.I dynimport +again returns nil. +For example: +.IP +.EX +Dev *d; +d = dynimport(obj, "XXXdevtab", signof(*d)); +if(d == nil) + error("not a dynamically-loadable driver"); +.EE +.PP +.I Dynobjfree +frees the module +.IR o . +There is no reference counting: it is the caller's responsibility to decide whether +a module is no longer needed. +.SH SEE ALSO +.IR 8l (1), +.\".IR mach (2), +.IR a.out (6) +.SH DIAGNOSTICS +Functions that return pointers return nil on error. +.I Dynloadfd +sets the error string and returns nil. diff --git a/sys/src/libdynld/NOTICE b/sys/src/libdynld/NOTICE new file mode 100644 index 0000000000..fca1655230 --- /dev/null +++ b/sys/src/libdynld/NOTICE @@ -0,0 +1,28 @@ +This copyright NOTICE applies to all files in this directory and +subdirectories, unless another copyright notice appears in a given +file or subdirectory. If you take substantial code from this software to use in +other programs, you must somehow include with it an appropriate +copyright notice that includes the copyright notice and the other +notices below. It is fine (and often tidier) to do that in a separate +file such as NOTICE, LICENCE or COPYING. + + Copyright © 2004-2007 Vita Nuova Holdings Limited (www.vitanuova.com) + +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. + diff --git a/sys/src/libdynld/dynld-386.c b/sys/src/libdynld/dynld-386.c new file mode 100644 index 0000000000..7381675d2c --- /dev/null +++ b/sys/src/libdynld/dynld-386.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | I_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + int i; + ulong v, *pp; + + p += (ulong)b; + pp = (ulong*)p; + v = *pp; + switch(m){ + case 0: + v += (ulong)b; + break; + case 1: + i = v>>22; + v &= 0x3fffff; + CHK(i, ntab); + v += tab[i]->addr; + break; + case 2: + i = v>>22; + CHK(i, ntab); + v = tab[i]->addr -p-4; + break; + default: + return "bad relocation mode"; + } + *pp = v; + return nil; +} diff --git a/sys/src/libdynld/dynld-68000.c b/sys/src/libdynld/dynld-68000.c new file mode 100644 index 0000000000..a25810685d --- /dev/null +++ b/sys/src/libdynld/dynld-68000.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | A_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "68000 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-amd64.c b/sys/src/libdynld/dynld-amd64.c new file mode 100644 index 0000000000..693af6452f --- /dev/null +++ b/sys/src/libdynld/dynld-amd64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | S_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "amd64 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-arm.c b/sys/src/libdynld/dynld-arm.c new file mode 100644 index 0000000000..1e455c9b12 --- /dev/null +++ b/sys/src/libdynld/dynld-arm.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | E_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + int i; + ulong v, *pp; + + p <<= 2; + p += (ulong)b; + pp = (ulong*)p; + v = *pp; + switch(m){ + case 0: + v += (ulong)b; + break; + case 1: + i = v>>22; + v &= 0x3fffff; + CHK(i, ntab); + v += tab[i]->addr; + break; + case 2: + i = v&0x3ff; + v &= ~0x3ff; + CHK(i, ntab); + v |= ((tab[i]->addr-p-8)>>2)&0xffffff; + break; + default: + return "invalid relocation mode"; + } + *pp = v; + return nil; +} diff --git a/sys/src/libdynld/dynld-arm64.c b/sys/src/libdynld/dynld-arm64.c new file mode 100644 index 0000000000..45cf1db611 --- /dev/null +++ b/sys/src/libdynld/dynld-arm64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | R_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "arm64 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-mips.c b/sys/src/libdynld/dynld-mips.c new file mode 100644 index 0000000000..b78b0195f2 --- /dev/null +++ b/sys/src/libdynld/dynld-mips.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | V_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "mips unimplemented"; +} diff --git a/sys/src/libdynld/dynld-mips64.c b/sys/src/libdynld/dynld-mips64.c new file mode 100644 index 0000000000..394bd73f0d --- /dev/null +++ b/sys/src/libdynld/dynld-mips64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | M_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "mips64 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-power.c b/sys/src/libdynld/dynld-power.c new file mode 100644 index 0000000000..5afe1faf8e --- /dev/null +++ b/sys/src/libdynld/dynld-power.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | Q_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + int i; + ulong v, *pp0, *pp1; + + p <<= 2; + p += (ulong)b; + pp0 = (ulong*)p; + v = *pp0; + switch(m){ + case 0: + v += (ulong)b; + break; + case 1: + i = v>>22; + v &= 0x3fffff; + CHK(i, ntab); + v += tab[i]->addr; + break; + case 2: + i = (v&0xffc)>>2; + v &= ~0xffc; + CHK(i, ntab); + v |= (tab[i]->addr-p)&0x3fffffc; + break; + case 3: + case 4: + case 5: + case 6: + pp1 = (ulong*)(p+4); + v = (v<<16)|(*pp1&0xffff); + if(m&1) + v += (ulong)b; + else{ + i = v>>22; + v &= 0x3fffff; + CHK(i, ntab); + v += tab[i]->addr; + } + if(m >= 5 && (v&0x8000)) + v += 0x10000; + *pp0 &= ~0xffff; + *pp0 |= v>>16; + *pp1 &= ~0xffff; + *pp1 |= v&0xffff; + return nil; + default: + return "invalid relocation mode"; + } + *pp0 = v; + return nil; +} diff --git a/sys/src/libdynld/dynld-power64.c b/sys/src/libdynld/dynld-power64.c new file mode 100644 index 0000000000..e9c149ac34 --- /dev/null +++ b/sys/src/libdynld/dynld-power64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | T_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "power64 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-riscv.c b/sys/src/libdynld/dynld-riscv.c new file mode 100644 index 0000000000..c2d0c57b93 --- /dev/null +++ b/sys/src/libdynld/dynld-riscv.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | Z_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "riscv unimplemented"; +} diff --git a/sys/src/libdynld/dynld-riscv64.c b/sys/src/libdynld/dynld-riscv64.c new file mode 100644 index 0000000000..895225b914 --- /dev/null +++ b/sys/src/libdynld/dynld-riscv64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | Y_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "riscv64 unimplemented"; +} diff --git a/sys/src/libdynld/dynld-sparc.c b/sys/src/libdynld/dynld-sparc.c new file mode 100644 index 0000000000..4ab620f391 --- /dev/null +++ b/sys/src/libdynld/dynld-sparc.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +long +dynmagic(void) +{ + return DYN_MAGIC | K_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "sparc unimplemented"; +} diff --git a/sys/src/libdynld/dynld-spim.c b/sys/src/libdynld/dynld-spim.c new file mode 100644 index 0000000000..5e9f208ec4 --- /dev/null +++ b/sys/src/libdynld/dynld-spim.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | P_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "mips-le (spim) unimplemented"; +} diff --git a/sys/src/libdynld/dynld-spim64.c b/sys/src/libdynld/dynld-spim64.c new file mode 100644 index 0000000000..10f4654afe --- /dev/null +++ b/sys/src/libdynld/dynld-spim64.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#define CHK(i,ntab) if((unsigned)(i)>=(ntab))return "bad relocation index" + +long +dynmagic(void) +{ + return DYN_MAGIC | N_MAGIC; +} + +char* +dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab) +{ + USED(b); + USED(p); + USED(m); + USED(tab); + USED(ntab); + return "mips64-le (spim64) unimplemented"; +} diff --git a/sys/src/libdynld/dynld.c b/sys/src/libdynld/dynld.c new file mode 100644 index 0000000000..fdce17e9c3 --- /dev/null +++ b/sys/src/libdynld/dynld.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include + +static ulong +get2(uchar *b) +{ + return (b[0] << 8) | b[1]; +} + +static ulong +get4(uchar *b) +{ + return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; +} + +static ulong +lgetbe(ulong l) +{ + union { + ulong l; + uchar c[4]; + } u; + u.l = l; + return get4(u.c); +} + +Dynsym* +dynfindsym(char *s, Dynsym *tab, int ntab) +{ + int n, n2, d; + Dynsym *t, *m; + + t = tab; + n = ntab; + while(n > 0){ + n2 = n>>1; + m = t+n2; + d = strcmp(s, m->name); + if(d < 0){ + n = n2; + continue; + } + if(d > 0){ + t = m+1; + n -= n2+1; + continue; + } + return m; + } + return nil; +} + +void* +dynimport(Dynobj *o, char *name, ulong sig) +{ + Dynsym *t; + + t = dynfindsym(name, o->export, o->nexport); + if(t == nil || sig != 0 && t->sig != 0 && t->sig != sig) + return nil; + return (void*)t->addr; +} + +int +dyntabsize(Dynsym *t) +{ + int n; + + for(n = 0; t->name != nil; t++) + n++; + return n; +} + +void +dynobjfree(Dynobj *o) +{ + if(o != nil){ + free(o->base); + free(o->import); + free(o); + } +} + +void +dynfreeimport(Dynobj *o) +{ + free(o->import); + o->import = nil; + o->nimport = 0; +} + +static char Ereloc[] = "error reading object file"; + +Dynobj* +dynloadgen(void *file, long (*rd)(void*,void*,long), vlong (*sk)(void*,vlong,int), void (*werr)(char*), Dynsym *tab, int ntab, ulong maxsize) +{ + int i, m, n, ni, nr, relsize; + ulong syms, entry, sig, p, a; + uchar *base; + Exec e; + Dynsym *t; + Dynobj *l; + char *s, *err, buf[64]; + uchar *reldata, *rp, *ep; + vlong off; + + err = Ereloc; /* default */ + off = (*sk)(file, 0, 1); + l = mallocz(sizeof(Dynobj), 1); + if(l == nil){ + err = "can't allocate Dynobj"; + goto Error; + } + if((*rd)(file, &e, sizeof(Exec)) != sizeof(Exec)) + goto Error; + if(lgetbe(e.magic) != dynmagic()){ + err = "not dynamic object file or wrong platform"; + goto Error; + } + l->text = lgetbe(e.text); + l->data = lgetbe(e.data); + l->bss = lgetbe(e.bss); + syms = lgetbe(e.syms)+lgetbe(e.spsz)+lgetbe(e.pcsz); + entry = lgetbe(e.entry); + l->size = l->text + l->data + l->bss; + if(entry < 0 || entry >= l->size || entry & 3){ + err = "invalid export table pointer (entry point)"; + goto Error; + } + if(maxsize && l->size >= maxsize){ + snprint(buf, sizeof(buf), "%lud: object too big", l->size); + err = buf; + goto Error; + } + + l->base = base = malloc(l->size); + if(base == nil){ + err = "out of memory: loading object file"; + goto Error; + } + l->export = (Dynsym*)(base+entry); + if((*rd)(file, base, l->text+l->data) != l->text+l->data) + goto Error; + memset(base+l->text+l->data, 0, l->bss); + if((*sk)(file, syms, 1) < 0) + goto Error; + if((*rd)(file, buf, 4) != 4) + goto Error; + relsize = get4((uchar*)buf); /* always contains at least an import count (might be zero) */ + if(relsize < 4) + goto Error; + reldata = malloc(relsize); + if(reldata == nil){ + err = "out of memory: relocation data"; + goto Error; + } + if((*rd)(file, reldata, relsize) != relsize) + goto Error; + rp = reldata; + ep = reldata+relsize; + ni = get4(rp); + rp += 4; + if(ni < 0 || ni > 8000) + goto Error; /* implausible size */ + l->nimport = ni; + l->import = malloc(ni*sizeof(Dynsym*)); + if(l->import == nil){ + err = "out of memory: symbol table"; + goto Error; + } + for(i = 0; i < ni; i++){ + if(rp+5 > ep) + goto Error; + sig = get4(rp); + rp += 4; + s = (char*)rp; + while(*rp++) + if(rp >= ep) + goto Error; + t = dynfindsym(s, tab, ntab); + if(t == nil){ + snprint(buf, sizeof(buf), "undefined symbol: %s", s); + err = buf; + goto Error; + } + if(sig != 0 && t->sig != 0 && t->sig != sig){ + snprint(buf, sizeof(buf), "signature mismatch: %s (%lux != %lux)", s, sig, t->sig); + err = buf; + goto Error; + } + l->import[i] = t; + } + + a = 0; + if(rp+4 > ep) + goto Error; + nr = get4(rp); + rp += 4; + for(i = 0; i < nr; i++){ + if(rp >= ep) + goto Error; + m = *rp++; + n = m>>6; + if(rp+(1< ep) + goto Error; + switch(n){ + case 0: + p = *rp++; + break; + case 1: + p = get2(rp); + rp += 2; + break; + case 2: + p = get4(rp); + rp += 4; + break; + default: + goto Error; + } + a += p; + err = dynreloc(base, a, m&0xf, l->import, ni); + if(err != nil){ + snprint(buf, sizeof(buf), "dynamic object: %s", err); + err = buf; + goto Error; + } + } + free(reldata); + + /* could check relocated export table here */ + l->nexport = dyntabsize(l->export); + + segflush(base, l->text); + + return l; + +Error: + if(off >= 0) + (*sk)(file, off, 0); /* restore original file offset */ + (*werr)(err); + dynobjfree(l); + return nil; +} + +int +dynloadable(void* file, long (*rd)(void*,void*,long), vlong (*sk)(void*,vlong,int)) +{ + long magic; + + if((*rd)(file, &magic, sizeof(magic)) != sizeof(magic)){ + (*sk)(file, -(signed int)sizeof(magic), 1); + return 0; + } + (*sk)(file, -(signed int)sizeof(magic), 1); + return lgetbe(magic) == dynmagic(); +} diff --git a/sys/src/libdynld/dynloadfd.c b/sys/src/libdynld/dynloadfd.c new file mode 100644 index 0000000000..61d50aea3c --- /dev/null +++ b/sys/src/libdynld/dynloadfd.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +typedef struct Fd Fd; +struct Fd { + int fd; +}; + +static long +readfd(void *a, void *buf, long nbytes) +{ + return read(((Fd*)a)->fd, buf, nbytes); +} + +static vlong +seekfd(void *a, vlong off, int t) +{ + return seek(((Fd*)a)->fd, off, t); +} + +static void +errfd(char *s) +{ + werrstr("%s", s); +} + +Dynobj* +dynloadfd(int fd, Dynsym *sym, int nsym, ulong maxsize) +{ + Fd f; + + f.fd = fd; + return dynloadgen(&f, readfd, seekfd, errfd, sym, nsym, maxsize); +} diff --git a/sys/src/libdynld/mkfile b/sys/src/libdynld/mkfile new file mode 100644 index 0000000000..4a7d701a6b --- /dev/null +++ b/sys/src/libdynld/mkfile @@ -0,0 +1,10 @@ + Date: Sun, 6 Mar 2016 20:21:04 +0000 Subject: [PATCH 201/402] sys/src/libframe: implement noredraw (thanks Russ Cox) --- sys/include/frame.h | 1 + sys/src/libframe/frdraw.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/include/frame.h b/sys/include/frame.h index 162483f2c5..d898e33e1e 100644 --- a/sys/include/frame.h +++ b/sys/include/frame.h @@ -49,6 +49,7 @@ struct Frame Image *tick; /* typing tick */ Image *tickback; /* saved image under tick */ int ticked; /* flag: is tick onscreen? */ + int noredraw; /* don't draw on the screen */ }; ulong frcharofpt(Frame*, Point); diff --git a/sys/src/libframe/frdraw.c b/sys/src/libframe/frdraw.c index 6a31a83836..2ecc231778 100644 --- a/sys/src/libframe/frdraw.c +++ b/sys/src/libframe/frdraw.c @@ -14,9 +14,8 @@ _frdrawtext(Frame *f, Point pt, Image *text, Image *back) for(nb=0,b=f->box; nbnbox; nb++, b++){ _frcklinewrap(f, &pt, b); - if(b->nrune >= 0){ + if(!f->noredraw && b->nrune >= 0) stringbg(f->b, pt, text, ZP, f->font, (char*)b->ptr, back, ZP); - } pt.x += b->wid; } } From b228fd1388403f22f3abce6b90e43e039bf93b37 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 6 Mar 2016 20:20:00 +0000 Subject: [PATCH 202/402] sys/src/cmd/acme: implement multiline tags (thanks Russ Cox) --- sys/src/cmd/acme/cols.c | 79 +++++++----------- sys/src/cmd/acme/dat.h | 10 ++- sys/src/cmd/acme/exec.c | 2 +- sys/src/cmd/acme/rows.c | 9 +- sys/src/cmd/acme/text.c | 52 ++++++++++-- sys/src/cmd/acme/wind.c | 178 +++++++++++++++++++++++++++++++--------- 6 files changed, 229 insertions(+), 101 deletions(-) diff --git a/sys/src/cmd/acme/cols.c b/sys/src/cmd/acme/cols.c index 463ff7a6fc..e1e91b84fc 100644 --- a/sys/src/cmd/acme/cols.c +++ b/sys/src/cmd/acme/cols.c @@ -75,9 +75,9 @@ coladd(Column *c, Window *w, Window *clone, int y) r.max.y = t; draw(screen, r, textcols[BACK], nil, ZP); r1 = r; - y = min(y, t-(v->tag.font->height+v->body.font->height+Border+1)); + y = min(y, t-(v->tag.font->height*v->taglines+v->body.font->height+Border+1)); r1.max.y = min(y, v->body.r.min.y+v->body.nlines*v->body.font->height); - r1.min.y = winresize(v, r1, FALSE); + r1.min.y = winresize(v, r1, FALSE, FALSE); r1.max.y = r1.min.y+Border; draw(screen, r1, display->black, nil, ZP); r.min.y = r1.max.y; @@ -89,7 +89,7 @@ coladd(Column *c, Window *w, Window *clone, int y) wininit(w, clone, r); }else{ w->col = c; - winresize(w, r, FALSE); + winresize(w, r, FALSE, TRUE); } w->tag.col = c; w->tag.row = c->row; @@ -149,7 +149,7 @@ colclose(Column *c, Window *w, int dofree) } draw(screen, r, textcols[BACK], nil, ZP); if(c->safe){ - winresize(w, r, FALSE); + winresize(w, r, FALSE, TRUE); USED(up); if(!didmouse) movetodel(w); @@ -191,7 +191,7 @@ colresize(Column *c, Rectangle r) clearmouse(); r1 = r; r1.max.y = r1.min.y + c->tag.font->height; - textresize(&c->tag, r1); + textresize(&c->tag, r1, TRUE); draw(screen, c->tag.scrollr, colbutton, nil, colbutton->r.min); r1.min.y = r1.max.y; r1.max.y += Border; @@ -208,7 +208,7 @@ colresize(Column *c, Rectangle r) r2.max.y = r2.min.y+Border; draw(screen, r2, display->black, nil, ZP); r1.min.y = r2.max.y; - r1.min.y = winresize(w, r1, FALSE); + r1.min.y = winresize(w, r1, FALSE, i==c->nw-1); } c->r = r; } @@ -264,7 +264,7 @@ colsort(Column *c) r1.max.y = r1.min.y+Border; draw(screen, r1, display->black, nil, ZP); r.min.y = r1.max.y; - y = winresize(w, r, FALSE); + y = winresize(w, r, FALSE, i==c->nw-1); } free(rp); free(c->w); @@ -291,7 +291,7 @@ colgrow(Column *c, Window *w, int but) r.max.y = cr.max.y; else r.max.y = c->w[i+1]->r.min.y; - winresize(w, r, FALSE); + winresize(w, r, FALSE, TRUE); return; } cr.min.y = c->w[0]->r.min.y; @@ -302,7 +302,7 @@ colgrow(Column *c, Window *w, int but) c->w[i] = v; } draw(screen, cr, textcols[BACK], nil, ZP); - winresize(w, cr, FALSE); + winresize(w, cr, FALSE, TRUE); for(i=1; inw; i++) c->w[i]->body.maxlines = 0; c->safe = FALSE; @@ -314,7 +314,7 @@ colgrow(Column *c, Window *w, int but) ny = emalloc(c->nw * sizeof(int)); tot = 0; for(j=0; jnw; j++){ - l = c->w[j]->body.maxlines; + l = c->w[j]->taglines-1 + c->w[j]->body.maxlines; nl[j] = l; tot += l; } @@ -323,9 +323,9 @@ colgrow(Column *c, Window *w, int but) memset(nl, 0, c->nw * sizeof(int)); goto Pack; } - nnl = min(onl + max(min(5, w->maxlines), onl/2), tot); - if(nnl < w->maxlines) - nnl = (w->maxlines+nnl)/2; + nnl = min(onl + max(min(5, w->taglines-1+w->maxlines), onl/2), tot); + if(nnl < w->taglines-1+w->maxlines) + nnl = (w->taglines-1+w->maxlines + nnl)/2; if(nnl == 0) nnl = 2; dnl = nnl - onl; @@ -355,14 +355,10 @@ colgrow(Column *c, Window *w, int but) v = c->w[j]; r = v->r; r.min.y = y1; - r.max.y = y1+Dy(v->tag.all); + r.max.y = y1+Dy(v->tagtop); if(nl[j]) r.max.y += 1 + nl[j]*v->body.font->height; - if(!c->safe || !eqrect(v->r, r)){ - draw(screen, r, textcols[BACK], nil, ZP); - winresize(v, r, c->safe); - } - r.min.y = v->r.max.y; + r.min.y = winresize(v, r, c->safe, FALSE); r.max.y += Border; draw(screen, r, display->black, nil, ZP); y1 = r.max.y; @@ -372,7 +368,7 @@ colgrow(Column *c, Window *w, int but) for(j=c->nw-1; j>i; j--){ v = c->w[j]; r = v->r; - r.min.y = y2-Dy(v->tag.all); + r.min.y = y2-Dy(v->tagtop); if(nl[j]) r.min.y -= 1 + nl[j]*v->body.font->height; r.min.y -= Border; @@ -382,17 +378,12 @@ colgrow(Column *c, Window *w, int but) /* compute new size of window */ r = w->r; r.min.y = y1; - r.max.y = r.min.y+Dy(w->tag.all); + r.max.y = y2; h = w->body.font->height; - if(y2-r.max.y >= 1+h+Border){ - r.max.y += 1; - r.max.y += h*((y2-r.max.y)/h); - } + if(Dy(r) < Dy(w->tagtop)+1+h+Border) + r.max.y = r.min.y + Dy(w->tagtop)+1+h+Border; /* draw window */ - if(!c->safe || !eqrect(w->r, r)){ - draw(screen, r, textcols[BACK], nil, ZP); - winresize(w, r, c->safe); - } + r.max.y = winresize(w, r, c->safe, TRUE); if(i < c->nw-1){ r.min.y = r.max.y; r.max.y += Border; @@ -406,13 +397,10 @@ colgrow(Column *c, Window *w, int but) v = c->w[j]; r = v->r; r.min.y = y1; - r.max.y = y1+Dy(v->tag.all); + r.max.y = y1+Dy(v->tagtop); if(nl[j]) r.max.y += 1 + nl[j]*v->body.font->height; - if(!c->safe || !eqrect(v->r, r)){ - draw(screen, r, textcols[BACK], nil, ZP); - winresize(v, r, c->safe); - } + winresize(v, r, c->safe, j==c->nw-1); if(j < c->nw-1){ /* no border on last window */ r.min.y = v->r.max.y; r.max.y += Border; @@ -458,6 +446,8 @@ coldragwin(Column *c, Window *w, int but) error("can't find window"); Found: + if(w->tagexpand) /* force recomputation of window tag size */ + w->taglines = 1; p = mouse->xy; if(abs(p.x-op.x)<5 && abs(p.y-op.y)<5){ colgrow(c, w, but); @@ -487,10 +477,10 @@ coldragwin(Column *c, Window *w, int but) if(i == 0) return; v = c->w[i-1]; - if(p.y < v->tag.all.max.y) - p.y = v->tag.all.max.y; - if(p.y > w->r.max.y-Dy(w->tag.all)-Border) - p.y = w->r.max.y-Dy(w->tag.all)-Border; + if(p.y < v->tagtop.max.y) + p.y = v->tagtop.max.y; + if(p.y > w->r.max.y-Dy(w->tagtop)-Border) + p.y = w->r.max.y-Dy(w->tagtop)-Border; r = v->r; r.max.y = p.y; if(r.max.y > v->body.r.min.y){ @@ -498,11 +488,7 @@ coldragwin(Column *c, Window *w, int but) if(v->body.r.min.y == v->body.r.max.y) r.max.y++; } - if(!eqrect(v->r, r)){ - draw(screen, r, textcols[BACK], nil, ZP); - winresize(v, r, c->safe); - } - r.min.y = v->r.max.y; + r.min.y = winresize(v, r, c->safe, FALSE); r.max.y = r.min.y+Border; draw(screen, r, display->black, nil, ZP); r.min.y = r.max.y; @@ -510,10 +496,7 @@ coldragwin(Column *c, Window *w, int but) r.max.y = c->r.max.y; else r.max.y = c->w[i+1]->r.min.y-Border; - if(!eqrect(w->r, r)){ - draw(screen, r, textcols[BACK], nil, ZP); - winresize(w, r, c->safe); - } + winresize(w, r, c->safe, TRUE); c->safe = TRUE; winmousebut(w); } @@ -531,7 +514,7 @@ colwhich(Column *c, Point p) for(i=0; inw; i++){ w = c->w[i]; if(ptinrect(p, w->r)){ - if(ptinrect(p, w->tag.all)) + if(ptinrect(p, w->tagtop) || ptinrect(p, w->tag.all)) return &w->tag; return &w->body; } diff --git a/sys/src/cmd/acme/dat.h b/sys/src/cmd/acme/dat.h index 4ef314c81a..10d0568f15 100644 --- a/sys/src/cmd/acme/dat.h +++ b/sys/src/cmd/acme/dat.h @@ -211,7 +211,7 @@ uint textload(Text*, uint, char*, int); Rune textreadc(Text*, uint); void textredraw(Text*, Rectangle, Font*, Image*, int); void textreset(Text*); -int textresize(Text*, Rectangle); +int textresize(Text*, Rectangle, int); void textscrdraw(Text*); void textscroll(Text*, int); void textselect(Text*); @@ -235,6 +235,7 @@ struct Window uchar filemenu; uchar dirty; uchar autoindent; + uchar showdel; int id; Range addr; Range limit; @@ -263,6 +264,11 @@ struct Window int utflastqid; int utflastboff; int utflastq; + int tagsafe; /* taglines is correct */ + int tagexpand; + int taglines; + Rectangle tagtop; + QLock editoutlk; }; void wininit(Window*, Window*, Rectangle); @@ -275,7 +281,7 @@ void winsetname(Window*, Rune*, int); void winsettag(Window*); void winsettag1(Window*); void wincommit(Window*, Text*); -int winresize(Window*, Rectangle, int); +int winresize(Window*, Rectangle, int, int); void winclose(Window*); void windelete(Window*); int winclean(Window*, int); diff --git a/sys/src/cmd/acme/exec.c b/sys/src/cmd/acme/exec.c index 46bec984ea..4cf67480f7 100644 --- a/sys/src/cmd/acme/exec.c +++ b/sys/src/cmd/acme/exec.c @@ -1170,7 +1170,7 @@ tab(Text *et, Text*, Text *argt, int, int, Rune *arg, int narg) if(tab > 0){ if(w->body.tabstop != tab){ w->body.tabstop = tab; - winresize(w, w->r, 1); + winresize(w, w->r, FALSE, TRUE); } }else warning(nil, "%.*S: Tab %d\n", w->body.file->nname, w->body.file->name, w->body.tabstop); diff --git a/sys/src/cmd/acme/rows.c b/sys/src/cmd/acme/rows.c index 919e90ba4e..0e4fff12be 100644 --- a/sys/src/cmd/acme/rows.c +++ b/sys/src/cmd/acme/rows.c @@ -102,7 +102,7 @@ rowresize(Row *row, Rectangle r) row->r = r; r1 = r; r1.max.y = r1.min.y + font->height; - textresize(&row->tag, r1); + textresize(&row->tag, r1, TRUE); r1.min.y = r1.max.y; r1.max.y += Border; draw(screen, r1, display->black, nil, ZP); @@ -271,6 +271,13 @@ rowtype(Row *row, Rune r, Point p) else{ winlock(w, 'K'); wintype(w, t, r); + /* Expand tag if necessary */ + if(t->what == Tag){ + t->w->tagsafe = FALSE; + if(r == '\n') + t->w->tagexpand = TRUE; + winresize(w, w->r, TRUE, TRUE); + } winunlock(w); } } diff --git a/sys/src/cmd/acme/text.c b/sys/src/cmd/acme/text.c index 439e5ec788..22bef9d2da 100644 --- a/sys/src/cmd/acme/text.c +++ b/sys/src/cmd/acme/text.c @@ -45,7 +45,8 @@ textredraw(Text *t, Rectangle r, Font *f, Image *b, int odx) frinit(t, r, f, b, t->Frame.cols); rr = t->r; rr.min.x -= Scrollwid+Scrollgap; /* back fill to scroll bar */ - draw(t->b, rr, t->cols[BACK], nil, ZP); + if(!t->noredraw) + draw(t->b, rr, t->cols[BACK], nil, ZP); /* use no wider than 3-space tabs in a directory */ maxt = maxtab; if(t->what == Body){ @@ -68,14 +69,14 @@ textredraw(Text *t, Rectangle r, Font *f, Image *b, int odx) } int -textresize(Text *t, Rectangle r) +textresize(Text *t, Rectangle r, int keepextra) { int odx; - if(Dy(r) > 0) - r.max.y -= Dy(r)%t->font->height; - else + if(Dy(r) <= 0) r.max.y = r.min.y; + else if(!keepextra) + r.max.y -= Dy(r)%t->font->height; odx = Dx(t->all); t->all = r; t->scrollr = r; @@ -84,7 +85,14 @@ textresize(Text *t, Rectangle r) r.min.x += Scrollwid+Scrollgap; frclear(t, 0); textredraw(t, r, t->font, t->b, odx); - return r.max.y; + if(keepextra && t->r.max.y < t->all.max.y && !t->noredraw){ + /* draw background in bottom fringe of window */ + r.min.x -= Scrollgap; + r.min.y = t->r.max.y; + r.max.y = t->all.max.y; + draw(screen, r, t->cols[BACK], nil, ZP); + } + return t->all.max.y; } void @@ -276,7 +284,7 @@ textload(Text *t, uint q0, char *file, int setqid) if(u != t){ if(u->org > u->file->nc) /* will be 0 because of reset(), but safety first */ u->org = 0; - textresize(u, u->all); + textresize(u, u->all, TRUE); textbacknl(u, u->org, 0); /* go to beginning of line */ } textsetselect(u, q0, q0); @@ -643,8 +651,11 @@ texttype(Text *t, Rune r) Rune *rp; Text *u; - if(t->what!=Body && r=='\n') + if(t->what!=Body && t->what!=Tag && r=='\n') return; + if(t->what == Tag) + t->w->tagsafe = FALSE; + nr = 1; rp = &r; switch(r){ @@ -661,9 +672,13 @@ texttype(Text *t, Rune r) } return; case Kdown: + if(t->what == Tag) + goto Tagdown; n = t->maxlines/3; goto case_Down; case Kscrollonedown: + if(t->what == Tag) + goto Tagdown; n = mousescrollsize(t->maxlines); if(n <= 0) n = 1; @@ -675,9 +690,13 @@ texttype(Text *t, Rune r) textsetorigin(t, q0, TRUE); return; case Kup: + if(t->what == Tag) + goto Tagup; n = t->maxlines/3; goto case_Up; case Kscrolloneup: + if(t->what == Tag) + goto Tagup; n = mousescrollsize(t->maxlines); goto case_Up; case Kpgup: @@ -709,6 +728,23 @@ texttype(Text *t, Rune r) q0++; textshow(t, q0, q0, TRUE); return; + + Tagdown: + /* expand tag to show all text */ + if(!t->w->tagexpand){ + t->w->tagexpand = TRUE; + winresize(t->w, t->w->r, FALSE, TRUE); + } + return; + + Tagup: + /* shrink tag to single line */ + if(t->w->tagexpand){ + t->w->tagexpand = FALSE; + t->w->taglines = 1; + winresize(t->w, t->w->r, FALSE, TRUE); + } + return; } if(t->what == Body){ seq++; diff --git a/sys/src/cmd/acme/wind.c b/sys/src/cmd/acme/wind.c index 29d7258c67..cb2370a3b4 100644 --- a/sys/src/cmd/acme/wind.c +++ b/sys/src/cmd/acme/wind.c @@ -23,6 +23,8 @@ wininit(Window *w, Window *clone, Rectangle r) int nc; w->tag.w = w; + w->taglines = 1; + w->tagexpand = TRUE; w->body.w = w; w->id = ++winid; incref(w); @@ -31,7 +33,11 @@ wininit(Window *w, Window *clone, Rectangle r) w->ctlfid = ~0; w->utflastqid = -1; r1 = r; - r1.max.y = r1.min.y + font->height; + + w->tagtop = r; + w->tagtop.max.y = r.min.y + font->height; + r1.max.y = r1.min.y + w->taglines*font->height; + incref(&reffont); f = fileaddtext(nil, &w->tag); textinit(&w->tag, f, r1, &reffont, tagcols); @@ -48,7 +54,7 @@ wininit(Window *w, Window *clone, Rectangle r) textsetselect(&w->tag, nc, nc); } r1 = r; - r1.min.y += font->height + 1; + r1.min.y += w->taglines*font->height + 1; if(r1.max.y < r1.min.y) r1.max.y = r1.min.y; f = nil; @@ -67,7 +73,6 @@ wininit(Window *w, Window *clone, Rectangle r) draw(screen, r1, tagcols[BORD], nil, ZP); textscrdraw(&w->body); w->r = r; - w->r.max.y = w->body.r.max.y; br.min = w->tag.scrollr.min; br.max.x = br.min.x + Dx(button->r); br.max.y = br.min.y + Dy(button->r); @@ -83,6 +88,24 @@ wininit(Window *w, Window *clone, Rectangle r) } } +/* + * Draw the appropriate button. + */ +void +windrawbutton(Window *w) +{ + Image *b; + Rectangle br; + + b = button; + if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache)) + b = modbutton; + br.min = w->tag.scrollr.min; + br.max.x = br.min.x + Dx(b->r); + br.max.y = br.min.y + Dy(b->r); + draw(screen, br, b, nil, b->r.min); +} + int delrunepos(Window *w) { @@ -111,46 +134,117 @@ movetodel(Window *w) moveto(mousectl, addpt(frptofchar(&w->tag, n), Pt(4, w->tag.font->height-4))); } +/* + * Compute number of tag lines required + * to display entire tag text. + */ +int +wintaglines(Window *w, Rectangle r) +{ + int n; + Rune rune; + Point p; + + if(!w->tagexpand && !w->showdel) + return 1; + w->showdel = FALSE; + w->tag.noredraw = 1; + textresize(&w->tag, r, TRUE); + w->tag.noredraw = 0; + w->tagsafe = FALSE; + + if(!w->tagexpand) { + /* use just as many lines as needed to show the Del */ + n = delrunepos(w); + if(n < 0) + return 1; + p = subpt(frptofchar(&w->tag, n), w->tag.r.min); + return 1 + p.y / w->tag.font->height; + } + + /* can't use more than we have */ + if(w->tag.nlines >= w->tag.maxlines) + return w->tag.maxlines; + + /* if tag ends with \n, include empty line at end for typing */ + n = w->tag.nlines; + if(w->tag.file->nc > 0){ + bufread(w->tag.file, w->tag.file->nc-1, &rune, 1); + if(rune == '\n') + n++; + } + if(n == 0) + n = 1; + return n; +} + int -winresize(Window *w, Rectangle r, int safe) +winresize(Window *w, Rectangle r, int safe, int keepextra) { + int oy, y, mouseintag, mouseinbody; + Point p; Rectangle r1; - int y; - Image *b; - Rectangle br; + + mouseintag = ptinrect(mouse->xy, w->tag.all); + mouseinbody = ptinrect(mouse->xy, w->body.all); + + /* tagtop is first line of tag */ + w->tagtop = r; + w->tagtop.max.y = r.min.y+font->height; r1 = r; - r1.max.y = r1.min.y + font->height; + r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height); + + /* If needed, recompute number of lines in tag. */ + if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){ + w->taglines = wintaglines(w, r); + r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height); + } + + /* If needed, resize & redraw tag. */ y = r1.max.y; - if(!safe || !eqrect(w->tag.r, r1)){ - y = textresize(&w->tag, r1); - b = button; - if(w->body.file->mod && !w->isdir && !w->isscratch) - b = modbutton; - br.min = w->tag.scrollr.min; - br.max.x = br.min.x + Dx(b->r); - br.max.y = br.min.y + Dy(b->r); - draw(screen, br, b, nil, b->r.min); + if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){ + textresize(&w->tag, r1, TRUE); + y = w->tag.r.max.y; + windrawbutton(w); + w->tagsafe = TRUE; + + /* If mouse is in tag, pull up as tag closes. */ + if(mouseintag && !ptinrect(mouse->xy, w->tag.all)){ + p = mouse->xy; + p.y = w->tag.all.max.y-3; + moveto(mousectl, p); + } + + /* If mouse is in body, push down as tag expands. */ + if(mouseinbody && ptinrect(mouse->xy, w->tag.all)){ + p = mouse->xy; + p.y = w->tag.all.max.y+3; + moveto(mousectl, p); + } } - if(!safe || !eqrect(w->body.r, r1)){ - if(y+1+font->height > r.max.y){ /* no body */ + + /* If needed, resize & redraw body. */ + r1 = r; + r1.min.y = y; + if(!safe || !eqrect(w->body.all, r1)){ + oy = y; + if(y+1+w->body.font->height <= r.max.y){ /* room for one line */ + r1.min.y = y; + r1.max.y = y+1; + draw(screen, r1, tagcols[BORD], nil, ZP); + y++; + r1.min.y = min(y, r.max.y); + r1.max.y = r.max.y; + }else{ r1.min.y = y; r1.max.y = y; - textresize(&w->body, r1); - w->r = r; - w->r.max.y = y; - return y; } - r1 = r; - r1.min.y = y; - r1.max.y = y + 1; - draw(screen, r1, tagcols[BORD], nil, ZP); - r1.min.y = y + 1; - r1.max.y = r.max.y; - y = textresize(&w->body, r1); + y = textresize(&w->body, r1, keepextra); w->r = r; w->r.max.y = y; textscrdraw(&w->body); + w->body.all.min.y = oy; } w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines)); return w->r.max.y; @@ -198,7 +292,8 @@ winunlock(Window *w) void winmousebut(Window *w) { - moveto(mousectl, divpt(addpt(w->tag.scrollr.min, w->tag.scrollr.max), 2)); + moveto(mousectl, addpt(w->tag.scrollr.min, + divpt(Pt(Dx(w->tag.scrollr), font->height), 2))); } void @@ -344,11 +439,9 @@ wincleartag(Window *w) void winsettag1(Window *w) { - int i, j, k, n, bar, dirty; + int i, j, k, n, bar, dirty, resize; Rune *new, *old, *r; - Image *b; uint q0, q1; - Rectangle br; /* there are races that get us here with stuff in the tag cache, so we take extra care to sync it */ if(w->tag.ncache!=0 || w->tag.file->mod) @@ -404,7 +497,12 @@ winsettag1(Window *w) i += 6; } } + new[i] = 0; + + /* replace tag if the new one is different */ + resize = 0; if(runeeq(new, i, old, k) == FALSE){ + resize = 1; n = k; if(n > i) n = i; @@ -435,13 +533,11 @@ winsettag1(Window *w) if(w->tag.q1 > n) w->tag.q1 = n; textsetselect(&w->tag, w->tag.q0, w->tag.q1); - b = button; - if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache)) - b = modbutton; - br.min = w->tag.scrollr.min; - br.max.x = br.min.x + Dx(b->r); - br.max.y = br.min.y + Dy(b->r); - draw(screen, br, b, nil, b->r.min); + windrawbutton(w); + if(resize){ + w->tagsafe = 0; + winresize(w, w->r, TRUE, TRUE); + } } void From 24b9f2c020887b4e38890ae53fcf6efc75f8d903 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 31 Oct 2021 14:27:09 +0000 Subject: [PATCH 203/402] sys/src/cmd/acme: fix extra print args (thanks Russ Cox) --- sys/src/cmd/acme/exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/cmd/acme/exec.c b/sys/src/cmd/acme/exec.c index 4cf67480f7..574fe73cce 100644 --- a/sys/src/cmd/acme/exec.c +++ b/sys/src/cmd/acme/exec.c @@ -172,14 +172,14 @@ execute(Text *t, uint aq0, uint aq1, int external, Text *argt) if(n <= EVENTSIZE) winevent(t->w, "%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r); else - winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f, n); + winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f); if(q0!=aq0 || q1!=aq1){ n = q1-q0; bufread(t->file, q0, r, n); if(n <= EVENTSIZE) winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r); else - winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1, n); + winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1); } if(a){ winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(a), a); From 8a35e7821508b1611c8ade71f6c69c4ebf5d6183 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 24 Oct 2016 22:36:20 +0000 Subject: [PATCH 204/402] rc/bin: import await (thanks Geoff Collyer) --- rc/bin/await | 21 +++++++++++++++++++++ sys/man/1/await | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 rc/bin/await create mode 100644 sys/man/1/await diff --git a/rc/bin/await b/rc/bin/await new file mode 100644 index 0000000000..bdf72517e1 --- /dev/null +++ b/rc/bin/await @@ -0,0 +1,21 @@ +#!/bin/rc +# await secs cmd ... - wait at most secs for cmd to complete, but don't kill it. +# cmd's stdin will be /dev/null. +switch ($#*) { +case 0 1 + echo usage: $0: 'maxsecs cmd ...' >[1=2] + exit usage +} + +rfork e +secs=$1 +shift + +$* & +cmdpid=$apid + +for (s in `{seq $secs}) + if (test -e /proc/$cmdpid) + sleep 1 +if (test -e /proc/$cmdpid) + echo $0: $"*: still running >[1=2] diff --git a/sys/man/1/await b/sys/man/1/await new file mode 100644 index 0000000000..f0edbeb510 --- /dev/null +++ b/sys/man/1/await @@ -0,0 +1,29 @@ +.TH AWAIT 1 +.SH NAME +await - wait at most some seconds for a command to complete +.SH SYNOPSIS +.B await +.I max-secs +.I cmd +\&... +.SH DESCRIPTION +Run +.I cmd +with any following arguments, +with standard input from +.BR /dev/null . +Wait at most +.IR max-secs ; +if +.I cmd +is then still running, +exit but leave it running. +.PP +Useful in start-up scripts that must not get stuck. +.SH EXAMPLES +.B +await 5 auth/secstore -s p9auth -n -G factotum >/mnt/factotum/ctl +.SH SOURCE +.B /rc/bin/await +.SH SEE ALSO +.IR wait (2) From 5e8f9f5671e8d07cb5002215800e0725b971cc04 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 205/402] rc/bin: indicate the real time clock is in GMT --- rc/bin/termrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rc/bin/termrc b/rc/bin/termrc index d7fc426b3f..d4555af60c 100755 --- a/rc/bin/termrc +++ b/rc/bin/termrc @@ -1,6 +1,6 @@ #!/bin/rc # terminal startup -TIMESYNCARGS=(-rLa1000000) +TIMESYNCARGS=(-ra1000000) NDBFILE=/lib/ndb/local mntgen -s slashn && chmod 666 /srv/slashn From 583231fdea2ea6c0599c73b10581effda28a938e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 30 Nov 2019 13:20:38 +0000 Subject: [PATCH 206/402] rc/bin: add flag to fshalt to bypass loading a new kernel (thanks Steven Stallion) --- rc/bin/fshalt | 10 ++++++++-- sys/man/8/fshalt | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/rc/bin/fshalt b/rc/bin/fshalt index 5cf6ce6e43..e69e7c7f24 100755 --- a/rc/bin/fshalt +++ b/rc/bin/fshalt @@ -4,9 +4,10 @@ rfork nes kern=() kerncopy=() +loadkern=yes reboot=no fn usage { - echo usage: $1 '[-r] [new-kernel]' >[1=2] + echo usage: $1 '[-r] [-R] [new-kernel]' >[1=2] exit usage } if (! ~ $#* 0) @@ -14,6 +15,10 @@ if (! ~ $#* 0) case -r reboot=yes shift + case -R + loadkern=no + reboot=yes + shift case -* usage $0 } @@ -53,7 +58,8 @@ fn usekernel { } # make a copy of the right kernel -if (~ $reboot yes) { +if (~ $reboot yes) +if (~ $loadkern yes) { if (~ $#kern 0) kern=`{echo $terminal | sed 's;^([^ ]+) .*/([^/ ]+).*$;/n/boot/'$cputype'/9\2;'} diff --git a/sys/man/8/fshalt b/sys/man/8/fshalt index bd025ac207..570c5d9f8f 100644 --- a/sys/man/8/fshalt +++ b/sys/man/8/fshalt @@ -6,6 +6,8 @@ fshalt, reboot \- halt any local file systems and optionally reboot the system [ .B -r ] [ +.B -R +] [ .I new-kernel ] .br @@ -26,7 +28,9 @@ servers. If given .BR -r , .I fshalt -will then reboot the machine. +will then reboot the machine by loading a new kernel. Specifying +.BR -R +will bypass loading a new kernel and restart the machine. If .I new-kernel is given, it will be loaded as the new kernel rather than From f6b5eb330020eb1f019198ac4a00436289444d41 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:39 +0000 Subject: [PATCH 207/402] rc/bin: use 9p.io instead of sources.cs.bell-labs.com in 9fs --- rc/bin/9fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rc/bin/9fs b/rc/bin/9fs index 70c4961763..2006564a3a 100755 --- a/rc/bin/9fs +++ b/rc/bin/9fs @@ -21,7 +21,7 @@ case other case juke # ye olde file server srv -q il!jukefs && mount /srv/il!jukefs /n/juke case sources - srv -nq tcp!sources.cs.bell-labs.com sources /n/sources + srv -nq tcp!9p.io sources /n/sources case sourcesdump 9fs sources mount -n /srv/sources /n/sourcesdump main/archive @@ -44,7 +44,7 @@ case *.vac } vacfs -m /n/`{basename $1 .vac} `{cat $score} case wiki - srv -m 'net!plan9.bell-labs.com!wiki' wiki /mnt/wiki + srv -m 'net!9p.io!wiki' wiki /mnt/wiki case * switch($#*){ case 1 From 4f8aba8a18b08cf29d62965c1263850581c130a8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 23 Apr 2016 19:29:04 +0000 Subject: [PATCH 208/402] lib: update PCI database from pcidatabase.com --- lib/pci | 1210 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 794 insertions(+), 416 deletions(-) diff --git a/lib/pci b/lib/pci index 2027571b76..2d76b8cc06 100644 --- a/lib/pci +++ b/lib/pci @@ -24,7 +24,7 @@ exit 0 ; Updated and currently maintained by: ; Kavi Corporation (admin@pcidatabase.com) ; -; This header created on Mon Feb 17 12:02:30 PST 2014 +; This header created on Thu Feb 18 00:00:00 EST 2016 ;--------------------------------------------------------------------------- ; ; This text file is formatted as follows: @@ -54,20 +54,23 @@ exit 0 ; 0033 Paradyne Corp. - 002F .43 ieee 1394 controller - 00333 1ACPI\GenuineIntel_-_x86_Family_6_Model_23\_0 1ACPI\GenuineIntel_-_x86_Family_6_Model_23\_0 + 002F MAIAM Spitfire VGA Accelerator + 00333 OTI107 Spitfire VGA Accelerator 003D master + 003a mx98715/25 i740pci 003d mx98715/25 1740pci 00D1 mx98715/25 i740 PCI 0070 Hauppauge Computer Works Inc. - 6800 PCI\VEN_14F1&DEV_8810&REV_05 Hauppage Nova -TD-500 DVB-T Tuner Device + 6800 PCI\VEN_14F1&DEV_2F30&SUBSY5_205D14F1&REV_01\3&130 Hauppage Nova -TD-500 DVB-T Tuner Device 68001 PCI\VEN_14F1&DEV_8810&REV_05 Hauppage Nova -TD-500 DVB-T Tuner Device 0100 USBPDO-8 0123 General Dynamics 0315 SK - Electronics Co., Ltd. 0402 Acer aspire one - 5606 0x8086 0x2592 - 9665 0009 ZCT8YBT + 1050 0x1050 ethernet controller + 5606 0x0436 0x4752 + 8086 0x8086 video controller + 9665 PCI\VEN_10DE&DEV_0059&SUBSYS_2052161F&REV_A2 ZCT8YBT' 046D Logitech Inc. 0805 atom ıntel ınsıde n.a. 0808 n/a Logitech Webcam C600 @@ -85,83 +88,97 @@ exit 0 0A1F USB _ phone toush Logitech G930 Headset 5a61 356254 C018 ? Baesline 3 Button Corded Optical Mouse, 2 button + scroll wheel - C045 M/N: M-BZ96C. P/N: 810-000207. PID: HS91013. Epoxy Hidden + C045 M/N: M-BJ96C. P/N: 830667-0000. PID: c00e Epoxy Hidden C046 n/a n/a c05b ee ftht C063 k251d DELL 6-Button mouse C226 n/a n/a C227 n/a n/a + C22D n/a n/a C281 J-UA9 Wingman Force J-UA9 C312 n/a n/a C404 n/a Logitech TrackMan Wheel C50E M-RAM99, C-BS35 MediaPlay Cordless Mouse C512 n/a n/a + C51B n/a n/a c51e Unknown Unknown C526 n/a n/a C52A Dell Wireless Keyboard w/ mouse HID Keyboard Device - C52B FC8708A607198-10F1043TA3 N/A + C52B FC8708A607198-10F1043TA3 USB Receiver for Wireless Mouse C52E n/a USB3 receiver + C52F Logitech Wireless Mouse USB Controller Logitech Wireless Mouse USB Controller 0483 UPEK 2016 UPEK fingerprint sensors Driver Windows xp 04A9 Canon + 314D unknown uhknown 04B3 IBM - 24D5 PCI\VEN_8086&DEV_24D5&SUBSYS_90111584&REV_02 Audio Controller + 24D5 PCI\VEN_8086&DEV_24D5&SUBSYS_B026144D&REV_02 Audio Controller 401 8086 PCI\VEN_8086&DEV_293E&SUBSYS_20F217AA&REV_03\3&B1BFB68&0&D8 401 24C5 PCI\VEN_8086&DEV_24C6&REV_03\3 267A616A - 4010 cc020000 PCI\VEN_8086&DEV_108C&SUBSYS_02F61014&REV03 - 9876 CC_040100 PCI\VEN_8086&DEV_101E&SUBSYS_0591014&REV_03\4&39A85202&0&08F0 + 4010 cc020000 PCI\VEN_10EC&DEV_5227&SUBSYS_220C17AA&REV_01 + 9876 CC_040100 PCI\VEN_8086&DEV_1C3A&SUBSYS_1C3A1458&REV_04 04D9 Filco 1603 n\a Samsung 2011 n/a n/a 04F2 Chicony Electronics Co. - b008 . .oem44.inf + b008 USB\VID_138A&PID_0001 .oem44.inf + B044 . Webcam B175 0001 SN + B217 01A000166 Integrated Camera B307 6030 Webcam -051D APC - 0002 n/a n/a - 051D INT33A0 0 x051d +051D ACPI\VEN_INT&DEV_33A0 + 0002 USB\VID_0B05&PID_580F\E6AZCY495152 Inter (R) Core [TM] 2 Duo cpu + 051D USB\VID_0B05&PID_580F\E6AZCY495152 0x051d + 9876 USB\VID_0B05&PID_580F\E6AZCY495152 USB\VID_0B05&PID_580F\E6AZCY495152 0529 Aladdin E-Token 0553 Aiptek USA 0200, 0x0201, 0x02 DS38xx Oregon Scientific 058f Alcor Micro Corp. - 0001 6377 AM usb storage + 0001 6387 AM usb storage + 0107 0x03 0x01 1234 9380 6387 + 1600 00000000 http://www.alldatasheet.com/datasheet-pdf/pdf/91600/ETC/AU9254A21.html 6362 UNKNOWN Unknown 4-in-1 card reader (istar) 6366 Unknown Multi Flash Reader USB Device - 6387 C508(FC8508)/AU6985/AU6992 - F/W 2902 USB Mass Storage Device(USB1005B Flash Disk) + 6387 intel g620 USB Mass Storage Device(USB1005B Flash Disk) + 8CBA PCI\VEN_8086&DEV_8CBA&SUBSYS_78211462&REV_00\3&115 PCI Simple Communications Controller 9254 AU9254A21-HAS http://www.alldatasheet.com/datasheet-pdf/pdf/91600/ETC/AU9254A21.html - 9380 2C680446 Micron=MT29F32G08CBABA + 9380 FC8708-3 Micron=MT29F32G08CBABA 9540 Unknown SmartCard Reader 0590 Omron Corp 0028 HEM-790IT hid device class blood pressure monitor -05ac Apple, Inc. +05ac Apple Inc. 021e Keyboard IT USB Alluminium Keyboard IT USB - 1293 Apple iPod Apple iPod - 1297 Apple iPhone Apple iPhone g3 + 1293 Apple iPod 5 Apple iPod 5 + 1297 Apple iPhone Apple iPhone 4 21e phone 3g Allumium keyboard it USB + 8215 BCM2046 Broadcom BCM2046 Bluetooth chipset iMac 05E1 D-MAX 0408 00000000000 USB 2.0 Video Capture Controller 0501 120315000000621 web cam 064e SUYIN Corporation - 064e VID_064E&PID_A111&MI_00 Suyin + 064e VID_0000&PID_0000\5&2B3B5BA1&0&1 Suyin a101 suYin Acer Crystal Eye Webcam a103 SuYin WebCam - a116 Suiyn Optronics USB 2.0 UVC 1.3M WebCam + a116 Suiyn Optronics USB 2.0 UVC 0.3M WebCam A219 SUYIN SUYIN 1.3M WebCam + B250 SuYin 1.3M HD WebCam c108 dont know its a webcam software d101 SuYin Web Cam + D217 SUYIN HP TrueVision HD 067B Prolific Technology Inc. 2303 2303 HXA Prolific USB 2 Serial Comm Port контроллеl 2305 PL-2303 USB-to-Printer Bridge Controller - 2393 prolific prolific + 2393 prolific prolificz 2506 PL-2506 Hi-Speed USB to IDE Bridge Controller 25a1 PL-2501 Prolific PCLinq3 USB Transfer Cable Driver 9876 067B TES 06FE Acresso Software Inc. 9700 i don't know a netcard used usb interface 0711 SIIG, Inc. -093a KYE Systems Corp. - 2468 Genius iLook 110 http://genius.ru/products.aspx?pnum=24948&archive=1 +093a KYE Systems Corp. / Pixart Imaging + 2468 Genius iLook 300 http://genius.ru/products.aspx?pnum=24948&archive=1 + 2600 PAC7311 http://www.speedlink.com/support/bin/24-02-2012/SETUP.rar 2608 PAC7311 - Toshiba PX1342E-1 CAM USB\VID_093A&PID_2608&REV_0100&MI_00 2620 CNR-WCAM53G WEBCAM http://www.canyon-tech.com/archive/voip/webcams/CNR-WCAM53#pr-switcher 096E USB Rockey dongle from Feitain @@ -172,11 +189,11 @@ exit 0 2000 0578A97 Broadcom Bluetooth Firmware Upgrade Device 2009 Broadcom Bluetooth Controller 200a Broadcom Bluetooth Controller - 200f Broadcom Bluetooth Controller + 200f PCI\VEN_14E4&DEV_43B1&SUBSYS_2B231A3B&REV_03 Broadcom 802.11ac Network Adapter 201d n450 BROADCOM Bluetooth Device 201e IBM Integrated Bluetooth IV 2020 Broadcom Bluetooth Dongle - 2021 BCM2035B3 ROM Adapter Generic + 2021 0A5C BCM2035B3 ROM Adapter Generic 2033 1ujy100539f Broadcom Blutonium Device Firmware Downloader 2035 5&263C7E89&0&1 BCM92035NMD Bluetooth 2038 Broadcom Blutonium Device Firmware Downloader (BCM2038) @@ -204,7 +221,7 @@ exit 0 2145 bcm9204md Broadcom BCM9204MD LENO Module 2146 Broadcom 2045 Bluetooth 2.1 USB UHE Dongle 2147 0A5C&PID_5800 Broadcom 2046 Bluetooth 2.1 USB Dongle - 2148 Broadcom 2046 Bluetooth 2.1 USB UHE Dongle + 2148 GBU421 Broadcom 2046 Bluetooth 2.1 USB UHE Dongle 2149 Broadcom 2046 Bluetooth 2.1 USB Dongle 214a Broadcom 2046 Bluetooth 2.1 USB Module 214b 52AF1AB24D Broadcom 2046 Bluetooth 2.1 USB Module @@ -221,6 +238,7 @@ exit 0 2157 BCM2046 B1 USB 500 2158 Broadcom 2046 Bluetooth 2.1 Device 219C BCM2070 Broadcom BCM2070 Bluetooth 3.0+HS USB Device + 21E1 Broadcom 20702 Bluetooth 4.0 .0112 21E3 BCM43142A0 Broadcom Bluetooth 4.0 4500 BCM2046B1 Broadcom 2046 Bluetooth 2.1 USB Dongle 4502 BCM2046B1 Broadcom 2046 Bluetooth 2.1 USB Dongle @@ -236,23 +254,24 @@ exit 0 1010 1010&REV_0101&MI_00 RoMI/o by Egosys - Midi USB Cable 0AC8 ASUS 1234 1 1 - 6719 asus PCI\VEN_8086&DEV_27DA&SUBSYS_81791043&REV_01\3&11583659&0&FB + 6719 3330 8086&DEV_0F18&SUBSYS_16DD1043&REV_0E + 9876 1 1 0b05 Toshiba Bluetooth RFBUS, RFCOM, RFHID 170C 6205 WIFI USB Card 0c45 Microdia Ltd. - 0C45 USB\VID_0000&PID_0000\6&14BE79D5&0&4 USB2.0 + 0C45 USB\VID_041&PID_6143&REV_0101 USB2.0 1111 USB\VID_0C45&PID_612A\5&B0F4C74&0&2 USB webcam 5243 USB xda exec Uknown device 6007 USB\VID_0C45&PID_6007&REV_0101 Genius WebCam Eye 600D USB\VID_0C45&PID_600D&REV_0101 USB(v1.1) webcam - 602C SN9C102C Webcam + 602C SN9C102C home made 602D VID_0C45&PID_6480&MI_00 USB Webcam - 6030 USB\VID_0C45&PID_6030\5&18D8BE1C&0&1 USB WebCam + 6030 USB\VID_0C45&PID_6029\5&18D8BE1C&0&1 USB WebCam 610C USB\VID_0C45&PID_610B\7&3211544E$0$2 usb web camera 6128 USB\VID_0C45&PID_613C&REV_0101 USB веб-камера 6128_ USB\VID_0C45&PID_6148&REV_0101 USB PC Camera Plus 6129 USB\VID_0C45&PID_6128\5&3875c171&0&1 USB WebCam - 6130 USB\VID_090C&PID_1000\0346113020045748 USB HUB + 6130 USB\VID_0000&PID_0000\5&1AAEDD8&0&2 USB HUB 613A USB\VID_0C45&PID_613A\5&2F621EE5&0&5 USB WEBCAM 613c USB\VID_0C45&PID_613C\5&377B3285&0&1 USB Webcam 613E 5&29957435&0&1 USB Camera @@ -263,31 +282,33 @@ exit 0 627F USB\VID_17A1&PID_0118&REV_0100 USB\VID_17A1&PID_0118&REV_0100 62B3 USB\Vid_0c45&Pid_62b3&Rev_0100&MI_00 USB 2.0 PC Camera 62BF USB\Vid_0c45&Pid_62bf USB\Vid_0c45&Pid_62bf&Rev_0100 - 62c0 SNP2UVC Sonix Wecam - 6353 USB\VID_0000&PID_0000\5&21F6DCD1&0&5 USB Microscope + 62c0 SNP2UVC Sonix Webcam + 6353 USB\VID_0000&PID_0000\5&1FFD6427&0&2 USB Microscope 641D USB\VID_0C45&PID_643d 1.3 MPixel Integrated Webcam used in Dell N5010 series 6421 USB\VID_0C45&PID_6421&REV_0224&MI_00 USB 2.0 Webcam slim 32 642F USB\VID_0C45&PID_642F&REV_1224 Webcam - 644b not known not known + 644b oc45&oid 641d& 9:07&mi oo oc45&oid 641d& 9:07&mi oo 6489 0x6489 Integrated Webcam Universal Serial Bus controllers 6840 USB\VID_0C45&PID_6480&MI_00 sonix 1.3 mp laptop integrated webcam + 7401 n.a. RDing TEMPer1V1.4 9876 USB\VID_090C&PID_B371&MI_00\6&462987E&0&0000 webcam 0cf3 TP-Link 1002 Wireless USB 2.0 adapter TL-WN821N Wireless USB 2.0 adapter TL-WN821N - 3000 неизвес& неизвестное уст& - 3002 unknown unkown + 3000 USB\VID_0000&PID_0000\6&F763642&0&4 USB\VID_0000&PID_0000\6&F763642&0&4 + 3002 USB\VID_0CF3&PID_3002&REV_0001 USB\VID_0CF3&PID_3002&REV_0001 3002_ unknown unknown 3005 AR3011 Atheros Bluetooth Module 9271 0x0108 TP-LINK 150 Mbps Wireless Lite N Adapter TL-WN721N 0D2E Feedback Instruments Ltd. 0D8C C-Media Electronics, Inc. + 000E 00 Generic USB Audio Device 0102 6206lc USB 5.1CH audio codec 5200 0x5200 C-Media USB 2.0 Mass Storage Controller 0DF6 Sitecom 9071 \t9071\t WL-113 - Wireless Network USB dongle 5 \t9071\t WL-113 - Wireless Network USB dongle 54g 0E11 Compaq Computer Corp. 0001 2 PCI to EISA Bridge - 0002 55919 W9B0Tx Win 8.1) (Win 2003 - 2008R2) 7268 PCI / ISA IEEE1284 ECP/EPP/SPP/BPP Signal Chips So PCI parallel port 7268 PCI / ISA IEEE1284 ECP/EPP/SPP/BPP PAR4008A PCI parallel port 140A DSP Research Inc @@ -6241,7 +6428,7 @@ exit 0 140F Salient Systems Corp 1412 IC Ensemble, Inc. 1712 ICE1712 M-audio Delta 44 (http://www.m-audio.com) - 1724 VT1723 Envy24PT/HT PCI Multi-Channel Audio Controller + 1724 VT1723 Envy24PT/HT PCI Multi-Channel Audio Controller (аудиоко 1413 Addonics 1415 Oxford Semiconductor Ltd - now part of PLX Technology 8401 OX9162 PCI Interface to local bus @@ -6258,13 +6445,14 @@ exit 0 9521 OX16PCI952 Dual UART 9523 OX16PCI952 Integrated Parallel Port c110 OXPCIe952 Parallel PCI Express Card (Manhattan 158176) - c158 OXPCIe952 2 native UARTs (function 0) + c158 OXPCIe952 Scheda PCI Express Seriale Due porte, X1 linea c15d OXPCIe952 2 native UARTs (function 1) c208 OXPCIe954 Quad UARTs c20d OXPCIe954 Quad UARTs (function 1) c308 OXPCIe958 Octo UARTs c30d OXPCIe958 Octo UARTs (function 1) 1418 Kyushu Electronics Systems Inc + 0781 RaLink RT2860 300Mbps 802.11n Wireless Card 1419 Excel Switching Corp 141B Zoom Telephonics Inc 141E Fanuc Co. Ltd @@ -6316,15 +6504,16 @@ exit 0 1441 Agie SA. 1443 Unibrain S.A. 1445 Logical Co Ltd -1446 Graphin Co. Ltd +1446 Graphin Co., LTD + 6A73 not known not known 1447 Aim GMBH 1448 Alesis Studio 0001 ADAT/EDIT Audio Editing 144A ADLINK Technology Inc 348A LPCI-3488A Low-profile High-Performance IEEE488 GPIB Interface Card for PCI Bus - 7230 + 7230 PLX PCI-9052 PLX PCI-9052 7248 PCI-9052 PLX PCI9052 - 7250 PCI-7250 PLX PCI9052 + 7250 PCI-7250 PLX PCI-9050 7256 PCI-7256 PCI-7256 16-CH Latching Relay & 16-CH Isolated Digital Input Card 7296 PCI-7296 (PLX PCI-9052) 96-ch digital I/O card 7432 PCI-7432 @@ -6343,8 +6532,9 @@ exit 0 1451 SP3D Chip Design GMBH 1453 Mycom Inc 1458 Giga-Byte Technologies - 1458 0x1458 microsoft + 1458 0x29e0 microsoft 5000 0x29e0 GA-X48T-DQ6 + 67B1 0x29e0 GA-X48T-DQ6 145C Cryptek 145F Baldor Electric Company 0001 NextMove PCI Multi-axis Motion Controller @@ -6354,7 +6544,7 @@ exit 0 00C1 NV41.1 NX6800-TD256E 4720 883 Audio controller 5071 883 Audio controller - 5964 0PCI\VEN_11C1&DEV_0620&SUBSYS_062011C1 RADEON 9250/9200 series AGP + 5964 PCI\VEN_1002&DEV_7291&SUBSYS_08101462&REV_9A0PCI\V RADEON 9250/9200 series AGP 7120 7960 MCP2T MCP2T 1463 Fast Corporation @@ -6386,12 +6576,12 @@ exit 0 148E OSI Plus Corporation 148F Plant Equipment Inc. 1000 unknown Ralink Motorola BC4 Bluetooth 3.0+HS Adapter - 148f 2070 TP-LINK 7200ND + 148f 5370 TP-LINK 7200ND 2000 Unknown Ralink Motorola BC8 Bluetooth 3.0 + HS Adapter 2070 1.0 802.11 g WLAN 2573 1192Af7b 802.11 bg 2870 1.0 802.11 n WLAN - 3000 RT3290 802.11n + Bluetooth 3.0 + 3000 RT3290 ralink rt3290_bluetooth_01 3070 RT3070L FreeWifiLink D3-10000N 3572 RT3572 Ralink 3572 5370 Ralink RT2870 802.11n USB Wireless LAN Card @@ -6410,13 +6600,14 @@ exit 0 149B Seiko Instruments Inc 149E Mapletree Networks Inc. 149F Lectron Co Ltd -14A0 Softing GMBH +14A0 Softing AG 14A2 Millennium Engineering Inc 14A4 GVC/BCM Advanced Research 14A9 Hivertec Inc. ad1f 1 1 14AB Mentor Graphics Corp. 14B1 Nextcom K.K. + 0FECF0000 i865P/PE/G/i848P rev. A2 Intel 82801EB (ICH5) rev. 02 1033 R6795-12 RH56D-PCI 2F30 01 zyxel omni 56k CI lus rev. 14B3 Xpeed Inc. @@ -6461,7 +6652,9 @@ exit 0 14C9 Odin Telesystems Inc 14CB Billionton Systems Inc./Cadmus Micro Inc 14CD Universal Scientific Ind. - 03 0x02 0x0200 + 03 0x02 0x1212 + 1001 BCM4356 802.11 ac wireless module + 168a NA Multi-Card reader 14CF TEK Microsystems Inc. 2920 FPMC-FIO1-F100-1 Serial I/O Controller aka FPMC-DFLEX64 14D4 Panacom Technology Corporation @@ -6534,6 +6727,7 @@ exit 0 1234 7175144F networkcontroller 1361 BCM4313 Ethernet 14E4 BCM57780 802.11b/g Wireless Lan Controller + 1570 720p FaceTime HD camera Webcam found on Macbook Pro with Retina Display, 2014 (aka. Macbook Pro /w Retina 11,3) 1600 BCM5752 NetXtreme BCM5752 Gigabit Ethernet PCI Express 1601 BCM5752M NetXtreme Desktop/Mobile 1610 BCM70010 Broadcom BCN70010 Video Decoder @@ -6545,7 +6739,7 @@ exit 0 1644 BCM5751F ven_1102dev_0004 1645 BCM570123 broadtcomBCM5701 Gigabit EthernetASD 1646 BCM5702x1 NetXtreme Gigabit Ethernet - 1647 BCM5703 NetXtreme Gigabit Ethernet + 1647 BCM57788 NetLink tm Gigabit Ethernet pcie 1648 BCM5704 NetXtreme Dual Gigabit Adapter 164C BCM5708 Broadcom NetXtreme II Gigabit Ethernet Adapter 164D 83471043 NetXtreme Fast Ethernet Controller @@ -6583,7 +6777,7 @@ exit 0 1692 BCM57780 NetLink 1693 BCM5787 Ethernet Controller Broadcom Netlink Gigabit 1696 BCM5782 Broadcom NetXtreme Gigabit Ethernet - 1698 02941028 NetLink-FOR DELL LAPTOP AND MAYBE OTHERS + 1698 02941028 NetLink Ethernet-FOR DELL LAPTOP AND MAYBE OTHERS 169A BCM5787 Broadcom Netlink (TM) gigabit ethernet Driver 169B BCM5786 NetXtreme Gigabit Ethernet 169C 17351043 Broadcom NetLink (TM) Gigabit Ethernet @@ -6596,21 +6790,22 @@ exit 0 16B1 BCM57781 BCM57781 16B5 BCM57785X Broadcom NetLink Gigabit Ethernet 16BE 16BE8 CardReader Broadcom 1.0.0.221 - 16BF 0x16BF CardReader Broadcom 1.0.0.221 + 16BF 0x16BF CardReader Broadcom 15.0.7.2 16C6 BCM5702A3 NetXtreme Gigabit Ethernet 16C7 BCM 94311 DELL Wireless 1390 WLAN MiniCard 16DD BCM5781 NetXtreme Gigabit Ethernet 16f7 BCM5753 NetXtreme BCM5753 Gigabit PCI Express 16FD BCM5753M NetXtreme Gigabit Ethernet PciXpress 16FE BCM5753F NetXtreme Gigabit Ethernet - 170C PCI\VEN_14E4&DEV_4727&SUBSYS_1483103C&REV_01 Broadcom 440x 10/100 Integrated Controller + 170C PCI\VEN_14E4&DEV_1692&CC_020000 Broadcom 440x 10/100 Integrated Controller 170D BCM5901 NetXtreme 170E BCM5901 NetXtreme 100Base-TX 1713 BCM5906m Broadcom NetLink (TM) Fast Ethernet + 21E3 BCM43142A0 Broadcom Bluetooth 4.0 333 BCM53333 16p 1G (PHY) 3352 BCM3352 BCM3352 QAMLink® Single-Chip 4-Line VoIP 3360 BCM3360 Advanced PHY Broadband Gateway Cable Modem - 4211 intel 10Mb/s NIC + 4211 intel CORE I5 10Mb/s NIC 4212 BCM V.90 56k Modem 4301 Broadcom BCM4301 802.11g Wireless LAN Controller Dell Truemobile 1180 802.11g MiniPCI 4303 BCM4303 BCM4301 802.11b802.11b Wireless LAN Controller @@ -6618,26 +6813,28 @@ exit 0 4306 BCM4306 Unknown device 4306 (rev 02) 4307 BCM4306 802.11b Wireless LAN Controller 4310 BCM4310 BCM4301USB Controller - 4311 BCM4311 Wireless LAN BroadCom + 4311 BCM4311 802.11b/g Wireless LAN 4312 BCM4310 broadcom wireless 1490 (dell) 4313 BCM4310 UART wireless network card 4315 BCM4315/BCM22062000 Broadcom Wireless b/g (Tested Drivers) - 4318 BCM4318 Broadcom 802.11b/g - 4320 BCM4306 802.11B/G Wireless Lan Controller Revision 3 + 4318 BCM4318 Broadcom 802.11b/g WLAN + 4320 BCM4306 802.11B/G Wireless Lan Controller 3-я Редакция 4321 BCM4306 802.11a Wireless LAN Controller 4322 BCM4306 UART 4323 BCM4306 V.90 56k Modem - 4324 BCM4357 802.11a/b/g Wireless LAN + 4324 Broadcom 43225 802.11a/b/g Wireless LAN 4325 BCM4306 802.11b/g Wireless LAN Controller 4326 BCM4306 Chipcommon I/O Controller? 4328 BCM4321KFBG Broadcom BCM43xx 1.0 (5.10.91.27) 4329 BCM43XX Broadcom 802.11n Network Adapter 432B 4322 Broadcom Wireless LAN Driver - 4353 BCM943224HMS Broadcom Half Mini PCI Express Wifi card / DL1520 + 4331 BCM4331 Broadcom BCM4331 + 4353 BCM943224HMS Broadcom Half Mini PCI Express Wifi card / DL1520 (aka Dell Wireless 1520 802.11n Mini Card WLAN Dri 4357 BCM94322c5HM Broadcom WiFi 802.11b/g/n 4358 BCM943227HM4L Broadcom 802.11n WLAN module 4359 BCM943228HM4L Half-mini wireless-N card DW1530 4365 061117AA Broadcom 43142 Wireless LAN Adapter + 43a1 0x4360 Broadcom BCM4708A0 4401 BCM4401 10/100 Integrated Ethernet Controller 4402 BCM440 10/100 Integrated Ethernet Controller 4403 BCM4402 V.90 56k Modem @@ -6665,7 +6862,7 @@ exit 0 4718 BCM47xx Sentry5 Crypto Accelerator 4720 BCM4712 MIPS CPU 4726 7175144f 01 - 4727 BCM94313HMGB Broadcom 802.11n Network Adapter + BT combo card + 4727 BCM1503HMGIPAD_NT61 Dell Wireless 1501/1503/1701 Half Mini Card Driver (used google chrome to download file) 4728 7175144f 01 53343 BCM53343 16P 1G (PHY) 5365 BCM5365P Sentry5 PCI to SB Bridge @@ -6701,6 +6898,7 @@ exit 0 8022 BCM53022 Next generation router SOC with gigabit switch with RGMII/SDIO 8023 BCM53023 Next generation router SOC with gigabit switch with SATA instead of RGMII/SDIO 8025 BCM53025 Next generation router SOC with gigabit switch with RGMII/SDIO, GMII, SGMII and SATA + 8202 BCM8202 Packet Processor ASIC 8334 BCM53334 24 1G 8342 BCM53342 8 1G (PHY) 8344 BCM53344 24P 1G +4P 1G (PHY) @@ -6717,6 +6915,15 @@ exit 0 8415 BCM53415 160Gbps L2+ Ethernet Switch 8416 BCM53416 160Gbps L2+ Ethernet Switch 8418 BCM53418 160Gbps L2+ Ethernet Switch + 8433 BCM53433 L2+ Ethernet switch: 16P 1G + 8434 BCM53434 L2+ Ethernet switch: 24P 1G + 8442 BCM53442 L2+ Ethernet switch: 8P 1G + 4P 1G + 8443 BCM53443 L2+ Ethernet switch: 16P 1G + 4P 1G + 8444 BCM53444 L2+ Ethernet switch: 24P 1G + 4P 1G + 8446 BCM53446 L2+ Ethernet switch: 24P 1G +2P 1G/10G +2P 1G/10G + 8447 BCM53447 L2+ Ethernet switch: 24P 1G +2P 1G/10G +2P 1G/10G + 8448 BCM53448 L2+ Ethernet switch: 8P 1G + 8P 1G/2.5G + 4P 10G + 8449 BCM53449 L2+ Ethernet switch: 16P 1G + 8P 1G/2.5G + 4P 10G + 2P 20G 9867 900000000 900000000 9876 Texas Instruments PCI GemCore based SmartCard cont 0x14E4 A8D6 BCM6368 Broadcom 802.11n WLAN chip @@ -6726,11 +6933,16 @@ exit 0 B064 BCM56064 160Gbps L2+ Ethernet Switch B150 BCM56150 Hurricane2 (Lightly Managed) 24P 1G +4P 1G/10G (PHY) b152 BCM56152 24P 1G (PHY) + B160 BCM56160 L2+ switch: 24P 1G +2P 1G/10G +2P 1G/10G + B161 BCM56161 L2+ Ethernet switch: 24P 1G +2P 1G/10G +2P 1G/10G + B162 BCM56162 L2+ Ethernet switch: 24P 1G +4P 1G B340 BCM56340 48-port multi-layer switch with embedded CPU B450 BCM56450 100G Multi-layer Ethernet Switch B640 BCM56640 260Gbps Extensible Switch with 100GE + B842 BCM56842 320Gbps Ethernet Multilayer Switch B845 BCM56845 640G Multi-layer Ethernet Switch B850 BCM56850 1.28T I/O Multi-layer Ethernet Switch + B960 BCM56960 3.2T I/O Multi-layer Ethernet Switch dev_4311 1364103c subsys 14EA Planex Communications, Inc. AB06 XFNW-3603-T 10/100 Fast Ethernet CardBus (RTL8139) @@ -6741,15 +6953,15 @@ exit 0 16BE CardReader_Broadcom 1.0.0.222_W7x86_A 14ED Datakinetics Ltd 14EF Carry Computer Eng. Co Ltd -14F1 Conexant Systems, Inc. (Formerly Rockwell) +14F1 Conexant 0F00 cx11252-11 HSF Generic Modem 0F30 0x14F1 0x14F1 1031 332 dfd 1033 RH56D RH56D-PCI 1033a RH56D RH56D-PCI 1035 R6795-11 RH56D/SP-PCI, R6795-11, E416921/1, 0336 Mexico - 1036 Conexant RH56D/SP-PCI unknown - 1056 4-1b359d48-0-10f06 Symphony modem DSL router6 + 1036 Conexant RH56D/SP-PCI + 1056 105614f1 subsys 1059 DI15630-5, DI5631, DI5633 SmartHCF 10B4 Conextant HFC All Conextant HFC Modems (PCI) 10B6 unknown Conexant HCF PCI Soft modem @@ -6778,9 +6990,9 @@ exit 0 2F81 2F82 cx9510-11z Conexant PCI-E Soft Data/Fax Modem with SmartCP 5045 4.0.3.1 http://h10025.www1.hp.com/ewfrf/wc/softwareDownloadIndex?softwareitem=ob-43284-1&lc=en&dlc=en&cc=us& - 50451 14f12f30 Conextant High Definition Audio-Venice 5051 + 50451 14f12f30 Conextant High Definition 50452 14e4 Conextant High Definition SmartAudio 221 - 50452 PCI\VEN_14F1&DEV_5047 Conextant High Definition Audio-Venice 5051 + 50452 PCI\VEN_14F1&DEV_5051 Conextant High Definition Audio-Venice 5051 5047 Not sure HDAUDIO Soft Data Fax Modm- Conexant Sound Card Audio Driver 5051 4.0.1.6 Conexant HD-Audio SmartAudio 221 5051_ DG31PR Conexant HD-Audio SmartAudio 221 @@ -6795,16 +7007,16 @@ exit 0 8800 Conexant CX23881 PAL audio/video decoder 88000 0x14F1 0x14F1 8801 CX23880 PCI Broadcast Audio/Video Decoder - 8802 CX2388x MPEG Encoder (ASUS Blackbird) + 8802 CX2388x MPEG Encoder 8811 CX2388x Audio Capture ike 8852 cx23885 Leadtek Winfast PxDVR3200 H (XC3028) 8880 CX23888 PCI Express Video and Broadcast Audio Decoder - 9876 PCI\VEN_14F1&DEV_2F20&SUBSYS_200C14F1&REV_00\4&CF8 f + 9876 PCI\VEN_14F1&DEV_2F20&SUBSYS_200C14F1&REV_00\4&CF8 Communication controller x27d8 A62516F3 INTEL IDT Audio 14F2 Mobility Electronics, Inc. 0001 Moselle Split Bridge 0002 Capilano Split Bridge - 0120 win7_rtm.090713-1255 Merlin Split Bridge + 0120 win7_rtm.090713-1257 Merlin Split Bridge 0121 PCI Parallel Port 0122 unknown PCI Serial Port 0123 6.1.7600.16385 PCI PS/2 Keyboard Port @@ -6850,14 +7062,14 @@ exit 0 1514 TFL LAN Inc 1515 ICS Advent 1516 Myson Technology Inc - 0800 MTD800 10/100 Mbps Fast Ethernet Controller + 0800 Myson MTD803/TAMARACK TC6020 PCI Ethernet controller 0803 Myson MTD803/TAMARACK TC6020 PCI Ethernet controller - 0891 MTD891 10/100/1000 Mbps Gigabit Ethernet Controller + 0891 Myson MTD803/TAMARACK TC6020 PCI Ethernet controller 1517 Echotek Corporation 1518 Kontron Modular Computers GmbH (PEP Modular Computers GMBH) 1519 Telefon Aktiebolaget LM Ericsson 0020 0123456789 HSIC Device - 2004 0x1 PCI Interface bus + 2004 1 PCI Interface bus 151A Globetek Inc. 1002 PCI-1002&DEV_4341&subsys_82441033&rev_01\ 4341 1004 PCI-1004 @@ -6879,7 +7091,7 @@ exit 0 8 MU9C8K64 Content Addressable Memory 1524 ENE Technology Inc 0751 08011558 pci - 0100 ACPI\ENE0100 ENE CIR Receiver + 0100 ACPI\ENE0100 ENE CIR Receiver 0510 1.4.5.0 PCI Memory Card Reader Controller 0530 CB-712/714/810 Memory Stick Card Reader 0550 CB-712/714/810 Secure Digital Card Reader @@ -6887,7 +7099,7 @@ exit 0 0555 10c11734 ven1524&dev_0551&SUBSYS_009F1025&REV_01 0610 ??? PCI Smart Card Reader Controller 0730 0x0751 CardBus Controller - 100 ACPI/ENE0100 ENE CIR Receiver + 100 ACPI/ENE0100/3&21436425&0 ENE CIR Receiver 1025 1025123 PCI\VEN_127a&DEV_1025&SUBSYS_1025123A&REV_01\4&1351887D&0&58F0 1211 CB-1211 CardBus Controller 1225 CB-1225 CardBus Controller @@ -6911,6 +7123,7 @@ exit 0 152C Macraigor Systems LLC 152D Quanta Computer Inc 2329 2338 J micron JM20329 + 2519 n/a JMicron Technology Corp. / JMicron USA Technology Corp 152E Melec Inc 2507 0 152F Philips - Crypto @@ -6967,7 +7180,7 @@ exit 0 5555 001 an cpci application 1557 Mediastar Co. Ltd 1558 Clevo/Kapok Computer - 1558 gtx 670mx GPU + 1558 0x1558 gtx 670mx GPU 1559 SI Logic Ltd 155A Innomedia Inc 155B Protac International Corp @@ -7006,7 +7219,7 @@ exit 0 A005 CCSI PCI20-CXS ARCnet A006 CCSI PCI20-FOG-SMA ARCnet A007 CCSI PCI20-FOG-ST ARCnet - A008 CCSI PCI20-TB5 ARCnet + A008 CCSI PCI20-TB5 SONY A009 CCSI PCI20-5-485 5 Mbit ARCnet A00A CCSI PCI20-5-485D 5 Mbit ARCnet A00B CCSI PCI20-5-485X 5 Mbit ARCnet @@ -7037,7 +7250,7 @@ exit 0 1581 SEH Computertechnik GMBH 1582 Cytec Corporation 1583 Inet Technologies Inc -1584 Uniwill Computer Corporation +1584 Vetronix Corporation Engenharia Ltda 5054 VAS5055 VAS Vetronix Automotive Service 4003 VAS5052 VAS Vetronix Automotive Service 1585 Marconi Commerce Systems SRL @@ -7095,10 +7308,10 @@ exit 0 15AB Bluesteel Networks Inc 15AC North Atlantic Instruments 15AD VMware Inc. - 0405 9500MGS VMWare Player 3.1.6 Software Driver + 0405 9500MGS VMWARE SVGA II 0710 0740 Virtual SVGA 0720 VMXNET VMware PCI Ethernet Adapter - 0740 0X0880 VMWare VMCI Bus Device + 0740 58 VMW5858are VMCI Bus Device 0770 n/a Standard Enhanced PCI to USB Host Controller 0778 0778 Sabrent USB-to-Parallel Adapter 07B0 VMXNET 3 VMware vSphere 4 PCI Ethernet Adapter @@ -7133,7 +7346,7 @@ exit 0 0101 n2530a DX2+ FC-AL Adapter 0103 QX4 4 Port Fibre Channel Controller 0B01 SUBSYS_000015BC&REV_00 Agilen PCI-GPIB - 1200 n/a Agilent QX4 Fibre Channel Controller + 1200 0x15bc Agilent QX4 Fibre Channel Controller 2530 ??? HP Communications Port 2531 ??? HP Toptools Remote Control Adapter 2532 ??? HP Toptools Remote Control Adapter @@ -7400,15 +7613,21 @@ exit 0 167F iba AG 4634 FOB-IO Card 4C32 L2B PCI Board - 5344 SD \ VID_03 и OID_5344 и PID_SU01G и REV_8.0 FOB-SD Card + 5344 SD \ VID_03 Ã�¸ OID_5344 Ã�¸ PID_SU01G Ã�¸ REV_ FOB-SD Card 5443 FOB-TDC Card + F0B1 ibaFOB-io-D ibaFOB-io-D F0B2 ibaFOB-2io-D ibaFOB-2io-D F0B4 ibaFOB-4io-D ibaFOB-4io-D + F1B2 ibaFOB-2i-D ibaFOB-2i-D + F5DE ibaFOB-SDexp ibaFOB-SDexp + FDCE ibaFOB-TDCexp ibaFOB-TDCexp + FEC1 ibaFOB-io-ExpressCard ibaFOB-io-ExpressCard 1680 Dunti Corp. 1681 Hercules 0050 HWGPCI-54 Hercules WiFi PCI 802.11G 1682 PINE Technology, Ltd. - 9875 + 2931 unknown HD-467X-DDF2 video card + 9875 779A HD 7700 Series 1688 CastleNet Technology Inc. 0013 AR5213 168A Utimaco Safeware AG @@ -7416,39 +7635,39 @@ exit 0 168C Atheros Communications Inc. 001c AR5005GS pci\ven_10ac&dev_ooo 00027 E017105B Atheros AR5B95 Wireless LAN 802.11 a/b/g/n Controller - 00030 PCI\VEN_168C&DEV_0030&SUBSYS_3112168C&REV_01 TP-LINK 450Mbps Wireless N Adapter - 0007 AR5007EG Wireless Network Adapter - 0011 11a/b/g Wireless LAN Mini PCI Adapter 11a/b/g Wireless LAN Mini PCI Adapter + 00030 PCI\VEN_168C&DEV_0030&SUBSYS_16A810CF&REV_01 TP-LINK 450Mbps Wireless N Adapter + 0007 AR5007UG ROOT\MS_SSTPMINIPORT\0000 + 0011 11L/b/g Wireless LAN Mini PCI Adapter 11L/b/g Wireless LAN Mini PCI Adapter 0012 AR5211 PCI\VEN_1217&DEV_7130&SUBSYS_FF501179&REV_01 DELL Latitude C510 as mini-PCI board behind the larg 0013 Netgear WPN311 Netgear RangeMax WPN311 PCI Wireless NIC 0019 AR5bmb5 802.11a Wireless Adapter 001A Atheros AR5005GS http://support1.toshiba-tro.de/tools/updates/atheros-wlan/atheros-wlan-xp-7702331.zip 001B AR5006X 802.11abg NIC - 001c ACPI\PNP0C32\1 PCI\VEN_8086&DEV_2805&SUBSYS_80860101&REV_1000\4&245E8196&0&0301 + 001c AR5007EG Atheros AR5007EG Wireless Network Adapter 001C other AR5BXB63 Atheros AR5BXB63 WWAN Chip 001c_again AR5BXB61 AR5006EX AR5423a - 001D TP-Link TL-WN350GD PCI\VEN_168C&DEV_002E&SUBSYS_E034105B&REV_01\4&124A40C8&0&00E1 + 001D TP-Link TL-WN350GD PCI\VEN_168C&DEV_002B&SUBSYS_E034105B&REV_01\4&124A40C8&0&00E1 002 c660 PCI/VEN_168C&DEV_002B&SUBSYS_7173144F&REV_01\4&200004B7&0&00E1 0023 AR5416 802.11a/b/g/nБеспроводной PC - 0024 AR5B95 Atheros 802.11a/b/g/n + 0024 AR5B97 Atheros 802.11a/b/g/n 0027 E017105B Atheros AR5B95 Wireless LAN 802.11 a/b/g/n Controller - 002A 2 Atheros AR5B91 - 002B 1461103c Atheros AR5B95 + 002A AR9283-ALIA or DW1525 Wireless Network Adapter + 002B 66318898888811ad Atheros AR5B95 002C AR5006 Wireless 802.11 a/b/g/n WiFi Adapter (PCI-Express) 002D AR9287 rev01 802.11b/g/n 002E AR9287 Atheros ar9287 PCI Можливості: З&# 0030 1102 - 1103 Killer Wireless - N - 0032 0x028000 Atheros AR9485 + 0032 168Cx0032 Atheros AR9485 0034 DW1901 802.11a/b/g/n, BT4.0+HS - 0036 Qualcomm Atheros 956x Wireless Adapter Acer E1-432g + 0036 AR956x Qualcomm Atheros AR956x Wireless Network Adapter 0037 AR1111 Atheros AR1111 WB-EG Wireless Network Adapter - 003e 1 1 + 003e QCA61x4 Wireless Network Adapter 007 AR5007UG Wireless Network Adapter 0280 0x002b PCI\VEN_168C&DEV_002B&SUBSYS_30AF185F 032 0x0280 Dell Wireless DW1703 802.11b/g/n, BT4.0 + HS - 1014 AR5112 Atheros AR5212 802.11abg wireless Drivers + 1014 AR9285 Atheros AR5212 802.11abg wireless Drivers 14F1 nForce6100-430 PCI\VEN_168C&DEV_001A&SUBSYS_04181468&REV_01\4&FCF0450&0&10A4 - 168C 0x001b PCI\VEN_168C + 168C AREG9485WB-0036 Qualcomm Atheros AR9485WB-EG Wireless Network Adapter 1a3b ar8132 802.11a/b/g/n Wireless PCI Adapte 3002 AR3011 Bluetooth 3.0 6666 AR5007UG Atheros AR5B95 Wireless LAN 802.11 a/b/g/n Controller @@ -7459,6 +7678,7 @@ exit 0 168E Hyundai MultiCAV Computer Co. Ltd. 168F KDS Innotech Corp. 1690 NetContinuum, Inc. + 0742 BCM2070 BRCM Bluetooth Controller BCM2070 1693 FERMA 0212 PLX PCI9054 EPONINE ESR-PCI Board 0213 Motorola MPC8245 EPONINE MTM120 PCI Board @@ -7505,7 +7725,7 @@ exit 0 170D SensoMotoric Instruments GmbH 170E San Valley Systems, Inc. 170F Cyberdyne Inc. -1710 Pelago Nutworks +1710 Pelago Networks 5812 5812 itech numeric small keyboard 9835 9825 2 serial, 1 LPT port PCI Card 1711 MyName Technologies, Inc. @@ -7534,6 +7754,7 @@ exit 0 0261 RV280 Sapphire Radeon 9250 - Secondary 7176 RV250 RADEON 9000 ATLANTIS PRO 7177 RV280 RADEON 9000 ATLANTIS PRO - Secondary + 71C6 RV530 ATI RADEON X1650 Series 7244 RV580 Sapphire ATI X1950 XT 7C12 RV280 RADEON 9200 ATLANTIS - Secondary 7C13 RV280 RADEON 9200 ATLANTIS @@ -7556,10 +7777,11 @@ exit 0 0128 17A1 USB2.0 JPEG WebCam 17A7 Start Network Technology Co., Ltd. 17AA Legend Ltd. (Beijing) + 0106 Intel HD Graphics 2000 Intel Sandy Bridge-MB GT1 - Integrated Graphics Controller [D2/J1/Q0] [Lenovo 7145 138A Mobility ATI Radeon X1400 17AB Phillips Components 17AF Hightech Information Systems, Ltd. - 4150 200 HIS Excalibur Radeon 9600 + 4150 200 HIS Excalibur Radeon 6870 7291 RV560 HIS Radeon X1650 XT 17BE Philips Semiconductors 17C0 Wistron Corp. @@ -7574,8 +7796,12 @@ exit 0 5832 X2 Xframe II 10GbE PCI-X 2.0 Adapter 5833 X3 E3100 PCI-Express 10Gb Ethernet Interface 17db Cray, Inc. + 0101 NA Seastar Network + 0201 NA Gemini Network + 0301 NA Aries Network 17E9 DH electronics GmbH / Sabrent 02a7 0000 USB VGA/DVI Adapter UV-D4A1-B + 4318 n/a Dell GigabitEthernet (USB-G1000) 17EE Connect Components, Ltd. 4153 RV350 Radeon 9550 17F3 RDC Semiconductor Co., Ltd. @@ -7590,7 +7816,7 @@ exit 0 6060 modem USB Controller (OHCI) 6061 V90479. 1 USB 2.0 Controller (EHCI) 17FE INPROCOMM - 2220 n/a Generic IEEE 802.11b/g Wireless LAN Card + 2220 2120 Generic IEEE 802.11b/g Wireless LAN Card 1813 Ambient Technologies Inc 3059 VT8237 AC97 Enhanced Audio Controller - the 8251 controller is different 4000 MD5628D-L-A intel V.92 HaM Modem @@ -7598,7 +7824,7 @@ exit 0 1814 Ralink Technology, Corp. 0001 ...B742000 ...I don't know 0101 2460 802.11b RT2460 802.11b Baseband/MAC integrated chip - 0201 PCI\VEN_1814&DEV_5390&SUBSYS_1451033 Ralink Chipset 802.11b/g WLAN Card + 0201 PCI\VEN_1814&DEV_3298&SUBSYS_1451033 Ralink Chipset 802.11b/g WLAN Card 0201 (1) WiFiSKY Ralink RT2500 802.11b/g WLAN Card 0201 (2) 001167F044E5 W-LAN 802.11b/g 0201 (3) RT2560F RaLink @@ -7616,10 +7842,10 @@ exit 0 3060 RT3060 Ralink corp. RT3060 Wireless 802.11n PCI adapter 3090 Ralink RT3090 Ralink RT3090 Wireless Lan Card with Bluetooth 3290 1010 802.11n Bluetooth 4.0 - 3298 -3298 Ralink Bluetooth + 3298 -3290 Ralink Bluetooth 3592 RT3592 Wireless LAN a/b/g/n plus Bluetooth 3.0 combo 5360 RT5360 http://www.wikidevi.com/wiki/D-Link_DWA-525_rev_A2 - 5390 RT5390 Ralink RT5390 802.11b/g/n WiFi + 5390 ASUS X55VD VEN_1814&DEV_5390&SUBSYS_E054105B&REV00 802.11n Wireless Lan Card - Asus X55V - Win 7 64bit - Foxconn Wireless 539B RT5390R Ralink RT5390R 802.11b/g/n WiFi 9876 b8341462 Edimax 54 MBit WLan 802.11g rt 2500 1815 devolo AG @@ -7670,13 +7896,13 @@ exit 0 000a 232/4-PCI-335 Fastcom:232/4-PCI-335 Asyncronous RS232 serial adapter 18FB Resilience Corporation 1904 Ritmo - 2031 n /a controladora ethernet - 8139 8139 Realtek RTL8139 PCI Fast Ethernet Adapter + 2031 n /a silan sc92031 Network adapter + 8139 8129 Realtek RTL8139 PCI Fast Ethernet Adapter 8139 8139 Realtek RTL8139 PCI Fast Ethernet Adapter 1905 WIS Technology, Inc. 1910 Seaway Networks 0001 SW5000-NCA Seaway Network Content Accelerator -1912 usb 3.0 Renesas Electronics +1912 Renesas Electronics 0014 YET-D720201-0014 usb3.0 renesas 0015 upd720202 nec 0015_ EC01-P Renesas Electronics USB 3.0 Host Controller @@ -7687,32 +7913,36 @@ exit 0 1026 AR8121/AR8113 PCI-E ETHERNET CONTROLLER 1048 Atheros L1 Gigabit Ethernet 10/100/1000 Base-T Controller 1060 AR8162 PCI-E Fast Ethernet Controller - 1062 AR8132 Atheros AR8132 PCI-E Контроллер Fast Eth + 1062 AR8132 Atheros AR8132 PCI-EКонтроллер Б&# 1062c Atheros L1 Gigabit Ethernet 10/100/1000 Base-T Controller 1063 AR8131 Atheros AR8131 PCI-E Gigabit Ethernet Controller - 1073 AR81512 Atheros AR81512 + 1073 AR8151 Atheros AR8151 1083 78161462 Atheros AR8151 PCI-E Gigabit Ethernet Controller (NDIS 6.20) - 1090 AR8162 Fast Ethernet + 1090 AR8162+ Fast Ethernet 1091 AR8161/8165 PCI-E Gigabit Ethernet Controller + 10a0 Atheros AR8172/8176/8178 Controller Ethernet Qualcomm Atheros AR8172/8176/8178 PCI-E Fast (NDIS 6.30) 168c Atheros L1 Gigabit Ethernet 10/100/1000 Base-T Controller - 1969 Atheros L1 Gigabit Ethernet 10/100/1000 Base-T à šà ¾Ã ½Ñ'ÃƒÆ’Ã¢â‚¬Ë + 1969 Atheros L3 Atheros AR815x/816x Ethernet Controller Driver 2048 Atheros L2 Fast Ethernet 10/100 Base-T Controller 2049 234543 der - 2060 f121 AR8152 v1.1 Fast Ethernet + 2060 fd501179&rev-c1 AR8152 v1.1 Fast Ethernet 2061 1 Ethernet Controller 2062 FB501179 Qualcomm Atheros AR8152/8158 4747 1969 VEN_1969 9876 Atheros L2 Fast Ethernet 10/100 Base-T Controller + E091 Killer E2200 Killer E2200 Network Card + R091 Killer E2200 Killer E2200 Network Card 1971 AGEIA Technologies, Inc. - 0001 PCI\\VEN_1971&DEV_0000&SUBSYS_00021028&REV_00\\4&2 AGEIA PhysX 100 Series PCI Express Card + 0001 PCI\VEN_1971&DEV_0000&SUBSYS_0003105B&REV_00 AGEIA PhysX 100 Series PCI Express Card 1011 PCI\\VEN_1971&DEV_1011&CC_FF00 AGEIA PhysX 100 Series PCI Card 1021 AGEIA PhysX 200 Series PCI Express Card 197B JMicron Technology Corp. 0250 JMC25 JMC250 PCI Express, Gigabit Ethernet 0256 JMC2XX JMC260 PCI Express Fast Ethernet - 0260 JMC2XX JMC260 PCI Express Fast Ethernet + 0260 ethernet JMC260 PCI Express Fast Ethernet + 0261 0261 JMB38X MS Host Controller 1234 12345678 1234567 - 197b JMB38X JMB38X SD/MMC Хост-Контролл& + 197b JMB38X JMB38X SD/MMC 2360 JMicron JMB36X JMB36X 2361 JMB363 PCI Express to SATA II and PATA Host Controller 2363 JMB36X JMicron JMB362/JMB363 AHCI Controller @@ -7720,13 +7950,14 @@ exit 0 2368 JMB368 IDE Comtroller 2380 JMB38X IEEE 1394 Host Controller 2381 JMB38X JMB38X SD Host Controller - 2382 JMB38Xam5 JMB38X SD/MMC Host Controller ftp://driver.jmicron.com.tw/CardReader/Windows/ + 2382 JMB38X JMB38X SD/MMC Host Controller 2383 0261 JMB38X MS Host Controller 2384 JMB38X JMB38X xD Host Controller - 2391 9.2.0.1031 Intel - 2392 721179 JMB38X SD/MMC Host Controller + 2391 JMB38X JMB38X SD/MMC - JMicron PCIe SD Host Controller + 2392 721179 JMB38X SD/MMC - JMicron PCIe SD Host Controller 2393 Chip Number: JMB38X Chip Description: JMB38X SD/MMC Host Controller 7002 JMB38Xam5 JMB38X SD/MMC Host Controller + JMB38 JMB38X JMB38X SD/MMC Host Controller 198a Nallatech 0210 XMC-210 0220 XMC-220 @@ -7747,7 +7978,7 @@ exit 0 19a2 ServerEngines 0710 Emulex OneConnect 10Gb NIC (be3) (rev01) 0712 Emulex OneConnect 10Gb iSCSI Initiator (be3) (rev 01) - 0714 Emulex OneConnect 10Gb FCoE Ини& Emulex OneConnect 10Gb FCoE Инициатор (be3) (& + 0714 Emulex OneConnect 10Gb FCoE Emulex OneConnect 10Gb FCoE Инициатор (be3) (& 19A8 DAQDATA GmbH 19AC Kasten Chase Applied Research 0001 ACA2400 Crypto Accelerator @@ -7764,12 +7995,14 @@ exit 0 1B13 Jaton Corporation USA 0001 GeForce4 MX 440 nVidia Corporation NV17 1B21 Asustek - ASMedia Technology Inc. + 0612 Asmedia 106x SATA Controler Link Below to Mainboard Driver inside 1041 SUBSYS_2104174C USB 3.0 Host Controller Driver for Windows 7 - 1042 1 Asmedia ASM104x USB 3.0 Host Controller + 1042 pci\ven_14f1&dev_2f50&subsys_205f14f1&rev_01\4&cf8 Asmedia ASM104x USB 3.0 Host Controller 1B6F Etron 7023 DEV_7023&REV_010 Etron USB 3.0 Extensible Host Controller 1B73 Fresco Logic Inc. 1000 1 PCI\VEN_1000&DEV_0020&SUBSYS_10301000&REV_01PCI\VEN + 1009 Unknown USB3.0 host controller 1100 n/a USB 3.0 eXtensibile Host controller 1B91 Averna 1BAD ReFLEX CES @@ -7787,10 +8020,10 @@ exit 0 1FCF Miranda Technologies Ltd. 2001 Temporal Research Ltd 3C19 Ralink RT5370 USB <=> Wireless N 150 Adapter - F103 . . + F103 .7D01 .driver 2646 Kingston Technology Co. 0001 12333 22323 - 2646 6.06000 22323 + 2646 6.06324 22323 270F ChainTek Computer Co. Ltd. 2EC1 Zenic Inc 3388 Hint Corp. @@ -7873,8 +8106,9 @@ exit 0 4348 wch.cn 1453 202204073 WCH353L 3253 32534348 SIE9835 PCI=>DUAL SERIAL - 5053 4348 5053 - 7173 ch CH35X + 5053 4348 4980 + 7053 35255 PCI Serial Port + 7173 ch350L CH35X 4680 UMAX Computer Corp. 4843 Hercules Computer Technology 4943 Growth Networks @@ -7890,7 +8124,8 @@ exit 0 4D54 Microtechnica Co Ltd 4DDC ILC Data Device Corp. 4E8 Samsung Windows Portable Devices - 618d rev_0400 usb lan adapter + 618c rev_0400 usb lan adapter4 + 618d rev_0400 usb lan adapter4 5053 TBS/Voyetra Technologies 2010 14441 Daytona Audio Adapter 508A Samsung T10 MP3 Player @@ -7933,7 +8168,7 @@ exit 0 88F2 86C968 Vision 968 GUI Accelerator VRAM rev. 2 88F3 86C968 Vision 968 GUI Accelerator VRAM rev. 3 8900 86C775 Trio64V2/DX - 8901 pci\ven_5333dev_8C2E&SUBSYS_00011179&REV_05\4&74C6 S3 trio64uv+ for windows xp + 8901 pci\ven_5333dev_8C2E&SUBSYS_00011179&REV_05\4&74C6 S3 trio64uv+ for windows 7 8902 86C551 SMA Family 8903 TrioV Family 8904 86C365/366 Trio3D QFP/BGA @@ -7988,6 +8223,7 @@ exit 0 5853 Citrix Systems, Inc. 0001 n/a Citrix XenServer PV SCSI Host Adapter 0002 n/a Citrix PV Bus Device + C000 N/A XenServer Device of Windows Update 6409 Logitec Corp. 6666 Decision Computer International Co. 0001 815 PCCOM4 @@ -7999,34 +8235,40 @@ exit 0 3c03 DWL-G122 Wifi PCI Same chipset of RALINK RT2500 3C07 D-Link Wireless G DWA-110 USB Adapter PCI\VEN_1799&DEV_700F&SUBSYS_700F1799&REV_20\3&61AAA01&0&48 8080 Xirlink, Inc - 1040 VIA 82C259 rev 0 PCI\VEN_8086&DEV_1040&SUBSYS_1008086&REV_00 + 1040 VIA 82C259 rev 0 PCI\VEN_8086&DEV_0084&SUBSYS_13158086&REV_00 8086 Intel Corporation 27B8 82801GB/GR Intel(R) 82801GB/GR (ICH7 Family) LPC Interface Controller + 0004 0x05971028 IUSB3\ROOT 0008 Extended Express System Support Ctrlr 0011 0x108D Ethernet Controller 0042 Intel graphics Intel Q57/H55 Clarkdale (Onboard on D2912-A1x) - 0046 Intel Graphics Media Accelerator HD Intel Graphics Media Accelerator HD + 0044 0044 Intel(R) Processor DRAM Controller + 0046 Intel(R) HD Graphics (Core i3) Intel(R) HD Graphics 0054 not known Audio 0082 6205 Centrino Advanced-N 6205 - 0083 Mobile Intel® 5 Series Chipset Intel® PROSet/Wireless Software and Drivers for Windows 7 32-Bit + 0083 Mobile Intel® 5 Series Chipset Intel Centrino Wireless-N 1000 0084 Intel PROSet WiFi 1000 Intel Wireless Link WiFi 1000, download -> http://downloadmirror.intel.com/20791/eng/Wireless_14.3.0 0085 0x0280 Intel Centrino(R) Advanced-N 6205 0087 1306 00E1 008A ??? Intel Centrino Wireless-N1030 008B Intel Wireless-N 1030 Intel(R) Centrino(R) Wireless-N 1030 0091 622ANHW Intel® Centrino® Advanced-N 6230 - 0102 0001 Intel HD Graphics 2000 + 0100 0100 2nd Generation Intel(R) Core(TM) Processor Family DRAM Controller + 0102 0001 Intel HD Graphics 3000 0104 2nd Gen Intel(R) Core(TM) Processor Family DRAM Controller (Host Bus Controller) - 0106 HD Graphics 3000/2000 2nd Generation Intel® Core™ Processors with Intel® HD Graphics 3000/2000 + 0106 HD Graphics 3000/2000 asus x501a 010A 010A Lenovo TS130 Intel Video Adapter HD - 0111 82810e Intel Graphics Conroller + 0111 82915 Intel Graphics Conroller 0116 intel core i3 Intel HD Graphics 3000 0123 0300 hardwareids + 0152 Intel HD Graphics 2500 3rd Generation Intel Core Processors with Intel HD Graphics 2500 + 0153 Intel® Dynamic Platform and Thermal Framework Driv Use the Link, choose Win7 64Bit -> Others -> Intel DPTF Driver -> Global. Then download, install and + 0154 0x01548086 3rd Gen Core processor DRAM Controller (rev 09) 0162 Core I5, Core I7, Ivy Bridge Graphics embedded - 0166 I3 3rd Generation Intel® HD Graphics 4000 + 0166 I3 Intel(R) HD Graphics 4000 0189 Intel Centrino Wireless-N 1030 Bluetooth Adapter Intel Centrino Wireless Bluetooth 3.0 + High Speed Adapter 027AE 82945GM Mobile Intel(R) 945 Express Chipset Family - 027D8 293esd Mobile PCI-to-PCIsdsdsdI2) + 027D8 293esd High Definition Audio Controller 0283E AA01211025 Intel(R) ICH8 Family SMBus Controller 0308 3220 PCI Audio Device + modem 0309 80303 I/O Processor PCI-to-PCI Bridge Unit @@ -8049,15 +8291,18 @@ exit 0 0341 41210 Serial to Parallel PCI Bridge B 0370 80333 Segment-A PCI Express-to-PCI Express Bridge 0371 80333 A-Bus IOAPIC - 0372 80333 Segment-B PCI Express-to-PCI Express Bridge + 0372 0893 network controller 0373 80333 B-Bus IOAPIC 0374 80333 Address Translation Unit 0401 266E P040100 - 0402 ACPI x86-based PC intel core i5 - 0482 82375MB PCI-EISA Bridge (PCEB)hp dx 7300 microwave tower + 0402 ACPI x86-based PC HD Graphics 4200 + 0412 Intel HD Graphics 4600 ven_8086&dev_0412 + 0416 SUBSYS_197A103C Intel(R) HD Graphics 4600 + 0482 82375MB PCI\VEN_8086&DEV_3B64&SUBSYS_20391B0A&REV_06 0483 82424TX/ZX CPU (i486) Bridge (Saturn) 0484 82378ZB/IB SIO ISA Bridge - 0486 82425EX 1261028 + 0486 PCI\VEN_8086&DEV_1C22&SUBSYS_2AC2103C&REV_04 HP Pro 3400 XPx32/7x32 drivers + 04931028 0x1502 Intel 82579 Gigabit Network Card 04A3 82434bX/zX Mercury/Neptune Cache/DRAM Controller 0500 E8870 Processor Bus Controller 0501 E8870 Memory Controller @@ -8086,14 +8331,33 @@ exit 0 0888 Intel Centrino Wireless-N 2230 088E 40608086 Intel Centrino Advanced N 6235 0890 Intel Network Controller - 0894 86881 MRMgRH + 0894 86881 Centrino Wireless-N 105 0896 Wireless-N 130 Intel Centrino Wireless-N 130 08AE 802.11n Intel Centrino Wireless-N 100 + 08B1 PCI\VEN_8086&DEV_08B1 Intel(R) Dual Band Wireless-AC 7260 + 08B3 ? Intel Dual Band Wireless-AC 3160 0960 80960RP i960 RP Microprocessor/Bridge 0962 80960RM/RN i960RM/RN Microprocessor/Bridge 0964 80960RP i960 RP Microprocessor Bridge + 0A03 0A03 Intel(R) Dynamic Platform and Thermal Framework Processor Participant + 0A04 0A04 PCI standard host CPU bridge + 0A0C 0A0C High Definition Audio Controller + 0A16 3000 Intel HD Graphics Controller + 0A1E 0A1 Intel(R) HD Graphics 0BE1 0000000 Intel Graphics Media Accelerator 3600 Series + 0C00 0C00 Intel(R) 4th Gen Core processor DRAM Controller 0C05 V9201015 Intel(R) 6 Series/C200 Series Chipset Family SMBus Controller + 0F00 0F00 Intel(R) Pentium(R)/Celeron(R) processor N-/J- series SoC Transaction Router + 0F04 0F04 High Definition Audio Controller + 0F12 0F12 Intel(R) Pentium(R)/Celeron(R) processor N-/J- series Platform Control Unit - SMBus Port + 0F18 0F18 Intel(R) Trusted Execution Engine Interface + 0F1C 0F1C Intel(R) Pentium(R)/Celeron(R) processor N-/J- series Platform Conrol Unit LPC: Bridge to Intel Lega + 0F23 0F23 Intel(R) Pentium(R)/Celeron(R) processor N-/J- series AHCI + 0f31 5200 Iris pro 5200 + 0F35 0F35 Intel(R) USB 3.0 eXtensible Host Controller + 0F48 0F48 Intel(R) Pentium(R)/Celeron(R) processor N-/J- series PCI Express Root Port + 0F4A 0F4A Intel(R) Pentium(R)/Celeron(R) processor N-/J- series PCI Express Root Port + 100 0100 2nd Generation Intel(R) Core(TM) Processor Family DRAM Controller 1000 82542 Gigabit Ethernet Controller 1001 2572 10/100/1000 Ethernet Controller (Fiber) 1002 Pro 100 LAN+Modem 56 CardBus II @@ -8103,7 +8367,7 @@ exit 0 100C 82543EI/GC Gigabit Ethernet Controller (Copper) 100D 82544GC Gigabit Ethernet Controller (LOM) 100E 02000 Intel Pro 1000/MT - 100F 82545EM Gigabit Ethernet Controller (copper) + 100F 82545EM Intel(R) PRO/1000 MT Network Connection 1010 82546EB Dual Port Gigabit Ethernet Controller (Copper) 1011 82545EM Gigabit Ethernet Controller (Fiber) 1012 82546EB Dual Port Gigabit Ethernet Controller (Fiber) @@ -8147,7 +8411,7 @@ exit 0 1050 82562EZ PRO/100 VE Network Connection 1051 82801EB/ER PRO/100 VE Network Connection 1052 82801EB/ER PRO/100 VM Network Connection - 1053 82801EB/ER PRO/100 VM Network Connection + 1053 82801EB/ER PRO/100 VM ork NetConnectionw 1054 82801EB/ER PRO/100 VE Network Connection (mobile) 1055 82801EB/ER PRO/100 VM Network Connection (mobile) 1059 82551QM Fast Ethernet PCI/CardBus Controller @@ -8182,6 +8446,7 @@ exit 0 10c4 82562GT Intel 82562GT 10/100 Network Controller 10c4 82562EZ PLC Intel 82562GT 10/100 Network Controller 10c9 82576? 82576 Gigabit ET Dual Port Server Adapter + 10cd 82567 Intel(R) 82567LF-2 Gigabit Network Connection 10CE 82567V-2 Intel 82567V-2 Gigabit Network Connection 10d3 82574L Intel® 82574L Gigabit Ethernet Controller 10d6 82575 82566 DM-2-gigabyte @@ -8202,9 +8467,10 @@ exit 0 1112 82815 Internal Graphics Device 1120 82815 Host-Hub Interface Bridge / DRAM Ctrlr 1121 82815 AGP Bridge + 112D 2200 pci simple controller 1130 82815/82815EM/EP Host-Hub Interface Bridge / DRAM Ctrlr 1131 82815/82815EM/EP AGP Bridge - 1132 65416 Internal Graphics Device [810/815 chipset AGP] + 1132 65416http://www.pcidatabase.com/update_device.php? Internal Graphics Device [810/815 chipset AGP] 1161 82806AA I/O APIC Device 1162 BECC XScale 80200 Companion Chip (FPGA) 1179 82546EB Dual Port Gigabit Ethernet Controller @@ -8218,7 +8484,7 @@ exit 0 1226 82596 EtherExpress PRO/10 1227 82801db ich4 LAN Controller with 82562EM 1228 EE PRO/100 Smart Intelligent 10/100 Fast Ethernet Adapter - 1229 1e22 Intel(R) PRO/100 M 00000Desktop Adapter http://downloadmirror.intel.com/8659/eng/LAN_ALLOS_11.2_PV + 1229 1e22 Intel(R) PRO/100 http://ftp.dell.com/network/R56484.EXE 122D 82437FX System Controller (TSC) 122E 82371AB/EB PCI PCI to ISA Bridge (Triton) 1230 FW82371AB IDE Interface (Triton) @@ -8232,9 +8498,10 @@ exit 0 123D 683053 Programmable Interrupt Device 123E 82466GX Integrated Hot-Plug Controller (IHPC) 123F 82466GX Integrated Hot-Plug Controller (IHPC) + 124 PCI\VEN_8086&DEV_9C22 24c6 1240 82752 AGP Graphics Accelerator 124B 293esd Mobile PCI-to-PCIsdsdsdI2) - 124B 293esd Mobile PCI-to-PCIsdsdsdI2)v5 + 124B PCI\VEN_8086&DEV_2E17&CC_070002 24c6 124C 9776 Mobile PCI-to-PCI Bridge (MPCI2) 1250 82430HX System Controller (TXC) 12D8 92XX SIGMATEL STAC 92XX C-Major HD Audio @@ -8259,6 +8526,12 @@ exit 0 1525 82567V-4 Intel 82567V-4 Gigabit Network Connection 1526 82576 Intel Gigabit ET2 Quad Port Server Adapter 1533 210 Intel I210 Gigabit Network Connection + 153A USB\VID_0424&PID_2504&REV_0001 Intel I217-LM Ethernet Connection + 153B I217-V Intel Gigabit Ethernet Controller I217-V + 1559 0x8CBA Intel Ethernet I218-V + 155a I218LM Gigabit Ethernet + 15A1 0x8CBA Intel® Ethernet Connection I218-V + 15A2 I218LM Gigabit Ethernet 167D 2200bg PCI Simple Communications Controller 1960 80960RP i960RP Microprocessor 1962 ??? Promise SuperTrak SX6000 IDE RAID Controller @@ -8272,35 +8545,57 @@ exit 0 1A30 82845G[GL/GV/GE/PE] Host-Hub Interface Bridge 1A31 82845[MP/MZ] AGP Bridge 1A38 5000P 5000 Series Chipset DMA Engine - 1c02 8086&dev_1c02 SATA ahci controller 3Gbps 6 ports + 1A3E Z77 C216 Chipset - Platform controller hub + 1c02 1C02 Intel(R) 6/C200 Series Chipset Family 6 Port SATA AHCI Controller 1c02_ 8086&dev_1c02 Intel(R) Desktop/Workstation/Server Express Chipset SATA AHCI Controller 1C03 Intel(R) Mobile Express Chipset SATA AHCI Controll Intel(R) CPT Chipset Family 6 Port SATA AHCI Controller - 1C22 win7 64-bit (tc40140300b.exe) Intel(R) 6 Series/C200 Series Chipset Family SMBus Controller - 1C26 HM65 USB Enhanced Host Controller + 1C10 1C10 Intel(R) 6/C200 Series Chipset Family PCI Express Root Port + 1C18 1C18 Intel(R) 6/C200 Series Chipset Family PCI Express Root Port + 1C1A 1C3Afsfsdf 1C3Asfsfsdf + 1C1C 1C1C Intel(R) 6/C200 Series Chipset Family PCI Express Root Port + 1C1E 1C1E Intel(R) 6/C200 Series Chipset Family PCI Express Root Port + 1C20 1C20 High Definition Audio Controller + 1C22 win7 64-bit Intel(R) 6 Series/C200 Series Chipset Family SMBus Controller + 1C26 HM65 Intel(R) 6/C200 Series Chipset Family USB Enhanced Host Controller + 1C2D 1C2D Intel(R) 6/C200 Series Chipset Family USB Enhanced Host Controller 1c34a 0780 pci simple communications controller 1c3a 161C103C Intel Management Engine Interface + 1c3a. 161C103C Intel Management Engine Interface 1C3b 111 Series Chipset Family HECI Controller #2 1C3D Intel(R) 6 Series Series Chipset Family Intel(R) Active Management Technology - SOL 1C49 FCD01179 04 + 1C4C Q65 Intel(R) Q65 Express Chipset Family LPC Interface Controller 1D3A X79 series chipset HECI Controller X79/C600 series chipset Management Engine Interface + 1D3D CC0700 Intel Active Management Technology AMT 1e00 Intel H77 Express Chipset 2 ports IDE Controller 1e02 SUBSYS_102E17AA&REV_04 Intel 7 Series/C216 Chipset Family SATA AHCI Controller + 1E03 PCI\CC_010601 Intel(R) 7 Series Chipset Family SATA AHCI Controller 1e08 Intel H77 Express Chipset 2 ports IDE Controller - 1E12 c4 rev + 1E10 C216 Intel(R) 7 Series/C216 Chipset Family PCI Express Root Port + 1E12 1E12 Intel(R) 7 Series/C216 Chipset Family PCI Express Root Port + 1E16 C216 Intel(R) 7 Series/C216 Chipset Family PCI Express Root Port + 1E20 1E20 High Definition Audio Controller 1E22 Intel(R) 7 SeriesC216 Chipset Family SMBus Host Co SM-Bus Controller of the Intel Z77 Chipset - 1e31 Intel USB 3.0 eXtensible Host Controller Intel USB 3.0 - 1E3A PCI\VEN_8086&DEV_1E3A&SUBSYS_500217&REV_04 Intel Management Engine Interface (MEI) + 1E26 C216 Intel(R) 7 Series/C216 Chipset Family USB Enhanced Host Controller + 1E2D C216 Intel(R) 7 Series/C216 Chipset Family USB Enhanced Host Controller + 1e31 Intel USB 3.0 eXtensible Host Controller 1E31 Intel USB 3.0 + 1E3A PCI\VEN_8086&DEV_1E3A&SUBSYS Intel Management Engine Interface (MEI) 1E3A_ C216 8555555555555999999999999999999999999999999999999999999999999999999900000000000000000001222222222222 1E3A__ Z77 C216 Chipset - Platform controller hub - 1E3D 833810F7 Intel(R) AMT LMS_SOL for AMT 8.xx - 1E59 140889 140889 + 1E3D 602317 Intel(R) AMT LMS_SOL for AMT 8.xx + 1E59 140889 Intel(R) HM76 Express Chipset LPC Controller + 1f41 Avoton SoC Intel Corporation Ethernet Connection I354 2000 CA 95054 505943621 2014 0x18C9 Framegrabber 2048 Atheros L2 Fast Ethernet 10/100 Base-T Controller 2124 27DA PRO/100 VE Network Connection - 2125 82801AA AC97 Audio Controller. website to download - http://www.intel.com/design/chipsets/manuals/29802801.p + 2125 82801G AC97 Audio Controller. website to download - http://www.intel.com/design/chipsets/manuals/29802801.p 2222 82801 Intel Management Interface + 2250 5110P Intel(R) Xeon Phi(TM) Coprocessor 2255 810D1043 02\3 + 225C SE10 Intel(R) Xeon Phi(TM) Coprocessor + 225D 3120 Intel(R) Xeon Phi(TM) Coprocessor + 225E 31S1P Intel(R) Xeon Phi(TM) Coprocessor 2406 82801 / ? AC97 Modem Controller / PCI Modem 2410 82801AA LPC Interface 2411 82801AA IDE Controller (UltraATA/66) @@ -8329,7 +8624,7 @@ exit 0 244A 82801BAM IDE Controller 244B 82801BA IDE Controller 244C 82801BAM LPC Interface Bridge - 244E 82801DB Hub Interface to PCI Bridge + 244E 82801DB Intel(R) 82801 PCI Bridge 2450 82801E LPC Interface Bridge 2452 82801E USB Controller 2453 82801E SMBus Controller @@ -8370,7 +8665,7 @@ exit 0 24D2 82801EB/ER USB UHCI Controller 1 24D3 82801EB/ER SMBus Controller 24D4 82801EB/ER USB UHCI Controller #2 - 24D5 ALC850 Realtek AC'97 Звуковой Сист& + 24D5 AD1888/AD1980 Analog Devices AD1888/AD1980 @ Intel 82801EB ICH5 - AC'97 Audio Controller [A-2/A-3] 24D6 82801EB/ER Motorola SM56 Data Fax Modem 24D7 82801EB/ER USB UHCI Controller #3 24DB 82801EB/ER EIDE Controller @@ -8492,46 +8787,50 @@ exit 0 269B 631xESB/6321ESB/3100 SMBus Controller 269E 631x/632x ESB2 PATA100 IDE Controller 27 82801G ICH7 Family - 2770 82945G/GZ/P/PL Host Bridge/DRAM Controller + 2770 82945G/GZ/P/PL Intel(R) 945G/GZ/GC/P/PL Processor to I/O Controller 2771 82945G/GZ/P/PL Host to PCI Express Bridge - 2772 82945G/GZ Chipset Intel® 82945G Express + 2772 82945G/GZ PCI\VEN_8086&DEV_2772&SUBSYS_2A57103C&REV_02\3&11583659&0&10 2776 82945G INTEL(R) 82945G EXPRESS FAMILY 277C 82975X Intel 975X Express Chipset 2780 82915G Graphics device 2782 82915G Graphics device: 82915G/GV/910GL Express Chipset Family 2792 038000 Mobile Intel(R) 915GM/GMS/, 910GML Express Chipset Family 2794 945 Mobile chipset - 27A0 874079 i945GM Express Chipset + 27A0 874079 Mobile Intel(R) 945GM/GU/PM/GMS/940GML/943GML and Intel(R) 945GT Express Processor to DRAM Controlle 27A1 Intel 82945PM Memory Controller Intel Corporation Mobile 945PM Express PCI Express Root Port 27A2 HPQ0006 Mobile Intel(R) 945 Express Chipset Family 27A6 945GM Intel 945GM/950 - 27B8 945GL PCI\VEN_8086&_27B8&SUBSYS_8179DEV1043&REV_01\3&11583659&0&F8 + 27B8 945GL Intel(R) ICH7 Family LPC Interface Controller + 27B9 ICH7 Intel(R) ICH7M/U LPC Interface Controller 27BC NM10 NM10 Family LPC Interface Controller - 27c0 82801GB/GR/GH 82801 GB Serial ATA Storage Controllers + 27c0 82801GB/GR/GH Intel(R) N10/ICH7 Family Serial ATA Storage Controller 27C1 82801GB/GR/GH AHCI Controller 27c3 82801GR/GH Raid Controller 27c4 82801GBM/GHM SATA IDE Controller - 27C5 82801GBM/GHM AHCI Controller + 27C5 82801GBM/GHM Intel(R) ICH7/M/MDH SATA AHCI Controller 27C6 82801GHM Raid Controller - 27c8 946 USB UHCI Controller - 27c9 USB UHCI Controller USB UHCI Controller - 27CA -INTEL USB UHCI Controller - 27CB USB UHCI Controller - 27CC 82801G Intel(R) 82801G (ICH7 Family) USB2 Enhanced Host Controller + 27c8 946 Intel(R) N10/ICH7 Family USB Universal Host Controller + 27c9 USB UHCI Controller Intel(R) N10/ICH7 Family USB Universal Host Controller + 27CA ICH7 Intel(R) N10/ICH7 Family USB Universal Host Controller + 27CB ICH7 Intel(R) N10/ICH7 Family USB Universal Host Controller + 27CC 82801G Intel(R) N10/ICH7 Family USB2 Enhanced Host Controller 27D0 82801G Intel(R) 82801G (ICH7 Family) PCI Express Root Port 27D2 82801G Intel(R) 82801G (ICH7 Family) PCI Express Root Port - 27d8 FF311179 Realtek High Definition Audio Driver FF311179 thequetta.com + 27D4 ICH7 Intel(R) N10/ICH7 Family PCI Express Root Port + 27d8 27D8 UAA Bus Driver for HD Audio 27d8xzx PCI\VEN_8086&DEV_2485&SUBSYS_AD021458&REV_02 Microsoft UAA Bus HD Audio 27D9 A62516F3 IDT High Definition Audio Driver - 27DA 82801G Intel[R] 82801G (ICH7 Family) C- 27DA - 27DC 336C1462 Intel® PRO/100 VE Desktop Adapter - 27DC0x27DC 336C1462 Intel® PRO/100 VE Desktop Adapter + 27DA 82801G Intel(R) N10/ICH7 Family SMBus Controller + 27DC 336C1462 Intel® PRO/100 VE Desktop Adapter + 27DC0x27DC 336C1462 Intel® PRO/100 VE Desktop Adapter 27DE RTL8100C AUDIO (ALC850) << Realtek - 27df 82801GB/GBM PATA100 + 27df 82801GB/GBM Intel(R) ICH7 Family Ultra ATA Storage Controller 27RR ALC850 no 2802 8086 INTEL(R) HIGH DEFINITION AUDIO HDMI 2803 0111 Intel(R) High Definition Audio HDMI Service 2804 80860101 IntcDAudModel + 2807 Intel HD Audio Intel HDMI Audio Chip + 2812 2812 Intel(R) ICH8DH LPC Interface Controller 2815 902D104D Intel(R) ICH8M LPC Interface Controller - 2815 Driver 2820 82801HB/HR/HH/HO SATA IDE Controller:4 port 2821 82821HR/HH/HO AHCI Controller @@ -8539,17 +8838,30 @@ exit 0 2824 82801HB ICH8 AHCI Controller 2825 82801IIH Intel Q35 2828 82801HBM/HEM SATA IDE Controller - 2829 82801HBM AHCI Controller + 2829 82801HBM Intel(R) ICH8M SATA AHCI Controller 282A ICH8M/9M/ICH10M/i5M Raid Controller - 283A 81EC1043 (?) ICH8 Enhanced USB2 Enhanced Host Controller - 283E PCI\VEN_8086&DEV_283E&SUBSYS_20A917AA&REV_03\3&B1B SM Bus Controller + 2830 2830 Intel(R) ICH8 Family USB Universal Host Controller + 2831 2831 Intel(R) ICH8 Family USB Universal Host Controller + 2832 2832 Intel(R) ICH8 Family USB Universal Host Controller + 2834 2834 Intel(R) ICH8 Family USB Universal Host Controller + 2835 2835 Intel(R) ICH8 Family USB Universal Host Controller + 2836 2836 Intel(R) ICH8 Family USB2 Enhanced Host Controller + 283A 81EC1043 (?) ICH8 Family USB2 Enhanced Host Controller + 283E PCI\VEN_8086&DEV_283E&SUBSYS_20A917AA&REV_03\3&B1B Intel(R) ICH8 Family SMBus Controller + 283F 283F Intel(R) ICH8 Family PCI Express Root Port 284 888 Microsoft UAA bus for HD audio + 2841 ICH8 Intel(R) ICH8 Family PCI Express Root Port + 2843 ICH8 Intel(R) ICH8 Family PCI Express Root Port + 2845 ICH8 Intel(R) ICH8 Family PCI Express Root Port + 2847 2847 Intel(R) ICH8 Family PCI Express Root Port 284B 888 Microsoft UAA bus for HD audio - 2850 82801HBM/HEM PATA Controller + 2850 82801HBM/HEM Intel(R) ICH8M Ultra ATA Storage Controller 2880 0000000 Intel Display Audio 2888 Q945 Q945 2914 ICH9D0 LPC bridge of ICH9 2916 3 PCI Simple Communications-Controller + 2918 ATK0110 driver for WindowsXP/Vista/Win7 32&64-bit http://dlcdnet.asus.com/pub/ASUS/misc/utils/MB_WIN7_ATK.ZIP + 2919 ICH9M Intel(R) ICH9M/M-E Family 4 Port SATA AHCI Controller 2920 82801(IB)/IR/IH/IO SATA IDE Controller:4 port 2921 82801IR/IH/IO SATA IDE Controller:2 port1 2922 82801IR/IH/IO AHCI Controller @@ -8562,62 +8874,81 @@ exit 0 292E ?(ICH9M Family) SATA IDE Controller:1port2 2930 8086 2930 2930 Intel ICH9 Family SMBus Controller Intel ICH9 Family SMBus Controller + 2932 ICH9 Intel(R) ICH9 Family Thermal Subsystem + 2934 ICH9 Intel(R) ICH9 Family USB Universal Host Controller + 2935 ICH9 Intel(R) ICH9 Family USB Universal Host Controller 2936 0x02141028 Intel(R) ICH9 Family USB Univeral Host Controller + 2937 ICH9 Intel(R) ICH9 Family USB Universal Host Controller + 2938 ICH9 Intel(R) ICH9 Family USB Universal Host Controller + 2939 ICH9 Intel(R) ICH9 Family USB Universal Host Controller + 293A ICH9 Intel(R) ICH9 Family USB2 Enhanced Host Controller + 293C ICH9 Intel(R) ICH9 Family USB2 Enhanced Host Controller 293E 486486 82801IB/IR/IH (ICH9 Family) HD Audio Controller 293E 486486 82801IB/IR/IH (ICH9 Family) HD Audio Controller + 2940 ICH9 Intel(R) ICH9 Family PCI Express Root Port + 2942 ICH9 Intel(R) ICH9 Family PCI Express Root Port + 2944 ICH9 Intel(R) ICH9 Family PCI Express Root Port + 2948 ICH9 Intel(R) ICH9 Family PCI Express Root Port 294C 82566DC-2 Intel(R) 82566DC-2 Gigabit Network Connection 2972 82946GZ Onboard Video Device for 82946GZ chips 2986 265452 Intel 2987 Q965/Q963 Intel PCI Serial Port 2992 Q965/Q963 Intel(R) Express Chipset video - 2993 G965 Intel(R) Express Chipset (Dell Version) - 2994 2802103C intel management engine interface + 2993 G965 Intel(R) Express Chipset Dell Version + 2994 2802103C Intel Management Engine Interface (HECI) 2996 Q963/Q965 IDE Controller - 2997 Q965/Q963 Intel® Active Management Technology (AMT) - SOL + 2997 Q965/Q963 PCI Serial Port 29a0 ?(82P965) Intel P965/G965 Processor to I/O Controller 29a1 ?(82Q965, 82G965, 82P965) Intel P965/G965 PCI Express Root Port 29A2 Intel 82G965 Graphics and Memory Controller Hub (G Intel 82G965 Graphics and Memory Controller Hub (GMCH) - 29A4 86881 MRMgRH Date: Mon, 22 Feb 2021 11:36:33 +0000 Subject: [PATCH 209/402] lib: update OUI database from IEEE --- lib/oui | 15915 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 13200 insertions(+), 2715 deletions(-) diff --git a/lib/oui b/lib/oui index f228f3cadf..4753e4434a 100755 --- a/lib/oui +++ b/lib/oui @@ -5,9 +5,11 @@ rfork n cd /n/boot/lib { sed '/^$/q' oui - hget http://standards.ieee.org/regauth/oui/oui.txt | + hget http://standards-oui.ieee.org/oui/oui.txt | tr A-Z a-z | - sed -n 's/([^ ]+)[ ]+.base 16.[ ]+(.*)[ ]*/\1 \2/p' + sed -n 's/([^ ]+)[ ]+.base 16.[ ]+(.*)[ ]*/ \1 \2/p' | + sed 's/ //' | + sort } >_oui && mv _oui oui chmod +x oui exit @@ -24,7 +26,7 @@ exit 000009 xerox corporation 00000a omron tateisi electronics co. 00000b matrix corporation - 00000c cisco systems, inc. + 00000c cisco systems, inc 00000d fibronics ltd. 00000e fujitsu limited 00000f next, inc. @@ -39,11 +41,11 @@ exit 000018 webster computer corporation 000019 applied dynamics international 00001a advanced micro devices - 00001b novell inc. + 00001b novell, inc. 00001c bell technologies 00001d cabletron systems, inc. 00001e telsist industria electronica - 00001f telco systems, inc. + 00001f telco systems, inc. 000020 dataindustrier diab ab 000021 sureman comp. & commun. corp. 000022 visual technology inc. @@ -61,7 +63,7 @@ exit 00002e societe evira 00002f timeplex inc. 000030 vg laboratory systems ltd - 000031 qpsx communications pty ltd + 000031 qpsx communications, ltd. 000032 marconi plc 000033 egan machinery company 000034 network resources corporation @@ -96,7 +98,7 @@ exit 000051 hob electronic gmbh & co. kg 000052 intrusion.com, inc. 000053 compucorp - 000054 schnieder electric + 000054 schneider electric 000055 commissariat a l`energie atom. 000056 dr. b. struck 000057 scitex corporation ltd. @@ -107,22 +109,22 @@ exit 00005c telematics international inc. 00005d cs telecom 00005e icann, iana department - 00005f sumitomo electric ind., ltd. + 00005f sumitomo electric industries, ltd 000060 kontron elektronik gmbh 000061 gateway communications 000062 bull hn information systems 000063 barco control rooms gmbh - 000064 yokogawa digital computer corp + 000064 yokogawa digital computer corporation 000065 network general corporation 000066 talaris systems, inc. 000067 soft * rite, inc. 000068 rosemount controls 000069 concord communications inc 00006a computer consoles inc. - 00006b silicon graphics inc./mips - 00006c + 00006b silicon graphics + 00006c private 00006d cray communications, ltd. - 00006e artisoft, inc. + 00006e artisoft inc. 00006f madge ltd. 000070 hcl limited 000071 adra systems inc. @@ -148,7 +150,7 @@ exit 000085 canon inc. 000086 megahertz corporation 000087 hitachi, ltd. - 000088 brocade communications systems, inc. + 000088 brocade communications systems llc 000089 cayman systems inc. 00008a datahouse information systems 00008b infotron @@ -163,7 +165,7 @@ exit 000094 asante technologies 000095 sony tektronix corp. 000096 marconi electronics ltd. - 000097 emc corporation + 000097 dell emc 000098 crosscomm corporation 000099 mtx, inc. 00009a rc computer a/s @@ -177,22 +179,22 @@ exit 0000a2 bay networks 0000a3 network application technology 0000a4 acorn computers limited - 0000a5 tattile srl + 0000a5 tattile srl 0000a6 network general corporation 0000a7 network computing devices inc. - 0000a8 stratus computer inc. + 0000a8 stratus technologies 0000a9 network systems corp. 0000aa xerox corporation 0000ab logic modeling corporation 0000ac conware computer consulting 0000ad bruker instruments inc. 0000ae dassault electronique - 0000af nuclear data instrumentation + 0000af canberra industries, inc. 0000b0 rnd-rad network devices - 0000b1 alpha microsystems inc. + 0000b1 alpha micro 0000b2 televideo systems, inc. 0000b3 cimlinc incorporated - 0000b4 edimax computer company + 0000b4 edimax technology co. ltd. 0000b5 datability software sys. inc. 0000b6 micro-matic research 0000b7 dove computer corporation @@ -201,20 +203,20 @@ exit 0000ba siig, inc. 0000bb tri-data 0000bc rockwell automation - 0000bd mitsubishi cable company + 0000bd mitsubishi cable industries, ltd. / ryosei systems 0000be the nti group 0000bf symmetric computer systems 0000c0 western digital corporation 0000c1 madge ltd. 0000c2 information presentation tech. - 0000c3 harris corp computer sys div + 0000c3 harris corporation 0000c4 waters div. of millipore - 0000c5 farallon computing/netopia + 0000c5 arris group, inc. 0000c6 eon systems 0000c7 arix corporation 0000c8 altos computer systems 0000c9 emulex corporation - 0000ca arris international + 0000ca arris group, inc. 0000cb compu-shack electronic gmbh 0000cc densan co., ltd. 0000cd allied telesis labs ltd @@ -252,11 +254,11 @@ exit 0000ed april 0000ee network designers, ltd. 0000ef kti - 0000f0 samsung electronics co., ltd. + 0000f0 samsung electronics co.,ltd 0000f1 magna computer corporation 0000f2 spider communications 0000f3 gandalf data limited - 0000f4 allied telesis + 0000f4 allied telesis, inc. 0000f5 diamond sales limited 0000f6 applied microsystems corp. 0000f7 youth keep enterprise co ltd @@ -266,12 +268,12 @@ exit 0000fb rechner zur kommunikation 0000fc meiko 0000fd high level hardware - 0000fe annapolis micro systems + 0000fe annapolis micro systems, inc. 0000ff camtec electronics ltd. 000100 equip'trans - 000101 - 000102 3com corporation - 000103 3com corporation + 000101 private + 000102 3com + 000103 3com 000104 dvico co., ltd. 000105 beckhoff automation gmbh 000106 tews datentechnik gmbh @@ -281,9 +283,9 @@ exit 00010a cis technology inc. 00010b space cyberlink, inc. 00010c system talks inc. - 00010d coreco, inc. + 00010d teledyne dalsa inc. 00010e bri-link technologies co., ltd - 00010f brocade communications systems, inc. + 00010f brocade communications systems llc 000110 gotham networks 000111 idigm inc. 000112 shark multimedia inc. @@ -303,7 +305,7 @@ exit 000120 oscilloquartz s.a. 000121 watchguard technologies, inc. 000122 trend communications, ltd. - 000123 digital electronics corp. + 000123 schneider electric japan holdings ltd. 000124 acer incorporated 000125 yaesu musen co., ltd. 000126 pac labs @@ -316,13 +318,13 @@ exit 00012d komodo technology 00012e pc partner ltd. 00012f twinhead international corp - 000130 extreme networks + 000130 extreme networks, inc. 000131 bosch security systems, inc. 000132 dranetz - bmi 000133 kyowa electronic instruments c 000134 selectron systems ag 000135 kdc corp. - 000136 cybertan technology, inc. + 000136 cybertan technology inc. 000137 it farm corporation 000138 xavi technologies corp. 000139 point multimedia systems @@ -334,14 +336,14 @@ exit 00013f neighbor world co., ltd. 000140 sendtek corporation 000141 cable print - 000142 cisco systems, inc. - 000143 cisco systems, inc. - 000144 emc corporation + 000142 cisco systems, inc + 000143 cisco systems, inc + 000144 dell emc 000145 winsystems, inc. 000146 tesco controls, inc. 000147 zhone technologies 000148 x-traweb inc. - 000149 t.d.t. transfer data test gmbh + 000149 tdt ag 00014a sony corporation 00014b ennovate networks, inc. 00014c berkeley process control @@ -361,14 +363,14 @@ exit 00015a digital video broadcasting 00015b italtel s.p.a/rf-up-i 00015c cadant inc. - 00015d oracle corporation + 00015d oracle corporation 00015e best technology co., ltd. 00015f digital design gmbh 000160 elmex co., ltd. 000161 meta machine technology 000162 cygnet technologies, inc. - 000163 cisco systems, inc. - 000164 cisco systems, inc. + 000163 cisco systems, inc + 000164 cisco systems, inc 000165 airswitch corporation 000166 tc group a/s 000167 hioki e.e. corporation @@ -418,8 +420,8 @@ exit 000193 hanbyul telecom co., ltd. 000194 capital equipment corporation 000195 sena technologies, inc. - 000196 cisco systems, inc. - 000197 cisco systems, inc. + 000196 cisco systems, inc + 000197 cisco systems, inc 000198 darim vision 000199 heisei electronics 00019a leunig gmbh @@ -443,7 +445,7 @@ exit 0001ac sitara networks, inc. 0001ad coach master international d.b.a. cmi worldwide, inc. 0001ae trex enterprises - 0001af emerson network power + 0001af artesyn embedded technologies 0001b0 fulltek technology co., ltd. 0001b1 general bandwidth 0001b2 digital processing systems, inc. @@ -453,7 +455,7 @@ exit 0001b6 saejin t&m co., ltd. 0001b7 centos, inc. 0001b8 netsensity, inc. - 0001b9 skf condition monitoring + 0001b9 skf (u.k.) limited 0001ba ic-net, inc. 0001bb frequentis 0001bc brains corporation @@ -467,10 +469,10 @@ exit 0001c4 neowave, inc. 0001c5 simpler networks 0001c6 quarry technologies - 0001c7 cisco systems, inc. - 0001c8 thomas conrad corp. + 0001c7 cisco systems, inc 0001c8 conrad corp. - 0001c9 cisco systems, inc. + 0001c8 thomas conrad corp. + 0001c9 cisco systems, inc 0001ca geocast network systems, inc. 0001cb evr 0001cc japan total design communication co., ltd. @@ -479,7 +481,7 @@ exit 0001cf alpha data parallel systems, ltd. 0001d0 vitalpoint, inc. 0001d1 conet communications, inc. - 0001d2 inxtron, inc. + 0001d2 inxtron, inc. 0001d3 paxcomm, inc. 0001d4 leisure time, inc. 0001d5 haedong info & comm co., ltd @@ -499,8 +501,8 @@ exit 0001e3 siemens ag 0001e4 sitera, inc. 0001e5 supernet, inc. - 0001e6 hewlett-packard company - 0001e7 hewlett-packard company + 0001e6 hewlett packard + 0001e7 hewlett packard 0001e8 force10 networks, inc. 0001e9 litton marine systems b.v. 0001ea cirilium corp. @@ -513,7 +515,7 @@ exit 0001f1 innovative concepts, inc. 0001f2 mark of the unicorn, inc. 0001f3 qps, inc. - 0001f4 enterasys networks + 0001f4 enterasys 0001f5 erim s.a. 0001f6 association of musical electronics industry 0001f7 image display systems, inc. @@ -539,7 +541,7 @@ exit 00020b native networks, inc. 00020c metro-optix 00020d micronpc.com - 00020e eci telecom, ltd + 00020e eci telecom ltd. 00020f aatr 000210 fenecom 000211 nature worldwide technology corp. @@ -547,8 +549,8 @@ exit 000213 s.d.e.l. 000214 dtvro 000215 cotas computer technology a/b - 000216 cisco systems, inc. - 000217 cisco systems, inc. + 000216 cisco systems, inc + 000217 cisco systems, inc 000218 advanced scientific corp 000219 paralon technologies 00021a zuma networks @@ -586,9 +588,9 @@ exit 00023a zsk stickmaschinen gmbh 00023b ericsson 00023c creative technology, ltd. - 00023d cisco systems, inc. + 00023d cisco systems, inc 00023e selta telematica s.p.a - 00023f compal electronics, inc. + 00023f compal electronics inc. 000240 seedek co., ltd. 000241 amer.com 000242 videoframe systems @@ -599,8 +601,8 @@ exit 000247 great dragon information technology (group) co., ltd. 000248 pilz gmbh & co. 000249 aviv infocom co, ltd. - 00024a cisco systems, inc. - 00024b cisco systems, inc. + 00024a cisco systems, inc + 00024b cisco systems, inc 00024c sibyte, inc. 00024d mannesman dematic colby pty. ltd. 00024e datacard group @@ -645,19 +647,19 @@ exit 000275 smart technologies, inc. 000276 primax electronics ltd. 000277 cash systemes industrie - 000278 samsung electro-mechanics co., ltd. + 000278 samsung electro mechanics co., ltd. 000279 control applications, ltd. 00027a ioi technology corporation 00027b amplify net, inc. 00027c trilithic, inc. - 00027d cisco systems, inc. - 00027e cisco systems, inc. + 00027d cisco systems, inc + 00027e cisco systems, inc 00027f ask-technologies.com 000280 mu net, inc. 000281 madge ltd. 000282 viaclix, inc. 000283 spectrum controls, inc. - 000284 areva t&d + 000284 uk grid solutions limited 000285 riverstone networks 000286 occam networks 000287 adapcom @@ -690,7 +692,7 @@ exit 0002a2 hilscher gmbh 0002a3 abb switzerland ltd, power systems 0002a4 addpac technology co., ltd. - 0002a5 hewlett-packard company + 0002a5 hewlett packard 0002a6 effinet systems co., ltd. 0002a7 vivace networks 0002a8 air link technology @@ -710,8 +712,8 @@ exit 0002b6 acrosser technology co., ltd. 0002b7 watanabe electric industry co., ltd. 0002b8 whi konsult ab - 0002b9 cisco systems, inc. - 0002ba cisco systems, inc. + 0002b9 cisco systems, inc + 0002ba cisco systems, inc 0002bb continuous computing corp 0002bc lvl 7 systems, inc. 0002bd bionet co., ltd. @@ -721,12 +723,12 @@ exit 0002c1 innovative electronic designs, inc. 0002c2 net vision telecom 0002c3 arelnet ltd. - 0002c4 vector international bvba + 0002c4 opt machine vision tech co., ltd 0002c5 evertz microsystems ltd. 0002c6 data track technology plc - 0002c7 alps electric co., ltd. + 0002c7 alpsalpine co,.ltd 0002c8 technocom communications technology (pte) ltd - 0002c9 mellanox technologies + 0002c9 mellanox technologies, inc. 0002ca endpoints, inc. 0002cb tristate ltd. 0002cc m.c.c.i @@ -777,12 +779,12 @@ exit 0002f9 mimos berhad 0002fa dx antenna co., ltd. 0002fb baumuller aulugen-systemtechnik gmbh - 0002fc cisco systems, inc. - 0002fd cisco systems, inc. + 0002fc cisco systems, inc + 0002fd cisco systems, inc 0002fe viditec, inc. 0002ff handan broadinfocom 000300 barracuda networks, inc. - 000301 avantas networks corporation + 000301 exfo 000302 charles industries, ltd. 000303 jama electronics co., ltd. 000304 pacific broadband communications @@ -799,7 +801,7 @@ exit 00030f digital china (shanghai) networks ltd. 000310 e-globaledge corporation 000311 micro technology co., ltd. - 000312 tr-systemtechnik gmbh + 000312 trsystems gmbh 000313 access media spa 000314 teleware network systems 000315 cidco incorporated @@ -830,10 +832,10 @@ exit 00032e scope information management, ltd. 00032f global sun technology, inc. 000330 imagenics, co., ltd. - 000331 cisco systems, inc. - 000332 cisco systems, inc. + 000331 cisco systems, inc + 000332 cisco systems, inc 000333 digitel co., ltd. - 000334 newport electronics + 000334 omega engineering inc. 000335 mirae technology 000336 zetes technologies 000337 vaone, inc. @@ -869,7 +871,7 @@ exit 000355 terabeam internet systems 000356 wincor nixdorf international gmbh 000357 intervoice-brite, inc. - 000358 hanyang digitech co., ltd. + 000358 hanyang digitech co.ltd 000359 digitalsis 00035a photron limited 00035b bridgewave communications @@ -888,8 +890,8 @@ exit 000368 embedone co., ltd. 000369 nippon antenna co., ltd. 00036a mainnet, ltd. - 00036b cisco systems, inc. - 00036c cisco systems, inc. + 00036b cisco systems, inc + 00036c cisco systems, inc 00036d runtop, inc. 00036e nicon systems (pty) limited 00036f telsey spa @@ -918,7 +920,7 @@ exit 000386 ho net, inc. 000387 blaze network products 000388 fastfame technology co., ltd. - 000389 plantronics + 000389 plantronics, inc. 00038a america online, inc. 00038b plus-one i&t, inc. 00038c total impact @@ -928,11 +930,11 @@ exit 000390 digital video communications, inc. 000391 advanced digital broadcast, ltd. 000392 hyundai teletek co., ltd. - 000393 apple + 000393 apple, inc. 000394 connect one 000395 california amplifier 000396 ez cast co., ltd. - 000397 watchfront limited + 000397 firebrick limited 000398 wisi 000399 dongju informations & communications co., ltd. 00039a siconnect @@ -940,8 +942,8 @@ exit 00039c optimight communications, inc. 00039d qisda corporation 00039e tera system co., ltd. - 00039f cisco systems, inc. - 0003a0 cisco systems, inc. + 00039f cisco systems, inc + 0003a0 cisco systems, inc 0003a1 hiper information & communication, inc. 0003a2 catapult communications 0003a3 mavix, ltd. @@ -984,7 +986,7 @@ exit 0003c8 cml emergency services 0003c9 tecom co., ltd. 0003ca mts systems corp. - 0003cb nippon systems development co., ltd. + 0003cb systemgear co., ltd. 0003cc momentum computer, inc. 0003cd clovertech, inc. 0003ce eten technologies, inc. @@ -1002,18 +1004,18 @@ exit 0003da takamisawa cybernetics co., ltd. 0003db apogee electronics corp. 0003dc lexar media, inc. - 0003dd comark corp. + 0003dd comark interactive solutions 0003de otc wireless 0003df desana systems 0003e0 arris group, inc. 0003e1 winmate communication, inc. 0003e2 comspace corporation - 0003e3 cisco systems, inc. - 0003e4 cisco systems, inc. + 0003e3 cisco systems, inc + 0003e4 cisco systems, inc 0003e5 hermstedt sg 0003e6 entone, inc. 0003e7 logostek co. ltd. - 0003e8 wavelength digital limited + 0003e8 wavesight limited 0003e9 akara canada, inc. 0003ea mega system technologies, inc. 0003eb atrica @@ -1034,8 +1036,8 @@ exit 0003fa timetra networks 0003fb enegate co.,ltd. 0003fc intertex data ab - 0003fd cisco systems, inc. - 0003fe cisco systems, inc. + 0003fd cisco systems, inc + 0003fe cisco systems, inc 0003ff microsoft corporation 000400 lexmark international, inc. 000401 osaki electric co., ltd. @@ -1048,15 +1050,15 @@ exit 000408 sanko electronics co., ltd. 000409 cratos networks 00040a sage systems - 00040b 3com europe ltd. + 00040b 3com europe ltd 00040c kanno works, ltd. - 00040d avaya, inc. + 00040d avaya inc 00040e avm gmbh 00040f asus network technologies, inc. 000410 spinnaker networks, inc. 000411 inkra networks, inc. 000412 wavesmith networks, inc. - 000413 snom technology ag + 000413 snom technology gmbh 000414 umezawa musen denki co., ltd. 000415 rasteme systems co., ltd. 000416 parks s/a comunicacoes digitais @@ -1068,16 +1070,16 @@ exit 00041c ipdialog, inc. 00041d corega of america 00041e shikoku instrumentation co., ltd. - 00041f sony computer entertainment, inc. + 00041f sony interactive entertainment inc. 000420 slim devices, inc. 000421 ocular networks - 000422 gordon kapes, inc. + 000422 studio technologies, inc 000423 intel corporation 000424 tmc s.r.l. 000425 atmel corporation 000426 autosys - 000427 cisco systems, inc. - 000428 cisco systems, inc. + 000427 cisco systems, inc + 000428 cisco systems, inc 000429 pixord corporation 00042a wireless networks, inc. 00042b it access co., ltd. @@ -1090,7 +1092,7 @@ exit 000432 voyetra turtle beach, inc. 000433 cyberboard a/s 000434 accelent systems, inc. - 000435 comptek international, inc. + 000435 infinet llc 000436 elansat technologies, inc. 000437 powin information technology, inc. 000438 nortel networks @@ -1114,9 +1116,9 @@ exit 00044a ipolicy networks, inc. 00044b nvidia 00044c jenoptik - 00044d cisco systems, inc. - 00044e cisco systems, inc. - 00044f leukhardt systemelektronik gmbh + 00044d cisco systems, inc + 00044e cisco systems, inc + 00044f schubert system elektronik gmbh 000450 dmd computers srl 000451 medrad, inc. 000452 rocketlogix, inc. @@ -1146,26 +1148,26 @@ exit 00046a navini networks 00046b palm wireless, inc. 00046c cyber technology co., ltd. - 00046d cisco systems, inc. - 00046e cisco systems, inc. + 00046d cisco systems, inc + 00046e cisco systems, inc 00046f digitel s/a industria eletronica 000470 ipunplugged ab 000471 iprad 000472 telelynx, inc. 000473 photonex corporation 000474 legrand - 000475 3 com corporation - 000476 3 com corporation + 000475 3com + 000476 3com 000477 scalant systems, inc. 000478 g. star technology corporation 000479 radius co., ltd. 00047a axxessit asa 00047b schlumberger 00047c skidata ag - 00047d pelco + 00047d motorola solutions inc. 00047e siqura b.v. 00047f chr. mayr gmbh & co. kg - 000480 brocade communications systems, inc + 000480 brocade communications systems llc 000481 econolite control products, inc. 000482 medialogic corp. 000483 deltron technology, inc. @@ -1178,7 +1180,7 @@ exit 00048a temia vertriebs gmbh 00048b poscon corporation 00048c nayna networks, inc. - 00048d tone commander systems, inc. + 00048d teo technologies, inc 00048e ohm tech labs, inc. 00048f td systems corporation 000490 optical access @@ -1187,12 +1189,12 @@ exit 000493 tsinghua unisplendour co., ltd. 000494 breezecom, ltd. 000495 tejas networks india limited - 000496 extreme networks + 000496 extreme networks, inc. 000497 macrosystem digital video ag 000498 mahi networks 000499 chino corporation - 00049a cisco systems, inc. - 00049b cisco systems, inc. + 00049a cisco systems, inc + 00049b cisco systems, inc 00049c surgient networks, inc. 00049d ipanema technologies 00049e wirelink co., ltd. @@ -1200,7 +1202,7 @@ exit 0004a0 verity instruments, inc. 0004a1 pathway connectivity 0004a2 l.s.i. japan co., ltd. - 0004a3 microchip technology, inc. + 0004a3 microchip technology inc. 0004a4 netenabled, inc. 0004a5 barco projection systems nv 0004a6 saf tehnika ltd. @@ -1208,7 +1210,7 @@ exit 0004a8 broadmax technologies, inc. 0004a9 sandstream technologies, inc. 0004aa jetstream communications - 0004ab comverse network systems, inc. + 0004ab mavenir inc. 0004ac ibm corp 0004ad malibu networks 0004ae sullair corporation @@ -1229,13 +1231,13 @@ exit 0004bd arris group, inc. 0004be optxcon, inc. 0004bf versalogic corp. - 0004c0 cisco systems, inc. - 0004c1 cisco systems, inc. + 0004c0 cisco systems, inc + 0004c1 cisco systems, inc 0004c2 magnipix, inc. 0004c3 castor informatique - 0004c4 allen & heath limited + 0004c4 audiotonix group limited 0004c5 ase technologies, usa - 0004c6 yamaha motor co., ltd. + 0004c6 yamaha motor co.,ltd 0004c7 netmount 0004c8 liba maschinenfabrik gmbh 0004c9 micro electron co., ltd. @@ -1258,20 +1260,20 @@ exit 0004da relax technology, inc. 0004db tellus group corp. 0004dc nortel networks - 0004dd cisco systems, inc. - 0004de cisco systems, inc. - 0004df teracom telematica ltda. + 0004dd cisco systems, inc + 0004de cisco systems, inc + 0004df teracom telematica s.a 0004e0 procket networks 0004e1 infinior microsystems 0004e2 smc networks, inc. - 0004e3 accton technology corp. + 0004e3 accton technology corp 0004e4 daeryung ind., inc. 0004e5 glonet systems, inc. 0004e6 banyan network private limited 0004e7 lightpointe communications, inc 0004e8 ier, inc. 0004e9 infiniswitch corporation - 0004ea hewlett-packard company + 0004ea hewlett packard 0004eb paxonet communications, inc. 0004ec memobox sa 0004ed billion electric co., ltd. @@ -1289,13 +1291,13 @@ exit 0004f9 xtera communications, inc. 0004fa nbs technologies inc. 0004fb commtech, inc. - 0004fc stratus computer (de), inc. + 0004fc stratus technologies 0004fd japan control engineering co., ltd. 0004fe pelago networks 0004ff acronet co., ltd. - 000500 cisco systems, inc. - 000501 cisco systems, inc. - 000502 apple + 000500 cisco systems, inc + 000501 cisco systems, inc + 000502 apple, inc. 000503 iconag 000504 naray information & communication enterprise 000505 systems integration solutions, inc. @@ -1311,7 +1313,7 @@ exit 00050f tanaka s/s ltd. 000510 infinite shanghai communication terminals ltd. 000511 complementary technologies ltd - 000512 meshnetworks, inc. + 000512 zebra technologies inc 000513 vtlinx multimedia systems, inc. 000514 kdt systems co., ltd. 000515 nuark co., ltd. @@ -1319,11 +1321,11 @@ exit 000517 shellcomm, inc. 000518 jupiters technology 000519 siemens building technologies ag, - 00051a 3com europe ltd. + 00051a 3com europe ltd 00051b magic control technology corporation 00051c xnet technology corp. 00051d airocon, inc. - 00051e brocade communications systems, inc. + 00051e brocade communications systems llc 00051f taijin media co., ltd. 000520 smartronix, inc. 000521 control microsystems @@ -1342,9 +1344,9 @@ exit 00052e cinta networks 00052f leviton network solutions 000530 andiamo systems, inc. - 000531 cisco systems, inc. - 000532 cisco systems, inc. - 000533 brocade communications systems, inc. + 000531 cisco systems, inc + 000532 cisco systems, inc + 000533 brocade communications systems llc 000534 northstar engineering ltd. 000535 chip pc ltd. 000536 danam communications, inc. @@ -1372,7 +1374,7 @@ exit 00054c rf innovations pty ltd 00054d brans technologies, inc. 00054e philips - 00054f + 00054f garmin international 000550 vcomms connect limited 000551 f & s elektronik systeme gmbh 000552 xycotec computer gmbh @@ -1387,8 +1389,8 @@ exit 00055b charles industries, ltd. 00055c kowa company, ltd. 00055d d-link systems, inc. - 00055e cisco systems, inc. - 00055f cisco systems, inc. + 00055e cisco systems, inc + 00055f cisco systems, inc 000560 leader comm.co., ltd 000561 nac image technology, inc. 000562 digital view limited @@ -1408,12 +1410,12 @@ exit 000570 baydel ltd. 000571 seiwa electronics co. 000572 deonet co., ltd. - 000573 cisco systems, inc. - 000574 cisco systems, inc. + 000573 cisco systems, inc + 000574 cisco systems, inc 000575 cds-electronics bv 000576 nsm technology ltd. 000577 sm information & communication - 000578 + 000578 private 000579 universal control solution corp. 00057a overture networks 00057b chung nam electronic co., ltd. @@ -1426,7 +1428,7 @@ exit 000582 clearcube technology 000583 imagecom limited 000584 absolutevalue systems, inc. - 000585 juniper networks, inc. + 000585 juniper networks 000586 lucent technologies 000587 locus, incorporated 000588 sensoria corp. @@ -1441,14 +1443,14 @@ exit 000591 active silicon ltd 000592 pultek corp. 000593 grammar engine inc. - 000594 ixxat automation gmbh + 000594 hms industrial networks 000595 alesis corporation 000596 genotech co., ltd. 000597 eagle traffic control systems 000598 cronos s.r.l. 000599 drs test and energy management or drs-tem - 00059a cisco systems, inc. - 00059b cisco systems, inc. + 00059a cisco systems, inc + 00059b cisco systems, inc 00059c kleinknecht gmbh, ing. büro 00059d daniel computing systems, inc. 00059e zinwell corporation @@ -1460,7 +1462,7 @@ exit 0005a4 lucid voice ltd. 0005a5 kott 0005a6 extron electronics - 0005a7 hyperchip, inc. + 0005a7 hyperchip inc. 0005a8 wyle electronics 0005a9 princeton networks, inc. 0005aa moore industries international inc. @@ -1494,11 +1496,11 @@ exit 0005c6 triz communications 0005c7 i/f-com a/s 0005c8 verytech - 0005c9 lg innotek co., ltd. + 0005c9 lg innotek 0005ca hitron technology, inc. 0005cb rois technologies, inc. 0005cc sumtel communications, inc. - 0005cd denon, ltd. + 0005cd d&m holdings inc. 0005ce prolink microsystems corporation 0005cf thunder river technologies, inc. 0005d0 solinet systems @@ -1513,8 +1515,8 @@ exit 0005d9 techno valley, inc. 0005da apex automationstechnik 0005db psi nentec gmbh - 0005dc cisco systems, inc. - 0005dd cisco systems, inc. + 0005dc cisco systems, inc + 0005dd cisco systems, inc 0005de gi fone korea, inc. 0005df electronic innovation, inc. 0005e0 empirix corp. @@ -1531,7 +1533,7 @@ exit 0005eb blue ridge networks, inc. 0005ec mosaic systems inc. 0005ed technikum joanneum gmbh - 0005ee siemens ab, infrastructure & cities, building technologies division, ic bt ssp sp ba pr + 0005ee vanderbilt international (swe) ab 0005ef adoir digital technology 0005f0 satec 0005f1 vrcom, inc. @@ -1560,7 +1562,7 @@ exit 000608 at-sky sas 000609 crossport systems 00060a blue2space - 00060b emerson network power + 00060b artesyn embedded technologies 00060c melco industries, inc. 00060d wave7 optics 00060e igys systems, inc. @@ -1589,16 +1591,16 @@ exit 000625 the linksys group, inc. 000626 mwe gmbh 000627 uniwide technologies, inc. - 000628 cisco systems, inc. + 000628 cisco systems, inc 000629 ibm corp - 00062a cisco systems, inc. + 00062a cisco systems, inc 00062b intraserver technology 00062c bivio networks 00062d touchstar technologies, l.l.c. 00062e aristos logic corp. 00062f pivotech systems inc. 000630 adtranz sweden - 000631 calix + 000631 calix inc. 000632 mesco engineering gmbh 000633 cross match technologies gmbh 000634 gte airfone inc. @@ -1617,7 +1619,7 @@ exit 000641 itcn 000642 genetel systems inc. 000643 sono computer co., ltd. - 000644 neix,inc + 000644 nextgen business solutions, inc 000645 meisei electric co. ltd. 000646 shenzhen xunbao network technology co ltd 000647 etrali s.a. @@ -1631,8 +1633,8 @@ exit 00064f pro-nets technology corporation 000650 tiburon networks, inc. 000651 aspen networks inc. - 000652 cisco systems, inc. - 000653 cisco systems, inc. + 000652 cisco systems, inc + 000653 cisco systems, inc 000654 winpresa building automation technologies gmbh 000655 yipee, inc. 000656 tactel ab @@ -1640,11 +1642,11 @@ exit 000658 helmut fischer gmbh institut für elektronik und messtechnik 000659 eal (apeldoorn) b.v. 00065a strix systems - 00065b dell computer corp. + 00065b dell inc. 00065c malachite technologies, inc. 00065d heidelberg web systems 00065e photuris, inc. - 00065f eci telecom - ngts ltd. + 00065f eci telecom ltd. 000660 nadex co., ltd. 000661 nia home technologies corp. 000662 mbm technology ltd. @@ -1669,11 +1671,11 @@ exit 000675 banderacom, inc. 000676 novra technologies inc. 000677 sick ag - 000678 marantz brand company + 000678 d&m holdings inc. 000679 konami corporation 00067a jmp systems 00067b toplink c&c corporation - 00067c cisco systems, inc. + 00067c cisco systems, inc 00067d takasago ltd. 00067e wincom systems, inc. 00067f digeo, inc. @@ -1689,7 +1691,7 @@ exit 000689 ylez technologies pte ltd 00068a neuronnet co. ltd. r&d center 00068b airrunner technologies, inc. - 00068c 3com corporation + 00068c 3com 00068d sepaton, inc. 00068e hid corporation 00068f telemonitor, inc. @@ -1742,7 +1744,7 @@ exit 0006be baumer optronic gmbh 0006bf accella technologies co., ltd. 0006c0 united internetworks, inc. - 0006c1 cisco systems, inc. + 0006c1 cisco systems, inc 0006c2 smartmatic corporation 0006c3 schindler elevator ltd. 0006c4 piolink inc. @@ -1763,8 +1765,8 @@ exit 0006d3 alpha telecom, inc. u.s.a. 0006d4 interactive objects, inc. 0006d5 diamond systems corp. - 0006d6 cisco systems, inc. - 0006d7 cisco systems, inc. + 0006d6 cisco systems, inc + 0006d7 cisco systems, inc 0006d8 maple optical systems 0006d9 ipm-net s.p.a. 0006da itran communications ltd. @@ -1794,9 +1796,9 @@ exit 0006f2 platys communications 0006f3 accelight networks 0006f4 prime electronics & satellitics inc. - 0006f5 alps co,. ltd. - 0006f6 cisco systems, inc. - 0006f7 alps co,. ltd. + 0006f5 alpsalpine co,.ltd + 0006f6 cisco systems, inc + 0006f7 alpsalpine co,.ltd 0006f8 the boeing company 0006f9 mitsui zosen systems research inc. 0006fa ip square co, ltd. @@ -1807,9 +1809,9 @@ exit 0006ff sheba systems co., ltd. 000700 zettamedia korea 000701 racal-datacom - 000702 varian medical systems + 000702 varex imaging 000703 csee transport - 000704 alps co,. ltd. + 000704 alpsalpine co,.ltd 000705 endress & hauser gmbh & co 000706 sanritz corporation 000707 interalia inc. @@ -1818,8 +1820,8 @@ exit 00070a unicom automation co., ltd. 00070b novabase sgps, sa 00070c sva-intrusion.com co. ltd. - 00070d cisco systems, inc. - 00070e cisco systems, inc. + 00070d cisco systems, inc + 00070e cisco systems, inc 00070f fujant, inc. 000710 adax, inc. 000711 acterna @@ -1833,7 +1835,7 @@ exit 000719 mobiis co., ltd. 00071a finedigital inc. 00071b cdvi americas ltd - 00071c at&t fixed wireless services + 00071c at&t 00071d satelsa sistemas y aplicaciones de telecomunicaciones, s.a. 00071e tri-m engineering / nupak dev. corp. 00071f european systems integration @@ -1843,7 +1845,7 @@ exit 000723 elcon systemtechnik gmbh 000724 telemax co., ltd. 000725 bematech international corp. - 000726 shenzhen gongjin electronics co., ltd. + 000726 shenzhen gongjin electronics co.,lt 000727 zi corporation (hk) ltd. 000728 neo telecom 000729 kistler instrumente ag @@ -1863,15 +1865,15 @@ exit 000737 soriya co. ltd. 000738 young technology co., ltd. 000739 scotty group austria gmbh - 00073a inventel systemes + 00073a inventel 00073b tenovis gmbh & co kg 00073c telecom design 00073d nanjing postel telecommunications co., ltd. 00073e china great-wall computer shenzhen co., ltd. 00073f woojyun systec co., ltd. - 000740 buffalo inc. + 000740 buffalo.inc 000741 sierra automated systems - 000742 current technologies, llc + 000742 ormazabal 000743 chelsio communications 000744 unico, inc. 000745 radlan computer communications ltd. @@ -1884,8 +1886,8 @@ exit 00074c beicom inc. 00074d zebra technologies corp. 00074e ipfront inc - 00074f cisco systems, inc. - 000750 cisco systems, inc. + 00074f cisco systems, inc + 000750 cisco systems, inc 000751 m-u-t ag 000752 rhythm watch co., ltd. 000753 beijing qxcomm technology co., ltd. @@ -1893,7 +1895,7 @@ exit 000755 lafon 000756 juyoung telecom 000757 topcall international ag - 000758 dragonwave + 000758 dragonwave inc. 000759 boris manufacturing corp. 00075a air products and chemicals, inc. 00075b gibson guitars @@ -1902,7 +1904,7 @@ exit 00075e ametek power instruments 00075f vcs video communication systems ag 000760 tomis information & telecom corp. - 000761 logitech europe sa + 000761 29530 000762 group sense limited 000763 sunniwell cyber tech. co., ltd. 000764 youngwoo telecom co. ltd. @@ -1919,7 +1921,7 @@ exit 00076f synoptics limited 000770 ubiquoss inc 000771 embedded system corporation - 000772 alcatel shanghai bell co., ltd. + 000772 alcatel-lucent shanghai bell co., ltd 000773 ascom powerline communications ltd. 000774 guangzhou thinker technology co. ltd. 000775 valence semiconductor, inc. @@ -1929,32 +1931,32 @@ exit 000779 sungil telecom co., ltd. 00077a infoware system co., ltd. 00077b millimetrix broadband networks - 00077c westermo teleindustri ab - 00077d cisco systems, inc. + 00077c westermo network technologies ab + 00077d cisco systems, inc 00077e elrest gmbh 00077f j communications co., ltd. 000780 bluegiga technologies oy 000781 itron inc. - 000782 oracle corporation + 000782 oracle corporation 000783 syncom network, inc. - 000784 cisco systems, inc. - 000785 cisco systems, inc. + 000784 cisco systems, inc + 000785 cisco systems, inc 000786 wireless networks inc. 000787 idea system co., ltd. 000788 clipcomm, inc. - 000789 dongwon systems + 000789 allradio co., ltd 00078a mentor data system inc. 00078b wegener communications, inc. 00078c elektronikspecialisten i borlange ab 00078d netengines ltd. - 00078e garz & friche gmbh + 00078e garz & fricke gmbh 00078f emkay innovative products 000790 tri-m technologies (s) limited 000791 international data communications, inc. 000792 sütron electronic gmbh 000793 shin satellite public company limited 000794 simple devices, inc. - 000795 elitegroup computer system co. (ecs) + 000795 elitegroup computer systems co.,ltd. 000796 lsi systems, inc. 000797 netpower co., ltd. 000798 selea srl @@ -1971,27 +1973,27 @@ exit 0007a3 ositis software, inc. 0007a4 gn netcom ltd. 0007a5 y.d.k co. ltd. - 0007a6 home automation, inc. + 0007a6 leviton manufacturing co., inc. 0007a7 a-z inc. - 0007a8 haier group technologies ltd. + 0007a8 haier group technologies ltd 0007a9 novasonics 0007aa quantum data inc. 0007ab samsung electronics co.,ltd 0007ac eolring 0007ad pentacon gmbh foto-und feinwerktechnik 0007ae britestream networks, inc. - 0007af n-tron corporation + 0007af red lion controls, lp 0007b0 office details, inc. 0007b1 equator technologies 0007b2 transaccess s.a. - 0007b3 cisco systems, inc. - 0007b4 cisco systems, inc. + 0007b3 cisco systems, inc + 0007b4 cisco systems, inc 0007b5 any one wireless ltd. 0007b6 telecom technology ltd. 0007b7 samurai ind. prods eletronicos ltda 0007b8 corvalent corporation 0007b9 ginganet corporation - 0007ba utstarcom, inc. + 0007ba utstarcom inc 0007bb candera inc. 0007bc identix inc. 0007bd radionet ltd. @@ -2008,9 +2010,9 @@ exit 0007c8 brain21, inc. 0007c9 technol seven co., ltd. 0007ca creatix polymedia ges fur kommunikaitonssysteme - 0007cb freebox sa + 0007cb freebox sas 0007cc kaba benzing gmbh - 0007cd nmtel co., ltd. + 0007cd kumoh electronic co, ltd 0007ce cabletime limited 0007cf anoto ab 0007d0 automat engenharia de automação ltda. @@ -2021,7 +2023,7 @@ exit 0007d5 3e technologies int;., inc. 0007d6 commil ltd. 0007d7 caporis networks ag - 0007d8 hitron systems inc. + 0007d8 hitron technologies. inc 0007d9 splicecom 0007da neuro telecom co., ltd. 0007db kirana networks, inc. @@ -2040,8 +2042,8 @@ exit 0007e8 edgewave 0007e9 intel corporation 0007ea massana, inc. - 0007eb cisco systems, inc. - 0007ec cisco systems, inc. + 0007eb cisco systems, inc + 0007ec cisco systems, inc 0007ed altera corporation 0007ee telco informationssysteme gmbh 0007ef lockheed martin tactical systems @@ -2063,7 +2065,7 @@ exit 0007ff gluon networks 000800 multitech systems, inc. 000801 highspeed surfing inc. - 000802 hewlett-packard company + 000802 hewlett packard 000803 cos tron 000804 ica inc. 000805 techno-holon corporation @@ -2073,7 +2075,7 @@ exit 000809 systemonic ag 00080a espera-werke gmbh 00080b birka bpa informationssystem ab - 00080c vda elettronica spa + 00080c vda group s.p.a. 00080d toshiba 00080e arris group, inc. 00080f proximion fiber optics ab @@ -2093,8 +2095,8 @@ exit 00081d ipsil, incorporated 00081e repeatit ab 00081f pou yuen tech corp. ltd. - 000820 cisco systems, inc. - 000821 cisco systems, inc. + 000820 cisco systems, inc + 000821 cisco systems, inc 000822 inpro comm 000823 texa corp. 000824 nuance document imaging @@ -2102,16 +2104,16 @@ exit 000826 colorado med tech 000827 adb broadband italia 000828 koei engineering ltd. - 000829 aval nagasaki corporation + 000829 tokyo electron device nagasaki limited 00082a powerwallz network security 00082b wooksung electronics, inc. 00082c homag ag 00082d indus teqsite private limited 00082e multitone electronics plc - 00082f cisco systems, inc. - 000830 cisco systems, inc. - 000831 cisco systems, inc. - 000832 cisco + 00082f cisco systems, inc + 000830 cisco systems, inc + 000831 cisco systems, inc + 000832 cisco systems, inc 00084e divergenet, inc. 00084f qualstar corporation 000850 arizona instrument corp. @@ -2127,7 +2129,7 @@ exit 00085a intigate inc. 00085b hanbit electronics co., ltd. 00085c shanghai dare technologies co. ltd. - 00085d aastra + 00085d mitel corporation 00085e pco ag 00085f picanol n.v. 000860 lodgenet entertainment corp. @@ -2150,7 +2152,7 @@ exit 000871 northdata co., ltd. 000872 sorenson communications 000873 daptechnology b.v. - 000874 dell computer corp. + 000874 dell inc. 000875 acorp electronics corp. 000876 sdsystem 000877 liebert-hiross spa @@ -2158,20 +2160,20 @@ exit 000879 cem corporation 00087a wipotec gmbh 00087b rtx telecom a/s - 00087c cisco systems, inc. - 00087d cisco systems, inc. + 00087c cisco systems, inc + 00087d cisco systems, inc 00087e bon electro-telecom inc. 00087f spaun electronic gmbh & co. kg 000880 broadtel canada communications inc. 000881 digital hands co.,ltd. 000882 sigma corporation - 000883 hewlett-packard company + 000883 hewlett packard 000884 index braille ab 000885 ems dr. thomas wünsche 000886 hansung teliann, inc. 000887 maschinenfabrik reinhausen gmbh 000888 oullim information technology inc,. - 000889 echostar technologies corp + 000889 dish technologies corp 00088a minds@work 00088b tropic networks inc. 00088c quanta network systems inc. @@ -2197,8 +2199,8 @@ exit 0008a0 stotz feinmesstechnik gmbh 0008a1 cnet technology inc. 0008a2 adi engineering, inc. - 0008a3 cisco systems, inc. - 0008a4 cisco systems, inc. + 0008a3 cisco systems, inc + 0008a4 cisco systems, inc 0008a5 peninsula systems inc. 0008a6 multiware & image co., ltd. 0008a7 ilogic inc. @@ -2210,7 +2212,7 @@ exit 0008ad toyo-linx co., ltd. 0008ae packetfront network products ab 0008af novatec corporation - 0008b0 bktel communications gmbh + 0008b0 huber+suhner bktel gmbh 0008b1 proquent systems 0008b2 shenzhen compass technology development co.,ltd 0008b3 fastwel @@ -2219,7 +2221,7 @@ exit 0008b6 routefree, inc. 0008b7 hit incorporated 0008b8 e.f. johnson - 0008b9 kaon media co., ltd. + 0008b9 kaonmedia co., ltd. 0008ba erskine systems ltd 0008bb netexcell 0008bc ilevo ab @@ -2228,14 +2230,14 @@ exit 0008bf aptus elektronik ab 0008c0 asa systems 0008c1 avistar communications corporation - 0008c2 cisco systems, inc. + 0008c2 cisco systems, inc 0008c3 contex a/s 0008c4 hikari co.,ltd. 0008c5 liontech co., ltd. 0008c6 philips consumer communications - 0008c7 hewlett-packard company + 0008c7 hewlett packard 0008c8 soneticom, inc. - 0008c9 technisat digital gmbh + 0008c9 technisat digital gmbh daun 0008ca twinhan technology co.,ltd 0008cb zeta broadband inc. 0008cc remotec, inc. @@ -2260,8 +2262,8 @@ exit 0008df alistel inc. 0008e0 ato technology ltd. 0008e1 barix ag - 0008e2 cisco systems, inc. - 0008e3 cisco systems, inc. + 0008e2 cisco systems, inc + 0008e3 cisco systems, inc 0008e4 envenergy inc 0008e5 idk corporation 0008e6 littlefeet @@ -2280,11 +2282,11 @@ exit 0008f3 wany 0008f4 bluetake technology co., ltd. 0008f5 yestechnology co.,ltd. - 0008f6 sumitomo electric system solutions co., ltd. + 0008f6 sumitomo electric industries, ltd 0008f7 hitachi ltd, semiconductor & integrated circuits gr 0008f8 utc ccs - 0008f9 emerson network power - 0008fa karl e.brinkmann gmbh + 0008f9 artesyn embedded technologies + 0008fa keb automation kg 0008fb sonosite, inc. 0008fc gigaphoton inc. 0008fd bluekorea co., ltd. @@ -2307,8 +2309,8 @@ exit 00090e helix technology inc. 00090f fortinet inc. 000910 simple access inc. - 000911 cisco systems, inc. - 000912 cisco systems, inc. + 000911 cisco systems, inc + 000912 cisco systems, inc 000913 systemk corporation 000914 computrols inc. 000915 cas corp. @@ -2348,17 +2350,17 @@ exit 000937 inventec appliance corp 000938 allot communications 000939 shibasoku co.,ltd. - 00093a molex fiber optics + 00093a molex cms 00093b hyundai networks inc. 00093c jacques technologies p/l 00093d newisys,inc. 00093e c&i technologies 00093f double-win enterpirse co., ltd 000940 agfeo gmbh & co. kg - 000941 allied telesis k.k. + 000941 allied telesis r&d center k.k. 000942 wireless technologies, inc - 000943 cisco systems, inc. - 000944 cisco systems, inc. + 000943 cisco systems, inc + 000944 cisco systems, inc 000945 palmmicro communications inc 000946 cluster labs gmbh 000947 aztek, inc. @@ -2381,7 +2383,7 @@ exit 000958 intelnet s.a. 000959 sitecsoft 00095a racewood technology - 00095b netgear, inc. + 00095b netgear 00095c philips medical systems - cardiac and monitoring systems (cm 00095d dialogue technology corp. 00095e masstech group inc. @@ -2392,7 +2394,7 @@ exit 000963 dominion lasercom inc. 000964 hi-techniques, inc. 000965 hyunju computer co., ltd. - 000966 thales navigation + 000966 trimble europe bv 000967 tachyon, inc 000968 technoventure, inc. 000969 meret optical communications @@ -2413,8 +2415,8 @@ exit 000978 aiji system co., ltd. 000979 advanced television systems committee, inc. 00097a louis design labs. - 00097b cisco systems, inc. - 00097c cisco systems, inc. + 00097b cisco systems, inc + 00097c cisco systems, inc 00097d secwell networks oy 00097e imi technology co., ltd 00097f vsecure 2000 ltd. @@ -2435,7 +2437,7 @@ exit 00098e ipcas gmbh 00098f cetacean networks 000990 acksys communications & systems - 000991 ge fanuc automation manufacturing, inc. + 000991 intelligent platforms, llc. 000992 interepoch technology,inc. 000993 visteon corporation 000994 cronyx engineering @@ -2472,13 +2474,13 @@ exit 0009b3 mcm systems ltd 0009b4 kisan telecom co., ltd. 0009b5 3j tech. co., ltd. - 0009b6 cisco systems, inc. - 0009b7 cisco systems, inc. + 0009b6 cisco systems, inc + 0009b7 cisco systems, inc 0009b8 entise systems 0009b9 action imaging solutions 0009ba maku informationstechik gmbh 0009bb mathstar, inc. - 0009bc digital safety technologies, inc + 0009bc utility, inc 0009bd epygi technologies, ltd. 0009be mamiya-op co.,ltd. 0009bf nintendo co., ltd. @@ -2513,7 +2515,7 @@ exit 0009dc galaxis technology ag 0009dd mavin technology inc. 0009de samjin information & communications co., ltd. - 0009df vestel komunikasyon sanayi ve ticaret a.s. + 0009df vestel elektronik san ve tic. a.Ş. 0009e0 xemics s.a. 0009e1 gemtek technology co., ltd. 0009e2 sinbon electronics co., ltd. @@ -2522,8 +2524,8 @@ exit 0009e5 hottinger baldwin messtechnik gmbh 0009e6 cyber switching inc. 0009e7 adc techonology - 0009e8 cisco systems, inc. - 0009e9 cisco systems, inc. + 0009e8 cisco systems, inc + 0009e9 cisco systems, inc 0009ea yem inc. 0009eb humandata ltd. 0009ec daktronics, inc. @@ -2558,7 +2560,7 @@ exit 000a0a sunix co., ltd. 000a0b sealevel systems, inc. 000a0c scientific research corporation - 000a0d fci deutschland gmbh + 000a0d amphenol 000a0e invivo research inc. 000a0f ilryung telesys, inc 000a10 fast media integrations ag @@ -2584,7 +2586,7 @@ exit 000a24 octave communications 000a25 ceragon networks 000a26 ceia s.p.a. - 000a27 apple + 000a27 apple, inc. 000a28 motorola 000a29 pan dacom networking ag 000a2a qsi systems inc. @@ -2593,7 +2595,7 @@ exit 000a2d cabot communications limited 000a2e maple networks co., ltd 000a2f artnix inc. - 000a30 johnson controls-asg + 000a30 visteon corporation 000a31 hcv consulting 000a32 xsido corporation 000a33 emulex corporation @@ -2610,8 +2612,8 @@ exit 000a3e eads telecom 000a3f data east corporation 000a40 crown audio -- harmanm international - 000a41 cisco systems, inc. - 000a42 cisco systems, inc. + 000a41 cisco systems, inc + 000a42 cisco systems, inc 000a43 chunghwa telecom co., ltd. 000a44 avery dennison deutschland gmbh 000a45 audio-technica corp. @@ -2632,14 +2634,14 @@ exit 000a54 laguna hills, inc. 000a55 markem corporation 000a56 hitachi maxell ltd. - 000a57 hewlett-packard company - standards + 000a57 hewlett packard 000a58 freyer & siegel elektronik gmbh & co. kg 000a59 hw server 000a5a greennet technologies co.,ltd. 000a5b power-one as 000a5c carel s.p.a. 000a5d fingertec worldwide sdn bhd - 000a5e 3com corporation + 000a5e 3com 000a5f almedio inc. 000a60 autostar technology pte ltd 000a61 cellinx systems inc. @@ -2649,7 +2651,7 @@ exit 000a65 gentechmedia.co.,ltd. 000a66 mitsubishi electric system & service co.,ltd. 000a67 ongcorp - 000a68 solarflare communications, inc. + 000a68 solarflare communications inc. 000a69 sunny bell technology co., ltd. 000a6a svm microwaves s.r.o. 000a6b tadiran telecom business systems ltd @@ -2683,8 +2685,8 @@ exit 000a87 integrated micromachines inc. 000a88 incypher s.a. 000a89 creval systems, inc. - 000a8a cisco systems, inc. - 000a8b cisco systems, inc. + 000a8a cisco systems, inc + 000a8b cisco systems, inc 000a8c guardware systems ltd. 000a8d eurotherm limited 000a8e invacom ltd @@ -2694,7 +2696,7 @@ exit 000a92 presonus corporation 000a93 w2 networks, inc. 000a94 shanghai cellink co., ltd - 000a95 apple + 000a95 apple, inc. 000a96 mewtel technology inc. 000a97 sonicblue, inc. 000a98 m+f gwinner gmbh & co @@ -2728,8 +2730,8 @@ exit 000ab4 etic telecommunications 000ab5 digital electronic network 000ab6 compunetix, inc - 000ab7 cisco systems, inc. - 000ab8 cisco systems, inc. + 000ab7 cisco systems, inc + 000ab8 cisco systems, inc 000ab9 astera technologies corp. 000aba arcon technology limited 000abb taiwan secom co,. ltd @@ -2739,7 +2741,7 @@ exit 000abf hirota ss 000ac0 fuyoh video industry co., ltd. 000ac1 futuretel - 000ac2 fiberhome telecommunication technologies co.,ltd + 000ac2 wuhan fiberhome digital technology co.,ltd. 000ac3 em technics co., ltd. 000ac4 daewoo teletech co., ltd 000ac5 color kinetics @@ -2762,9 +2764,9 @@ exit 000ad6 beamreach networks 000ad7 origin electric co.,ltd. 000ad8 ipcserv technology corp. - 000ad9 sony ericsson mobile communications ab + 000ad9 sony mobile communications inc 000ada vindicator technologies - 000adb skypilot network, inc + 000adb trilliant 000adc ruggedcom inc. 000add allworx corp. 000ade happy communication co., ltd. @@ -2773,32 +2775,32 @@ exit 000ae1 eg technology 000ae2 binatone electronics international, ltd 000ae3 yang mei technology co., ltd - 000ae4 wistron corp. + 000ae4 wistron corporation 000ae5 scottcare corporation - 000ae6 elitegroup computer system co. (ecs) + 000ae6 elitegroup computer systems co.,ltd. 000ae7 eliop s.a. 000ae8 cathay roxus information technology co. ltd 000ae9 airvast technology inc. 000aea adam elektronik ltd. Şti - 000aeb shenzhen tp-link technology co; ltd. + 000aeb tp-link technologies co.,ltd. 000aec koatsu gas kogyo co., ltd. - 000aed harting systems gmbh & co kg + 000aed harting electronics gmbh 000aee gcd hard- & software gmbh 000aef otrum asa 000af0 shin-oh electronics co., ltd. r&d 000af1 clarity design, inc. 000af2 neoaxiom corp. - 000af3 cisco systems, inc. - 000af4 cisco systems, inc. + 000af3 cisco systems, inc + 000af4 cisco systems, inc 000af5 airgo networks, inc. 000af6 emerson climate technologies retail solutions, inc. - 000af7 broadcom corp. + 000af7 broadcom 000af8 american telecare inc. 000af9 hiconnect, inc. 000afa traverse technologies australia 000afb ambri limited 000afc core tec communications, llc - 000afd viking electronic services + 000afd kentec electronics 000afe novapal ltd 000aff kilchherr elektronik ag 000b00 fujian start computer equipment co.,ltd @@ -2825,7 +2827,7 @@ exit 000b15 platypus technology 000b16 communication machinery corporation 000b17 mks instruments - 000b18 + 000b18 private 000b19 vernier networks, inc. 000b1a industrial defender, inc. 000b1b systronix, inc. @@ -2836,7 +2838,7 @@ exit 000b20 hirata corporation 000b21 g-star communications inc. 000b22 environmental systems and services - 000b23 siemens subscriber networks + 000b23 siemens home & office comm. devices 000b24 airlogic 000b25 aeluros 000b26 wetek corporation @@ -2847,7 +2849,7 @@ exit 000b2b hostnet corporation 000b2c eiki industrial co. ltd. 000b2d danfoss inc. - 000b2e cal-comp electronics (thailand) public company limited taipe + 000b2e cal-comp electronics & communications company ltd. 000b2f bplan gmbh 000b30 beijing gongye science & technology co.,ltd 000b31 yantai zhiyang scientific and technology industry co., ltd @@ -2865,13 +2867,13 @@ exit 000b3d contal ok ltd. 000b3e bittware, inc 000b3f anthology solutions inc. - 000b40 oclaro + 000b40 cambridge industries group (cig) 000b41 ing. büro dr. beutlhauser 000b42 commax co., ltd. 000b43 microscan systems, inc. 000b44 concord idea corp. - 000b45 cisco systems, inc. - 000b46 cisco systems, inc. + 000b45 cisco systems, inc + 000b46 cisco systems, inc 000b47 advanced energy 000b48 sofrel 000b49 rf-link system inc. @@ -2879,8 +2881,8 @@ exit 000b4b visiowave sa 000b4c clarion (m) sdn bhd 000b4d emuzed - 000b4e vertexrsi, general dynamics satcom technologies, inc. - 000b4f verifone, inc. + 000b4e communications & power industries + 000b4f verifone 000b50 oxygnet 000b51 micetek international inc. 000b52 joymax electronics co. ltd. @@ -2896,8 +2898,8 @@ exit 000b5c newtech co.,ltd 000b5d fujitsu limited 000b5e audio engineering society inc. - 000b5f cisco systems, inc. - 000b60 cisco systems, inc. + 000b5f cisco systems, inc + 000b60 cisco systems, inc 000b61 friedrich lütze gmbh & co. kg 000b62 ib-mohnen kg 000b63 kaleidescape @@ -2907,8 +2909,8 @@ exit 000b67 topview technology corporation 000b68 addvalue communications pte ltd 000b69 franke finland oy - 000b6a asiarock incorporation - 000b6b wistron neweb corp. + 000b6a asiarock technology limited + 000b6b wistron neweb corporation 000b6c sychip inc. 000b6d solectron japan nakaniida 000b6e neff instrument corp. @@ -2934,8 +2936,8 @@ exit 000b82 grandstream networks, inc. 000b83 datawatt b.v. 000b84 bodet - 000b85 cisco systems, inc. - 000b86 aruba networks + 000b85 cisco systems, inc + 000b86 aruba, a hewlett packard enterprise company 000b87 american reliance inc. 000b88 vidisco ltd. 000b89 top global technology, ltd. @@ -2962,9 +2964,9 @@ exit 000b9e yasing technology corp. 000b9f neue elsa gmbh 000ba0 t&l information inc. - 000ba1 syscom ltd. - 000ba2 sumitomo electric networks, inc - 000ba3 siemens ag, i&s + 000ba1 fujikura solutions ltd. + 000ba2 sumitomo electric industries, ltd + 000ba3 siemens ag 000ba4 shiron satellite communications ltd. (1996) 000ba5 quasar cipta mandiri, pt 000ba6 miyakawa electric works ltd. @@ -2991,8 +2993,8 @@ exit 000bbb etin systems co., ltd 000bbc en garde systems, inc. 000bbd connexionz limited - 000bbe cisco systems, inc. - 000bbf cisco systems, inc. + 000bbe cisco systems, inc + 000bbf cisco systems, inc 000bc0 china iwncomm co., ltd. 000bc1 bay microsystems, inc. 000bc2 corinex communication corp. @@ -3003,10 +3005,10 @@ exit 000bc7 icet s.p.a. 000bc8 airflow networks 000bc9 electroline equipment - 000bca datavan international corporation + 000bca datavan tc 000bcb fagor automation , s. coop 000bcc jusan, s.a. - 000bcd hewlett-packard company + 000bcd hewlett packard 000bce free2move ab 000bcf agfa ndt inc. 000bd0 ximeta technology americas inc. @@ -3020,7 +3022,7 @@ exit 000bd8 industrial scientific corp. 000bd9 general hydrogen 000bda eyecross co.,inc. - 000bdb dell inc + 000bdb dell inc. 000bdc akcp 000bdd tohoku ricoh co., ltd. 000bde teldix gmbh @@ -3045,7 +3047,7 @@ exit 000bf1 lap laser applikations 000bf2 chih-kan technology co., ltd. 000bf3 bae systems - 000bf4 + 000bf4 private 000bf5 shanghai sibo telecom technology co.,ltd 000bf6 nitgen co., ltd 000bf7 nidek co.,ltd @@ -3053,8 +3055,8 @@ exit 000bf9 gemstone communications, inc. 000bfa exemys srl 000bfb d-net international corporation - 000bfc cisco systems, inc. - 000bfd cisco systems, inc. + 000bfc cisco systems, inc + 000bfd cisco systems, inc 000bfe castel broadband limited 000bff berkeley camera engineering 000c00 beb industrie-elektronik ag @@ -3094,7 +3096,7 @@ exit 000c22 double d electronics ltd 000c23 beijing lanchuan tech. co., ltd. 000c24 anator - 000c25 allied telesis labs, inc. + 000c25 allied telesis labs, inc. 000c26 weintek labs. inc. 000c27 sammy corporation 000c28 rifatron @@ -3105,9 +3107,9 @@ exit 000c2d fullwave technology co., ltd. 000c2e openet information technology(shenzhen) co., ltd. 000c2f seorimtechnology co.,ltd. - 000c30 cisco systems, inc. - 000c31 cisco systems, inc. - 000c32 avionic design development gmbh + 000c30 cisco systems, inc + 000c31 cisco systems, inc + 000c32 avionic design gmbh 000c33 compucase enterprise co. ltd. 000c34 vixen co., ltd. 000c35 kavo dental gmbh & co. kg @@ -3122,7 +3124,7 @@ exit 000c3e crest audio 000c3f cogent defence & security networks, 000c40 altech controls - 000c41 cisco-linksys + 000c41 cisco-linksys, llc 000c42 routerboard.com 000c43 ralink technology, corp. 000c44 automated interfaces, inc. @@ -3130,7 +3132,7 @@ exit 000c46 allied telesyn inc. 000c47 sk teletech(r&d planning team) 000c48 qostek corporation - 000c49 dangaard telecom rtc division a/s + 000c49 dangaard telecom denmark a/s 000c4a cygnus microsystems (p) limited 000c4b cheops elektronik 000c4c arcor ag&co. @@ -3140,7 +3142,7 @@ exit 000c50 seagate technology 000c51 scientific technologies inc. 000c52 roll systems inc. - 000c53 + 000c53 private 000c54 pedestal networks, inc 000c55 microlink communications inc. 000c56 megatel computer (1986) corp. @@ -3155,7 +3157,7 @@ exit 000c5f avtec, inc. 000c60 acm systems 000c61 ac tech corporation dba advanced digital - 000c62 abb ab, cewe-control + 000c62 abb ab, cewe-control 000c63 zenith electronics corporation 000c64 x2 msa group 000c65 sunin telecom @@ -3165,7 +3167,7 @@ exit 000c69 national radio astronomy observatory 000c6a mbari 000c6b kurz industrie-elektronik gmbh - 000c6c elgato systems llc + 000c6c eve systems gmbh 000c6d edwards ltd. 000c6e asustek computer inc. 000c6f amtek system co.,ltd. @@ -3186,12 +3188,12 @@ exit 000c7e tellium incorporated 000c7f synertronixx gmbh 000c80 opelcomm inc. - 000c81 schneider electric (australia) + 000c81 schneider electric (australia) 000c82 network technologies inc 000c83 logical solutions 000c84 eazix, inc. - 000c85 cisco systems, inc. - 000c86 cisco systems, inc. + 000c85 cisco systems, inc + 000c86 cisco systems, inc 000c87 amd 000c88 apache micro peripherals, inc. 000c89 ac electric vehicles, ltd. @@ -3228,14 +3230,14 @@ exit 000ca8 garuda networks corporation 000ca9 ebtron inc. 000caa cubic transportation systems inc - 000cab commend international + 000cab commend international gmbh 000cac citizen watch co., ltd. 000cad btu international 000cae ailocom oy 000caf tri term co.,ltd. 000cb0 star semiconductor corporation 000cb1 salland engineering (europe) bv - 000cb2 comstar co., ltd. + 000cb2 union co., ltd. 000cb3 round co.,ltd. 000cb4 autocell laboratories, inc. 000cb5 premier technolgies, inc @@ -3250,7 +3252,7 @@ exit 000cbe innominate security technologies ag 000cbf holy stone ent. co., ltd. 000cc0 genera oy - 000cc1 cooper industries inc. + 000cc1 eaton corporation 000cc2 controlnet (india) private limited 000cc3 bewan systems 000cc4 tiptel ag @@ -3263,8 +3265,8 @@ exit 000ccb design combus ltd 000ccc aeroscout ltd. 000ccd iec - tc57 - 000cce cisco systems, inc. - 000ccf cisco systems, inc. + 000cce cisco systems, inc + 000ccf cisco systems, inc 000cd0 symetrix 000cd1 sfom technology corp. 000cd2 schaffner emv ag @@ -3276,18 +3278,18 @@ exit 000cd8 m. k. juchheim gmbh & co 000cd9 itcare co., ltd 000cda freehand systems, inc. - 000cdb brocade communications systems, inc + 000cdb brocade communications systems llc 000cdc becs technology, inc 000cdd aos technologies ag 000cde abb stotz-kontakt gmbh - 000cdf pulnix america, inc + 000cdf jai manufacturing 000ce0 trek diagnostics inc. 000ce1 the open group 000ce2 rolls-royce 000ce3 option international n.v. 000ce4 neurocom international, inc. 000ce5 arris group, inc. - 000ce6 meru networks inc + 000ce6 fortinet inc. 000ce7 mediatek inc. 000ce8 guangzhou anjubao co., ltd 000ce9 bloomberg l.p. @@ -3312,10 +3314,10 @@ exit 000cfc s2io technologies corp 000cfd hyundai imagequest co.,ltd. 000cfe grand electronic co., ltd - 000cff mro-tek limited + 000cff mro-tek realty limited 000d00 seaway networks inc. 000d01 p&e microcomputer systems, inc. - 000d02 nec accesstechnica, ltd. + 000d02 nec platforms, ltd. 000d03 matrics, inc. 000d04 foxboro eckardt development gmbh 000d05 cybernet manufacturing inc. @@ -3323,8 +3325,8 @@ exit 000d07 calrec audio ltd 000d08 abovecable, inc. 000d09 yuehua(zhuhai) electronic co. ltd - 000d0a projectiondesign as - 000d0b buffalo inc. + 000d0a barco projection systems nv + 000d0b buffalo.inc 000d0c mdi security systems 000d0d itsupported, llc 000d0e inqnet systems, inc. @@ -3353,11 +3355,11 @@ exit 000d25 sanden corporation 000d26 primagraphics limited 000d27 microplex printware ag - 000d28 cisco systems, inc. - 000d29 cisco systems, inc. + 000d28 cisco systems, inc + 000d29 cisco systems, inc 000d2a scanmatic as 000d2b racal instruments - 000d2c patapsco designs ltd + 000d2c net2edge limited 000d2d nct deutschland gmbh 000d2e matsushita avionics systems corporation 000d2f ain comm.tech.co., ltd @@ -3388,7 +3390,7 @@ exit 000d48 aewin technologies co., ltd. 000d49 triton systems of delaware, inc. 000d4a steag eta-optik - 000d4b roku, llc + 000d4b roku, inc. 000d4c outline electronics ltd. 000d4d ninelanes 000d4e ndr co.,ltd. @@ -3399,9 +3401,9 @@ exit 000d53 beijing 5w communication corp. 000d54 3com ltd 000d55 sanycom technology co.,ltd - 000d56 dell inc + 000d56 dell inc. 000d57 fujitsu i-network systems limited. - 000d58 + 000d58 private 000d59 amity systems, inc. 000d5a tiesse spa 000d5b smart empire investments limited @@ -3414,8 +3416,8 @@ exit 000d62 funkwerk dabendorf gmbh 000d63 dent instruments, inc. 000d64 comag handels ag - 000d65 cisco systems, inc. - 000d66 cisco systems, inc. + 000d65 cisco systems, inc + 000d66 cisco systems, inc 000d67 ericsson 000d68 vinci systems, inc. 000d69 tmt&d corporation @@ -3427,7 +3429,7 @@ exit 000d6f ember corporation 000d70 datamax corporation 000d71 boca systems - 000d72 2wire, inc + 000d72 2wire inc 000d73 technical support, inc. 000d74 sand network systems, inc. 000d75 kobian pte ltd - taiwan branch @@ -3443,12 +3445,12 @@ exit 000d7f midas communication technologies pte ltd ( foreign branch) 000d80 online development inc 000d81 pepperl+fuchs gmbh - 000d82 phs srl + 000d82 phsnet 000d83 sanmina-sci hungary ltd. 000d84 makus inc. 000d85 tapwave, inc. 000d86 huber + suhner ag - 000d87 elitegroup computer system co. (ecs) + 000d87 elitegroup computer systems co.,ltd. 000d88 d-link corporation 000d89 bils technology inc 000d8a winners electronics co., ltd. @@ -3459,18 +3461,18 @@ exit 000d8f king tsushin kogyo co., ltd. 000d90 factum electronics ab 000d91 eclipse (hq espana) s.l. - 000d92 arima communication corporation - 000d93 apple + 000d92 arima communications corp. + 000d93 apple, inc. 000d94 afar communications,inc 000d95 opti-cell, inc. 000d96 vtera technology inc. - 000d97 tropos networks, inc. + 000d97 abb inc./tropos 000d98 s.w.a.c. schmitt-walter automation consult gmbh 000d99 orbital sciences corp.; launch systems group 000d9a infotec ltd 000d9b heraeus electro-nite international n.v. 000d9c elan gmbh & co kg - 000d9d hewlett-packard company + 000d9d hewlett packard 000d9e tokuden ohizumi seisakusyo co.,ltd. 000d9f rf micro devices 000da0 nedap n.v. @@ -3480,7 +3482,7 @@ exit 000da4 dosch & amand systems ag 000da5 fabric7 systems, inc 000da6 universal switching corporation - 000da7 + 000da7 private 000da8 teletronics technology corporation 000da9 t.e.a.m. s.l. 000daa s.a.tehnology co.,ltd. @@ -3493,24 +3495,24 @@ exit 000db1 japan network service co., ltd. 000db2 ammasso, inc. 000db3 sdo communication corperation - 000db4 netasq + 000db4 stormshield 000db5 globalsat technology corporation - 000db6 broadcom corporation + 000db6 broadcom 000db7 sanko electric co,.ltd 000db8 schiller ag 000db9 pc engines gmbh 000dba océ document technologies gmbh 000dbb nippon dentsu co.,ltd. - 000dbc cisco systems, inc. - 000dbd cisco systems, inc. + 000dbc cisco systems, inc + 000dbd cisco systems, inc 000dbe bel fuse europe ltd.,uk 000dbf tektone sound & signal mfg., inc. 000dc0 spagat as 000dc1 safeweb inc - 000dc2 + 000dc2 private 000dc3 first communication, inc. 000dc4 emcore corporation - 000dc5 echostar global b.v. + 000dc5 echostar global b.v. 000dc6 digirose technology co., ltd. 000dc7 cosmic engineering inc. 000dc8 airmagnet, inc @@ -3549,13 +3551,13 @@ exit 000de9 napatech aps 000dea kingtel telecommunication corp. 000deb compxs limited - 000dec cisco systems, inc. - 000ded cisco systems, inc. + 000dec cisco systems, inc + 000ded cisco systems, inc 000dee andrew rf power amplifier group 000def soc. coop. bilanciai 000df0 qcom technology inc. 000df1 ionix inc. - 000df2 + 000df2 private 000df3 asmax solutions 000df4 watertek co. 000df5 teletronics international inc. @@ -3576,8 +3578,8 @@ exit 000e04 cma/microdialysis ab 000e05 wireless matrix corp. 000e06 team simoco ltd - 000e07 sony ericsson mobile communications ab - 000e08 cisco linksys llc + 000e07 sony mobile communications inc + 000e08 cisco-linksys, llc 000e09 shenzhen coship software co.,ltd. 000e0a sakuma design office 000e0b netac technology co., ltd. @@ -3586,13 +3588,13 @@ exit 000e0e esa elettronica s.p.a. 000e0f ermme 000e10 c-guys, inc. - 000e11 bdt büro und datentechnik gmbh & co.kg + 000e11 bdt büro und datentechnik gmbh & co.kg 000e12 adaptive micro systems inc. 000e13 accu-sort systems inc. 000e14 visionary solutions, inc. 000e15 tadlys ltd 000e16 southwing s.l. - 000e17 + 000e17 private 000e18 mya technology 000e19 logicacmg pty ltd 000e1a jps communications @@ -3603,7 +3605,7 @@ exit 000e1f tcl networks equipment co., ltd. 000e20 access systems americas, inc. 000e21 mtu friedrichshafen gmbh - 000e22 + 000e22 private 000e23 incipient, inc. 000e24 huwell technology inc. 000e25 hannae technology co., ltd @@ -3611,22 +3613,22 @@ exit 000e27 crere networks, inc. 000e28 dynamic ratings p/l 000e29 shester communications inc - 000e2a + 000e2a private 000e2b safari technologies 000e2c netcodec co. 000e2d hyundai digital technology co.,ltd. - 000e2e edimax technology co., ltd. + 000e2e edimax technology co. ltd. 000e2f roche diagnostics gmbh 000e30 aeras networks, inc. 000e31 olympus soft imaging solutions gmbh 000e32 kontron medical 000e33 shuko electronics co.,ltd 000e34 nexgen city, lp - 000e35 intel corp + 000e35 intel corporation 000e36 heinesys, inc. 000e37 harms & wende gmbh & co.kg - 000e38 cisco systems, inc. - 000e39 cisco systems, inc. + 000e38 cisco systems, inc + 000e39 cisco systems, inc 000e3a cirrus logic 000e3b hawking technologies, inc. 000e3c transact technologies inc @@ -3658,7 +3660,7 @@ exit 000e56 4g systems gmbh & co. kg 000e57 iworld networking, inc. 000e58 sonos, inc. - 000e59 sagem sa + 000e59 sagemcom broadband sas 000e5a telefield inc. 000e5b parkervision - direct2data 000e5c arris group, inc. @@ -3671,7 +3673,7 @@ exit 000e63 lemke diagnostics gmbh 000e64 elphel, inc 000e65 transcore - 000e66 hitachi advanced digital, inc. + 000e66 hitachi industry & control solutions, ltd. 000e67 eltis microelectronics ltd. 000e68 e-top network technology inc. 000e69 china electric power research institute @@ -3696,12 +3698,12 @@ exit 000e7c televes s.a. 000e7d electronics line 3000 ltd. 000e7e ionsign oy - 000e7f hewlett-packard company + 000e7f hewlett packard 000e80 thomson technology inc 000e81 devicescape software, inc. 000e82 commtech wireless - 000e83 cisco systems, inc. - 000e84 cisco systems, inc. + 000e83 cisco systems, inc + 000e84 cisco systems, inc 000e85 catalyst enterprises, inc. 000e86 alcatel north america 000e87 adp gauselmann gmbh @@ -3709,10 +3711,10 @@ exit 000e89 clematic 000e8a avara technologies pty. ltd. 000e8b astarte technology co, ltd. - 000e8c siemens ag a&d et + 000e8c siemens ag 000e8d systems in progress holding gmbh 000e8e sparklan communications, inc. - 000e8f sercomm corp. + 000e8f sercomm corporation. 000e90 ponico corp. 000e91 navico auckland ltd 000e92 open telecom @@ -3725,7 +3727,7 @@ exit 000e99 spectrum digital, inc 000e9a boe technology group co.,ltd 000e9b ambit microsystems corporation - 000e9c benchmark electronics + 000e9c benchmark electronics 000e9d tiscali uk ltd 000e9e topfield co., ltd 000e9f temic sds gmbh @@ -3733,7 +3735,7 @@ exit 000ea1 formosa teletek corporation 000ea2 mcafee, inc 000ea3 cncr-it co.,ltd,hangzhou p.r.china - 000ea4 certance inc. + 000ea4 quantum corp. 000ea5 blip systems 000ea6 asustek computer inc. 000ea7 endace technology @@ -3748,7 +3750,7 @@ exit 000eb0 solutions radio bv 000eb1 newcotech,ltd 000eb2 micro-research finland oy - 000eb3 hewlett-packard + 000eb3 hewlett packard 000eb4 guangzhou gaoke communications technology co.ltd. 000eb5 ecastle electronics co., ltd. 000eb6 riverbed technology, inc. @@ -3783,9 +3785,9 @@ exit 000ed3 epicenter, inc. 000ed4 cresitt industrie 000ed5 copan systems inc. - 000ed6 cisco systems, inc. - 000ed7 cisco systems, inc. - 000ed8 aktino, inc. + 000ed6 cisco systems, inc + 000ed7 cisco systems, inc + 000ed8 positron access solutions corp 000ed9 aksys, ltd. 000eda c-tech united corp. 000edb xincom corp. @@ -3795,25 +3797,25 @@ exit 000edf plx technology 000ee0 mcharge 000ee1 extremespeed inc. - 000ee2 custom engineering s.p.a. + 000ee2 custom engineering 000ee3 chiyu technology co.,ltd 000ee4 boe technology group co.,ltd 000ee5 bitwallet, inc. 000ee6 adimos systems ltd 000ee7 aac electronics corp. - 000ee8 zioncom + 000ee8 zioncom electronics (shenzhen) ltd. 000ee9 waytech development, inc. 000eea shadong luneng jicheng electronics,co.,ltd 000eeb sandmartin(zhong shan)electronics co.,ltd 000eec orban 000eed nokia danmark a/s 000eee muco industrie bv - 000eef + 000eef private 000ef0 festo ag & co. kg 000ef1 ezquest inc. 000ef2 infinico corporation - 000ef3 smarthome - 000ef4 kasda digital technology co.,ltd + 000ef3 smartlabs, inc. + 000ef4 kasda networks inc 000ef5 ipac technology co., ltd. 000ef6 e-ten information systems co., ltd. 000ef7 vulcan portals inc @@ -3834,7 +3836,7 @@ exit 000f06 nortel networks 000f07 mangrove systems, inc. 000f08 indagon oy - 000f09 + 000f09 private 000f0a clear edge networks 000f0b kentima technologies ab 000f0c synchronic engineering @@ -3846,7 +3848,7 @@ exit 000f12 panasonic europe ltd. 000f13 nisca corporation 000f14 mindray co., ltd. - 000f15 kjaerulff1 a/s + 000f15 icotera a/s 000f16 jay how technology co., 000f17 insta elektro gmbh 000f18 industrial control systems @@ -3856,12 +3858,12 @@ exit 000f1c digitall world co., ltd 000f1d cosmo techs co., ltd. 000f1e chengdu kt electric co.of high & new technology - 000f1f dell inc - 000f20 hewlett-packard company + 000f1f dell inc. + 000f20 hewlett packard 000f21 scientific atlanta, inc 000f22 helius, inc. - 000f23 cisco systems, inc. - 000f24 cisco systems, inc. + 000f23 cisco systems, inc + 000f24 cisco systems, inc 000f25 aimvalley b.v. 000f26 worldaccxx llc 000f27 teal electronics, inc. @@ -3877,8 +3879,8 @@ exit 000f31 allied vision technologies canada inc 000f32 lootom telcovideo network wuxi co ltd 000f33 duali inc. - 000f34 cisco systems, inc. - 000f35 cisco systems, inc. + 000f34 cisco systems, inc + 000f35 cisco systems, inc 000f36 accurate techhnologies, inc. 000f37 xambala incorporated 000f38 netstar @@ -3904,17 +3906,17 @@ exit 000f4c elextech inc 000f4d talkswitch 000f4e cellink - 000f4f cadmus technology ltd + 000f4f pcs systemtechnik gmbh 000f50 streamscale limited 000f51 azul systems, inc. 000f52 york refrigeration, marine & controls - 000f53 solarflare communications inc + 000f53 solarflare communications inc. 000f54 entrelogic corporation 000f55 datawire communication networks inc. 000f56 continuum photonics inc 000f57 cablelogic co., ltd. 000f58 adder technology limited - 000f59 phonak communications ag + 000f59 phonak ag 000f5a peribit networks 000f5b delta information systems, inc. 000f5c day one digital media limited @@ -3922,12 +3924,12 @@ exit 000f5e veo 000f5f nicety technologies inc. (nts) 000f60 lifetron co.,ltd - 000f61 hewlett-packard company + 000f61 hewlett packard 000f62 alcatel bell space n.v. 000f63 obzerv technologies 000f64 d&r electronica weesp bv 000f65 icube corp. - 000f66 cisco-linksys + 000f66 cisco-linksys, llc 000f67 west instruments 000f68 vavic network technology, inc. 000f69 sew eurodrive gmbh & co. kg @@ -3959,7 +3961,7 @@ exit 000f83 brainium technologies inc. 000f84 astute networks, inc. 000f85 addo-japan corporation - 000f86 research in motion limited + 000f86 blackberry rts 000f87 maxcess international 000f88 ametek, inc. 000f89 winnertec system co., ltd. @@ -3968,14 +3970,14 @@ exit 000f8c gigawavetech pte ltd 000f8d fast tv-server ag 000f8e dongyang telecom co.,ltd. - 000f8f cisco systems, inc. - 000f90 cisco systems, inc. + 000f8f cisco systems, inc + 000f90 cisco systems, inc 000f91 aerotelecom co.,ltd. 000f92 microhard systems inc. 000f93 landis+gyr ltd. 000f94 genexis bv 000f95 elecom co.,ltd laneed division - 000f96 telco systems, inc. + 000f96 telco systems, inc. 000f97 avanex corporation 000f98 avamax co. ltd. 000f99 apac opto electronics inc. @@ -4001,14 +4003,14 @@ exit 000fad fmn communications gmbh 000fae e2o communications 000faf dialog inc. - 000fb0 compal electronics,inc. + 000fb0 compal electronics inc. 000fb1 cognio inc. 000fb2 broadband pacenet (india) pvt. ltd. 000fb3 actiontec electronics, inc 000fb4 timespace technology - 000fb5 netgear inc + 000fb5 netgear 000fb6 europlex technologies - 000fb7 cavium networks + 000fb7 cavium 000fb8 callurl inc. 000fb9 adaptive instruments 000fba tevebox ab @@ -4029,7 +4031,7 @@ exit 000fc9 allnet gmbh 000fca a-jin techline co, ltd 000fcb 3com ltd - 000fcc netopia, inc. + 000fcc arris group, inc. 000fcd nortel networks 000fce kikusui electronics corp. 000fcf datawind research @@ -4044,14 +4046,14 @@ exit 000fd8 force, inc. 000fd9 flexdsl telecommunications ag 000fda yazaki corporation - 000fdb westell technologies + 000fdb westell technologies inc. 000fdc ueda japan radio co., ltd. 000fdd sordin ab - 000fde sony ericsson mobile communications ab + 000fde sony mobile communications inc 000fdf solomon technology corp. 000fe0 ncomputing co.,ltd. 000fe1 id digital corporation - 000fe2 hangzhou h3c technologies co., ltd. + 000fe2 hangzhou h3c technologies co., limited 000fe3 damm cellular systems a/s 000fe4 pantech co.,ltd 000fe5 mercury security corporation @@ -4071,9 +4073,9 @@ exit 000ff3 jung myoung communications&technology 000ff4 guntermann & drunck gmbh 000ff5 gn&s company - 000ff6 darfon electronics corp. - 000ff7 cisco systems, inc. - 000ff8 cisco systems, inc. + 000ff6 darfon lighting corp + 000ff7 cisco systems, inc + 000ff8 cisco systems, inc 000ff9 valcretec, inc. 000ffa optinel systems, inc. 000ffb nippon denso industry co., ltd. @@ -4088,31 +4090,31 @@ exit 001004 the brantley coile company,inc 001005 uec commercial 001006 thales contact solutions ltd. - 001007 cisco systems, inc. + 001007 cisco systems, inc 001008 vienna systems corporation - 001009 horo quartz + 001009 horanet 00100a williams communications group - 00100b cisco systems, inc. + 00100b cisco systems, inc 00100c ito co., ltd. - 00100d cisco systems, inc. + 00100d cisco systems, inc 00100e micro linear coporation 00100f industrial cpu systems 001010 initio corporation - 001011 cisco systems, inc. + 001011 cisco systems, inc 001012 processor systems (i) pvt ltd 001013 kontron america, inc. - 001014 cisco systems, inc. + 001014 cisco systems, inc 001015 oomon inc. 001016 t.sqware 001017 bosch access systems gmbh - 001018 broadcom corporation + 001018 broadcom 001019 sirona dental systems gmbh & co. kg 00101a picturetel corp. 00101b cornet technology, inc. 00101c ohm technologies intl, llc 00101d winbond electronics corp. 00101e matsushita electronic instruments corp. - 00101f cisco systems, inc. + 00101f cisco systems, inc 001020 hand held products inc 001021 encanto networks, inc. 001022 satcom media corporation @@ -4122,22 +4124,22 @@ exit 001026 accelerated networks, inc. 001027 l-3 communications east 001028 computer technica, inc. - 001029 cisco systems, inc. + 001029 cisco systems, inc 00102a zf microsystems, inc. 00102b umax data systems, inc. 00102c lasat networks a/s 00102d hitachi software engineering 00102e network systems & technologies pvt. ltd. - 00102f cisco systems, inc. + 00102f cisco systems, inc 001030 eion inc. 001031 objective communications, inc. 001032 alta technology 001033 accesslan communications, inc. 001034 gnp computers - 001035 elitegroup computer systems co., ltd + 001035 elitegroup computer systems co.,ltd. 001036 inter-tel integrated systems 001037 cyq've technology co., ltd. - 001038 micro research institute, inc. + 001038 micro research ltd. 001039 vectron systems ag 00103a diamond network tech 00103b hippi networking forum @@ -4156,26 +4158,26 @@ exit 001048 htrc automation, inc. 001049 shoretel, inc 00104a the parvus corporation - 00104b 3com corporation + 00104b 3com 00104c teledyne lecroy, inc 00104d surtec industries, inc. 00104e ceologic - 00104f oracle corporation + 00104f oracle corporation 001050 rion co., ltd. 001051 cmicro corporation 001052 mettler-toledo (albstadt) gmbh 001053 computer technology corp. - 001054 cisco systems, inc. + 001054 cisco systems, inc 001055 fujitsu microelectronics, inc. 001056 sodick co., ltd. 001057 rebel.com, inc. 001058 arrowpoint communications 001059 diablo research co. llc - 00105a 3com corporation + 00105a 3com 00105b net insight ab 00105c quantum designs (h.k.) ltd. 00105d draeger medical - 00105e hekimian laboratories, inc. + 00105e spirent plc, service assurance broadband 00105f zodiac data systems 001060 billionton systems, inc. 001061 hostlink corp. @@ -4202,9 +4204,9 @@ exit 001076 eurem gmbh 001077 saf drive systems, ltd. 001078 nuera communications, inc. - 001079 cisco systems, inc. + 001079 cisco systems, inc 00107a ambicom, inc. - 00107b cisco systems, inc. + 00107b cisco systems, inc 00107c p-com, inc. 00107d aurora communications, ltd. 00107e bachmann electronic gmbh @@ -4212,7 +4214,7 @@ exit 001080 metawave communications 001081 dps, inc. 001082 jna telecommunications limited - 001083 hewlett-packard company + 001083 hewlett packard 001084 k-bot communications 001085 polaris communications, inc. 001086 atto technology, inc. @@ -4221,7 +4223,7 @@ exit 001089 websonic 00108a teralogic, inc. 00108b laseranimation sollinger gmbh - 00108c fujitsu telecommunications europe, ltd. + 00108c fujitsu services ltd 00108d johnson controls, inc. 00108e hugh symons concept technologies ltd. 00108f raptor systems @@ -4247,7 +4249,7 @@ exit 0010a3 omnitronix, inc. 0010a4 xircom 0010a5 oxford instruments - 0010a6 cisco systems, inc. + 0010a6 cisco systems, inc 0010a7 unex technology corporation 0010a8 reliance computer corp. 0010a9 adhoc technologies @@ -4262,7 +4264,7 @@ exit 0010b2 coactive aesthetics 0010b3 nokia multimedia terminals 0010b4 atmosphere networks - 0010b5 accton technology corporation + 0010b5 accton technology corp 0010b6 entrata communications corp. 0010b7 coyote technologies, llc 0010b8 ishigaki computer system co. @@ -4274,16 +4276,16 @@ exit 0010be march networks corporation 0010bf interair wireless 0010c0 arma, inc. - 0010c1 oi electric co., ltd. + 0010c1 oi electric co.,ltd 0010c2 willnet, inc. 0010c3 csi-control systems - 0010c4 media links co., ltd. + 0010c4 media global links co., ltd. 0010c5 protocol technologies, inc. 0010c6 universal global scientific industrial co., ltd. 0010c7 data transmission network 0010c8 communications electronics security group 0010c9 mitsubishi electronics logistic support co. - 0010ca telco systems, inc. + 0010ca telco systems, inc. 0010cb facit k.k. 0010cc clp computer logistik planung gmbh 0010cd interface concept @@ -4295,24 +4297,24 @@ exit 0010d3 grips electronic gmbh 0010d4 storage computer corporation 0010d5 imasde canarias, s.a. - 0010d6 itt - a/cd + 0010d6 exelis 0010d7 argosy research inc. 0010d8 calista 0010d9 ibm japan, fujisawa mt+d 0010da kollmorgen corp - 0010db juniper networks, inc. + 0010db juniper networks 0010dc micro-star international co., ltd. 0010dd enable semiconductor, inc. 0010de international datacasting corporation 0010df rise computer inc. - 0010e0 oracle corporation + 0010e0 oracle corporation 0010e1 s.i. tech, inc. 0010e2 arraycomm, inc. - 0010e3 hewlett-packard company + 0010e3 hewlett packard 0010e4 nsi corporation 0010e5 solectron texas 0010e6 applied intelligent systems, inc. - 0010e7 breezecom + 0010e7 breezecom, ltd. 0010e8 telocity, incorporated 0010e9 raidtec ltd. 0010ea adept technology @@ -4327,16 +4329,16 @@ exit 0010f3 nexcom international co., ltd. 0010f4 vertical communications 0010f5 amherst systems, inc. - 0010f6 cisco systems, inc. + 0010f6 cisco systems, inc 0010f7 iriichi technologies inc. 0010f8 texio technology corporation 0010f9 unique systems, inc. - 0010fa apple + 0010fa apple, inc. 0010fb zida technologies limited 0010fc broadband networks, inc. 0010fd cocom a/s 0010fe digital equipment corporation - 0010ff cisco systems, inc. + 0010ff cisco systems, inc 001100 schneider electric 001101 cet technologies pte ltd 001102 aurora multimedia corp. @@ -4347,7 +4349,7 @@ exit 001107 rgb networks inc. 001108 orbital data corporation 001109 micro-star international - 00110a hewlett-packard company + 00110a hewlett packard 00110b franklin technology systems 00110c atmark techno, inc. 00110d sanblaze technology, inc. @@ -4364,16 +4366,16 @@ exit 001118 blx ic design corp., ltd. 001119 solteras, inc. 00111a arris group, inc. - 00111b targa systems div l-3 communications canada + 00111b targa systems div l-3 communications 00111c pleora technologies inc. 00111d hectrix limited - 00111e epsg (ethernet powerlink standardization group) + 00111e ethernet powerlink standarization group (epsg) 00111f doremi labs, inc. - 001120 cisco systems, inc. - 001121 cisco systems, inc. + 001120 cisco systems, inc + 001121 cisco systems, inc 001122 cimsys inc 001123 appointech, inc. - 001124 apple + 001124 apple, inc. 001125 ibm corp 001126 venstar inc. 001127 tasi, inc @@ -4388,7 +4390,7 @@ exit 001130 allied telesis (hong kong) ltd. 001131 unatech. co.,ltd 001132 synology incorporated - 001133 siemens austria simea + 001133 siemens ag austria 001134 mediacell, inc. 001135 grandeye ltd 001136 goodrich sensor systems @@ -4404,7 +4406,7 @@ exit 001140 nanometrics inc. 001141 goodman corporation 001142 e-smartcom inc. - 001143 dell inc + 001143 dell inc. 001144 assurance technology corp 001145 valuepoint networks 001146 telecard-pribor ltd @@ -4424,13 +4426,13 @@ exit 001154 webpro technologies inc. 001155 sevis systems 001156 pharos systems nz - 001157 of networks co., ltd. + 001157 oki electric industry co., ltd. 001158 nortel networks 001159 matisse networks inc 00115a ivoclar vivadent ag - 00115b elitegroup computer system co. (ecs) - 00115c cisco systems, inc. - 00115d cisco systems, inc. + 00115b elitegroup computer systems co.,ltd. + 00115c cisco systems, inc + 00115d cisco systems, inc 00115e prominent dosiertechnik gmbh 00115f itx security co., ltd. 001160 artdio company co., ltd @@ -4438,7 +4440,7 @@ exit 001162 star micronics co.,ltd. 001163 system spa dept. electronics 001164 acard technology corp. - 001165 znyx networks + 001165 znyx networks, inc. 001166 taelim electronics co., ltd. 001167 integrated system solution corp. 001168 homelogic llc @@ -4447,14 +4449,14 @@ exit 00116b digital data communications asia co.,ltd 00116c nanwang multimedia inc.,ltd 00116d american time and signal - 00116e peplink ltd. + 00116e peplink international ltd. 00116f netforyou co., ltd. 001170 gsc srl 001171 dexter communications, inc. 001172 cotron corporation 001173 smart storage systems - 001174 wibhu technologies, inc. - 001175 pathscale, inc. + 001174 mojo networks, inc. + 001175 intel corporation 001176 intellambda systems, inc. 001177 coaxial networks, inc. 001178 chiron technology ltd @@ -4463,28 +4465,28 @@ exit 00117b büchi labortechnik ag 00117c e-zy.net 00117d zmd america, inc. - 00117e progeny, a division of midmark corp + 00117e midmark corp 00117f neotune information technology corporation,.ltd 001180 arris group, inc. 001181 interenergy co.ltd, 001182 imi norgren ltd 001183 datalogic adc, inc. 001184 humo laboratory,ltd. - 001185 hewlett-packard company + 001185 hewlett packard 001186 prime systems, inc. 001187 category solutions, inc 001188 enterasys 001189 aerotech inc 00118a viewtran technology limited - 00118b alcatel-lucent, enterprise business group + 00118b alcatel-lucent enterprise 00118c missouri department of transportation 00118d hanchang system corp. 00118e halytech mace 00118f eutech instruments pte. ltd. 001190 digital design corporation 001191 cts-clima temperatur systeme gmbh - 001192 cisco systems, inc. - 001193 cisco systems, inc. + 001192 cisco systems, inc + 001193 cisco systems, inc 001194 chi mei communication systems, inc. 001195 d-link corporation 001196 actuality systems, inc. @@ -4517,15 +4519,15 @@ exit 0011b1 blueexpert technology corp. 0011b2 2001 technology inc. 0011b3 yoshimiya co.,ltd. - 0011b4 westermo teleindustri ab + 0011b4 westermo network technologies ab 0011b5 shenzhen powercom co.,ltd 0011b6 open systems international 0011b7 octalix b.v. 0011b8 liebherr - elektronik gmbh 0011b9 inner range pty. ltd. 0011ba elexol pty ltd - 0011bb cisco systems, inc. - 0011bc cisco systems, inc. + 0011bb cisco systems, inc + 0011bc cisco systems, inc 0011bd bombardier transportation 0011be agp telecom co. ltd 0011bf aesys s.p.a. @@ -4582,19 +4584,19 @@ exit 0011f2 institute of network technologies 0011f3 neomedia europe ag 0011f4 woori-net - 0011f5 askey computer corp. + 0011f5 askey computer corp 0011f6 asia pacific microsystems , inc. 0011f7 shenzhen forward industry co., ltd 0011f8 airaya corp 0011f9 nortel networks 0011fa rane corporation 0011fb heidelberg engineering gmbh - 0011fc harting electric gmbh & co.kg + 0011fc harting electronics gmbh 0011fd korg inc. 0011fe keiyo system research, inc. 0011ff digitro tecnologia ltda - 001200 cisco systems, inc. - 001201 cisco systems, inc. + 001200 cisco systems, inc + 001201 cisco systems, inc 001202 decrane aerospace - audio international inc. 001203 activnetworks 001204 u10 networks, inc. @@ -4618,12 +4620,12 @@ exit 001216 icp internet communication payment ag 001217 cisco-linksys, llc 001218 aruze corporation - 001219 ahead communication systems inc + 001219 general datacomm llc 00121a techno soft systemnics inc. 00121b sound devices, llc - 00121c parrot s.a. + 00121c parrot sa 00121d netfabric corporation - 00121e juniper networks, inc. + 00121e juniper networks 00121f harding instruments 001220 cadco systems 001221 b.braun melsungen ag @@ -4654,25 +4656,25 @@ exit 00123a posystech inc., co. 00123b kero systems aps 00123c second rule llc - 00123d ges + 00123d ges co, ltd 00123e erune technology co., ltd. - 00123f dell inc + 00123f dell inc. 001240 amoi electronics co.,ltd 001241 a2i marketing center 001242 millennial net - 001243 cisco systems, inc. - 001244 cisco systems, inc. + 001243 cisco systems, inc + 001244 cisco systems, inc 001245 zellweger analytics, inc. 001246 t.o.m technology inc.. - 001247 samsung electronics co., ltd. - 001248 emc corporation (kashya) + 001247 samsung electronics co.,ltd + 001248 dell emc 001249 delta elettronica s.p.a. 00124a dedicated devices, inc. 00124b texas instruments 00124c bbwm corporation 00124d inducon bv 00124e xac automation corp. - 00124f pentair thermal management + 00124f nvent 001250 tokyo aircaft instrument co., ltd. 001251 silink 001252 citronix, llc @@ -4681,7 +4683,7 @@ exit 001255 neteffect incorporated 001256 lg information & comm. 001257 leapcomm communication technologies inc. - 001258 activis polska + 001258 techvoip sp z o.o. 001259 thermo electron karlsruhe 00125a microsoft corporation 00125b kaimei electroni @@ -4701,7 +4703,7 @@ exit 001269 value electronics 00126a optoelectronics co., ltd. 00126b ascalade communications limited - 00126c visonic ltd. + 00126c visonic technologies 1993 ltd. 00126d university of california, berkeley 00126e seidel elektronik gmbh nfg.kg 00126f rayson technology co., ltd. @@ -4714,14 +4716,14 @@ exit 001276 cg power systems ireland limited 001277 korenix technologies co., ltd. 001278 international bar code - 001279 hewlett-packard company + 001279 hewlett packard 00127a sanyu industry co.,ltd. 00127b via networking technologies, inc. 00127c swegon ab 00127d mobilearia 00127e digital lifestyles group, inc. - 00127f cisco systems, inc. - 001280 cisco systems, inc. + 00127f cisco systems, inc + 001280 cisco systems, inc 001281 march networks s.p.a. 001282 qovia 001283 nortel networks @@ -4729,7 +4731,7 @@ exit 001285 gizmondo europe ltd 001286 endevco corp 001287 digital everywhere unterhaltungselektronik gmbh - 001288 2wire, inc + 001288 2wire inc 001289 advance sterilization products 00128a arris group, inc. 00128b sensory networks inc @@ -4740,7 +4742,7 @@ exit 001290 kyowa electric & machinery corp. 001291 kws computersysteme gmbh 001292 griffin technology - 001293 ge energy + 001293 abb power protection (ch) 001294 sumitomo electric device innovations, inc 001295 aiware inc. 001296 addlogix @@ -4758,7 +4760,7 @@ exit 0012a2 vita 0012a3 trust international b.v. 0012a4 thingmagic, llc - 0012a5 stargen, inc. + 0012a5 dolphin interconnect solutions as 0012a6 dolby australia 0012a7 isr technologies inc 0012a8 intec gmbh @@ -4766,7 +4768,7 @@ exit 0012aa iee, inc. 0012ab wilife, inc. 0012ac ontimetek inc. - 0012ad ids gmbh + 0012ad vivavis ag 0012ae hls hard-line solutions inc. 0012af elpro technologies 0012b0 efore oyj (plc) @@ -4800,9 +4802,9 @@ exit 0012cc bitatek co., ltd 0012cd asem spa 0012ce advanced cybernetics group - 0012cf accton technology corporation + 0012cf accton technology corp 0012d0 gossen-metrawatt-gmbh - 0012d1 texas instruments inc + 0012d1 texas instruments 0012d2 texas instruments 0012d3 zetta systems, inc. 0012d4 princeton technology, ltd @@ -4810,8 +4812,8 @@ exit 0012d6 jiangsu yitong high-tech co.,ltd 0012d7 invento networks, inc. 0012d8 international games system co., ltd. - 0012d9 cisco systems, inc. - 0012da cisco systems, inc. + 0012d9 cisco systems, inc + 0012da cisco systems, inc 0012db ziehl industrie-elektronik gmbh + co kg 0012dc suncorp industrial limited 0012dd shengqu information technology (shanghai) co., ltd. @@ -4820,7 +4822,7 @@ exit 0012e0 codan limited 0012e1 alliant networks, inc 0012e2 alaxala networks corporation - 0012e3 agat-rt, ltd. + 0012e3 agat soft llc 0012e4 ziehl industrie-electronik gmbh + co kg 0012e5 time america, inc. 0012e6 spectec computer co., ltd. @@ -4831,11 +4833,11 @@ exit 0012eb pdh solutions, llc 0012ec movacolor b.v. 0012ed avg advanced technologies - 0012ee sony ericsson mobile communications ab + 0012ee sony mobile communications inc 0012ef oneaccess sa 0012f0 intel corporate 0012f1 ifotec - 0012f2 brocade communications systems, inc + 0012f2 brocade communications systems llc 0012f3 connectblue ab 0012f4 belco international co.,ltd. 0012f5 imarda new zealand limited @@ -4844,7 +4846,7 @@ exit 0012f8 wni resources, llc 0012f9 uryu seisaku, ltd. 0012fa thx ltd - 0012fb samsung electronics + 0012fb samsung electronics co.,ltd 0012fc planet system co.,ltd 0012fd optimus ic s.a. 0012fe lenovo mobile communication technology ltd. @@ -4859,30 +4861,30 @@ exit 001307 paravirtual corporation 001308 nuvera fuel cells 001309 ocean broadband networks - 00130a nortel + 00130a nortel networks 00130b mextal b.v. 00130c hf system corporation 00130d galileo avionica 00130e focusrite audio engineering limited 00130f egemen bilgisayar muh san ve tic ltd sti 001310 cisco-linksys, llc - 001311 arris international + 001311 arris group, inc. 001312 amedia networks inc. 001313 guangzhou post & telecom equipment ltd 001314 asiamajor inc. - 001315 sony computer entertainment inc, + 001315 sony interactive entertainment inc. 001316 l-s-b broadcast technologies gmbh - 001317 gn netcom as + 001317 gn netcom a/s 001318 dgstation co., ltd. - 001319 cisco systems, inc. - 00131a cisco systems, inc. + 001319 cisco systems, inc + 00131a cisco systems, inc 00131b becell innovations corp. 00131c litetouch, inc. 00131d scanvaegt international a/s - 00131e peiker acustic gmbh & co. kg + 00131e peiker acustic gmbh 00131f nxtphase t&d, corp. 001320 intel corporate - 001321 hewlett-packard company + 001321 hewlett packard 001322 daq electronics, inc. 001323 cap co., ltd. 001324 schneider electric ultra terminal @@ -4920,7 +4922,7 @@ exit 001344 fargo electronics inc. 001345 eaton corporation 001346 d-link corporation - 001347 bluetree wireless data inc. + 001347 red lion controls, lp 001348 artila electronics co., ltd. 001349 zyxel communications corporation 00134a engim, inc. @@ -4928,7 +4930,7 @@ exit 00134c ydt technology international 00134d inepro bv 00134e valox systems, inc. - 00134f tranzeo wireless technologies inc. + 00134f rapidus wireless networks inc. 001350 silver spring networks, inc 001351 niles audio corporation 001352 naztec, inc. @@ -4944,13 +4946,13 @@ exit 00135c onsite systems, inc. 00135d nttpc communications, inc. 00135e eab/rwi/k - 00135f cisco systems, inc. - 001360 cisco systems, inc. + 00135f cisco systems, inc + 001360 cisco systems, inc 001361 biospace co., ltd. 001362 shinheung precision co., ltd. 001363 verascape, inc. 001364 paradigm technology inc.. - 001365 nortel + 001365 nortel networks 001366 neturity technologies inc. 001367 narayon. co., ltd. 001368 saab danmark a/s @@ -4963,12 +4965,12 @@ exit 00136f packetmotion, inc. 001370 nokia danmark a/s 001371 arris group, inc. - 001372 dell inc + 001372 dell inc. 001373 blwave electronics co., ltd 001374 atheros communications, inc. 001375 american security products co. 001376 tabor electronics ltd. - 001377 samsung electronics co., ltd + 001377 samsung electronics co.,ltd 001378 qsan technology, inc. 001379 ponder information industries ltd. 00137a netvox technology co., ltd. @@ -4976,23 +4978,23 @@ exit 00137c kaicom co., ltd. 00137d dynalab, inc. 00137e coredge networks, inc. - 00137f cisco systems, inc. - 001380 cisco systems, inc. + 00137f cisco systems, inc + 001380 cisco systems, inc 001381 chips & systems, inc. 001382 cetacea networks corporation 001383 application technologies and engineering research laboratory 001384 advanced motion controls 001385 add-on technology co., ltd. - 001386 abb inc./totalflow + 001386 abb inc/totalflow 001387 27m technologies ab 001388 wimedia alliance 001389 redes de telefonía móvil s.a. - 00138a qingdao goertek electronics co.,ltd. + 00138a qingdao goertek technology co., ltd. 00138b phantom technologies llc 00138c kumyoung.co.ltd 00138d kinghold 00138e foab elektronik ab - 00138f asiarock incorporation + 00138f asiarock technology limited 001390 termtek computer co., ltd 001391 ouen co.,ltd. 001392 ruckus wireless @@ -5000,19 +5002,19 @@ exit 001394 infohand co.,ltd 001395 congatec ag 001396 acbel polytech inc. - 001397 oracle corporation + 001397 oracle corporation 001398 trafficsim co.,ltd 001399 stac corporation. 00139a k-ubique id corp. 00139b ioimage ltd. 00139c exavera technologies, inc. - 00139d marvell hispana s.l. + 00139d maxlinear hispania s.l.u. 00139e ciara technologies inc. 00139f electronics design services, co., ltd. 0013a0 algosystem co., ltd. 0013a1 crow electronic engeneering 0013a2 maxstream, inc - 0013a3 siemens com cpe devices + 0013a3 siemens home & office comm. devices 0013a4 keyeye communications 0013a5 general solutions, ltd. 0013a6 extricom ltd @@ -5044,8 +5046,8 @@ exit 0013c0 trix tecnologia ltda. 0013c1 asoka usa corporation 0013c2 wacom co.,ltd - 0013c3 cisco systems, inc. - 0013c4 cisco systems, inc. + 0013c3 cisco systems, inc + 0013c4 cisco systems, inc 0013c5 lightron fiber-optic devices inc. 0013c6 opengear, inc 0013c7 ionos co.,ltd. @@ -5085,7 +5087,7 @@ exit 0013e9 veriwave, inc. 0013ea kamstrup a/s 0013eb sysmaster corporation - 0013ec sunbay software ag + 0013ec netsnapper technologies sarl 0013ed psia 0013ee jbx designs inc. 0013ef kingjon digital technology co.,ltd @@ -5118,8 +5120,8 @@ exit 00140a wepio co., ltd. 00140b first international computer, inc. 00140c gkb cctv co., ltd. - 00140d nortel - 00140e nortel + 00140d nortel networks + 00140e nortel networks 00140f federal state unitary enterprise leningrad r&d institute of 001410 suzhou keda technology co.,ltd 001411 deutschmann automation gmbh & co. kg @@ -5132,27 +5134,27 @@ exit 001418 c4line 001419 sidsa 00141a deicy corporation - 00141b cisco systems, inc. - 00141c cisco systems, inc. - 00141d lti drives gmbh + 00141b cisco systems, inc + 00141c cisco systems, inc + 00141d keba industrial automation germany gmbh 00141e p.a. semi, inc. 00141f sunkwang electronics co., ltd 001420 g-links networking company 001421 total wireless technologies pte. ltd. - 001422 dell inc + 001422 dell inc. 001423 j-s co. neurocom 001424 merry electrics co., ltd. 001425 galactic computing corp. 001426 nl technology 001427 jazzmutant - 001428 vocollect, inc + 001428 vocollect inc 001429 v center technologies co., ltd. - 00142a elitegroup computer system co., ltd + 00142a elitegroup computer systems co.,ltd. 00142b edata communication inc. 00142c koncept international, inc. 00142d toradex ag 00142e 77 elektronika kft. - 00142f wildpackets + 00142f savvius 001430 vipower, inc 001431 pdl electronics ltd 001432 tarallax wireless, inc. @@ -5161,8 +5163,8 @@ exit 001435 citycom corp. 001436 qwerty elektronik ab 001437 gsteletech co.,ltd. - 001438 hewlett-packard company - 001439 blonder tongue laboratories, inc. + 001438 hewlett packard enterprise + 001439 blonder tongue laboratories, inc 00143a raytalk international srl 00143b sensovation ag 00143c rheinmetall canada inc. @@ -5184,9 +5186,9 @@ exit 00144c general meters corp. 00144d intelligent systems 00144e srisa - 00144f oracle corporation + 00144f oracle corporation 001450 heim systems gmbh - 001451 apple + 001451 apple, inc. 001452 calculex,inc. 001453 advantech technologies co.,ltd 001454 symwave @@ -5195,7 +5197,7 @@ exit 001457 t-vips as 001458 hs automatic aps 001459 moram co., ltd. - 00145a neratec solutions ag + 00145a westermo neratec ag 00145b seekernet inc. 00145c intronics b.v. 00145d wj communications, inc. @@ -5210,22 +5212,22 @@ exit 001466 kleinhenz elektronik gmbh 001467 arrowspan inc. 001468 celplan international, inc. - 001469 cisco systems, inc. - 00146a cisco systems, inc. + 001469 cisco systems, inc + 00146a cisco systems, inc 00146b anagran, inc. - 00146c netgear inc. + 00146c netgear 00146d rf technologies 00146e h. stoll gmbh & co. kg 00146f kohler co 001470 prokom software sa 001471 eastern asia technology limited - 001472 china broadband wireless ip standard group + 001472 china broadband wireless ip standard group(chinabwips) 001473 bookham inc 001474 k40 electronics 001475 wiline networks, inc. 001476 multicom industries limited - 001477 nertec inc. - 001478 shenzhen tp-link technologies co., ltd. + 001477 trilliant + 001478 tp-link technologies co.,ltd. 001479 nec magnus communications,ltd. 00147a eubus gmbh 00147b iteris, inc. @@ -5245,7 +5247,7 @@ exit 001489 b15402100 - jandei, s.l. 00148a elin ebg traction gmbh 00148b globo electronic gmbh & co. kg - 00148c fortress technologies + 00148c general dynamics mission systems 00148d cubic defense simulation systems 00148e tele power inc. 00148f protronic (far east) ltd. @@ -5254,7 +5256,7 @@ exit 001492 liteon, mobile media solution sbu 001493 systimax solutions 001494 esu ag - 001495 2wire, inc. + 001495 2wire inc 001496 phonic corp. 001497 zhiyuan eletronics co.,ltd. 001498 viking design technology @@ -5269,12 +5271,12 @@ exit 0014a1 synchronous communication corp 0014a2 core micro systems inc. 0014a3 vitelec bv - 0014a4 hon hai precision ind. co., ltd. + 0014a4 hon hai precision ind. co.,ltd. 0014a5 gemtek technology co., ltd. 0014a6 teranetics, inc. 0014a7 nokia danmark a/s - 0014a8 cisco systems, inc. - 0014a9 cisco systems, inc. + 0014a8 cisco systems, inc + 0014a9 cisco systems, inc 0014aa ashly audio, inc. 0014ab senhai electronic technology co., ltd. 0014ac bountiful wifi @@ -5282,7 +5284,7 @@ exit 0014ae wizlogics co., ltd. 0014af datasym pos inc. 0014b0 naeil community - 0014b1 avitec ab + 0014b1 axell wireless limited 0014b2 mcubelogics corporation 0014b3 corestar international corp 0014b4 general dynamics united kingdom ltd @@ -5296,17 +5298,17 @@ exit 0014bc synectic telecom exports pvt. ltd. 0014bd incnetworks, inc 0014be wink communication technology co.ltd - 0014bf cisco-linksys llc + 0014bf cisco-linksys, llc 0014c0 symstream technology group ltd 0014c1 u.s. robotics corporation - 0014c2 hewlett-packard company + 0014c2 hewlett packard 0014c3 seagate technology 0014c4 vitelcom mobile technology 0014c5 alive technologies pty ltd 0014c6 quixant ltd - 0014c7 nortel + 0014c7 nortel networks 0014c8 contemporary research corp - 0014c9 brocade communications systems, inc. + 0014c9 brocade communications systems llc 0014ca key radio systems limited 0014cb lifesync corporation 0014cc zetec, inc. @@ -5314,7 +5316,7 @@ exit 0014ce nf corporation 0014cf invisio communications 0014d0 bti systems inc. - 0014d1 trendnet + 0014d1 trendnet, inc. 0014d2 kyuden technosystems corporation 0014d3 sepsa 0014d4 k technology corporation @@ -5346,12 +5348,12 @@ exit 0014ee western digital technologies, inc. 0014ef tzero technologies, inc. 0014f0 business security ol ab - 0014f1 cisco systems, inc. - 0014f2 cisco systems, inc. + 0014f1 cisco systems, inc + 0014f2 cisco systems, inc 0014f3 vixs systems inc 0014f4 dektec digital video b.v. 0014f5 osi security devices - 0014f6 juniper networks, inc. + 0014f6 juniper networks 0014f7 crevis co., ltd 0014f8 scientific atlanta 0014f9 vantage controls @@ -5391,7 +5393,7 @@ exit 00151b isilon systems inc. 00151c leneco 00151d m2i corporation - 00151e ethernet powerlink standardization group (epsg) + 00151e ethernet powerlink standarization group (epsg) 00151f multivision intelligent surveillance (hong kong) ltd 001520 radiocrafts as 001521 horoquartz @@ -5403,13 +5405,13 @@ exit 001527 balboa instruments 001528 beacon medical products llc d.b.a. beaconmedaes 001529 n3 corporation - 00152a nokia gmbh - 00152b cisco systems, inc. - 00152c cisco systems, inc. + 00152a nokia corporation + 00152b cisco systems, inc + 00152c cisco systems, inc 00152d tenx networks, llc 00152e packethop, inc. 00152f arris group, inc. - 001530 emc corporation + 001530 dell emc 001531 kocom 001532 consumer technologies group, llc 001533 nadam.co.,ltd @@ -5425,7 +5427,7 @@ exit 00153d elim product co. 00153e q-matic sweden ab 00153f alcatel alenia space italia - 001540 nortel + 001540 nortel networks 001541 stratalight communications, inc. 001542 microhard s.r.l. 001543 aberdeen test center @@ -5447,7 +5449,7 @@ exit 001553 cytyc corporation 001554 atalum wireless s.a. 001555 dfm gmbh - 001556 sagem communication + 001556 sagemcom broadband sas 001557 olivetti 001558 foxconn 001559 securaplane technologies, inc. @@ -5457,10 +5459,10 @@ exit 00155d microsoft corporation 00155e morgan stanley 00155f greenpeak technologies - 001560 hewlett-packard company + 001560 hewlett packard 001561 jjplus corporation - 001562 cisco systems, inc. - 001563 cisco systems, inc. + 001562 cisco systems, inc + 001563 cisco systems, inc 001564 behringer spezielle studiotechnik gmbh 001565 xiamen yealink network technology co.,ltd 001566 a-first technology co., ltd. @@ -5473,20 +5475,20 @@ exit 00156d ubiquiti networks inc. 00156e a. w. communication systems ltd 00156f xiranet communications gmbh - 001570 symbol technologieswholly owned subsidiary of motorola + 001570 zebra technologies inc 001571 nolan systems 001572 red-lemon 001573 newsoft technology corporation 001574 horizon semiconductors ltd. 001575 nevis networks inc. 001576 labitec - labor biomedical technologies gmbh - 001577 allied telesis + 001577 allied telesis, inc. 001578 audio / video innovations 001579 lunatone industrielle elektronik gmbh 00157a telefin s.p.a. 00157b leuze electronic gmbh + co. kg 00157c dave networks, inc. - 00157d posdata co., ltd. + 00157d posdata 00157e weidmüller interface gmbh & co. kg 00157f chuang international holding co.,ltd. 001580 u-way corporation @@ -5511,21 +5513,21 @@ exit 001593 u4ea technologies inc. 001594 bixolon co.,ltd 001595 quester tangent corporation - 001596 arris international + 001596 arris group, inc. 001597 aeta audio systems 001598 kolektor group - 001599 samsung electronics co., ltd + 001599 samsung electronics co.,ltd 00159a arris group, inc. - 00159b nortel + 00159b nortel networks 00159c b-kyung system co.,ltd. - 00159d minicom advanced systems ltd + 00159d tripp lite 00159e mad catz interactive inc 00159f terascala, inc. 0015a0 nokia danmark a/s 0015a1 eca-sinters - 0015a2 arris international - 0015a3 arris international - 0015a4 arris international + 0015a2 arris group, inc. + 0015a3 arris group, inc. + 0015a4 arris group, inc. 0015a5 dci co., ltd. 0015a6 digital electronics products ltd. 0015a7 robatech ag @@ -5536,7 +5538,7 @@ exit 0015ac capelon ab 0015ad accedian networks 0015ae kyung il - 0015af azurewave technologies, inc. + 0015af azurewave technology inc. 0015b0 autotelenet co.,ltd 0015b1 ambient corporation 0015b2 advanced industrial computer, inc. @@ -5546,7 +5548,7 @@ exit 0015b6 shinmaywa industries, ltd. 0015b7 toshiba 0015b8 tahoe - 0015b9 samsung electronics co., ltd. + 0015b9 samsung electronics co.,ltd 0015ba iba ag 0015bb sma solar technology ag 0015bc develco @@ -5554,22 +5556,22 @@ exit 0015be iqua ltd. 0015bf technicob 0015c0 digital telemedia co.,ltd. - 0015c1 sony computer entertainment inc, + 0015c1 sony interactive entertainment inc. 0015c2 3m germany 0015c3 ruf telematik ag 0015c4 flovel co., ltd. - 0015c5 dell inc - 0015c6 cisco systems, inc. - 0015c7 cisco systems, inc. + 0015c5 dell inc. + 0015c6 cisco systems, inc + 0015c7 cisco systems, inc 0015c8 flexipanel ltd 0015c9 gumstix, inc 0015ca terarecon, inc. 0015cb surf communication solutions ltd. 0015cc uquest, ltd. 0015cd exartech international corp. - 0015ce arris international - 0015cf arris international - 0015d0 arris international + 0015ce arris group, inc. + 0015cf arris group, inc. + 0015d0 arris group, inc. 0015d1 arris group, inc. 0015d2 xantech corporation 0015d3 pantech&curitel communications, inc. @@ -5585,7 +5587,7 @@ exit 0015dd ip control systems ltd. 0015de nokia danmark a/s 0015df clivet s.p.a. - 0015e0 st-ericsson + 0015e0 ericsson 0015e1 picochip ltd 0015e2 dr.ing. herbert knauer gmbh 0015e3 dream technologies corporation @@ -5593,7 +5595,7 @@ exit 0015e5 cheertek inc. 0015e6 mobile technika inc. 0015e7 quantec tontechnik - 0015e8 nortel + 0015e8 nortel networks 0015e9 d-link corporation 0015ea tellumat (pty) ltd 0015eb zte corporation @@ -5610,15 +5612,15 @@ exit 0015f6 science and engineering services, inc. 0015f7 wintecronics ltd. 0015f8 kingtronics industrial co. ltd. - 0015f9 cisco systems, inc. - 0015fa cisco systems, inc. + 0015f9 cisco systems, inc + 0015fa cisco systems, inc 0015fb setex schermuly textile computer gmbh 0015fc littelfuse startco 0015fd complete media systems 0015fe schilling robotics llc - 0015ff novatel wireless, inc. + 0015ff novatel wireless solutions, inc. 001600 cellebrite mobile synchronization - 001601 buffalo inc. + 001601 buffalo.inc 001602 ceyon technology co.,ltd. 001603 coolksky co., ltd 001604 sigpro @@ -5649,7 +5651,7 @@ exit 00161d innovative wireless technologies, inc. 00161e woojinnet 00161f sunwavetec co., ltd. - 001620 sony ericsson mobile communications ab + 001620 sony mobile communications inc 001621 colorado vnet 001622 bbh systems gmbh 001623 interval media @@ -5657,7 +5659,7 @@ exit 001625 impinj, inc. 001626 arris group, inc. 001627 embedded-logic design and more gmbh - 001628 ultra electronics manufacturing and card systems + 001628 magicard ltd 001629 nivus gmbh 00162a antik computers & communications s.r.o. 00162b togami electric mfg.co.,ltd. @@ -5667,16 +5669,16 @@ exit 00162f geutebrück gmbh 001630 vativ technologies 001631 xteam - 001632 samsung electronics co., ltd. + 001632 samsung electronics co.,ltd 001633 oxford diagnostics ltd. 001634 mathtech, inc. - 001635 hewlett-packard company + 001635 hewlett packard 001636 quanta computer inc. 001637 citel spa 001638 tecom co., ltd. - 001639 ubiquam co.,ltd + 001639 ubiquam co., ltd. 00163a yves technology co., ltd. - 00163b vertexrsi/general dynamics + 00163b communications & power industries 00163c rebox b.v. 00163d tsinghua tongfang legend silicon tech. co., ltd. 00163e xensource, inc. @@ -5687,17 +5689,17 @@ exit 001643 sunhillo corporation 001644 lite-on technology corp. 001645 power distribution, inc. - 001646 cisco systems, inc. - 001647 cisco systems, inc. + 001646 cisco systems, inc + 001647 cisco systems, inc 001648 ssd company limited 001649 setone gmbh 00164a vibration technology limited 00164b quorion data systems gmbh 00164c planet int co., ltd - 00164d alcatel north america ip division + 00164d alcatel-lucent ipd 00164e nokia danmark a/s 00164f world ethnic broadcastin inc. - 001650 herley general microwave israel. + 001650 kratos epd 001651 exeo systems 001652 hoatech technologies, inc. 001653 lego system a/s ie electronics division @@ -5709,11 +5711,11 @@ exit 001659 z.m.p. radwag 00165a harman specialty group 00165b grip audio - 00165c trackflow ltd + 00165c trackflow ltd. 00165d airdefense, inc. 00165e precision i/o 00165f fairmount automation - 001660 nortel + 001660 nortel networks 001661 novatium solutions (p) ltd 001662 liyuh technology ltd. 001663 kbt mobile @@ -5724,9 +5726,9 @@ exit 001668 eishin electronics 001669 mrv communication (networks) ltd 00166a tps - 00166b samsung electronics - 00166c samsung electonics digital video system division - 00166d yulong computer telecommunication scientific(shenzhen)co.,lt + 00166b samsung electronics co.,ltd + 00166c samsung electronics co.,ltd + 00166d yulong computer telecommunication scientific (shenzhen) co.,ltd 00166e arbitron inc. 00166f intel corporate 001670 sknet corporation @@ -5739,7 +5741,7 @@ exit 001677 bihl + wiedemann gmbh 001678 shenzhen baoan gaoke electronics co., ltd 001679 eon communications - 00167a skyworth overseas dvelopment ltd. + 00167a skyworth overseas development ltd. 00167b haver&boecker 00167c irex technologies bv 00167d sky-line information co., ltd. @@ -5760,7 +5762,7 @@ exit 00168c dsl partner as 00168d korwin co., ltd. 00168e vimicro corporation - 00168f gn netcom as + 00168f gn netcom a/s 001690 j-tek incorporation 001691 moser-baer ag 001692 scientific-atlanta, inc. @@ -5773,8 +5775,8 @@ exit 001699 tonic dvb marketing ltd 00169a quadrics ltd 00169b alstom transport - 00169c cisco systems, inc. - 00169d cisco systems, inc. + 00169c cisco systems, inc + 00169d cisco systems, inc 00169e tv one ltd 00169f vimtron electronics co., ltd. 0016a0 auto-maskin @@ -5797,12 +5799,12 @@ exit 0016b1 kbs 0016b2 drivecam inc 0016b3 photonicbridges (china) co., ltd. - 0016b4 + 0016b4 private 0016b5 arris group, inc. - 0016b6 cisco-linksys + 0016b6 cisco-linksys, llc 0016b7 seoul commtech - 0016b8 sony ericsson mobile communications - 0016b9 procurve networking + 0016b8 sony mobile communications inc + 0016b9 procurve networking by hp 0016ba weathernews inc. 0016bb law-chain computer technology co ltd 0016bc nokia danmark a/s @@ -5816,15 +5818,15 @@ exit 0016c4 sirf technology, inc. 0016c5 shenzhen xing feng industry co.,ltd 0016c6 north atlantic industries - 0016c7 cisco systems, inc. - 0016c8 cisco systems, inc. + 0016c7 cisco systems, inc + 0016c8 cisco systems, inc 0016c9 nat seattle, inc. - 0016ca nortel - 0016cb apple + 0016ca nortel networks + 0016cb apple, inc. 0016cc xcute mobile corp. 0016cd hiji high-tech co., ltd. - 0016ce hon hai precision ind. co., ltd. - 0016cf hon hai precision ind. co., ltd. + 0016ce hon hai precision ind. co.,ltd. + 0016cf hon hai precision ind. co.,ltd. 0016d0 atech elektronika d.o.o. 0016d1 zat a.s. 0016d2 caspian @@ -5836,7 +5838,7 @@ exit 0016d8 senea ab 0016d9 ningbo bird co.,ltd. 0016da futronic technology co. ltd. - 0016db samsung electronics co., ltd. + 0016db samsung electronics co.,ltd 0016dc archos 0016dd gigabeam corporation 0016de fast inc @@ -5844,7 +5846,7 @@ exit 0016e0 3com ltd 0016e1 siliconstor, inc. 0016e2 american fibertek, inc. - 0016e3 askey computer corp. + 0016e3 askey computer corp 0016e4 vanguard security engineering corp. 0016e5 fordley development limited 0016e6 giga-byte technology co.,ltd. @@ -5853,8 +5855,8 @@ exit 0016e9 tiba medical inc 0016ea intel corporate 0016eb intel corporate - 0016ec elitegroup computer systems co., ltd. - 0016ed digital safety technologies, inc + 0016ec elitegroup computer systems co.,ltd. + 0016ed utility, inc 0016ee royaldigital inc. 0016ef koko fitness, inc. 0016f0 dell @@ -5868,10 +5870,10 @@ exit 0016f8 aviqtech technology co., ltd. 0016f9 cetrta pot, d.o.o., kranj 0016fa eci telecom ltd. - 0016fb shenzhen mtc co.,ltd. + 0016fb shenzhen mtc co ltd 0016fc tohken co.,ltd. 0016fd jaty electronics - 0016fe alps electric co., ltd + 0016fe alpsalpine co,.ltd 0016ff wamin optocomm mfg corp 001700 arris group, inc. 001701 kde, inc. @@ -5879,18 +5881,18 @@ exit 001703 mosdan internation co.,ltd 001704 shinco electronics group co.,ltd 001705 methode electronics - 001706 techfaith wireless communication technology limited. + 001706 techfaithwireless communication technology limited. 001707 ingrid, inc - 001708 hewlett-packard company + 001708 hewlett packard 001709 exalt communications 00170a inew digital company 00170b contela, inc. 00170c twig com ltd. 00170d dust networks inc. - 00170e cisco systems, inc. - 00170f cisco systems, inc. + 00170e cisco systems, inc + 00170f cisco systems, inc 001710 casa systems inc. - 001711 ge healthcare bio-sciences ab + 001711 cytiva sweden ab 001712 isco international 001713 tiger netcom 001714 br controls nederland bv @@ -5923,20 +5925,20 @@ exit 00172f neulion incorporated 001730 automation electronics 001731 asustek computer inc. - 001732 science-technical center "rissa" + 001732 science-technical center rissa 001733 sfr 001734 adc telecommunications - 001735 + 001735 intel wireless network group 001736 iitron inc. 001737 industrie dial face s.p.a. 001738 international business machines 001739 bright headphone electronics company - 00173a reach systems inc. - 00173b cisco systems, inc. + 00173a cloudastructure inc + 00173b cisco systems, inc 00173c extreme engineering solutions 00173d neology 00173e leucotronequipamentos ltda. - 00173f belkin corporation + 00173f belkin international inc. 001740 bluberi gaming technologies inc 001741 defidev 001742 fujitsu limited @@ -5962,19 +5964,19 @@ exit 001756 vinci labs oy 001757 rix technology limited 001758 thruvision ltd - 001759 cisco systems, inc. - 00175a cisco systems, inc. + 001759 cisco systems, inc + 00175a cisco systems, inc 00175b acs solutions switzerland ltd. 00175c sharp corporation 00175d dongseo system. 00175e zed-3 00175f xenolink communications co., ltd. 001760 naito densei machida mfg.co.,ltd - 001761 + 001761 private 001762 solar technology, inc. 001763 essentia s.p.a. 001764 atmedia gmbh - 001765 nortel + 001765 nortel networks 001766 accense technology, inc. 001767 earforce as 001768 zinwave ltd @@ -5998,7 +6000,7 @@ exit 00177a assa abloy ab 00177b azalea networks inc 00177c smartlink network systems limited - 00177d idt international limited + 00177d idt technology limited 00177e meshcom technologies inc. 00177f worldsmart retech 001780 applied biosystems b.v. @@ -6021,14 +6023,14 @@ exit 001791 lintech gmbh 001792 falcom wireless comunications gmbh 001793 tigi corporation - 001794 cisco systems, inc. - 001795 cisco systems, inc. + 001794 cisco systems, inc + 001795 cisco systems, inc 001796 rittmeyer ag 001797 telsy elettronica s.p.a. 001798 azonic technology co., ltd 001799 smartire systems inc. 00179a d-link corporation - 00179b chant sincere co., ltd. + 00179b chant sincere co.,ltd 00179c deprag schulz gmbh u. co. 00179d kelman limited 00179e sirit inc @@ -6037,7 +6039,7 @@ exit 0017a1 3soft inc. 0017a2 camrivox ltd. 0017a3 mix s.r.l. - 0017a4 hewlett-packard company + 0017a4 hewlett packard 0017a5 ralink technology corp 0017a6 yosin electronics co., ltd. 0017a7 mobile computing promotion consortium @@ -6055,7 +6057,7 @@ exit 0017b3 aftek infosys limited 0017b4 remote security systems, llc 0017b5 peerless systems corporation - 0017b6 aquantia + 0017b6 aquantia corporation 0017b7 tonze technology co. 0017b8 novatron co., ltd. 0017b9 gambro lundia ab @@ -6073,8 +6075,8 @@ exit 0017c5 sonicwall 0017c6 cross match technologies inc 0017c7 mara systems consulting ab - 0017c8 kyocera document solutions inc. - 0017c9 samsung electronics co., ltd. + 0017c8 kyocera display corporation + 0017c9 samsung electronics co.,ltd 0017ca qisda corporation 0017cb juniper networks 0017cc alcatel-lucent @@ -6082,11 +6084,11 @@ exit 0017ce screen service spa 0017cf imca-gmbh 0017d0 opticom communications, llc - 0017d1 nortel + 0017d1 nortel networks 0017d2 thinlinx pty ltd 0017d3 etymotic research, inc. 0017d4 monsoon multimedia, inc - 0017d5 samsung electronics co., ltd. + 0017d5 samsung electronics co.,ltd 0017d6 bluechips microhouse co.,ltd. 0017d7 ion geophysical corporation inc. 0017d8 magnum semiconductor, inc. @@ -6096,8 +6098,8 @@ exit 0017dc daemyung zero1 0017dd clipsal australia 0017de advantage six ltd - 0017df cisco systems, inc. - 0017e0 cisco systems, inc. + 0017df cisco systems, inc + 0017e0 cisco systems, inc 0017e1 dacos technologies co., ltd. 0017e2 arris group, inc. 0017e3 texas instruments @@ -6115,8 +6117,8 @@ exit 0017ef ibm corp 0017f0 szcom broadband network technology co.,ltd 0017f1 renu electronics pvt ltd - 0017f2 apple - 0017f3 harris corparation + 0017f2 apple, inc. + 0017f3 harris corporation 0017f4 zeron alliance 0017f5 lig neoptek 0017f6 pyramid meriden inc. @@ -6139,7 +6141,7 @@ exit 001807 fanstel corp. 001808 sightlogix, inc. 001809 cresyn - 00180a meraki, inc. + 00180a cisco meraki 00180b brilliant telecommunications 00180c optelian access networks 00180d terabytes server storage tech corp @@ -6148,13 +6150,13 @@ exit 001810 iptrade s.a. 001811 neuros technology international, llc. 001812 beijing xinwei telecom technology co., ltd. - 001813 sony ericsson mobile communications + 001813 sony mobile communications inc 001814 mitutoyo corporation 001815 gz technologies, inc. 001816 ubixon co., ltd. 001817 d. e. shaw research, llc - 001818 cisco systems, inc. - 001819 cisco systems, inc. + 001818 cisco systems, inc + 001819 cisco systems, inc 00181a avermedia information inc. 00181b taijin metal co., ltd. 00181c exterity limited @@ -6166,7 +6168,7 @@ exit 001822 cec telecom co.,ltd. 001823 delta electronics, inc. 001824 kimaldi electronics, s.l. - 001825 + 001825 private 001826 cale access ab 001827 nec unified solutions nederland b.v. 001828 e2v technologies (uk) ltd. @@ -6175,7 +6177,7 @@ exit 00182b softier 00182c ascend networks, inc. 00182d artec design - 00182e xstreamhd, llc + 00182e xstreamhd 00182f texas instruments 001830 texas instruments 001831 texas instruments @@ -6183,16 +6185,16 @@ exit 001833 texas instruments 001834 texas instruments 001835 thoratec / itc - 001836 reliance electric limited + 001836 rej co.,ltd 001837 universal abit co., ltd. 001838 panaccess communications,inc. - 001839 cisco-linksys llc - 00183a westell technologies + 001839 cisco-linksys, llc + 00183a westell technologies inc. 00183b cenits co., ltd. 00183c encore software limited 00183d vertex link corporation 00183e digilent, inc - 00183f 2wire, inc + 00183f 2wire inc 001840 3 phoenix, inc. 001841 high tech computer corp 001842 nokia danmark a/s @@ -6202,11 +6204,11 @@ exit 001846 crypto s.a. 001847 acenet technology inc. 001848 vecima networks inc. - 001849 pigeon point systems llc + 001849 nvent, schroff gmbh 00184a catcher, inc. 00184b las vegas gaming, inc. 00184c bogen communications - 00184d netgear inc. + 00184d netgear 00184e lianhe technologies, inc. 00184f 8 ways technology corp. 001850 secfone kft @@ -6221,7 +6223,7 @@ exit 001859 strawberry linux co.,ltd. 00185a ucontrol, inc. 00185b network chemistry, inc - 00185c eds lab pte ltd + 00185c edslab technologies 00185d taiguen technology (shen-zhen) co., ltd. 00185e nexterm inc. 00185f tac inc. @@ -6233,7 +6235,7 @@ exit 001865 siemens healthcare diagnostics manufacturing ltd 001866 leutron vision 001867 datalogic adc - 001868 scientific atlanta, a cisco company + 001868 cisco spvtg 001869 kingjim 00186a global link digital technology co,.ltd 00186b sambu communics co., ltd. @@ -6242,10 +6244,10 @@ exit 00186e 3com ltd 00186f setha industria eletronica ltda 001870 e28 shanghai limited - 001871 hewlett-packard company + 001871 hewlett packard 001872 expertise engineering - 001873 cisco systems, inc. - 001874 cisco systems, inc. + 001873 cisco systems, inc + 001874 cisco systems, inc 001875 anacise testnology pte ltd 001876 wowwee ltd. 001877 amplex a/s @@ -6254,21 +6256,21 @@ exit 00187a wiremold 00187b 4nsys co. ltd. 00187c intercross, llc - 00187d armorlink shanghai co. ltd + 00187d armorlink co .ltd 00187e rgb spectrum 00187f zodianet 001880 maxim integrated products 001881 buyang electronics industrial co., ltd - 001882 huawei technologies co., ltd. + 001882 huawei technologies co.,ltd 001883 formosa21 inc. 001884 fon technology s.l. - 001885 avigilon corporation + 001885 motorola solutions inc. 001886 el-tech, inc. 001887 metasystem spa 001888 gotive a.s. 001889 winnet solutions limited 00188a infinova llc - 00188b dell inc + 00188b dell inc. 00188c mobile action technology inc. 00188d nokia danmark a/s 00188e ekahau, inc. @@ -6277,7 +6279,7 @@ exit 001891 zhongshan general k-mate electronics co., ltd 001892 ads-tec gmbh 001893 shenzhen photon broadband technology co.,ltd - 001894 zimocom + 001894 npcore, inc. 001895 hansun technologies inc. 001896 great well electronic ltd 001897 jess-link products co., ltd @@ -6304,8 +6306,8 @@ exit 0018ac shanghai jiao da hisys technology co. ltd. 0018ad nidec sankyo corporation 0018ae tvt co.,ltd - 0018af samsung electronics co., ltd. - 0018b0 nortel + 0018af samsung electronics co.,ltd + 0018b0 nortel networks 0018b1 ibm corp 0018b2 adeunis rf 0018b3 tec wizhome co., ltd. @@ -6314,8 +6316,8 @@ exit 0018b6 s3c, inc. 0018b7 d3 led, llc 0018b8 new voice international ag - 0018b9 cisco systems, inc. - 0018ba cisco systems, inc. + 0018b9 cisco systems, inc + 0018ba cisco systems, inc 0018bb eliwell controls srl 0018bc zao nvp bolid 0018bd shenzhen dvbworld technology co., ltd. @@ -6344,10 +6346,10 @@ exit 0018d4 unified display interface sig 0018d5 reigncom 0018d6 swirlnet a/s - 0018d7 javad navigation systems inc. + 0018d7 javad gnss, inc. 0018d8 arch meter corporation 0018d9 santosha internatonal, inc - 0018da amber wireless gmbh + 0018da würth elektronik eisos gmbh & co. kg 0018db epl technology ltd 0018dc prostar co., ltd. 0018dd silicondust engineering ltd @@ -6364,7 +6366,7 @@ exit 0018e8 hacetron corporation 0018e9 numata corporation 0018ea alltec gmbh - 0018eb brovis wireless networks + 0018eb blue zen enterprises private limited 0018ec welding technology corporation 0018ed accutech ultrasystems co., ltd. 0018ee videology imaging solutions, inc. @@ -6377,13 +6379,13 @@ exit 0018f5 shenzhen streaming video technology company limited 0018f6 thomson telecom belgium 0018f7 kameleon technologies - 0018f8 cisco-linksys llc + 0018f8 cisco-linksys, llc 0018f9 vvond, inc. 0018fa yushin precision equipment co.,ltd. 0018fb compro technology 0018fc altec electronic ag 0018fd optimal technologies international inc. - 0018fe hewlett-packard company + 0018fe hewlett packard 0018ff powerquattro co. 001900 intelliverese - dba voicecom 001901 f1media @@ -6391,8 +6393,8 @@ exit 001903 bigfoot networks inc 001904 wb electronics sp. z o.o. 001905 schrack seconet ag - 001906 cisco systems, inc. - 001907 cisco systems, inc. + 001906 cisco systems, inc + 001907 cisco systems, inc 001908 duaxes corporation 001909 devi - danfoss a/s 00190a hasware inc. @@ -6418,7 +6420,7 @@ exit 00191e beyondwiz co., ltd. 00191f microlink communications inc. 001920 kume electric co.,ltd. - 001921 elitegroup computer system co. + 001921 elitegroup computer systems co.,ltd. 001922 cm comandos lineares 001923 phonex korea co., ltd. 001924 lbnl engineering @@ -6432,10 +6434,10 @@ exit 00192c arris group, inc. 00192d nokia corporation 00192e spectral instruments, inc. - 00192f cisco systems, inc. - 001930 cisco systems, inc. + 00192f cisco systems, inc + 001930 cisco systems, inc 001931 balluff gmbh - 001932 gude analog- und digialsysteme gmbh + 001932 gude systems gmbh 001933 strix systems, inc. 001934 trendon touch technology corp. 001935 duerr dental ag @@ -6444,7 +6446,7 @@ exit 001938 umb communications co., ltd. 001939 gigamips 00193a oesolutions - 00193b wilibox deliberant group llc + 00193b ligowave 00193c highpoint technologies incorporated 00193d gmc guardian mobility corp. 00193e adb broadband italia @@ -6454,13 +6456,13 @@ exit 001942 on software international limited 001943 belden 001944 fossil partners, l.p. - 001945 ten-tec inc. + 001945 rf concepts, llc 001946 cianet industria e comercio s/a - 001947 scientific atlanta, a cisco company + 001947 cisco spvtg 001948 airespider networks 001949 tentel comtech co., ltd. 00194a testo ag - 00194b sagem communication + 00194b sagemcom broadband sas 00194c fujian stelcom information & technology co.,ltd 00194d avago technologies sdn bhd 00194e ultra electronics - tcs (tactical communication systems) @@ -6470,8 +6472,8 @@ exit 001952 acogito co., ltd 001953 chainleader communications corp. 001954 leaf corporation. - 001955 cisco systems, inc. - 001956 cisco systems, inc. + 001955 cisco systems, inc + 001956 cisco systems, inc 001957 saafnet canada inc. 001958 bluetooth sig, inc. 001959 staccato communications inc. @@ -6484,13 +6486,13 @@ exit 001960 docomo systems, inc. 001961 blaupunkt embedded systems gmbh 001962 commerciant, lp - 001963 sony ericsson mobile communications ab + 001963 sony mobile communications inc 001964 doorking inc. 001965 yuhua teltech (shanghai) co., ltd. 001966 asiarock technology limited 001967 teldat sp.j. 001968 digital video networks(shanghai) co. ltd. - 001969 nortel + 001969 nortel networks 00196a mikrom gmbh 00196b danpex corporation 00196c etrovision technology @@ -6499,19 +6501,19 @@ exit 00196f sensopart gmbh 001970 z-com, inc. 001971 guangzhou unicomp technology co.,ltd - 001972 plexus (xiamen) co.,ltd + 001972 plexus (xiamen) co.,ltd. 001973 zeugma systems - 001974 abocom systems, inc. + 001974 16063 001975 beijing huisen networks technology inc 001976 xipher technologies, llc - 001977 aerohive networks, inc. + 001977 extreme networks, inc. 001978 datum systems, inc. 001979 nokia danmark a/s 00197a mazet gmbh 00197b picotest corp. 00197c riedel communications gmbh - 00197d hon hai precision ind. co., ltd - 00197e hon hai precision ind. co., ltd + 00197d hon hai precision ind. co.,ltd. + 00197e hon hai precision ind. co.,ltd. 00197f plantronics, inc. 001980 gridpoint systems 001981 vivox inc @@ -6520,7 +6522,7 @@ exit 001984 estic corporation 001985 it watchdogs, inc 001986 cheng hongjian - 001987 panasonic mobile communications co., ltd. + 001987 panasonic mobile communications co.,ltd. 001988 wi2wi, inc 001989 sonitrol corporation 00198a northrop grumman systems corp. @@ -6528,21 +6530,21 @@ exit 00198c ixsea 00198d ocean optics, inc. 00198e oticon a/s - 00198f alcatel bell n.v. + 00198f nokia bell n.v. 001990 elm data co., ltd. 001991 avinfo - 001992 adtran inc. + 001992 adtran inc 001993 changshu switchgear mfg. co.,ltd. (former changshu switchgea 001994 jorjin technologies inc. 001995 jurong hi-tech (suzhou)co.ltd 001996 turbochef technologies inc. 001997 soft device sdn bhd 001998 sato corporation - 001999 fujitsu technology solutions + 001999 fujitsu technology solutions gmbh 00199a edo-evi 00199b diversified technical systems, inc. 00199c ctring - 00199d vizio, inc. + 00199d vizio, inc 00199e nifty 00199f dkt a/s 0019a0 nihon data systens, inc. @@ -6554,8 +6556,8 @@ exit 0019a6 arris group, inc. 0019a7 itu-t 0019a8 wiquest communications - 0019a9 cisco systems, inc. - 0019aa cisco systems, inc. + 0019a9 cisco systems, inc + 0019aa cisco systems, inc 0019ab raycom co ., ltd 0019ac gsp systems inc. 0019ad bobst sa @@ -6565,24 +6567,24 @@ exit 0019b1 arrow7 corporation 0019b2 xynetsoft co.,ltd 0019b3 stanford research systems - 0019b4 videocast ltd. + 0019b4 intellio ltd 0019b5 famar fueguina s.a. 0019b6 euro emme s.r.l. 0019b7 nokia danmark a/s 0019b8 boundary devices 0019b9 dell inc. 0019ba paradox security systems ltd - 0019bb hewlett-packard company + 0019bb hewlett packard 0019bc electro chance srl 0019bd new media life 0019be altai technologies limited 0019bf citiway technology co.,ltd 0019c0 arris group, inc. - 0019c1 alps electric co., ltd + 0019c1 alpsalpine co,.ltd 0019c2 equustek solutions, inc. 0019c3 qualitrol 0019c4 infocrypt inc. - 0019c5 sony computer entertainment inc, + 0019c5 sony interactive entertainment inc. 0019c6 zte corporation 0019c7 cambridge industries(group) co.,ltd. 0019c8 anydata corporation @@ -6609,15 +6611,15 @@ exit 0019dd fei-zyfer, inc. 0019de mobitek 0019df thomson inc. - 0019e0 tp-link technologies co., ltd. - 0019e1 nortel + 0019e0 tp-link technologies co.,ltd. + 0019e1 nortel networks 0019e2 juniper networks - 0019e3 apple - 0019e4 2wire, inc + 0019e3 apple, inc. + 0019e4 2wire inc 0019e5 lynx studio technology, inc. 0019e6 toyo medic co.,ltd. - 0019e7 cisco systems, inc. - 0019e8 cisco systems, inc. + 0019e7 cisco systems, inc + 0019e8 cisco systems, inc 0019e9 s-information technolgy, co., ltd. 0019ea teramage technologies co., ltd. 0019eb pyronix ltd @@ -6658,7 +6660,7 @@ exit 001a0e cheng uei precision industry co.,ltd 001a0f sistemas avanzados de control, s.a. 001a10 lucent trans electronics co.,ltd - 001a11 google inc. + 001a11 google, inc. 001a12 essilor 001a13 wanlida group co., ltd 001a14 xin hua control engineering co.,ltd. @@ -6671,10 +6673,10 @@ exit 001a1b arris group, inc. 001a1c gt&t engineering pte ltd 001a1d pchome online inc. - 001a1e aruba networks + 001a1e aruba, a hewlett packard enterprise company 001a1f coastal environmental systems 001a20 cmotech co. ltd. - 001a21 indac b.v. + 001a21 brookhuis applied technologies bv 001a22 eq-3 entwicklung gmbh 001a23 ice qube, inc 001a24 galaxy telecom technologies ltd @@ -6682,15 +6684,15 @@ exit 001a26 deltanode solutions ab 001a27 ubistar 001a28 aswt co., ltd. taiwan branch h.k. - 001a29 johnson outdoors marine electronics, inc + 001a29 johnson outdoors marine electronics d/b/a minnkota 001a2a arcadyan technology corporation 001a2b ayecom technology co., ltd. 001a2c satec co.,ltd 001a2d the navvo group 001a2e ziova coporation - 001a2f cisco systems, inc. - 001a30 cisco systems, inc. - 001a31 scan coin industries ab + 001a2f cisco systems, inc + 001a30 cisco systems, inc + 001a31 scan coin ab 001a32 activa multimedia 001a33 asi communications, inc. 001a34 konka group co., ltd. @@ -6710,13 +6712,13 @@ exit 001a42 techcity technology co., ltd. 001a43 logical link communications 001a44 jwtrading co., ltd - 001a45 gn netcom as + 001a45 gn netcom a/s 001a46 digital multimedia technology co., ltd 001a47 agami systems, inc. 001a48 takacom corporation 001a49 micro vision co.,ltd 001a4a qumranet inc. - 001a4b hewlett-packard company + 001a4b hewlett packard 001a4c crossbow technology, inc 001a4d giga-byte technology co.,ltd. 001a4e nti ag / linmot @@ -6749,8 +6751,8 @@ exit 001a69 wuhan yangtze optical technology co.,ltd. 001a6a tranzas, inc. 001a6b universal global scientific industrial co., ltd. - 001a6c cisco systems, inc. - 001a6d cisco systems, inc. + 001a6c cisco systems, inc + 001a6d cisco systems, inc 001a6e impro technologies 001a6f mi.tel s.r.l. 001a70 cisco-linksys, llc @@ -6758,7 +6760,7 @@ exit 001a72 mosart semiconductor corp. 001a73 gemtek technology co., ltd. 001a74 procare international co - 001a75 sony ericsson mobile communications + 001a75 sony mobile communications inc 001a76 sdt information technology co.,ltd. 001a77 arris group, inc. 001a78 ubtos @@ -6768,24 +6770,24 @@ exit 001a7c hirschmann multimedia b.v. 001a7d cyber-blue(hk)ltd 001a7e ln srithai comm ltd. - 001a7f gci science&technology co.,ltd. + 001a7f gci science & technology co.,ltd 001a80 sony corporation 001a81 zelax 001a82 proba building automation co.,ltd 001a83 pegasus technologies inc. 001a84 v one multimedia pte ltd 001a85 nv michel van de wiele - 001a86 advancedio systems inc + 001a86 new wave design & verification 001a87 canhold international limited 001a88 venergy,co,ltd 001a89 nokia danmark a/s - 001a8a samsung electronics co., ltd. + 001a8a samsung electronics co.,ltd 001a8b chunil electric ind., co. - 001a8c astaro ag + 001a8c sophos ltd 001a8d avecs bergen gmbh 001a8e 3way networks ltd - 001a8f nortel - 001a90 trópico sistemas e telecomunicações da amazônia ltda. + 001a8f nortel networks + 001a90 trópico sistemas e telecomunicações da amazônia ltda. 001a91 fusiondynamic ltd. 001a92 asustek computer inc. 001a93 erco leuchten gmbh @@ -6795,15 +6797,15 @@ exit 001a97 fitivision technology inc. 001a98 asotel communication limited taiwan branch 001a99 smarty (hz) information electronics co., ltd - 001a9a skyworth digital technology(shenzhen)co.ltd. + 001a9a skyworth digital technology(shenzhen) co.,ltd 001a9b adec & parter ag 001a9c righthand technologies, inc. 001a9d skipper wireless, inc. 001a9e icon digital international limited 001a9f a-link ltd - 001aa0 dell inc - 001aa1 cisco systems, inc. - 001aa2 cisco systems, inc. + 001aa0 dell inc. + 001aa1 cisco systems, inc + 001aa2 cisco systems, inc 001aa3 delorme 001aa4 future university-hakodate 001aa5 brn phoenix @@ -6837,8 +6839,8 @@ exit 001ac1 3com ltd 001ac2 yec co.,ltd. 001ac3 scientific-atlanta, inc - 001ac4 2wire, inc - 001ac5 breakingpoint systems, inc. + 001ac4 2wire inc + 001ac5 keysight technologies, inc. 001ac6 micro control designs 001ac7 unipoint 001ac8 isl (instrumentation scientifique de laboratoire) @@ -6867,21 +6869,21 @@ exit 001adf interactivetv pty limited 001ae0 mythology tech express inc. 001ae1 edge access inc - 001ae2 cisco systems, inc. - 001ae3 cisco systems, inc. + 001ae2 cisco systems, inc + 001ae3 cisco systems, inc 001ae4 medicis technologies corporation 001ae5 mvox technologies inc. 001ae6 atlanta advanced communications holdings limited 001ae7 aztek networks, inc. - 001ae8 unify gmbh and co kg + 001ae8 unify software and solutions gmbh & co. kg 001ae9 nintendo co., ltd. 001aea radio terminal systems pty ltd - 001aeb allied telesis k.k. + 001aeb allied telesis r&d center k.k. 001aec keumbee electronics co.,ltd. 001aed incotec gmbh 001aee shenztech ltd 001aef loopcomm technology, inc. - 001af0 alcatel - ipd + 001af0 alcatel-lucent ipd 001af1 embedded artists ab 001af2 dynavisions schweiz ag 001af3 samyoung electronics @@ -6909,8 +6911,8 @@ exit 001b09 matrix telecom pvt. ltd. 001b0a intelligent distributed controls ltd 001b0b phidgets inc. - 001b0c cisco systems, inc. - 001b0d cisco systems, inc. + 001b0c cisco systems, inc + 001b0d cisco systems, inc 001b0e inotec gmbh organisationssysteme 001b0f petratec 001b10 shenzhen kang hui technology co.,ltd @@ -6934,17 +6936,17 @@ exit 001b22 palit microsystems ( h.k.) ltd. 001b23 simplecomtools 001b24 quanta computer inc. - 001b25 nortel + 001b25 nortel networks 001b26 ron-telecom zao 001b27 merlin csi 001b28 polygon, jsc 001b29 avantis.co.,ltd - 001b2a cisco systems, inc. - 001b2b cisco systems, inc. + 001b2a cisco systems, inc + 001b2b cisco systems, inc 001b2c atron electronic gmbh 001b2d med-eng systems inc. 001b2e sinkyo electron inc - 001b2f netgear inc. + 001b2f netgear 001b30 solitech inc. 001b31 neural image. co. ltd. 001b32 qlogic corporation @@ -6953,7 +6955,7 @@ exit 001b35 chongqing jinou science & technology development co.,ltd 001b36 tsubata engineering co.,ltd. (head office) 001b37 computec oy - 001b38 compal information (kunshan) co., ltd. + 001b38 compal information (kunshan) co., ltd. 001b39 proxicast 001b3a sims corp. 001b3b yi-qing co., ltd @@ -6976,19 +6978,19 @@ exit 001b4c signtech 001b4d areca technology corporation 001b4e navman new zealand - 001b4f avaya inc. + 001b4f avaya inc 001b50 nizhny novgorod factory named after m.frunze, fsue (nzif) 001b51 vector technology corp. 001b52 arris group, inc. - 001b53 cisco systems, inc. - 001b54 cisco systems, inc. + 001b53 cisco systems, inc + 001b54 cisco systems, inc 001b55 hurco automation ltd. 001b56 tehuti networks ltd. 001b57 semindia systems private limited 001b58 ace cad enterprise co., ltd. - 001b59 sony ericsson mobile communications ab + 001b59 sony mobile communications inc 001b5a apollo imaging technologies, inc. - 001b5b 2wire, inc. + 001b5b 2wire inc 001b5c azuretec co., ltd. 001b5d vololink pty ltd 001b5e bpl limited @@ -6996,7 +6998,7 @@ exit 001b60 navigon ag 001b61 digital acoustics, llc 001b62 jht optoelectronics co.,ltd. - 001b63 apple + 001b63 apple, inc. 001b64 isaaclandkorea co., ltd, 001b65 china gridcom co., ltd 001b66 sennheiser electronic gmbh & co. kg @@ -7007,7 +7009,7 @@ exit 001b6b swyx solutions ag 001b6c lookx digital media bv 001b6d midtronics, inc. - 001b6e anue systems, inc. + 001b6e keysight technologies, inc. 001b6f teletrak ltd 001b70 iri ubiteq, inc. 001b71 telular corp. @@ -7017,7 +7019,7 @@ exit 001b75 hypermedia systems 001b76 ripcode, inc. 001b77 intel corporate - 001b78 hewlett-packard company + 001b78 hewlett packard 001b79 faiveley transport 001b7a nintendo co., ltd. 001b7b the tintometer ltd @@ -7030,18 +7032,18 @@ exit 001b82 taiwan semiconductor co., ltd. 001b83 finsoft ltd 001b84 scan engineering telecom - 001b85 man diesel se + 001b85 man energy solutions 001b86 bosch access systems gmbh 001b87 deepsound tech. co., ltd 001b88 divinet access technologies ltd 001b89 emza visual sense ltd. 001b8a 2m electronic a/s - 001b8b nec accesstechnica, ltd. + 001b8b nec platforms, ltd. 001b8c jmicron technology corp. 001b8d electronic computer systems, inc. 001b8e hulu sweden ab - 001b8f cisco systems, inc. - 001b90 cisco systems, inc. + 001b8f cisco systems, inc + 001b90 cisco systems, inc 001b91 efkon ag 001b92 l-acoustics 001b93 jc decaux sa dnt @@ -7049,13 +7051,13 @@ exit 001b95 video systems srl 001b96 general sensing 001b97 violin technologies - 001b98 samsung electronics co., ltd. + 001b98 samsung electronics co.,ltd 001b99 ks system gmbh 001b9a apollo fire detectors ltd 001b9b hose-mccann communications 001b9c satel sp. z o.o. 001b9d novus security sp. z o.o. - 001b9e askey computer corp + 001b9e askey computer corp 001b9f calyptech pty ltd 001ba0 awox 001ba1 Åmic ab @@ -7073,22 +7075,22 @@ exit 001bad icontrol incorporated 001bae micro control systems, inc 001baf nokia danmark a/s - 001bb0 bharat electronics - 001bb1 wistron neweb corp. + 001bb0 bharat electronics limited + 001bb1 wistron neweb corporation 001bb2 intellect international nv 001bb3 condalo gmbh 001bb4 airvod limited - 001bb5 zf electronics gmbh + 001bb5 cherry gmbh 001bb6 bird electronic corp. 001bb7 alta heights technology corp. 001bb8 blueway electronic co;ltd - 001bb9 elitegroup computer system co. - 001bba nortel + 001bb9 elitegroup computer systems co.,ltd. + 001bba nortel networks 001bbb rftech co.,ltd 001bbc silver peak systems, inc. 001bbd fmc kongsberg subsea as 001bbe icop digital - 001bbf sagem communication + 001bbf sagemcom broadband sas 001bc0 juniper networks 001bc1 holux technology, inc. 001bc2 integrated control technology limitied @@ -7108,13 +7110,13 @@ exit 001bd0 identec solutions 001bd1 sogestmatic 001bd2 ultra-x asia pacific inc. - 001bd3 panasonic corp. avc company - 001bd4 cisco systems, inc. - 001bd5 cisco systems, inc. + 001bd3 panasonic corporation avc networks company + 001bd4 cisco systems, inc + 001bd5 cisco systems, inc 001bd6 kelvin hughes ltd - 001bd7 scientific atlanta, a cisco company - 001bd8 dvtel ltd - 001bd9 edgewater computer systems + 001bd7 cisco spvtg + 001bd8 flir systems inc + 001bd9 edgewater wireless systems inc 001bda utstarcom inc 001bdb valeo vecs 001bdc vencer co., ltd. @@ -7130,11 +7132,11 @@ exit 001be6 vr ag 001be7 postek electronics co., ltd. 001be8 ultratronik gmbh - 001be9 broadcom corporation + 001be9 broadcom 001bea nintendo co., ltd. 001beb dmp electronics inc. 001bec netio technologies co., ltd - 001bed brocade communications systems, inc + 001bed brocade communications systems llc 001bee nokia danmark a/s 001bef blossoms digital technology co.,ltd. 001bf0 value platforms limited @@ -7148,7 +7150,7 @@ exit 001bf8 digitrax inc. 001bf9 intellitect water ltd 001bfa g.i.n. mbh - 001bfb alps electric co., ltd + 001bfb alpsalpine co,.ltd 001bfc asustek computer inc. 001bfd dignsys inc. 001bfe zavio inc. @@ -7167,16 +7169,16 @@ exit 001c0b smartant telecom 001c0c tanita corporation 001c0d g-technology, inc. - 001c0e cisco systems, inc. - 001c0f cisco systems, inc. + 001c0e cisco systems, inc + 001c0f cisco systems, inc 001c10 cisco-linksys, llc 001c11 arris group, inc. 001c12 arris group, inc. 001c13 optsys technology co., ltd. - 001c14 vmware, inc - 001c15 txp corporation + 001c14 vmware, inc. + 001c15 iphotonix llc 001c16 thyssenkrupp elevator - 001c17 nortel + 001c17 nortel networks 001c18 sicert s.r.l. 001c19 secunet security networks ag 001c1a thomas instrumentation, inc @@ -7188,12 +7190,12 @@ exit 001c20 clb benelux 001c21 nucsafe inc. 001c22 aeris elettronica s.r.l. - 001c23 dell inc + 001c23 dell inc. 001c24 formosa wireless systems corp. 001c25 hon hai precision ind. co.,ltd. 001c26 hon hai precision ind. co.,ltd. 001c27 sunell electronics co. - 001c28 sphairon technologies gmbh + 001c28 sphairon technologies gmbh 001c29 core digital electronics co., ltd 001c2a envisacor technologies inc. 001c2b alertme.com limited @@ -7233,15 +7235,15 @@ exit 001c4d aplix ip holdings corporation 001c4e tasa international limited 001c4f macab ab - 001c50 tcl technoly electronics(huizhou)co.,ltd + 001c50 tcl technoly electronics (huizhou) co., ltd. 001c51 celeno communications 001c52 visionee srl 001c53 synergy lighting controls 001c54 hillstone networks inc 001c55 shenzhen kaifa technology co. 001c56 pado systems, inc. - 001c57 cisco systems, inc. - 001c58 cisco systems, inc. + 001c57 cisco systems, inc + 001c58 cisco systems, inc 001c59 devon it 001c5a advanced relay corporation 001c5b chubb electronic security systems ltd @@ -7251,7 +7253,7 @@ exit 001c5f winland electronics, inc. 001c60 csp frontier technologies,inc. 001c61 galaxy microsystems limited - 001c62 lg electronics inc + 001c62 lg electronics (mobile communications) 001c63 truen 001c64 landis+gyr 001c65 joescan, inc. @@ -7261,16 +7263,16 @@ exit 001c69 packet vision ltd 001c6a weiss engineering ltd. 001c6b covax co. ltd - 001c6c jabil circuit (guangzhou) limited + 001c6c 30805 001c6d kyohritsu electronic industry co., ltd. 001c6e newbury networks, inc. 001c6f emfit ltd 001c70 novacomm ltda 001c71 emergent electronics 001c72 mayer & cie gmbh & co kg - 001c73 arista networks, inc. + 001c73 arista networks 001c74 syswan technologies inc. - 001c75 rf systems gmbh + 001c75 segnet ltd. 001c76 the wandsworth group ltd 001c77 prodys 001c78 wyplay sas @@ -7298,7 +7300,7 @@ exit 001c8e alcatel-lucent ipd 001c8f advanced electronic design, inc. 001c90 empacket corporation - 001c91 gefen inc. + 001c91 gefen llc 001c92 tervela 001c93 exadigm inc 001c94 li-cor biosciences @@ -7309,7 +7311,7 @@ exit 001c99 shunra software ltd. 001c9a nokia danmark a/s 001c9b feig electronic gmbh - 001c9c nortel + 001c9c nortel networks 001c9d liecthi ag 001c9e dualtech it ab 001c9f razorstream, llc @@ -7317,7 +7319,7 @@ exit 001ca1 akamai technologies, inc. 001ca2 adb broadband italia 001ca3 terra - 001ca4 sony ericsson mobile communications + 001ca4 sony mobile communications inc 001ca5 zygo corporation 001ca6 win4net 001ca7 international quartz limited @@ -7329,10 +7331,10 @@ exit 001cad wuhan telecommunication devices co.,ltd 001cae wichorus, inc. 001caf plato networks inc. - 001cb0 cisco systems, inc. - 001cb1 cisco systems, inc. + 001cb0 cisco systems, inc + 001cb1 cisco systems, inc 001cb2 bpt spa - 001cb3 apple + 001cb3 apple, inc. 001cb4 iridium satellite llc 001cb5 neihua network technology co.,ltd.(nhn) 001cb6 duzon cnt co., ltd. @@ -7348,8 +7350,8 @@ exit 001cc0 intel corporate 001cc1 arris group, inc. 001cc2 part ii research, inc. - 001cc3 pace plc - 001cc4 hewlett-packard company + 001cc3 arris group, inc. + 001cc4 hewlett packard 001cc5 3com ltd 001cc6 prostor systems 001cc7 rembrandt technologies, llc d/b/a remstream @@ -7357,7 +7359,7 @@ exit 001cc9 kaise electronic technology co., ltd. 001cca shanghai gaozhi science & technology development co. 001ccb forth corporation public company limited - 001ccc research in motion limited + 001ccc blackberry rts 001ccd alektrona corporation 001cce by techdesign 001ccf limetek @@ -7388,25 +7390,25 @@ exit 001ce8 cummins inc 001ce9 galaxy technology limited 001cea scientific-atlanta, inc - 001ceb nortel + 001ceb nortel networks 001cec mobilesoft (aust.) pty ltd 001ced environnement sa 001cee sharp corporation - 001cef primax electronics ltd + 001cef primax electronics ltd. 001cf0 d-link corporation 001cf1 supox technology co. , ltd. 001cf2 tenlon technology co.,ltd. 001cf3 evs broadcast equipment 001cf4 media technology systems inc 001cf5 wiseblue technology limited - 001cf6 cisco systems, inc. + 001cf6 cisco systems, inc 001cf7 audioscience 001cf8 parade technologies, ltd. - 001cf9 cisco systems, inc. + 001cf9 cisco systems, inc 001cfa alarm.com 001cfb arris group, inc. - 001cfc suminet communication technologies (shanghai) co., ltd. - 001cfd universal electronics + 001cfc sumitomo electric industries, ltd + 001cfd universal electronics, inc. 001cfe quartics inc 001cff napera networks inc 001d00 brivo systems, llc @@ -7414,24 +7416,24 @@ exit 001d02 cybertech telecom development 001d03 design solutions inc. 001d04 zipit wireless, inc. - 001d05 ilight + 001d05 cooper lighting solutions 001d06 hm electronics, inc. 001d07 shenzhen sang fei consumer communications co.,ltd - 001d08 jiangsu yinhe electronics co., ltd - 001d09 dell inc + 001d08 jiangsu yinhe electronics co.,ltd. + 001d09 dell inc. 001d0a davis instruments, inc. 001d0b power standards lab 001d0c mobilecompia - 001d0d sony computer entertainment inc. + 001d0d sony interactive entertainment inc. 001d0e agapha technology co., ltd. - 001d0f tp-link technologies co., ltd. + 001d0f tp-link technologies co.,ltd. 001d10 lighthaus logic, inc. 001d11 analogue & micro ltd 001d12 rohm co., ltd. 001d13 nextgtv 001d14 speradtone information technology limited 001d15 shenzhen dolphin electronic co., ltd - 001d16 efixo + 001d16 sfr 001d17 digital sky corporation 001d18 power innovation gmbh 001d19 arcadyan technology corporation @@ -7441,15 +7443,15 @@ exit 001d1d inter-m corporation 001d1e kyushu ten co.,ltd 001d1f siauliu tauro televizoriai, jsc - 001d20 comtrend co. + 001d20 comtrend corporation 001d21 alcad sl 001d22 foss analytical a/s - 001d23 sensus + 001d23 sensus 001d24 aclara power-line systems inc. 001d25 samsung electronics co.,ltd 001d26 rockridgesound technology co. 001d27 nac-intercom - 001d28 sony ericsson mobile communications ab + 001d28 sony mobile communications inc 001d29 doro ab 001d2a shenzhen bul-tech co.,ltd. 001d2b wuhan pont technology co. , ltd @@ -7475,11 +7477,11 @@ exit 001d3f mitron pty ltd 001d40 intel – ge care innovations llc 001d41 hardy instruments - 001d42 nortel + 001d42 nortel networks 001d43 shenzhen g-link digital technology co., ltd. 001d44 krohne - 001d45 cisco systems, inc. - 001d46 cisco systems, inc. + 001d45 cisco systems, inc + 001d46 cisco systems, inc 001d47 covote gmbh & co kg 001d48 sensor-technik wiedemann gmbh 001d49 innovation wireless inc. @@ -7488,7 +7490,7 @@ exit 001d4c alcatel-lucent 001d4d adaptive recognition hungary, inc 001d4e tcm mobile llc - 001d4f apple + 001d4f apple, inc. 001d50 spinetix sa 001d51 babcock & wilcox power generation group, inc 001d52 defzone b.v. @@ -7499,7 +7501,7 @@ exit 001d57 caetec messtechnik 001d58 cq inc 001d59 mitra energy & infrastructure - 001d5a 2wire inc. + 001d5a 2wire inc 001d5b tecvan informática ltda 001d5c tom communication industrial co.,ltd. 001d5d control dynamics pty. ltd. @@ -7521,10 +7523,10 @@ exit 001d6d confidant international llc 001d6e nokia danmark a/s 001d6f chainzone technology co., ltd - 001d70 cisco systems, inc. - 001d71 cisco systems, inc. + 001d70 cisco systems, inc + 001d71 cisco systems, inc 001d72 wistron corporation - 001d73 buffalo inc. + 001d73 buffalo.inc 001d74 tianjin china-silicon microelectronics co., ltd. 001d75 radioscape plc 001d76 eyeheight ltd. @@ -7539,7 +7541,7 @@ exit 001d7f tekron international ltd 001d80 beijing huahuan eletronics co.,ltd 001d81 guangzhou gateway electronics co., ltd - 001d82 gn a/s (gn netcom a/s) + 001d82 gn netcom a/s 001d83 emitech corporation 001d84 gateway, inc. 001d85 call direct cellular solutions @@ -7550,7 +7552,7 @@ exit 001d8a techtrex inc 001d8b adb broadband italia 001d8c la crosse technology ltd - 001d8d raytek gmbh + 001d8d fluke process instruments gmbh 001d8e alereon, inc. 001d8f purewave networks 001d90 emco flow systems @@ -7570,8 +7572,8 @@ exit 001d9e axion technologies 001d9f matt r.p.traczynscy sp.j. 001da0 heng yu electronic manufacturing company limited - 001da1 cisco systems, inc. - 001da2 cisco systems, inc. + 001da1 cisco systems, inc + 001da2 cisco systems, inc 001da3 sabioso 001da4 hangzhou system technology co., ltd 001da5 wb electronics @@ -7584,7 +7586,7 @@ exit 001dac gigamon systems llc 001dad sinotech engineering consultants, inc. geotechnical enginee 001dae chang tseng technology co., ltd - 001daf nortel + 001daf nortel networks 001db0 fujian hengtong information technology co.,ltd 001db1 crescendo networks 001db2 hokkaido electric engineering co.,ltd. @@ -7613,7 +7615,7 @@ exit 001dc9 gainspan corp. 001dca pav electronics limited 001dcb exéns development oy - 001dcc hetra secure solutions + 001dcc ayon cyber security, inc 001dcd arris group, inc. 001dce arris group, inc. 001dcf arris group, inc. @@ -7626,20 +7628,20 @@ exit 001dd6 arris group, inc. 001dd7 algolith 001dd8 microsoft corporation - 001dd9 hon hai precision ind.co.,ltd. + 001dd9 hon hai precision ind. co.,ltd. 001dda mikroelektronika spol. s r. o. 001ddb c-bel corporation 001ddc hangzhou dechanglong tech&info co.,ltd 001ddd dat h.k. limited 001dde zhejiang broadcast&television technology co.,ltd. - 001ddf sunitec enterprise co., ltd. + 001ddf sunitec enterprise co.,ltd 001de0 intel corporate 001de1 intel corporate 001de2 radionor communications 001de3 intuicom 001de4 visioneered image systems - 001de5 cisco systems, inc. - 001de6 cisco systems, inc. + 001de5 cisco systems, inc + 001de6 cisco systems, inc 001de7 marine sonic technology, ltd. 001de8 nikko denki tsushin corporation(ndtc) 001de9 nokia danmark a/s @@ -7676,16 +7678,16 @@ exit 001e08 centec networks inc 001e09 zefatek co.,ltd 001e0a syba tech limited - 001e0b hewlett-packard company + 001e0b hewlett packard 001e0c sherwood information partners, inc. 001e0d micran ltd. 001e0e maxi view holdings limited 001e0f briot international - 001e10 shenzhen huawei communication technologies co.,ltd. + 001e10 huawei technologies co.,ltd 001e11 elelux international ltd 001e12 ecolab - 001e13 cisco systems, inc. - 001e14 cisco systems, inc. + 001e13 cisco systems, inc + 001e14 cisco systems, inc 001e15 beech hill electronics 001e16 keytronix 001e17 stn bv @@ -7696,25 +7698,25 @@ exit 001e1c sws australia pty limited 001e1d east coast datacom, inc. 001e1e honeywell life safety - 001e1f nortel + 001e1f nortel networks 001e20 intertain inc. - 001e21 qisda co. + 001e21 qisda corporation 001e22 arvoo imaging products bv 001e23 electronic educational devices, inc 001e24 zhejiang bell technology co.,ltd - 001e25 intek digital inc + 001e25 intek digital 001e26 digifriends co. ltd 001e27 sbn tech co.,ltd. 001e28 lumexis corporation 001e29 hypertherm inc - 001e2a netgear inc. + 001e2a netgear 001e2b radio systems design, inc. 001e2c cyverse corporation 001e2d stim 001e2e sirti s.p.a. 001e2f dimoto pty ltd 001e30 shireen inc - 001e31 infomark co.,ltd. + 001e31 infomark 001e32 zensys 001e33 inventec corporation 001e34 cryptometrics @@ -7726,28 +7728,28 @@ exit 001e3a nokia danmark a/s 001e3b nokia danmark a/s 001e3c lyngbox media ab - 001e3d alps electric co., ltd + 001e3d alpsalpine co,.ltd 001e3e kmw inc. 001e3f trellisware technologies, inc. - 001e40 shanghai dareglobal technologies co.,ltd. + 001e40 shanghai dareglobal technologies co.,ltd 001e41 microwave communication & component, inc. 001e42 teltonika 001e43 aisin aw co.,ltd. 001e44 santec - 001e45 sony ericsson mobile communications ab + 001e45 sony mobile communications inc 001e46 arris group, inc. 001e47 pt. hariff daya tunggal engineering 001e48 wi-links - 001e49 cisco systems, inc. - 001e4a cisco systems, inc. + 001e49 cisco systems, inc + 001e4a cisco systems, inc 001e4b city theatrical - 001e4c hon hai precision ind.co., ltd. + 001e4c hon hai precision ind. co.,ltd. 001e4d welkin sciences, llc 001e4e dako edv-ingenieur- und systemhaus gmbh 001e4f dell inc. 001e50 battistoni research 001e51 converter industry srl - 001e52 apple + 001e52 apple, inc. 001e53 further tech co., ltd 001e54 toyo electric corporation 001e55 cowon systems,inc. @@ -7769,31 +7771,31 @@ exit 001e65 intel corporate 001e66 resol elektronische regelungen gmbh 001e67 intel corporate - 001e68 quanta computer + 001e68 quanta computer inc. 001e69 thomson inc. 001e6a beijing bluexon technology co.,ltd 001e6b cisco spvtg - 001e6c carbon mountain llc + 001e6c opaque systems 001e6d it r&d center 001e6e shenzhen first mile communications ltd 001e6f magna-power electronics, inc. - 001e70 cobham defence communications ltd + 001e70 cobham antenna systems 001e71 mircom group of companies 001e72 pcs 001e73 zte corporation - 001e74 sagem communication - 001e75 lg electronics + 001e74 sagemcom broadband sas + 001e75 lg electronics (mobile communications) 001e76 thermo fisher scientific 001e77 air2app 001e78 owitek technology ltd., - 001e79 cisco systems, inc. - 001e7a cisco systems, inc. + 001e79 cisco systems, inc + 001e7a cisco systems, inc 001e7b r.i.co. s.r.l. 001e7c taiwick limited 001e7d samsung electronics co.,ltd - 001e7e nortel + 001e7e nortel networks 001e7f cbm of america - 001e80 last mile ltd. + 001e80 icotera a/s 001e81 cnb technology inc. 001e82 sandisk corporation 001e83 lan/man standards association (lmsc) @@ -7809,7 +7811,7 @@ exit 001e8d arris group, inc. 001e8e hunkeler ag 001e8f canon inc. - 001e90 elitegroup computer systems co + 001e90 elitegroup computer systems co.,ltd. 001e91 kimin electronic co., ltd. 001e92 jeulin s.a. 001e93 ciritech systems inc @@ -7839,7 +7841,7 @@ exit 001eab telewell oy 001eac armadeus systems 001ead wingtech group limited - 001eae continental automotive systems + 001eae continental automotive systems inc. 001eaf ophir optronics ltd 001eb0 imesd electronica s.l. 001eb1 cryptsoft pty ltd @@ -7849,47 +7851,47 @@ exit 001eb5 ever sparkle technologies ltd 001eb6 tag heuer sa 001eb7 tbtech, co., ltd. - 001eb8 fortis, inc. + 001eb8 aloys, inc 001eb9 sing fai technology limited 001eba high density devices as 001ebb bluelight technology inc. 001ebc wintech automation co.,ltd. - 001ebd cisco systems, inc. - 001ebe cisco systems, inc. + 001ebd cisco systems, inc + 001ebe cisco systems, inc 001ebf haas automation inc. 001ec0 microchip technology inc. 001ec1 3com europe ltd - 001ec2 apple + 001ec2 apple, inc. 001ec3 kozio, inc. 001ec4 celio corp 001ec5 middle atlantic products inc 001ec6 obvius holdings llc - 001ec7 2wire, inc. - 001ec8 2wire, inc. - 001ec9 2wire, inc. - 001eca 2wire, inc. - 001ecb 2wire, inc. - 001ecc 2wire, inc. + 001ec7 2wire inc + 001ec8 rapid mobile (pty) ltd + 001ec9 dell inc. + 001eca nortel networks + 001ecb rpc energoautomatika ltd + 001ecc cdvi 001ecd kyland technology co. ltd - 001ece 2wire, inc. - 001ecf 2wire, inc. - 001ed0 2wire, inc. - 001ed1 2wire, inc. - 001ed2 2wire, inc. - 001ed3 2wire, inc. - 001ed4 2wire, inc. - 001ed5 2wire, inc. - 001ed6 2wire, inc. - 001ed7 2wire, inc. - 001ed8 2wire, inc. - 001ed9 2wire, inc. - 001eda 2wire, inc. - 001edb 2wire, inc. - 001edc 2wire, inc. - 001edd 2wire, inc. - 001ede 2wire, inc. - 001edf 2wire, inc. - 001ee0 urmet domus spa + 001ece bisa technologies (hong kong) limited + 001ecf philips electronics uk ltd + 001ed0 ingespace + 001ed1 keyprocessor b.v. + 001ed2 ray shine video technology inc + 001ed3 dot technology int'l co., ltd. + 001ed4 doble engineering + 001ed5 tekon-automatics + 001ed6 alentec & orion ab + 001ed7 h-stream wireless, inc. + 001ed8 digital united inc. + 001ed9 mitsubishi precision co.,ltd. + 001eda wesemann elektrotechniek b.v. + 001edb giken trastem co., ltd. + 001edc sony mobile communications inc + 001edd wasko s.a. + 001ede byd company limited + 001edf master industrialization center kista + 001ee0 urmet spa 001ee1 samsung electronics co.,ltd 001ee2 samsung electronics co.,ltd 001ee3 t&w electronics (shenzhen) co.,ltd @@ -7901,7 +7903,7 @@ exit 001ee9 stoneridge electronics ab 001eea sensor switch, inc. 001eeb talk-a-phone co. - 001eec compal information (kunshan) co., ltd. + 001eec compal information (kunshan) co., ltd. 001eed adventiq ltd. 001eee etl systems ltd 001eef cantronic international limited @@ -7911,13 +7913,13 @@ exit 001ef3 from2 001ef4 l-3 communications display systems 001ef5 hitek automated inc. - 001ef6 cisco systems, inc. - 001ef7 cisco systems, inc. + 001ef6 cisco systems, inc + 001ef7 cisco systems, inc 001ef8 emfinity inc. 001ef9 pascom kommunikations systeme gmbh. 001efa protei ltd. 001efb trio motion technology ltd - 001efc jsc "massa-k" + 001efc jsc massa-k 001efd microbit 2.0 ab 001efe level s.r.o. 001eff mueller-elektronik gmbh & co. kg @@ -7930,9 +7932,9 @@ exit 001f06 integrated dispatch solutions 001f07 azteq mobile 001f08 risco ltd - 001f09 jastec co., ltd. - 001f0a nortel - 001f0b federal state unitary enterprise industrial union"electropribor" + 001f09 jastec + 001f0a nortel networks + 001f0b federal state unitary enterprise industrial unionelectropribor 001f0c intelligent digital services gmbh 001f0d l3 communications - telemetry west 001f0e japan kyastem co., ltd @@ -7959,10 +7961,10 @@ exit 001f23 interacoustics 001f24 digitview technology co., ltd. 001f25 mbs gmbh - 001f26 cisco systems, inc. - 001f27 cisco systems, inc. + 001f26 cisco systems, inc + 001f27 cisco systems, inc 001f28 hpn supply chain - 001f29 hewlett-packard company + 001f29 hewlett packard 001f2a accm 001f2b orange logic 001f2c starbridge networks @@ -7972,14 +7974,14 @@ exit 001f30 travelping 001f31 radiocomp 001f32 nintendo co., ltd. - 001f33 netgear inc. + 001f33 netgear 001f34 lung hwa electronics co., ltd. 001f35 air802 llc 001f36 bellwin information co. ltd., 001f37 genesis i&c 001f38 positron 001f39 construcciones y auxiliar de ferrocarriles, s.a. - 001f3a hon hai precision ind.co., ltd. + 001f3a hon hai precision ind. co.,ltd. 001f3b intel corporate 001f3c intel corporate 001f3d qbit gmbh @@ -7991,10 +7993,10 @@ exit 001f43 entes elektronik 001f44 ge transportation systems 001f45 enterasys - 001f46 nortel + 001f46 nortel networks 001f47 mcs logic inc. 001f48 mojix inc. - 001f49 eurosat distribution ltd + 001f49 manhattan tv ltd 001f4a albentia systems s.a. 001f4b lineage power 001f4c roseman engineering ltd @@ -8004,7 +8006,7 @@ exit 001f50 swissdis ag 001f51 hd communications corp 001f52 uvt unternehmensberatung fur verkehr und technik gmbh - 001f53 gemac gesellschaft für mikroelektronikanwendung chemnitz mbh + 001f53 gemac chemnitz gmbh 001f54 lorex technology inc. 001f55 honeywell security (china) co., ltd. 001f56 digital forecast @@ -8012,14 +8014,14 @@ exit 001f58 emh energiemesstechnik gmbh 001f59 kronback tracers 001f5a beckwith electric co. - 001f5b apple + 001f5b apple, inc. 001f5c nokia danmark a/s 001f5d nokia danmark a/s 001f5e dyna technology co.,ltd. 001f5f blatand gmbh 001f60 compass systems corp. 001f61 talent communication networks inc. - 001f62 jsc "stilsoft" + 001f62 jsc stilsoft 001f63 jsc goodwin-europa 001f64 beijing autelan technology inc. 001f65 korea electric terminal co., ltd. @@ -8028,9 +8030,9 @@ exit 001f68 martinsson elektronik ab 001f69 pingood technology co., ltd. 001f6a packetflux technologies, inc. - 001f6b lg electronics - 001f6c cisco systems, inc. - 001f6d cisco systems, inc. + 001f6b lg electronics (mobile communications) + 001f6c cisco systems, inc + 001f6d cisco systems, inc 001f6e vtech engineering corporation 001f6f fujian sunnada communication co.,ltd. 001f70 botik technologies ltd @@ -8051,7 +8053,7 @@ exit 001f7f phabrix limited 001f80 lucas holding bv 001f81 accel semiconductor corp - 001f82 cal-comp electronics & communications co., ltd + 001f82 cal-comp electronics & communications company ltd. 001f83 teleplan technology services sdn bhd 001f84 gigle semiconductor 001f85 apriva iss, llc @@ -8067,10 +8069,10 @@ exit 001f8f shanghai bellmann digital source co.,ltd. 001f90 actiontec electronics, inc 001f91 dbs lodging technologies, llc - 001f92 videoiq, inc. + 001f92 motorola solutions inc. 001f93 xiotech corporation 001f94 lascar electronics ltd - 001f95 sagem communication + 001f95 sagemcom broadband sas 001f96 aprotech co.ltd 001f97 bertana srl 001f98 daiichi-dentsu ltd. @@ -8078,17 +8080,17 @@ exit 001f9a nortel networks 001f9b posbro 001f9c ledco - 001f9d cisco systems, inc. - 001f9e cisco systems, inc. + 001f9d cisco systems, inc + 001f9e cisco systems, inc 001f9f thomson telecom belgium 001fa0 a10 networks 001fa1 gtran inc 001fa2 datron world communications, inc. 001fa3 t&w electronics(shenzhen)co.,ltd. - 001fa4 shenzhen gongjin electronics co.,ltd + 001fa4 shenzhen gongjin electronics co.,lt 001fa5 blue-white industries 001fa6 stilo srl - 001fa7 sony computer entertainment inc. + 001fa7 sony interactive entertainment inc. 001fa8 smart energy instruments inc. 001fa9 atlanta dth, inc. 001faa taseon, inc. @@ -8100,14 +8102,14 @@ exit 001fb0 timeips, inc. 001fb1 cybertech inc. 001fb2 sontheim industrie elektronik gmbh - 001fb3 2wire + 001fb3 2wire inc 001fb4 smartshare systems 001fb5 i/o interconnect inc. 001fb6 chi lin technology co., ltd. 001fb7 wimate technologies corp. 001fb8 universal remote control, inc. 001fb9 paltronics - 001fba boyoung tech. & marketing, inc. + 001fba boyoung tech 001fbb xenatech co.,ltd 001fbc evga corporation 001fbd kyocera wireless corp. @@ -8120,13 +8122,13 @@ exit 001fc4 arris group, inc. 001fc5 nintendo co., ltd. 001fc6 asustek computer inc. - 001fc7 casio hitachi mobile comunications co., ltd. + 001fc7 casio hitachi mobile communications co., ltd. 001fc8 up-today industrial co., ltd. - 001fc9 cisco systems, inc. - 001fca cisco systems, inc. + 001fc9 cisco systems, inc + 001fca cisco systems, inc 001fcb niw solutions 001fcc samsung electronics co.,ltd - 001fcd samsung electronics + 001fcd samsung electronics co.,ltd 001fce qtech llc 001fcf msi technology gmbh 001fd0 giga-byte technology co.,ltd. @@ -8146,10 +8148,10 @@ exit 001fde nokia danmark a/s 001fdf nokia danmark a/s 001fe0 edgevelocity corp - 001fe1 hon hai precision ind. co., ltd. - 001fe2 hon hai precision ind. co., ltd. - 001fe3 lg electronics - 001fe4 sony ericsson mobile communications + 001fe1 hon hai precision ind. co.,ltd. + 001fe2 hon hai precision ind. co.,ltd. + 001fe3 lg electronics (mobile communications) + 001fe4 sony mobile communications inc 001fe5 in-circuit gmbh 001fe6 alphion corporation 001fe7 simet @@ -8164,7 +8166,7 @@ exit 001ff0 audio partnership 001ff1 paradox hellas s.a. 001ff2 via technologies, inc. - 001ff3 apple + 001ff3 apple, inc. 001ff4 power monitors, inc. 001ff5 kongsberg defence & aerospace 001ff6 ps audio international @@ -8191,8 +8193,8 @@ exit 00200b octagon systems corp. 00200c adastra systems corp. 00200d carl zeiss - 00200e satellite technology mgmt, inc - 00200f tanbac co., ltd. + 00200e nsslglobal technologies as + 00200f ebrains inc 002010 jeol system technology co. ltd 002011 canopus co., ltd. 002012 camtronics medical systems @@ -8226,7 +8228,7 @@ exit 00202e daystar digital 00202f zeta communications, ltd. 002030 analog & digital systems - 002031 tattile srl + 002031 tattile srl 002032 alcatel taisel 002033 synapse technologies, inc. 002034 rotec industrieautomation gmbh @@ -8238,7 +8240,7 @@ exit 00203a digital bi0metrics inc. 00203b wisdm ltd. 00203c eurotime ab - 00203d honeywell ecc + 00203d honeywell environmental & combustion controls 00203e logican technologies, inc. 00203f juki corporation 002040 arris group, inc. @@ -8280,7 +8282,7 @@ exit 002064 protec microsystems, inc. 002065 supernet networking inc. 002066 general magic, inc. - 002067 + 002067 private 002068 isdyne 002069 isdn systems corporation 00206a osaka computer corp. @@ -8310,7 +8312,7 @@ exit 002082 oneac corporation 002083 presticom incorporated 002084 oce printing systems, gmbh - 002085 exide electronics + 002085 eaton corporation 002086 microtech electronics limited 002087 memotec, inc. 002088 global village communication @@ -8352,11 +8354,11 @@ exit 0020ac interflex datensysteme gmbh 0020ad linq systems 0020ae ornet data communication tech. - 0020af 3com corporation + 0020af 3com 0020b0 gateway devices, inc. 0020b1 comtech research inc. 0020b2 gkd gesellschaft fur kommunikation und datentechnik - 0020b3 tattile srl + 0020b3 tattile srl 0020b4 terma elektronik as 0020b5 yaskawa electric corporation 0020b6 agile networks, inc. @@ -8389,19 +8391,19 @@ exit 0020d1 microcomputer systems (m) sdn. 0020d2 rad data communications, ltd. 0020d3 ost (ouest standard telematiqu - 0020d4 cabletron - zeittnet inc. + 0020d4 cabletron systems, inc. 0020d5 vipa gmbh - 0020d6 breezecom + 0020d6 breezecom, ltd. 0020d7 japan minicomputer systems co., ltd. 0020d8 nortel networks 0020d9 panasonic technologies, inc./mieco-us - 0020da alcatel north america esd + 0020da alcatel-lucent enterprise 0020db xnet technology, inc. 0020dc densitron taiwan ltd. 0020dd cybertec pty ltd 0020de japan digital laborat'y co.ltd 0020df kyosan electric mfg. co., ltd. - 0020e0 actiontec electronics, inc. + 0020e0 actiontec electronics, inc 0020e1 alamar electronics 0020e2 information resource engineering 0020e3 mcd kencom corporation @@ -8419,7 +8421,7 @@ exit 0020ef usc corporation 0020f0 universal microelectronics co. 0020f1 altos india limited - 0020f2 oracle corporation + 0020f2 oracle corporation 0020f3 raynet corporation 0020f4 spectrix corporation 0020f5 pandatel ag @@ -8438,7 +8440,7 @@ exit 002102 updatelogic inc. 002103 ghi electronics, llc 002104 gigaset communications gmbh - 002105 alcatel-lucent + 002105 alcatel-lucent ipd 002106 rim testing services 002107 seowonintech co ltd. 002108 nokia danmark a/s @@ -8458,10 +8460,10 @@ exit 002116 transcon electronic systems, spol. s r. o. 002117 tellord 002118 athena tech, inc. - 002119 samsung electro-mechanics + 002119 samsung electro mechanics co., ltd. 00211a lintech corporation - 00211b cisco systems, inc. - 00211c cisco systems, inc. + 00211b cisco systems, inc + 00211c cisco systems, inc 00211d dataline ab 00211e arris group, inc. 00211f shinsung deltatech co.,ltd. @@ -8472,7 +8474,7 @@ exit 002124 optos plc 002125 kuk je tong shin co.,ltd 002126 shenzhen torch equipment co., ltd. - 002127 tp-link technology co., ltd. + 002127 tp-link technologies co.,ltd. 002128 oracle corporation 002129 cisco-linksys, llc 00212a audiovox corporation @@ -8495,7 +8497,7 @@ exit 00213b berkshire products, inc 00213c aliphcom 00213d cermetek microelectronics, inc. - 00213e tomtom + 00213e tomtom international bv 00213f a-team technology ltd. 002140 en technologies inc. 002141 radlive @@ -8509,29 +8511,29 @@ exit 002149 china daheng group ,inc. 00214a pixel velocity, inc 00214b shenzhen hamp science & technology co.,ltd - 00214c samsung electronics co., ltd. + 00214c samsung electronics co.,ltd 00214d guangzhou skytone transmission technology com. ltd. 00214e gs yuasa power supply ltd. - 00214f alps electric co., ltd + 00214f alpsalpine co,.ltd 002150 eyeview electronics 002151 millinet co., ltd. 002152 general satellite research & development limited 002153 seamicro inc. 002154 d-tacq solutions ltd - 002155 cisco systems, inc. - 002156 cisco systems, inc. + 002155 cisco systems, inc + 002156 cisco systems, inc 002157 national datacast, inc. 002158 style flying technology co. 002159 juniper networks - 00215a hewlett-packard company - 00215b inotive + 00215a hewlett packard + 00215b senseanywhere 00215c intel corporate 00215d intel corporate 00215e ibm corp 00215f ihse gmbh 002160 hidea solutions co. ltd. 002161 yournet inc. - 002162 nortel + 002162 nortel networks 002163 askey computer corp 002164 special design bureau for seismic instrumentation 002165 presstek inc. @@ -8545,7 +8547,7 @@ exit 00216d soltech co., ltd. 00216e function ati (huizhou) telecommunications co., ltd. 00216f symcom, inc. - 002170 dell inc + 002170 dell inc. 002171 wesung tnc co., ltd. 002172 seoultek valley 002173 ion torrent systems, inc. @@ -8557,17 +8559,17 @@ exit 002179 iogear, inc. 00217a sejin electron, inc. 00217b bastec ab - 00217c 2wire + 00217c 2wire inc 00217d pyxis s.r.l. 00217e telit communication s.p.a 00217f intraco technology pte ltd 002180 arris group, inc. 002181 si2 microsystems limited 002182 sandlinks systems, ltd. - 002183 vatech hydro + 002183 andritz hydro gmbh 002184 powersoft srl 002185 micro-star int'l co.,ltd. - 002186 universal global scientific industrial co., ltd + 002186 universal global scientific industrial co., ltd. 002187 imacs gmbh 002188 emc corporation 002189 apptech, inc. @@ -8584,17 +8586,17 @@ exit 002194 ping communication 002195 gwd media limited 002196 telsey s.p.a. - 002197 elitegroup computer system + 002197 elitegroup computer systems co.,ltd. 002198 thai radio co, ltd 002199 vacon plc 00219a cambridge visual networks ltd - 00219b dell inc + 00219b dell inc. 00219c honeywld technology corp. 00219d adesys bv - 00219e sony ericsson mobile communications + 00219e sony mobile communications inc 00219f satel oy - 0021a0 cisco systems, inc. - 0021a1 cisco systems, inc. + 0021a0 cisco systems, inc + 0021a1 cisco systems, inc 0021a2 eke-electronics ltd. 0021a3 micromint 0021a4 dbii networks @@ -8616,14 +8618,14 @@ exit 0021b4 apro media co., ltd 0021b5 galvanic ltd 0021b6 triacta power technologies inc. - 0021b7 lexmark international inc. + 0021b7 lexmark international, inc. 0021b8 inphi corporation 0021b9 universal devices inc. 0021ba texas instruments 0021bb riken keiki co., ltd. 0021bc zala computer 0021bd nintendo co., ltd. - 0021be cisco, service provider video technology group + 0021be cisco spvtg 0021bf hitachi high-tech control systems corporation 0021c0 mobile appliance, inc. 0021c1 abb oy / medium voltage products @@ -8648,8 +8650,8 @@ exit 0021d4 vollmer werke gmbh 0021d5 x2e gmbh 0021d6 lxi consortium - 0021d7 cisco systems, inc. - 0021d8 cisco systems, inc. + 0021d7 cisco systems, inc + 0021d8 cisco systems, inc 0021d9 sekonic corporation 0021da automation products group inc. 0021db santachi video technology (shenzhen) co., ltd. @@ -8659,14 +8661,14 @@ exit 0021df martin christ gmbh 0021e0 commagility ltd 0021e1 nortel networks - 0021e2 creative electronic gmbh + 0021e2 visago systems & controls gmbh & co. kg 0021e3 serialtek llc 0021e4 i-win 0021e5 display solution ag 0021e6 starlight video limited 0021e7 informatics services corporation 0021e8 murata manufacturing co., ltd. - 0021e9 apple + 0021e9 apple, inc. 0021ea bystronic laser ag 0021eb esp systems, llc 0021ec solutronic gmbh @@ -8684,9 +8686,9 @@ exit 0021f8 enseo, inc. 0021f9 wirecom technologies 0021fa a4sp technologies ltd. - 0021fb lg electronics + 0021fb lg electronics (mobile communications) 0021fc nokia danmark a/s - 0021fd dsta s.l. + 0021fd lacroix traffic s.a.u 0021fe nokia danmark a/s 0021ff cyfrowy polsat sa 002200 ibm corp @@ -8701,8 +8703,8 @@ exit 002209 omron healthcare co., ltd 00220a onlive, inc 00220b national source coding center - 00220c cisco systems, inc. - 00220d cisco systems, inc. + 00220c cisco systems, inc + 00220d cisco systems, inc 00220e indigo security co., ltd. 00220f moca (multimedia over coax alliance) 002210 arris group, inc. @@ -8713,11 +8715,11 @@ exit 002215 asustek computer inc. 002216 shibaura vending machine corporation 002217 neat electronics - 002218 verivue inc. - 002219 dell inc + 002218 akamai technologies inc + 002219 dell inc. 00221a audio precision 00221b morega systems - 00221c + 00221c private 00221d freegene technology ltd 00221e media devices co., ltd. 00221f esang technologies co., ltd. @@ -8747,16 +8749,16 @@ exit 002237 shinhint group 002238 logiplus 002239 indiana life sciences incorporated - 00223a scientific atlanta, cisco spvt group + 00223a cisco spvtg 00223b communication networks, llc 00223c ratio entwicklungen gmbh 00223d jumpgen systems, llc 00223e irtrans gmbh - 00223f netgear inc. + 00223f netgear 002240 universal telecom s/a - 002241 apple + 002241 apple, inc. 002242 alacron inc. - 002243 azurewave technologies, inc. + 002243 azurewave technology inc. 002244 chengdu linkon communications device co., ltd 002245 leine & linde ab 002246 evoc intelligent technology co.,ltd. @@ -8774,8 +8776,8 @@ exit 002252 zoll lifecor corporation 002253 entorian technologies 002254 bigelow aerospace - 002255 cisco systems, inc. - 002256 cisco systems, inc. + 002255 cisco systems, inc + 002256 cisco systems, inc 002257 3com europe ltd 002258 taiyo yuden co., ltd. 002259 guangzhou new postcom equipment co.,ltd. @@ -8789,12 +8791,12 @@ exit 002261 frontier silicon ltd 002262 bep marine 002263 koos technical services, inc. - 002264 hewlett-packard company + 002264 hewlett packard 002265 nokia danmark a/s 002266 nokia danmark a/s 002267 nortel networks - 002268 hon hai precision ind. co., ltd. - 002269 hon hai precision ind. co., ltd. + 002268 hon hai precision ind. co.,ltd. + 002269 hon hai precision ind. co.,ltd. 00226a honeywell 00226b cisco-linksys, llc 00226c linksprite technologies, inc. @@ -8826,22 +8828,22 @@ exit 002286 astron 002287 titan wireless llc 002288 sagrad, inc. - 002289 optosecurity inc. + 002289 vandelrande apc inc. 00228a teratronik elektronische systeme gmbh 00228b kensington computer products group 00228c photon europe gmbh 00228d gbs laboratories llc 00228e tv-numeric 00228f cnrs - 002290 cisco systems, inc. - 002291 cisco systems, inc. + 002290 cisco systems, inc + 002291 cisco systems, inc 002292 cinetal 002293 zte corporation - 002294 kyocera corporation + 002294 kyocera corporation 002295 sgm technology for lighting spa 002296 linowave corporation 002297 xmos semiconductor - 002298 sony ericsson mobile communications + 002298 sony mobile communications inc 002299 seamicro inc. 00229a lastar, inc. 00229b averlogic technologies, inc. @@ -8849,24 +8851,24 @@ exit 00229d pyung-hwa ind.co.,ltd 00229e social aid research co., ltd. 00229f sensys traffic ab - 0022a0 delphi corporation + 0022a0 aptiv services us, llc 0022a1 huawei symantec technologies co.,ltd. 0022a2 xtramus technologies 0022a3 california eastern laboratories - 0022a4 2wire + 0022a4 2wire inc 0022a5 texas instruments 0022a6 sony computer entertainment america 0022a7 tyco electronics amp gmbh 0022a8 ouman oy - 0022a9 lg electronics inc + 0022a9 lg electronics (mobile communications) 0022aa nintendo co., ltd. 0022ab shenzhen turbosight technology ltd 0022ac hangzhou siyuan tech. co., ltd 0022ad telesis technologies, inc. 0022ae mattel inc. - 0022af safety vision + 0022af safety vision, llc 0022b0 d-link corporation - 0022b1 elbit systems + 0022b1 elbit systems ltd. 0022b2 4rf communications ltd 0022b3 sei s.p.a. 0022b4 arris group, inc. @@ -8878,8 +8880,8 @@ exit 0022ba huth elektronik systeme gmbh 0022bb beyerdynamic gmbh & co. kg 0022bc jdsu france sas - 0022bd cisco systems, inc. - 0022be cisco systems, inc. + 0022bd cisco systems, inc + 0022be cisco systems, inc 0022bf sieamp group of companies 0022c0 shenzhen forcelink electronic co, ltd 0022c1 active storage inc. @@ -8895,8 +8897,8 @@ exit 0022cb ionodes inc. 0022cc scilog, inc. 0022cd ared technology co., ltd. - 0022ce cisco, service provider video technology group - 0022cf planex communications inc + 0022ce cisco spvtg + 0022cf planex communications inc. 0022d0 polar electro oy 0022d1 albrecht jung gmbh & co. kg 0022d2 all earth comércio de eletrônicos ltda. @@ -8930,7 +8932,7 @@ exit 0022ee algo communication products ltd 0022ef iwdl technologies 0022f0 3 greens aviation limited - 0022f1 + 0022f1 private 0022f2 sunpower corp 0022f3 sharp corporation 0022f4 ampak technology, inc. @@ -8943,15 +8945,15 @@ exit 0022fb intel corporate 0022fc nokia danmark a/s 0022fd nokia danmark a/s - 0022fe microprocessor designs inc - 0022ff iwdl technologies + 0022fe advanced illumination + 0022ff nivis llc 002300 cayee computer ltd. 002301 witron technology limited 002302 cobalt digital, inc. 002303 lite-on it corporation - 002304 cisco systems, inc. - 002305 cisco systems, inc. - 002306 alps electric co., ltd + 002304 cisco systems, inc + 002305 cisco systems, inc + 002306 alpsalpine co,.ltd 002307 future innovation tech co.,ltd 002308 arcadyan technology corporation 002309 janam technologies llc @@ -8963,7 +8965,7 @@ exit 00230f hirsch electronics corporation 002310 lnc technology co., ltd. 002311 gloscom co., ltd. - 002312 apple + 002312 apple, inc. 002313 qool technologies ltd. 002314 intel corporate 002315 intel corporate @@ -8995,38 +8997,38 @@ exit 00232f advanced card systems ltd. 002330 dizipia, inc. 002331 nintendo co., ltd. - 002332 apple - 002333 cisco systems, inc. - 002334 cisco systems, inc. + 002332 apple, inc. + 002333 cisco systems, inc + 002334 cisco systems, inc 002335 linkflex co.,ltd 002336 metel s.r.o. 002337 global star solutions ulc 002338 oj-electronics a/s - 002339 samsung electronics + 002339 samsung electronics co.,ltd 00233a samsung electronics co.,ltd 00233b c-matic systems ltd 00233c alflex - 00233d novero holding b.v. - 00233e alcatel-lucent-ipd + 00233d laird technologies + 00233e alcatel-lucent ipd 00233f purechoice inc - 002340 mix telematics - 002341 siemens ab, infrastructure & cities, building technologies division, ic bt ssp sp ba pr + 002340 mixtelematics + 002341 vanderbilt international (swe) ab 002342 coffee equipment company 002343 tem ag 002344 objective interface systems, inc. - 002345 sony ericsson mobile communications + 002345 sony mobile communications inc 002346 vestac 002347 procurve networking by hp - 002348 sagem communication + 002348 sagemcom broadband sas 002349 helmholtz centre berlin for material and energy - 00234a + 00234a private 00234b inyuan technology inc. 00234c ktc ab - 00234d hon hai precision ind. co., ltd. - 00234e hon hai precision ind. co., ltd. + 00234d hon hai precision ind. co.,ltd. + 00234e hon hai precision ind. co.,ltd. 00234f luminous power technologies pvt. ltd. - 002350 lyntec - 002351 2wire + 002350 rdc, inc. dba lyntec + 002351 2wire inc 002352 datasensor s.p.a. 002353 f e t elettronica snc 002354 asustek computer inc. @@ -9035,25 +9037,25 @@ exit 002357 pitronot technologies and engineering p.t.e. ltd. 002358 systel sa 002359 benchmark electronics ( thailand ) public company limited - 00235a compal information (kunshan) co., ltd. + 00235a compal information (kunshan) co., ltd. 00235b gulfstream 00235c aprius, inc. - 00235d cisco systems, inc. - 00235e cisco systems, inc. + 00235d cisco systems, inc + 00235e cisco systems, inc 00235f silicon micro sensors gmbh 002360 lookit technology co., ltd 002361 unigen corporation 002362 goldline controls - 002363 zhuhai raysharp technology co., ltd. + 002363 zhuhai raysharp technology co.,ltd 002364 power instruments pte ltd - 002365 elka-elektronik gmbh + 002365 insta elektro gmbh 002366 beijing siasun electronic system co.,ltd. 002367 unicontrols a.s. - 002368 motorola + 002368 zebra technologies inc 002369 cisco-linksys, llc 00236a smartrg inc 00236b xembedded, inc. - 00236c apple + 00236c apple, inc. 00236d resmed ltd 00236e burster gmbh & co kg 00236f daq system @@ -9070,7 +9072,7 @@ exit 00237a rim 00237b whdi llc 00237c neotion - 00237d hewlett-packard company + 00237d hewlett packard 00237e elster gmbh 00237f plantronics, inc. 002380 nanoteq @@ -9079,15 +9081,15 @@ exit 002383 inmage systems inc 002384 ggh engineering s.r.l. 002385 antipode - 002386 tour & andersson ab + 002386 imi hydronic engineering international sa 002387 thinkflood, inc. 002388 v.t. telematica s.p.a. - 002389 hangzhou h3c technologies co., ltd. + 002389 hangzhou h3c technologies co., limited 00238a ciena corporation 00238b quanta computer inc. - 00238c + 00238c private 00238d techno design co., ltd. - 00238e pirelli tyre s.p.a. + 00238e adb broadband italia 00238f nidec copal corporation 002390 algolware corporation 002391 maxian @@ -9097,8 +9099,8 @@ exit 002395 arris group, inc. 002396 andes technology corporation 002397 westell technologies inc. - 002398 sky control - 002399 vd division, samsung electronics co. + 002398 vutlan sro + 002399 samsung electronics co.,ltd 00239a easydata hardware gmbh 00239b elster solutions, llc 00239c juniper networks @@ -9116,8 +9118,8 @@ exit 0023a8 marshall electronics 0023a9 beijing detianquan electromechanical equipment co., ltd 0023aa hfr, inc. - 0023ab cisco systems, inc. - 0023ac cisco systems, inc. + 0023ab cisco systems, inc + 0023ac cisco systems, inc 0023ad xmark corporation 0023ae dell inc. 0023af arris group, inc. @@ -9130,9 +9132,9 @@ exit 0023b6 securite communications / honeywell 0023b7 q-light co., ltd. 0023b8 sichuan jiuzhou electronic technology co.,ltd - 0023b9 eads deutschland gmbh + 0023b9 airbus defence and space deutschland gmbh 0023ba chroma - 0023bb schmitt industries + 0023bb accretech sbs, inc. 0023bc eq-sys gmbh 0023bd digital ally, inc. 0023be cisco spvtg @@ -9150,7 +9152,7 @@ exit 0023ca behind the set, llc 0023cb shenzhen full-join technology co.,ltd 0023cc nintendo co., ltd. - 0023cd tp-link technologies co., ltd. + 0023cd tp-link technologies co.,ltd. 0023ce kita denshi corporation 0023cf cummins-allison corp. 0023d0 uniloc usa inc. @@ -9160,7 +9162,7 @@ exit 0023d4 texas instruments 0023d5 warema electronic gmbh 0023d6 samsung electronics co.,ltd - 0023d7 samsung electronics + 0023d7 samsung electronics co.,ltd 0023d8 ball-it oy 0023d9 banner engineering 0023da industrial computer source (deutschland)gmbh @@ -9168,31 +9170,31 @@ exit 0023dc benein, inc 0023dd elgin s.a. 0023de ansync inc. - 0023df apple + 0023df apple, inc. 0023e0 ino therapeutics llc 0023e1 cavena image products ab 0023e2 sea signalisation 0023e3 microtronic ag 0023e4 ipnect co. ltd. 0023e5 ipaxiom networks - 0023e6 pirkus, inc. + 0023e6 innovation farm, inc. 0023e7 hinke a/s 0023e8 demco corp. 0023e9 f5 networks, inc. - 0023ea cisco systems, inc. - 0023eb cisco systems, inc. + 0023ea cisco systems, inc + 0023eb cisco systems, inc 0023ec algorithmix gmbh 0023ed arris group, inc. 0023ee arris group, inc. 0023ef zuend systemtechnik ag 0023f0 shanghai jinghan weighing apparatus co. ltd. - 0023f1 sony ericsson mobile communications + 0023f1 sony mobile communications inc 0023f2 tvlogic 0023f3 glocom, inc. 0023f4 masternaut 0023f5 wilo se 0023f6 softwell technology co., ltd. - 0023f7 + 0023f7 private 0023f8 zyxel communications corporation 0023f9 double-take software, inc. 0023fa rg nets, inc. @@ -9220,13 +9222,13 @@ exit 002410 nueteq technology,inc. 002411 pharmasmart llc 002412 benign technologies co, ltd. - 002413 cisco systems, inc. - 002414 cisco systems, inc. + 002413 cisco systems, inc + 002414 cisco systems, inc 002415 magnetic autocontrol gmbh 002416 any use 002417 thomson telecom belgium 002418 nextwave semiconductor - 002419 + 002419 private 00241a red beetle inc. 00241b iwow communications pte ltd 00241c fugang electronic (dg) co.,ltd @@ -9237,26 +9239,26 @@ exit 002421 micro-star int'l co., ltd. 002422 knapp logistik automation gmbh 002423 azurewave technologies (shanghai) inc. - 002424 axis network technology + 002424 ace axis limited 002425 shenzhenshi chuangzhicheng technology co.,ltd 002426 nohmi bosai ltd. 002427 ssi computer corp 002428 energyict 002429 mk master inc. 00242a hittite microwave corporation - 00242b hon hai precision ind.co.,ltd. - 00242c hon hai precision ind. co., ltd. + 00242b hon hai precision ind. co.,ltd. + 00242c hon hai precision ind. co.,ltd. 00242e datastrip inc. - 00242f virtensys inc + 00242f micron 002430 ruby tech corp. 002431 uni-v co.,ltd 002432 neostar technology co.,ltd - 002433 alps electric co., ltd + 002433 alpsalpine co,.ltd 002434 lectrosonics, inc. 002435 wide corporation - 002436 apple + 002436 apple, inc. 002437 motorola - bsg - 002438 brocade communications systems, inc + 002438 brocade communications systems llc 002439 digital barriers advanced technologies 00243a ludl electronic products 00243b cssi (s) pte ltd @@ -9268,7 +9270,7 @@ exit 002442 axona limited 002443 nortel networks 002444 nintendo co., ltd. - 002445 commscope canada inc. + 002445 adtran inc 002446 mmb research inc. 002447 kaztek systems 002448 spidercloud wireless, inc @@ -9279,15 +9281,15 @@ exit 00244d hokkaido electronics corporation 00244e radchips, inc. 00244f asantron technologies ltd. - 002450 cisco systems, inc. - 002451 cisco systems, inc. + 002450 cisco systems, inc + 002451 cisco systems, inc 002452 silicon software gmbh 002453 initra d.o.o. - 002454 samsung electronics co., ltd + 002454 samsung electronics co.,ltd 002455 mulogic bv - 002456 2wire + 002456 2wire inc 002458 pa bastion cc - 002459 abb stotz-kontakt gmbh + 002459 abb automation products gmbh 00245a nanjing panda electronics company limited 00245b raidon technology, inc. 00245c design-com technologies pty. ltd. @@ -9306,7 +9308,7 @@ exit 002469 smart doorphones 00246a solid year co., ltd. 00246b covia, inc. - 00246c aruba networks, inc. + 00246c aruba, a hewlett packard enterprise company 00246d weinzierl engineering gmbh 00246e phihong usa corp. 00246f onda communication spa @@ -9324,33 +9326,33 @@ exit 00247b actiontec electronics, inc 00247c nokia danmark a/s 00247d nokia danmark a/s - 00247e universal global scientific industrial co., ltd + 00247e universal global scientific industrial co., ltd. 00247f nortel networks 002480 meteocontrol gmbh - 002481 hewlett-packard company + 002481 hewlett packard 002482 ruckus wireless - 002483 lg electronics + 002483 lg electronics (mobile communications) 002484 bang and olufsen medicom a/s 002485 contextream ltd 002486 designart networks - 002487 blackboard inc. + 002487 transact campus, inc. 002488 centre for development of telematics 002489 vodafone omnitel n.v. 00248a kaga electronics co., ltd. 00248b hybus co., ltd. 00248c asustek computer inc. - 00248d sony computer entertainment inc. + 00248d sony interactive entertainment inc. 00248e infoware zrt. 00248f do-monix 002490 samsung electronics co.,ltd - 002491 samsung electronics + 002491 samsung electronics co.,ltd 002492 motorola, broadband solutions group 002493 arris group, inc. 002494 shenzhen baoxin tech co., ltd. 002495 arris group, inc. 002496 ginzinger electronic systems - 002497 cisco systems, inc. - 002498 cisco systems, inc. + 002497 cisco systems, inc + 002498 cisco systems, inc 002499 aquila technologies 00249a beijing zhongchuang telecommunication test co., ltd. 00249b action star enterprise co., ltd. @@ -9363,7 +9365,7 @@ exit 0024a2 hong kong middleware technology limited 0024a3 sonim technologies inc 0024a4 siklu communication - 0024a5 buffalo inc. + 0024a5 buffalo.inc 0024a6 telestar digital gmbh 0024a7 advanced video communications inc. 0024a8 procurve networking by hp @@ -9372,8 +9374,8 @@ exit 0024ab a7 engineering, inc. 0024ac hangzhou dptech technologies co., ltd. 0024ad adolf thies gmbh & co. kg - 0024ae morpho - 0024af echostar technologies + 0024ae idemia + 0024af dish technologies corp 0024b0 esab ab 0024b1 coulomb technologies 0024b2 netgear @@ -9393,8 +9395,8 @@ exit 0024c0 nti comodo inc 0024c1 arris group, inc. 0024c2 asumo co.,ltd. - 0024c3 cisco systems, inc. - 0024c4 cisco systems, inc. + 0024c3 cisco systems, inc + 0024c4 cisco systems, inc 0024c5 meridian audio limited 0024c6 hager electro sas 0024c7 mobilarm ltd @@ -9408,9 +9410,9 @@ exit 0024cf inscape data corporation 0024d0 shenzhen sogood industry co.,ltd. 0024d1 thomson inc. - 0024d2 askey computer + 0024d2 askey computer corp 0024d3 qualica inc. - 0024d4 freebox sa + 0024d4 freebox sas 0024d5 winward industrial limited 0024d6 intel corporate 0024d7 intel corporate @@ -9431,31 +9433,31 @@ exit 0024e6 in motion technology inc. 0024e7 plaster networks 0024e8 dell inc. - 0024e9 samsung electronics co., ltd., storage system division + 0024e9 samsung electronics co.,ltd 0024ea iris-gmbh infrared & intelligent sensors 0024eb clearpath networks, inc. 0024ec united information technology co.,ltd. 0024ed yt elec. co,.ltd. 0024ee wynmax inc. - 0024ef sony ericsson mobile communications + 0024ef sony mobile communications inc 0024f0 seanodes 0024f1 shenzhen fanhai sanjiang electronics co., ltd. 0024f2 uniphone telecommunication co., ltd. 0024f3 nintendo co., ltd. - 0024f4 kaminario technologies ltd. + 0024f4 kaminario, ltd. 0024f5 nds surgical imaging 0024f6 miyoshi electronics corporation - 0024f7 cisco systems, inc. + 0024f7 cisco systems, inc 0024f8 technical solutions company ltd. - 0024f9 cisco systems, inc. + 0024f9 cisco systems, inc 0024fa hilger u. kern gmbh - 0024fb + 0024fb private 0024fc quopin co., ltd. 0024fd accedian networks inc 0024fe avm gmbh 0024ff qlogic corporation - 002500 apple - 002501 jsc "supertel" + 002500 apple, inc. + 002501 jsc supertel 002502 naturalpoint 002503 ibm corp 002504 valiant communications limited @@ -9466,12 +9468,12 @@ exit 002509 sharetronic group ltd 00250a security expert co. ltd 00250b centrofactor inc - 00250c enertrac + 00250c senet inc 00250d gzt telkom-telmor sp. z o.o. 00250e gt german telematics gmbh 00250f on-ramp wireless, inc. 002510 pico-tesla magnetic therapies - 002511 elitegroup computer system co., ltd. + 002511 elitegroup computer systems co.,ltd. 002512 zte corporation 002513 cxp digital bv 002514 pc worth int'l co., ltd. @@ -9513,7 +9515,7 @@ exit 002539 ifta gmbh 00253a ceva, ltd. 00253b din dietmar nocker facilitymanagement gmbh - 00253c 2wire + 00253c 2wire inc 00253d drs consolidated controls 00253e sensus metering systems 002540 quasar technologies, inc. @@ -9521,25 +9523,25 @@ exit 002542 pittasoft 002543 moneytech 002544 lojack corporation - 002545 cisco systems, inc. - 002546 cisco systems, inc. + 002545 cisco systems, inc + 002546 cisco systems, inc 002547 nokia danmark a/s 002548 nokia danmark a/s 002549 jeorich tech. co.,ltd. 00254a ringcube technologies, inc. - 00254b apple + 00254b apple, inc. 00254c videon central, inc. 00254d singapore technologies electronics limited 00254e vertex wireless co., ltd. 00254f elettrolab srl - 002550 riverbed technology + 002550 riverbed technology, inc. 002551 se-elektronic gmbh 002552 vxi corporation - 002553 pirelli tyre s.p.a. + 002553 adb broadband italia 002554 pixel8 networks - 002555 visonic technologies 1993 ltd - 002556 hon hai precision ind. co., ltd. - 002557 research in motion + 002555 visonic technologies 1993 ltd. + 002556 hon hai precision ind. co.,ltd. + 002557 blackberry rts 002558 mpedia 002559 syphan technologies ltd 00255a tantalus systems corp. @@ -9555,12 +9557,12 @@ exit 002564 dell inc. 002565 vizimax inc. 002566 samsung electronics co.,ltd - 002567 samsung electronics - 002568 shenzhen huawei communication technologies co., ltd - 002569 sagem communication + 002567 samsung electronics co.,ltd + 002568 huawei technologies co.,ltd + 002569 sagemcom broadband sas 00256a init - institut industrial it 00256b atenix e.e. s.r.l. - 00256c "azimut" production association jsc + 00256c azimut production association jsc 00256d broadband forum 00256e van breda b.v. 00256f dantherm power @@ -9572,7 +9574,7 @@ exit 002575 fiberplex technologies, llc 002576 neli technologies 002577 d-box technologies - 002578 jsc "concern "sozvezdie" + 002578 jsc concern sozvezdie 002579 j & f labs 00257a camco produktions- und vertriebs-gmbh für beschallungs- und beleuchtungsanlagen 00257b stj electronics pvt ltd @@ -9583,15 +9585,15 @@ exit 002580 equipson s.a. 002581 x-star networks inc. 002582 maksat technologies (p) ltd - 002583 cisco systems, inc. - 002584 cisco systems, inc. + 002583 cisco systems, inc + 002584 cisco systems, inc 002585 kokuyo s&t co., ltd. - 002586 tp-link technologies co., ltd. + 002586 tp-link technologies co.,ltd. 002587 vitality, inc. 002588 genie industries, inc. 002589 hills industries limited 00258a pole/zero corporation - 00258b mellanox technologies ltd + 00258b mellanox technologies, inc. 00258c esus elektronik san. ve dis. tic. ltd. sti. 00258d haier 00258e the weather channel @@ -9609,8 +9611,8 @@ exit 00259a cestronics gmbh 00259b beijing pkunity microsystems technology co., ltd 00259c cisco-linksys, llc - 00259d - 00259e huawei technologies co., ltd. + 00259d private + 00259e huawei technologies co.,ltd 00259f technodigital technologies gmbh 0025a0 nintendo co., ltd. 0025a1 enalasys @@ -9619,7 +9621,7 @@ exit 0025a4 eurodesign embedded technologies gmbh 0025a5 walnut media network 0025a6 central network solution co., ltd. - 0025a7 comverge, inc. + 0025a7 itron 0025a8 kontron (beijing) technology co.,ltd 0025a9 shanghai embedway information technologies co.,ltd 0025aa beijing soul technology co.,ltd. @@ -9631,23 +9633,23 @@ exit 0025b0 schmartz inc 0025b1 maya-creation corporation 0025b2 mbda deutschland gmbh - 0025b3 hewlett-packard company - 0025b4 cisco systems, inc. - 0025b5 cisco systems, inc. + 0025b3 hewlett packard + 0025b4 cisco systems, inc + 0025b5 cisco systems, inc 0025b6 telecom fm 0025b7 costar electronics, inc., 0025b8 agile communications, inc. 0025b9 cypress solutions inc 0025ba alcatel-lucent ipd 0025bb innerint co., ltd. - 0025bc apple + 0025bc apple, inc. 0025bd italdata ingegneria dell'idea s.p.a. 0025be tektrap systems inc. 0025bf wireless cables inc. 0025c0 zilliontv corporation 0025c1 nawoo korea corp. 0025c2 ringbell co.,ltd. - 0025c3 nortel networks + 0025c3 21168 0025c4 ruckus wireless 0025c5 star link communication pvt. ltd. 0025c6 kasercorp, ltd @@ -9663,8 +9665,8 @@ exit 0025d0 nokia danmark a/s 0025d1 eastern asia technology limited 0025d2 inpegvision co., ltd - 0025d3 azurewave technologies, inc - 0025d4 fortress technologies + 0025d3 azurewave technology inc. + 0025d4 general dynamics mission systems 0025d5 robonica (pty) ltd 0025d6 the kroger co. 0025d7 cedo @@ -9672,18 +9674,18 @@ exit 0025d9 datafab systems inc. 0025da secura key 0025db ati electronics(shenzhen) co., ltd - 0025dc sumitomo electric networks, inc + 0025dc sumitomo electric industries, ltd 0025dd sunnytek information co., ltd. 0025de probits co., ltd. - 0025df + 0025df taser international inc. 0025e0 ceedtec sdn bhd 0025e1 shanghai seeyoo electronic & technology co., ltd 0025e2 everspring industry co., ltd. 0025e3 hanshinit inc. 0025e4 omni-wifi, llc - 0025e5 lg electronics inc + 0025e5 lg electronics (mobile communications) 0025e6 belgian monitoring systems bvba - 0025e7 sony ericsson mobile communications + 0025e7 sony mobile communications inc 0025e8 idaho technology 0025e9 i-mate development, inc. 0025ea iphion bv @@ -9715,10 +9717,10 @@ exit 002605 cc systems ab 002606 raumfeld gmbh 002607 enabling technology pty ltd - 002608 apple + 002608 apple, inc. 002609 phyllis co., ltd. - 00260a cisco systems, inc. - 00260b cisco systems, inc. + 00260a cisco systems, inc + 00260b cisco systems, inc 00260c dataram 00260d mercury systems, inc. 00260e ablaze systems, llc @@ -9741,7 +9743,7 @@ exit 00261f sae magnetics (h.k.) ltd. 002620 isgus gmbh 002621 intelicloud technology inc. - 002622 compal information (kunshan) co., ltd. + 002622 compal information (kunshan) co., ltd. 002623 jrd communication inc 002624 thomson inc. 002625 mediasputnik @@ -9762,7 +9764,7 @@ exit 002634 infineta systems, inc 002635 bluetechnix gmbh 002636 arris group, inc. - 002637 samsung electro-mechanics + 002637 samsung electro mechanics co., ltd. 002638 xia men joyatech co., ltd. 002639 t.m. electronics, inc. 00263a digitec systems @@ -9774,23 +9776,23 @@ exit 002640 baustem broadband technologies, ltd. 002641 arris group, inc. 002642 arris group, inc. - 002643 alps electric co., ltd + 002643 alpsalpine co,.ltd 002644 thomson telecom belgium 002645 circontrol s.a. 002646 shenyang tongfang multimedia technology company limited 002647 wfe technology corp. 002648 emitech corp. - 00264a apple + 00264a apple, inc. 00264c shanghai digivision technology co., ltd. 00264d arcadyan technology corporation - 00264e rail & road protec gmbh + 00264e r2p gmbh 00264f krüger &gothe gmbh - 002650 2wire - 002651 cisco systems, inc. - 002652 cisco systems, inc. + 002650 2wire inc + 002651 cisco systems, inc + 002652 cisco systems, inc 002653 daysequerra corporation - 002654 3com corporation - 002655 hewlett-packard company + 002654 3com + 002655 hewlett packard 002656 sansonic electronics usa 002657 ooo npp ekra 002658 t-platforms (cyprus) limited @@ -9798,7 +9800,7 @@ exit 00265a d-link corporation 00265b hitron technologies. inc 00265c hon hai precision ind. co.,ltd. - 00265d samsung electronics + 00265d samsung electronics co.,ltd 00265e hon hai precision ind. co.,ltd. 00265f samsung electronics co.,ltd 002660 logiways @@ -9813,7 +9815,7 @@ exit 002669 nokia danmark a/s 00266a essensium nv 00266b shine union enterprise limited - 00266c inventec + 00266c inventec corporation 00266d mobileaccess networks 00266e nissho-denki co.,ltd. 00266f coordiwise technology corp. @@ -9821,7 +9823,7 @@ exit 002671 autovision co., ltd 002672 aamp of america 002673 ricoh company,ltd. - 002674 electronic solutions, inc. + 002674 hunter douglas 002675 aztech electronics pte ltd 002676 commidt as 002677 deif a/s @@ -9833,7 +9835,7 @@ exit 00267d a-max technology macao commercial offshore company limited 00267e parrot sa 00267f zenterio ab - 002680 lockie innovation pty ltd + 002680 sil3 pty.ltd 002681 interspiro ab 002682 gemtek technology co., ltd. 002683 ajoho enterprise co., ltd. @@ -9850,21 +9852,21 @@ exit 00268e alta solutions, inc. 00268f mta spa 002690 i do it - 002691 sagem communication - 002692 mitsubishi electric co. + 002691 sagemcom broadband sas + 002692 mitsubishi electric corporation 002693 qvidium technologies, inc. 002694 senscient ltd 002695 zt group int'l inc 002696 noolix co., ltd - 002697 cheetah technologies, l.p. - 002698 cisco systems, inc. - 002699 cisco systems, inc. + 002697 alpha technologies inc. + 002698 cisco systems, inc + 002699 cisco systems, inc 00269a carina system co., ltd. 00269b sokrat ltd. 00269c itus japan co. ltd 00269d m2mnet co., ltd. - 00269e quanta computer inc - 00269f + 00269e quanta computer inc. + 00269f private 0026a0 moblic 0026a1 megger 0026a2 instrumentation technology systems @@ -9881,20 +9883,20 @@ exit 0026ad arada systems, inc. 0026ae wireless measurement ltd 0026af duelco a/s - 0026b0 apple + 0026b0 apple, inc. 0026b1 navis auto motive systems, inc. 0026b2 setrix gmbh 0026b3 thales communications inc 0026b4 ford motor company 0026b5 icomm tele ltd - 0026b6 askey computer + 0026b6 askey computer corp 0026b7 kingston technology company, inc. 0026b8 actiontec electronics, inc - 0026b9 dell inc + 0026b9 dell inc. 0026ba arris group, inc. - 0026bb apple + 0026bb apple, inc. 0026bc general jack technology ltd. - 0026bd jtec card & communication co., ltd. + 0026bd jtec card & communication co., ltd 0026be schoonderbeek elektronica systemen b.v. 0026bf shenzhen temobi science&tech development co.,ltd 0026c0 energyhub @@ -9907,8 +9909,8 @@ exit 0026c7 intel corporate 0026c8 system sensor 0026c9 proventix systems, inc. - 0026ca cisco systems, inc. - 0026cb cisco systems, inc. + 0026ca cisco systems, inc + 0026cb cisco systems, inc 0026cc nokia danmark a/s 0026cd purplecomm, inc. 0026ce kozumi usa corp. @@ -9922,7 +9924,7 @@ exit 0026d6 ningbo andy optoelectronic co., ltd. 0026d7 km electornic technology co., ltd. 0026d8 magic point inc. - 0026d9 pace plc + 0026d9 arris group, inc. 0026da universal media corporation /slovakia/ s.r.o. 0026db ionics ems inc. 0026dc optical systems design @@ -9931,9 +9933,9 @@ exit 0026df taidoc technology corp. 0026e0 asiteq 0026e1 stanford university, openflow group - 0026e2 lg electronics + 0026e2 lg electronics (mobile communications) 0026e3 dti - 0026e4 canal overseas + 0026e4 canal + 0026e5 aeg power solutions 0026e6 visionhitech co., ltd. 0026e7 shanghai onlan communication tech. co., ltd. @@ -9952,7 +9954,7 @@ exit 0026f4 nesslab 0026f5 xrplus inc. 0026f6 military communication institute - 0026f7 infosys technologies ltd. + 0026f7 nivetti systems pvt. ltd. 0026f8 golden highway industry development co., ltd. 0026f9 s.e.m. srl 0026fa bandrich inc. @@ -9960,7 +9962,7 @@ exit 0026fc acsip technology corp. 0026fd interactive intelligence 0026fe mkd technology inc. - 0026ff research in motion + 0026ff blackberry rts 002700 shenzhen siglent technology co., ltd. 002701 incostartec gmbh 002702 solaredge technologies @@ -9973,8 +9975,8 @@ exit 002709 nintendo co., ltd. 00270a iee s.a. 00270b adura technologies - 00270c cisco systems, inc. - 00270d cisco systems, inc. + 00270c cisco systems, inc + 00270d cisco systems, inc 00270e intel corporate 00270f envisionnovation inc 002710 intel corporate @@ -9986,7 +9988,7 @@ exit 002716 adachi-syokai co., ltd. 002717 ce digital(zhenjiang)co.,ltd 002718 suzhou new seaunion video technology co.,ltd - 002719 tp-link technologies co., ltd. + 002719 tp-link technologies co.,ltd. 00271a geenovo technology ltd. 00271b alec sicherheitssysteme gmbh 00271c mercury corporation @@ -9995,11 +9997,24 @@ exit 00271f mipro electronics co., ltd 002720 new-sol com 002721 shenzhen baoan fenda industrial co., ltd - 002722 ubiquiti networks - 0027f8 brocade communications systems, inc. - 002a6a cisco systems, inc. + 002722 ubiquiti networks inc. + 002790 cisco systems, inc + 0027e3 cisco systems, inc + 0027f8 brocade communications systems llc + 00289f semptian co., ltd. + 0028f8 intel corporate + 002926 applied optoelectronics, inc taiwan branch + 0029c2 cisco systems, inc + 002a10 cisco systems, inc + 002a6a cisco systems, inc 002aaf larsys-automation gmbh + 002b67 lcfc(hefei) electronics technology co., ltd + 002cc8 cisco systems, inc 002d76 titech gmbh + 002db3 ampak technology,inc. + 002ec7 huawei technologies co.,ltd + 002f5c cisco systems, inc + 002fd9 fiberhome telecommunication technologies co.,ltd 003000 allwell technology corp. 003001 smp 003002 expand networks @@ -10017,7 +10032,7 @@ exit 00300e klotz digital ag 00300f imt - information management t 003010 visionetics international - 003011 hms industrial networks + 003011 hms industrial networks 003012 digital engineering ltd. 003013 nec corporation 003014 divio, inc. @@ -10025,18 +10040,18 @@ exit 003016 ishida co., ltd. 003017 bluearc uk ltd 003018 jetway information co., ltd. - 003019 cisco systems, inc. + 003019 cisco systems, inc 00301a smartbridges pte. ltd. 00301b shuttle, inc. 00301c altvater airdata systems 00301d skystream, inc. - 00301e 3com europe ltd. + 00301e 3com europe ltd 00301f optical networks, inc. 003020 tsi, inc.. 003021 hsing tech. enterprise co.,ltd 003022 fong kai industrial co., ltd. 003023 cogent computer systems, inc. - 003024 cisco systems, inc. + 003024 cisco systems, inc 003025 checkout computer systems, ltd 003026 heitel digital video gmbh 003027 kerbango, inc. @@ -10064,7 +10079,7 @@ exit 00303d iva corporation 00303e radcom ltd. 00303f turbocomm tech inc. - 003040 cisco systems, inc. + 003040 cisco systems, inc 003041 saejin t & m co., ltd. 003042 detewe-deutsche telephonwerke 003043 idream technologies, pte. ltd. @@ -10072,7 +10087,7 @@ exit 003045 village networks, inc. (vni) 003046 controlled electronic manageme 003047 nissei electric co., ltd. - 003048 supermicro computer, inc. + 003048 super micro computer, inc. 003049 bryant technology, ltd. 00304a fraunhofer ipms 00304b orbacom systems, inc. @@ -10084,9 +10099,9 @@ exit 003051 orbit avionic & communication 003052 elastic networks 003053 basler ag - 003054 castlenet technology, inc. + 003054 castlenet technology inc. 003055 renesas technology america, inc. - 003056 beck ipc gmbh + 003056 hms industrial networks 003057 qtelnet, inc. 003058 api motion 003059 kontron compact computers ag @@ -10101,7 +10116,7 @@ exit 003062 ip video networks inc 003063 santera systems, inc. 003064 adlink technology, inc. - 003065 apple + 003065 apple, inc. 003066 rfm 003067 biostar microtech int'l corp. 003068 cybernetics tech. co., ltd. @@ -10113,27 +10128,27 @@ exit 00306e hewlett packard 00306f seyeon tech. co., ltd. 003070 1net corporation - 003071 cisco systems, inc. + 003071 cisco systems, inc 003072 intellibyte inc. 003073 international microsystems, in 003074 equiinet ltd. 003075 adtech 003076 akamba corporation 003077 onprem networks - 003078 cisco systems, inc. + 003078 cisco systems, inc 003079 cqos, inc. 00307a advanced technology & systems - 00307b cisco systems, inc. + 00307b cisco systems, inc 00307c adid sa 00307d gre america, inc. 00307e redflex communication systems 00307f irlan ltd. - 003080 cisco systems, inc. + 003080 cisco systems, inc 003081 altos c&c 003082 taihan electric wire co., ltd. 003083 ivron systems 003084 allied telesyn internaional - 003085 cisco systems, inc. + 003085 cisco systems, inc 003086 transistor devices, inc. 003087 vega grieshaber kg 003088 ericsson @@ -10146,11 +10161,11 @@ exit 00308f micrilor, inc. 003090 cyra technologies, inc. 003091 taiwan first line elec. corp. - 003092 modunorm gmbh + 003092 kontron electronics ag 003093 sonnet technologies, inc - 003094 cisco systems, inc. + 003094 cisco systems, inc 003095 procomp informatics, ltd. - 003096 cisco systems, inc. + 003096 cisco systems, inc 003097 ab regin 003098 global converging technologies 003099 boenig und kallenbach ohg @@ -10163,7 +10178,7 @@ exit 0030a0 tyco submarine systems, ltd. 0030a1 webgate inc. 0030a2 lightner engineering - 0030a3 cisco systems, inc. + 0030a3 cisco systems, inc 0030a4 woodwind communications system 0030a5 active power 0030a6 vianet technologies, ltd. @@ -10182,7 +10197,7 @@ exit 0030b3 san valley systems, inc. 0030b4 intersil corp. 0030b5 tadiran microwave networks - 0030b6 cisco systems, inc. + 0030b6 cisco systems, inc 0030b7 teletrol systems, inc. 0030b8 riverdelta networks 0030b9 ectel @@ -10193,11 +10208,11 @@ exit 0030be city-net technology, inc. 0030bf multidata gmbh 0030c0 lara technology, inc. - 0030c1 hewlett-packard + 0030c1 hewlett packard 0030c2 comone 0030c3 flueckiger elektronik ag 0030c4 canon imaging systems inc. - 0030c5 cadence design systems + 0030c5 cadence design systems, inc. 0030c6 control solutions, inc. 0030c7 macromate corp. 0030c8 gad line, ltd. @@ -10211,14 +10226,14 @@ exit 0030d0 tellabs 0030d1 inova corporation 0030d2 win technologies, co., ltd. - 0030d3 agilent technologies + 0030d3 agilent technologies, inc. 0030d4 aae systems, inc. 0030d5 dresearch gmbh 0030d6 msc vertriebs gmbh 0030d7 innovative systems, l.l.c. 0030d8 sitek 0030d9 datacore software corp. - 0030da comtrend co. + 0030da comtrend corporation 0030db mindready solutions, inc. 0030dc rightech corporation 0030dd indigita corporation @@ -10241,8 +10256,8 @@ exit 0030ee dsg technology, inc. 0030ef neon technology, inc. 0030f0 uniform industrial corp. - 0030f1 accton technology corp. - 0030f2 cisco systems, inc. + 0030f1 accton technology corp + 0030f2 cisco systems, inc 0030f3 at work computers 0030f4 stardot technologies 0030f5 wild lab. ltd. @@ -10255,23 +10270,41 @@ exit 0030fc terawave communications, inc. 0030fd integrated systems design 0030fe dsa gmbh - 0030ff datafab systems, inc. + 0030ff datafab systems inc. + 003146 juniper networks + 003192 tp-link corporation limited + 003217 cisco systems, inc + 00323a so-logic 00336c synapsense corporation + 0034a1 rf-lambda usa inc. + 0034da lg electronics (mobile communications) 0034f1 radicom research, inc. + 0034fe huawei technologies co.,ltd + 00351a cisco systems, inc 003532 electro-metrics corporation + 003560 rosen aviation + 0035ff texas instruments + 003676 arris group, inc. + 0036be northwest towers 0036f8 conti temic microelectronic gmbh 0036fe supervision 00376d murata manufacturing co., ltd. - 003a98 cisco systems, inc. - 003a99 cisco systems, inc. - 003a9a cisco systems, inc. - 003a9b cisco systems, inc. - 003a9c cisco systems, inc. - 003a9d nec accesstechnica, ltd. + 0037b7 sagemcom broadband sas + 0038df cisco systems, inc + 003a7d cisco systems, inc + 003a98 cisco systems, inc + 003a99 cisco systems, inc + 003a9a cisco systems, inc + 003a9b cisco systems, inc + 003a9c cisco systems, inc + 003a9d nec platforms, ltd. 003aaf bluebit ltd. + 003c10 cisco systems, inc 003cc5 wonwoo engineering co., ltd 003d41 hatteland computer as - 003ee1 apple + 003de1 huawei device co., ltd. + 003de8 lg electronics (mobile communications) + 003ee1 apple, inc. 004000 pci componentes da amzonia ltd 004001 zero one technology co. ltd. 004002 perle systems limited @@ -10283,7 +10316,7 @@ exit 004008 a plus info corporation 004009 tachibana tectron co., ltd. 00400a pivotal technologies, inc. - 00400b cisco systems, inc. + 00400b cisco systems, inc 00400c general micro systems, inc. 00400d lannet data communications,ltd 00400e memotec, inc. @@ -10304,17 +10337,17 @@ exit 00401d invisible software, inc. 00401e icc 00401f colorgraph ltd - 004020 te connectivity ltd. + 004020 commscope inc 004021 raster graphics 004022 klever computers, inc. 004023 logic corporation 004024 compac inc. 004025 molecular dynamics - 004026 buffalo inc. + 004026 buffalo.inc 004027 smc massachusetts, inc. 004028 netcomm limited 004029 compex - 00402a canoga-perkins + 00402a canoga perkins corporation 00402b trigem computer, inc. 00402c isis distributed systems, inc. 00402d harris adacom corporation @@ -10326,7 +10359,7 @@ exit 004033 addtron technology co., ltd. 004034 bustek corporation 004035 opcom - 004036 tribe computer works, inc. + 004036 zoom telephonics, inc 004037 sea-ilan, inc. 004038 talent electric incorporated 004039 optec daiichi denko co., ltd. @@ -10353,7 +10386,7 @@ exit 00404e fluent, inc. 00404f space & naval warfare systems 004050 ironics, incorporated - 004051 gracilis, inc. + 004051 garbee and garbee 004052 star technologies, inc. 004053 ampro computers 004054 connection machines services @@ -10374,7 +10407,7 @@ exit 004063 via technologies, inc. 004064 kla instruments corporation 004065 gte spacenet - 004066 hitachi metals, ltd. + 004066 apresia systems ltd 004067 omnibyte corporation 004068 extended systems 004069 lemcom systems, inc. @@ -10389,7 +10422,7 @@ exit 004072 applied innovation inc. 004073 bass associates 004074 cable and wireless - 004075 tattile srl + 004075 tattile srl 004076 sun conversion technologies 004077 maxton technology corporation 004078 wearnes automation pte ltd @@ -10404,7 +10437,7 @@ exit 004081 mannesmann scangraphic gmbh 004082 laboratory equipment corp. 004083 tda industria de produtos - 004084 honeywell acs + 004084 honeywell international hps 004085 saab instruments ab 004086 michels & kleberhoff computer 004087 ubitrex corporation @@ -10414,7 +10447,7 @@ exit 00408b raylan corporation 00408c axis communications ab 00408d the goodyear tire & rubber co. - 00408e tattile srl + 00408e tattile srl 00408f wm-data minfo ab 004090 ansel communications 004091 procomp industria eletronica @@ -10422,16 +10455,16 @@ exit 004093 paxdata networks ltd. 004094 shographics, inc. 004095 r.p.t. intergroups int'l ltd. - 004096 cisco systems + 004096 cisco systems, inc 004097 datex division of 004098 dressler gmbh & co. 004099 newgen systems corp. 00409a network express, inc. 00409b hal computer systems inc. 00409c transware - 00409d digiboard, inc. + 00409d digiboard 00409e concurrent technologies ltd. - 00409f telco systems, inc. + 00409f telco systems, inc. 0040a0 goldstar co., ltd. 0040a1 ergo computing 0040a2 kingstar technology inc. @@ -10442,7 +10475,7 @@ exit 0040a7 itautec philco s.a. 0040a8 imf international ltd. 0040a9 datacom inc. - 0040aa metso automation + 0040aa valmet automation 0040ab roland dg corporation 0040ac super workstation, inc. 0040ad sma regelsysteme gmbh @@ -10485,7 +10518,7 @@ exit 0040d2 pagine corporation 0040d3 kimpsion international corp. 0040d4 gage talker corp. - 0040d5 sartorius mechatronics t&h gmbh + 0040d5 sartorius mechatronics t&h gmbh 0040d6 locamation b.v. 0040d7 studio gen inc. 0040d8 ocean office automation ltd. @@ -10523,45 +10556,56 @@ exit 0040f8 systemhaus discom 0040f9 combinet 0040fa microboards, inc. - 0040fb cascade communications corp. + 0040fb cascade communications 0040fc ibr computer technik gmbh 0040fd lxe 0040fe symplex communications 0040ff telebit corporation 0041b4 wuxi zhongxing optoelectronics technology co.,ltd. + 0041d2 cisco systems, inc + 004238 intel corporate 004252 rlx technologies + 00425a cisco systems, inc + 004268 cisco systems, inc + 004279 sunitec enterprise co.,ltd 0043ff ketron s.r.l. - 004501 versus technology, inc. + 004501 midmark rtls + 00451d cisco systems, inc + 0045e2 cybertan technology inc. 00464b huawei technologies co.,ltd + 004a77 zte corporation + 004bf3 shenzhen mercury communication technologies co.,ltd. 004d32 andon health co.,ltd. + 004e01 dell inc. + 004e35 hewlett packard enterprise 005000 nexo communications, inc. 005001 yamashita systems corp. 005002 omnisec ag 005003 xrite inc - 005004 3com corporation + 005004 3com 005006 tac ab 005007 siemens telecommunication systems limited 005008 tiva microcomputer corp. (tmc) 005009 philips broadband networks 00500a iris technologies, inc. - 00500b cisco systems, inc. + 00500b cisco systems, inc 00500c e-tek labs, inc. 00500d satori electoric co., ltd. 00500e chromatis networks, inc. - 00500f cisco systems, inc. + 00500f cisco systems, inc 005010 novanet learning, inc. 005012 cbl - gmbh - 005013 chaparral network storage - 005014 cisco systems, inc. + 005013 seagate cloud systems inc + 005014 cisco systems, inc 005015 bright star engineering - 005016 sst/woodhead industries + 005016 molex canada ltd 005017 rsr s.r.l. 005018 amit, inc. 005019 spring tide networks, inc. 00501a iqinvision 00501b abl canada, inc. 00501c jatom systems, inc. - 00501e miranda technologies, inc. + 00501e grass valley, a belden brand 00501f mrg systems, ltd. 005020 mediastar co., ltd. 005021 eis international, inc. @@ -10572,7 +10616,7 @@ exit 005027 genicom corporation 005028 aval communications 005029 1394 printer working group - 00502a cisco systems, inc. + 00502a cisco systems, inc 00502b genrad ltd. 00502c soyo computer, inc. 00502d accel, inc. @@ -10589,7 +10633,7 @@ exit 00503a datong electronics ltd. 00503b mediafire corporation 00503c tsinghua novel electronics - 00503e cisco systems, inc. + 00503e cisco systems, inc 00503f anchor games 005040 panasonic electric works co., ltd. 005041 coretronic corporation @@ -10598,7 +10642,7 @@ exit 005044 asaca corporation 005045 rioworks solutions, inc. 005046 menicx international co., ltd. - 005047 + 005047 private 005048 infolibria 005049 arbor networks inc 00504a elteco a.s. @@ -10607,15 +10651,15 @@ exit 00504d tokyo electron device limited 00504e sierra monitor corp. 00504f olencom electronics - 005050 cisco systems, inc. + 005050 cisco systems, inc 005051 iwatsu electric co., ltd. 005052 tiara networks, inc. - 005053 cisco systems, inc. - 005054 cisco systems, inc. + 005053 cisco systems, inc + 005054 cisco systems, inc 005055 doms a/s 005056 vmware, inc. 005057 broadband access systems - 005058 vegastream group limted + 005058 sangoma technologies 005059 ibahn 00505a network alchemy, inc. 00505b kawasaki lsi u.s.a., inc. @@ -10640,43 +10684,43 @@ exit 005070 chaintech computer co., ltd. 005071 aiwa co., ltd. 005072 corvis corporation - 005073 cisco systems, inc. + 005073 cisco systems, inc 005074 advanced hi-tech corp. 005075 kestrel solutions 005076 ibm corp 005077 prolific technology, inc. 005078 megaton house, ltd. - 005079 + 005079 private 00507a xpeed, inc. 00507b merlot communications 00507c videocon ag 00507d ifp 00507e newer technology 00507f draytek corp. - 005080 cisco systems, inc. + 005080 cisco systems, inc 005081 murata machinery, ltd. 005082 foresson corporation 005083 gilbarco, inc. - 005084 atl products + 005084 quantum corp. 005086 telkom sa, ltd. 005087 terasaki electric co., ltd. 005088 amano corporation 005089 safety management systems - 00508b hewlett-packard company + 00508b hewlett packard 00508c rsi systems 00508d abit computer corporation 00508e optimation, inc. 00508f asita technologies int'l ltd. 005090 dctri 005091 netaccess, inc. - 005092 rigaku industrial corporation + 005092 rigaku corporation osaka plant 005093 boeing - 005094 pace plc + 005094 arris group, inc. 005095 peracom networks 005096 salix technologies, inc. 005097 mmc-embedded computertechnik gmbh 005098 globaloop, ltd. - 005099 3com europe, ltd. + 005099 3com europe ltd 00509a tag electronic systems 00509b switchcore ab 00509c beta research @@ -10685,12 +10729,12 @@ exit 00509f horizon computer 0050a0 delta computer systems, inc. 0050a1 carlo gavazzi, inc. - 0050a2 cisco systems, inc. + 0050a2 cisco systems, inc 0050a3 transmedia communications, inc. 0050a4 io tech, inc. 0050a5 capitol business systems, ltd. 0050a6 optronics - 0050a7 cisco systems, inc. + 0050a7 cisco systems, inc 0050a8 opencon systems, inc. 0050a9 moldat wireless technolgies 0050aa konica minolta holdings, inc. @@ -10704,33 +10748,34 @@ exit 0050b2 brodel gmbh 0050b3 voiceboard corporation 0050b4 satchwell control systems, ltd - 0050b5 fichet-bauche + 0050b5 fichet securite electronique 0050b6 good way ind. co., ltd. 0050b7 boser technology co., ltd. 0050b8 inova computers gmbh & co. kg 0050b9 xitron technologies, inc. - 0050ba d-link + 0050ba d-link corporation 0050bb cms technologies 0050bc hammer storage solutions - 0050bd cisco systems, inc. + 0050bd cisco systems, inc 0050be fast multimedia ag 0050bf metalligence technology corp. 0050c0 gatan, inc. 0050c1 gemflex networks, ltd. - 0050c2 ieee registration authority - please see iab public listing for more information. + 0050c2 ieee registration authority 0050c4 imd 0050c5 ads technologies, inc 0050c6 loop telecommunication international, inc. + 0050c7 private 0050c8 addonics technologies, inc. 0050c9 maspro denkoh corp. 0050ca net to net technologies 0050cb jetter - 0050cc xyratex + 0050cc seagate cloud systems inc 0050cd digianswer a/s 0050ce lg international corp. 0050cf vanlink communication technology research institute 0050d0 minerva systems - 0050d1 cisco systems, inc. + 0050d1 cisco systems, inc 0050d2 cmc electronics inc 0050d3 digital audio processing pty. ltd. 0050d4 joohong information & @@ -10739,16 +10784,16 @@ exit 0050d7 telstrat 0050d8 unicorn computer corp. 0050d9 engetron-engenharia eletronica ind. e com. ltda - 0050da 3com corporation + 0050da 3com 0050db contemporary control 0050dc tas telefonbau a. schwabe gmbh & co. kg 0050dd serra soldadura, s.a. 0050de signum systems corp. 0050df airfiber, inc. 0050e1 ns tech electronics sdn bhd - 0050e2 cisco systems, inc. + 0050e2 cisco systems, inc 0050e3 arris group, inc. - 0050e4 apple + 0050e4 apple, inc. 0050e6 hakusan corporation 0050e7 paradise innovations (asia) 0050e8 nomadix inc. @@ -10758,26 +10803,49 @@ exit 0050ed anda networks 0050ee tek digitel corporation 0050ef spe systemhaus gmbh - 0050f0 cisco systems, inc. - 0050f1 intel corporation + 0050f0 cisco systems, inc + 0050f1 maxlinear, inc 0050f2 microsoft corp. 0050f3 global net information co., ltd. 0050f4 sigmatek gmbh & co. kg 0050f6 pan-international industrial corp. 0050f7 venture manufacturing (singapore) ltd. 0050f8 entrega technologies, inc. - 0050f9 sensormatic acd + 0050f9 sensormatic electronics llc 0050fa oxtel, ltd. 0050fb vsk electronics - 0050fc edimax technology co., ltd. + 0050fc edimax technology co. ltd. 0050fd visioncomm co., ltd. 0050fe pctvnet asa 0050ff hakko electronics co., ltd. + 0051ed lg innotek 005218 wuxi keboda electron co.ltd + 0052c2 peiker acustic gmbh + 00549f avaya inc 0054af continental automotive systems inc. + 0054bd swelaser ab + 0055b1 shanghai baud data communication co.,ltd. + 0055da ieee registration authority + 00562b cisco systems, inc + 0056cd apple, inc. + 0057c1 lg electronics (mobile communications) + 0057d2 cisco systems, inc + 00583f pc aquarius 005907 lenovoemc products usa, llc + 005979 networked energy services + 0059ac kpn. b.v. + 0059dc cisco systems, inc + 005a13 huawei technologies co.,ltd + 005a39 shenzhen fast technologies co.,ltd + 005b94 apple, inc. + 005ba1 shanghai huayuan chuangxin software co., ltd. + 005c86 shenzhen fast technologies co.,ltd 005cb1 gospell digital technology co., ltd 005d03 xilinx, inc + 005d73 cisco systems, inc + 005e0c hmd global oy + 005f67 tp-link corporation limited + 005f86 cisco systems, inc 006000 xycom inc. 006001 innosys, inc. 006002 screen subtitling systems, ltd @@ -10786,14 +10854,14 @@ exit 006005 feedback data ltd. 006006 sotec co., ltd 006007 acres gaming, inc. - 006008 3com corporation - 006009 cisco systems, inc. + 006008 3com + 006009 cisco systems, inc 00600a sord computer corporation 00600b logware gmbh 00600c eurotech inc. 00600d digital logic gmbh 00600e wavenet international, inc. - 00600f westell, inc. + 00600f westell technologies inc. 006010 network machines, inc. 006011 crystal semiconductor corp. 006012 power computing corporation @@ -10825,7 +10893,7 @@ exit 00602c linx data terminals, inc. 00602d alerton technologies, inc. 00602e cyclades corporation - 00602f cisco systems, inc. + 00602f cisco systems, inc 006030 village tronic entwicklung 006031 hrk systems 006032 i-cube, inc. @@ -10840,24 +10908,24 @@ exit 00603b amtec spa 00603c hagiwara sys-com co., ltd. 00603d 3cx - 00603e cisco systems, inc. + 00603e cisco systems, inc 00603f patapsco designs 006040 netro corp. - 006041 yokogawa electric corporation + 006041 yokogawa digital computer corporation 006042 tks (usa), inc. 006043 idirect, inc. 006044 litton/poly-scientific 006045 pathlight technologies 006046 vmetro, inc. - 006047 cisco systems, inc. - 006048 emc corporation + 006047 cisco systems, inc + 006048 dell emc 006049 vina technologies 00604a saic ideas group 00604b safe-com gmbh & co. kg - 00604c sagem communication + 00604c sagemcom broadband sas 00604d mmc networks, inc. 00604e cycle computer corporation, inc. - 00604f tattile srl + 00604f tattile srl 006050 internix inc. 006051 quality semiconductor 006052 peripherals enterprise co., ltd. @@ -10870,31 +10938,31 @@ exit 006059 technical communications corp. 00605a celcore, inc. 00605b intraserver technology, inc. - 00605c cisco systems, inc. + 00605c cisco systems, inc 00605d scanivalve corp. 00605e liberty technology networking 00605f nippon unisoft corporation - 006060 dawning technologies, inc. + 006060 data innovations north america 006061 whistle communications corp. 006062 telesync, inc. 006063 psion dacom plc. 006064 netcomm limited - 006065 bernecker & rainer industrie-elektronic gmbh + 006065 b&r industrial automation gmbh 006066 lacroix trafic 006067 acer netxus inc. 006068 dialogic corporation - 006069 brocade communications systems, inc. + 006069 brocade communications systems llc 00606a mitsubishi wireless communications. inc. 00606b synclayer inc. 00606c arescom 00606d digital equipment corp. 00606e davicom semiconductor, inc. 00606f clarion corporation of america - 006070 cisco systems, inc. + 006070 cisco systems, inc 006071 midas lab, inc. 006072 vxl instruments, limited 006073 redcreek communications, inc. - 006074 qsc audio products + 006074 qsc llc 006075 pentek, inc. 006076 schlumberger technologies retail petroleum systems 006077 prisa networks @@ -10909,16 +10977,16 @@ exit 006080 microtronix datacom ltd. 006081 tv/com international 006082 novalink technologies, inc. - 006083 cisco systems, inc. + 006083 cisco systems, inc 006084 digital video 006085 storage concepts 006086 logic replacement tech. ltd. 006087 kansai electric co., ltd. - 006088 white mountain dsp, inc. + 006088 analog devices, inc. 006089 xata 00608a citadel computer 00608b confertech international - 00608c 3com corporation + 00608c 3com 00608d unipulse corp. 00608e he electronics, technologie & systemtechnik gmbh 00608f tekram technology co., ltd. @@ -10929,11 +10997,11 @@ exit 006094 ibm corp 006095 accu-time systems, inc. 006096 t.s. microtech inc. - 006097 3com corporation + 006097 3com 006098 ht communications 006099 sbe, inc. 00609a njk techno co. - 00609b astro-med, inc. + 00609b astronova, inc 00609c perkin-elmer incorporated 00609d pmi food equipment group 00609e asc x3 - information technology standards secretariats @@ -10954,7 +11022,7 @@ exit 0060ad megachips corporation 0060ae trio information systems ab 0060af pacific micro data, inc. - 0060b0 hewlett-packard co. + 0060b0 hewlett packard 0060b1 input/output, inc. 0060b2 process control corp. 0060b3 z-com, inc. @@ -10963,11 +11031,11 @@ exit 0060b6 land computer co., ltd. 0060b7 channelmatic, inc. 0060b8 corelis inc. - 0060b9 nec infrontia corporation + 0060b9 nec platforms, ltd 0060ba sahara networks, inc. - 0060bb cabletron - netlink, inc. + 0060bb cabletron systems, inc. 0060bc keunyoung electronics & communication co., ltd. - 0060bd hubbell-pulsecom + 0060bd enginuity communications 0060be webtronics 0060bf macraigor systems, inc. 0060c0 nera networks as @@ -10991,17 +11059,17 @@ exit 0060d2 lucent technologies taiwan telecommunications co., ltd. 0060d3 at&t 0060d4 eldat communication ltd. - 0060d5 miyachi technos corp. - 0060d6 novatel wireless technologies ltd. + 0060d5 amada miyachi co., ltd + 0060d6 novatel inc. 0060d7 ecole polytechnique federale de lausanne (epfl) 0060d8 elmic systems, inc. 0060d9 transys networks inc. - 0060da jbm electronics co. + 0060da red lion controls, lp 0060db ntp elektronik a/s - 0060dc toyo network systems & system integration co. ltd + 0060dc nec magnus communications,ltd. 0060dd myricom, inc. 0060de kayser-threde gmbh - 0060df brocade communications systems, inc. + 0060df brocade communications systems llc 0060e0 axiom technology co., ltd. 0060e1 orckit communications ltd. 0060e2 quest engineering & development @@ -11034,19 +11102,59 @@ exit 0060fd netics, inc. 0060fe lynx system developers, inc. 0060ff quvis, inc. - 006440 cisco systems, inc. + 006151 huawei technologies co.,ltd + 006171 apple, inc. + 0062ec cisco systems, inc + 0063de cloudwalk technology co.,ltd + 006440 cisco systems, inc 0064a6 maquet cardiovascular - 00664b huawei technologies co., ltd - 006b9e vizio inc + 006619 huawei device co., ltd. + 00664b huawei technologies co.,ltd + 006762 fiberhome telecommunication technologies co.,ltd + 00682b huawei device co., ltd. + 0068eb hp inc. + 00692d sunnovo international limited + 006967 ieee registration authority + 006b6f huawei technologies co.,ltd + 006b8e shanghai feixun communication co.,ltd. + 006b9e vizio, inc 006ba0 shenzhen universal intellisys pte ltd - 006dfb vutrix (uk) ltd + 006bf1 cisco systems, inc + 006cbc cisco systems, inc + 006cfd sichuan changhong electric ltd. + 006d52 apple, inc. + 006d61 guangzhou v-solution electronic technology co., ltd. + 006dfb vutrix technologies ltd + 006e02 xovis ag + 006f64 samsung electronics co.,ltd + 006ff2 mitsumi electric co.,ltd. 0070b0 m/a-com inc. companies 0070b3 data recall ltd. - 00738d tinno mobile technology corp + 007147 amazon technologies inc. + 0071c2 pegatron corporation + 0071cc hon hai precision ind. co.,ltd. + 007204 samsung electronics co., ltd. artik + 007263 netcore technology inc. + 007278 cisco systems, inc + 00738d shenzhen tinno mobile technology corp. 0073e0 samsung electronics co.,ltd + 00749c ruijie networks co.,ltd + 007532 inid bv 0075e1 ampt, llc - 00789e sagemcom + 00763d veea + 007686 cisco systems, inc + 0076b1 somfy-protect by myfox sas + 00778d cisco systems, inc + 0077e4 nokia solutions and networks gmbh & co. kg + 007888 cisco systems, inc + 00789e sagemcom broadband sas + 0078cd ignition design labs + 007b18 sentry co., ltd. + 007c2d samsung electronics co.,ltd + 007d60 apple, inc. 007dfa volkswagen group of america + 007e56 china dragon technology limited + 007e95 cisco systems, inc 007f28 actiontec electronics, inc 008000 multitech systems, inc. 008001 periphonics corporation @@ -11085,7 +11193,7 @@ exit 008022 scan-optics 008023 integrated business networks 008024 kalpana, inc. - 008025 stollmann gmbh + 008025 telit wireless solutions gmbh 008026 network products corporation 008027 adaptive systems, inc. 008028 tradpost (hk) ltd @@ -11114,11 +11222,11 @@ exit 00803f tatung company 008040 john fluke manufacturing co. 008041 veb kombinat robotron - 008042 emerson network power + 008042 artesyn embedded technologies 008043 networld, inc. 008044 systech computer corp. 008045 matsushita electric ind. co - 008046 tattile srl + 008046 tattile srl 008047 in-net corp. 008048 compex incorporated 008049 nissin electric co., ltd. @@ -11134,16 +11242,16 @@ exit 008053 intellicom, inc. 008054 frontier technologies corp. 008055 fermilab - 008056 sphinx elektronik gmbh + 008056 sphinx electronics gmbh & co kg 008057 adsoft, ltd. - 008058 printer systems corporation + 008058 printer systems corp. 008059 stanley electric co., ltd 00805a tulip computers internat'l b.v 00805b condor systems, inc. 00805c agilis corporation 00805d canstar 00805e lsi logic corporation - 00805f hewlett-packard company + 00805f hewlett packard 008060 network interface corporation 008061 litton systems, inc. 008062 interface co. @@ -11156,7 +11264,7 @@ exit 008069 computone systems 00806a eri (empac research inc.) 00806b schmid telecommunication - 00806c cegelec projects ltd + 00806c secure systems & services 00806d century systems corp. 00806e nippon steel corporation 00806f onelan ltd. @@ -11188,7 +11296,7 @@ exit 008089 tecnetics (pty) ltd. 00808a summit microsystems corp. 00808b dacoll limited - 00808c netscout systems, inc. + 00808c netscout systems inc 00808d westcoast technology b.v. 00808e radstone technology 00808f c. itoh electronics, inc. @@ -11207,8 +11315,8 @@ exit 00809c luxcom, inc. 00809d commscraft ltd. 00809e datus gmbh - 00809f alcatel business systems - 0080a0 edisa hewlett packard s/a + 00809f ale international + 0080a0 hewlett packard 0080a1 microtest, inc. 0080a2 creative electronic systems 0080a3 lantronix @@ -11230,9 +11338,9 @@ exit 0080b3 aval data corporation 0080b4 sophia systems 0080b5 united networks inc. - 0080b6 themis computer + 0080b6 mercury systems – trusted mission solutions, inc. 0080b7 stellar computer - 0080b8 b.u.g. moriseiki, incorporated + 0080b8 dmg mori b.u.g. co., ltd. 0080b9 arche technoligies inc. 0080ba specialix (asia) pte, ltd 0080bb hughes lan systems @@ -11242,7 +11350,7 @@ exit 0080bf takaoka electric mfg. co. ltd. 0080c0 penril datacomm 0080c1 lanex corporation - 0080c2 ieee 802.1 committee + 0080c2 ieee 802.1 working group 0080c3 bicc information systems & svc 0080c4 document technologies, inc. 0080c5 novellco de mexico @@ -11273,13 +11381,13 @@ exit 0080de gipsi s.a. 0080df adc codenoll technology corp. 0080e0 xtp systems, inc. - 0080e1 stmicroelectronics + 0080e1 stmicroelectronics srl 0080e2 t.d.i. co., ltd. 0080e3 coral network corporation 0080e4 northwest digital systems, inc - 0080e5 netapp, inc + 0080e5 netapp 0080e6 peer networks, inc. - 0080e7 lynwood scientific dev. ltd. + 0080e7 leonardo tactical systems. 0080e8 cumulus corporatiion 0080e9 madge ltd. 0080ea adva optical networking ltd. @@ -11295,7 +11403,7 @@ exit 0080f4 telemecanique electrique 0080f5 quantel ltd 0080f6 synergy microsystems - 0080f7 zenith electronics + 0080f7 zenith electronics corporation 0080f8 mizar, inc. 0080f9 heurikon corporation 0080fa rwt gmbh @@ -11304,20 +11412,32 @@ exit 0080fd exsceed corpration 0080fe azure technologies, inc. 0080ff soc. de teleinformatique rtc - 0086a0 - 008865 apple + 0081c4 cisco systems, inc + 0081f9 texas instruments + 0084ed private + 00869c palo alto networks + 0086a0 private + 008701 samsung electronics co.,ltd + 008731 cisco systems, inc + 008764 cisco systems, inc + 008865 apple, inc. + 0088ba nc&c + 008a55 huawei device co., ltd. + 008a96 cisco systems, inc 008b43 rftech + 008bfc mixi,inc. 008c10 black box corp. 008c54 adb broadband italia 008cfa inventec corporation 008d4e cjsc nii stt 008dda link one co., ltd. - 008ef2 netgear inc., + 008e73 cisco systems, inc + 008ef2 netgear 009000 diamond multimedia 009001 nishimu electronics industries co., ltd. 009002 allgon ab 009003 aplio - 009004 3com europe ltd. + 009004 3com europe ltd 009005 protech systems co., ltd. 009006 hamamatsu photonics k.k. 009007 domex technology corp. @@ -11325,7 +11445,7 @@ exit 009009 i controls, inc. 00900a proton electronic industrial co., ltd. 00900b lanner electronics, inc. - 00900c cisco systems, inc. + 00900c cisco systems, inc 00900d overland storage inc. 00900e handlink technologies, inc. 00900f kawasaki heavy industries, ltd @@ -11346,7 +11466,7 @@ exit 00901e selesta ingegneria s.p.a. 00901f adtec productions, inc. 009020 philips analytical x-ray b.v. - 009021 cisco systems, inc. + 009021 cisco systems, inc 009022 ivex 009023 zilog inc. 009024 pipelinks, inc. @@ -11356,7 +11476,7 @@ exit 009028 nippon signal co., ltd. 009029 crypto ag 00902a communication devices, inc. - 00902b cisco systems, inc. + 00902b cisco systems, inc 00902c data & control equipment ltd. 00902d data electronics (aust.) pty, ltd. 00902e namco limited @@ -11380,7 +11500,7 @@ exit 009040 siemens network convergence llc 009041 applied digital access 009042 eccs, inc. - 009043 tattile srl + 009043 tattile srl 009044 assured digital, inc. 009045 marconi communications 009046 dexdyne, ltd. @@ -11393,7 +11513,7 @@ exit 00904d spec s.a. 00904e delem bv 00904f abb power t&d company, inc. - 009050 teleste oy + 009050 teleste corporation 009051 ultimate technology corp. 009052 selcom elettronica s.r.l. 009053 daewoo electronics co., ltd. @@ -11401,14 +11521,14 @@ exit 009055 parker hannifin corporation compumotor division 009056 telestream, inc. 009057 aanetcom, inc. - 009058 ultra electronics ltd., command and control systems + 009058 ultra electronics command & control systems 009059 telecom device k.k. 00905a dearborn group, inc. 00905b raymond and lae engineering 00905c edmi 00905d netcom sicherheitstechnik gmbh 00905e rauland-borg corporation - 00905f cisco systems, inc. + 00905f cisco systems, inc 009060 system create corp. 009061 pacific research & engineering corporation 009062 icp vortex computersysteme gmbh @@ -11418,13 +11538,13 @@ exit 009066 troika networks, inc. 009067 walkabout computers, inc. 009068 dvt corp. - 009069 juniper networks, inc. + 009069 juniper networks 00906a turnstone systems, inc. 00906b applied resources, inc. 00906c sartorius hamburg gmbh - 00906d cisco systems, inc. + 00906d cisco systems, inc 00906e praxon, inc. - 00906f cisco systems, inc. + 00906f cisco systems, inc 009070 neo networks, inc. 009071 applied innovation inc. 009072 simrad as @@ -11447,7 +11567,7 @@ exit 009083 turbo communication, inc. 009084 atech system 009085 golden enterprises, inc. - 009086 cisco systems, inc. + 009086 cisco systems, inc 009087 itis 009088 baxall security ltd. 009089 softcom microsystems, inc. @@ -11459,11 +11579,11 @@ exit 00908f audio codes ltd. 009090 i-bus 009091 digitalscape, inc. - 009092 cisco systems, inc. - 009093 nanao corporation + 009092 cisco systems, inc + 009093 eizo corporation 009094 osprey technologies, inc. 009095 universal avionics - 009096 askey computer corp. + 009096 askey computer corp 009097 sycamore networks 009098 sbc designs, inc. 009099 allied telesis, k.k. @@ -11475,22 +11595,22 @@ exit 00909f digi-data corporation 0090a0 8x8 inc. 0090a1 flying pig systems/high end systems inc. - 0090a2 cybertan technology, inc. + 0090a2 cybertan technology inc. 0090a3 corecess inc. 0090a4 altiga networks 0090a5 spectra logic - 0090a6 cisco systems, inc. + 0090a6 cisco systems, inc 0090a7 clientec corporation 0090a8 ninetiles networks, ltd. 0090a9 western digital 0090aa indigo active vision systems limited - 0090ab cisco systems, inc. + 0090ab cisco systems, inc 0090ac optivision, inc. 0090ad aspect electronics, inc. - 0090ae italtel s.p.a. + 0090ae italtel s.p.a/rf-up-i 0090af j. morita mfg. corp. 0090b0 vadem - 0090b1 cisco systems, inc. + 0090b1 cisco systems, inc 0090b2 avici systems inc. 0090b3 agranat systems 0090b4 willowbrook technologies @@ -11504,7 +11624,7 @@ exit 0090bc telemann co., ltd. 0090bd omnia communications, inc. 0090be ibc/integrated business computers - 0090bf cisco systems, inc. + 0090bf cisco systems, inc 0090c0 k.j. law engineers, inc. 0090c1 peco ii, inc. 0090c2 jk microsystems, inc. @@ -11517,9 +11637,9 @@ exit 0090c9 dpac technologies 0090ca accord video telecommunications, ltd. 0090cb wireless online, inc. - 0090cc planex communications + 0090cc planex communications inc. 0090cd ent-empresa nacional de telecommunicacoes, s.a. - 0090ce tetra gmbh + 0090ce avateramedical mechatronics gmbh 0090cf nortel 0090d0 thomson telecom belgium 0090d1 leichu enterprise co., ltd. @@ -11527,10 +11647,10 @@ exit 0090d3 giesecke & devrient gmbh 0090d4 bindview development corp. 0090d5 euphonix, inc. - 0090d6 crystal group + 0090d6 crystal group, inc. 0090d7 netboost corp. 0090d8 whitecross systems - 0090d9 cisco systems, inc. + 0090d9 cisco systems, inc 0090da dynarc, inc. 0090db next level communications 0090dc teco information systems @@ -11554,15 +11674,15 @@ exit 0090ee personal communications technologies 0090ef integrix, inc. 0090f0 harmonic video systems ltd. - 0090f1 dot hill systems corporation - 0090f2 cisco systems, inc. + 0090f1 seagate cloud systems inc + 0090f2 cisco systems, inc 0090f3 aspect communications 0090f4 lightning instrumentation 0090f5 clevo co. 0090f6 escalate networks, inc. 0090f7 nbase communications ltd. 0090f8 mediatrix telecom - 0090f9 leitch + 0090f9 imagine communications 0090fa emulex corporation 0090fb portwell, inc. 0090fc network computing devices @@ -11571,12 +11691,21 @@ exit 0090ff tellus technology inc. 0091d6 crystal group, inc. 0091fa synapse product development + 00927d ficosa internationa(taicang) c0.,ltd. 0092fa shenzhen wisky technology co.,ltd 009363 uni-link technology co., ltd. + 0094a1 f5 networks, inc. + 0094ec huawei device co., ltd. 009569 lsd science and technology co.,ltd. 0097ff heimann sensor gmbh - 009c02 hewlett-packard company + 009acd huawei technologies co.,ltd + 009ad2 cisco systems, inc + 009c02 hewlett packard + 009d6b murata manufacturing co., ltd. 009d8e cardiac recorders, inc. + 009e1e cisco systems, inc + 009ec8 xiaomi communications co ltd + 009eee positivo tecnologia s.a. 00a000 centillion networks, inc. 00a001 drs signal solutions 00a002 leeds & northrup australia pty ltd @@ -11591,11 +11720,11 @@ exit 00a00b computex co., ltd. 00a00c kingmax technology, inc. 00a00d the panda project - 00a00e visual networks, inc. + 00a00e netscout systems inc 00a00f broadband technologies 00a010 syslogic datentechnik ag 00a011 mutoh industries ltd. - 00a012 telco systems, inc. + 00a012 telco systems, inc. 00a013 teltrend ltd. 00a014 csir 00a015 wyle @@ -11606,14 +11735,14 @@ exit 00a01a binar elektronik ab 00a01b premisys communications, inc. 00a01c nascent networks corporation - 00a01d sixnet + 00a01d red lion controls, lp 00a01e est corporation 00a01f tricord systems, inc. 00a020 citicorp/tti - 00a021 general dynamics + 00a021 general dynamics mission systems 00a022 centre for development of advanced computing 00a023 applied creative technology, inc. - 00a024 3com corporation + 00a024 3com 00a025 redcom labs inc. 00a026 teldat, s.a. 00a027 firepower systems, inc. @@ -11624,7 +11753,7 @@ exit 00a02c interwave communications 00a02d 1394 trade association 00a02e brand communications, ltd. - 00a02f pirelli cavi + 00a02f adb broadband italia 00a030 captor nv/sa 00a031 hazeltine corporation, ms 1-17 00a032 ges singapore pte. ltd. @@ -11641,12 +11770,12 @@ exit 00a03d opto-22 00a03e atm forum 00a03f computer society microprocessor & microprocessor standards c - 00a040 apple + 00a040 apple, inc. 00a041 inficon 00a042 spur products corp. 00a043 american technology labs, inc. 00a044 ntt it co., ltd. - 00a045 phoenix contact gmbh & co. + 00a045 phoenix contact electronics gmbh 00a046 scitex corp. ltd. 00a047 integrated fitness corp. 00a048 questech, ltd. @@ -11661,7 +11790,7 @@ exit 00a051 angia communications. inc. 00a052 stanilite electronics pty. ltd 00a053 compact devices, inc. - 00a054 + 00a054 private 00a055 data device corporation 00a056 micropross 00a057 lancom systems gmbh @@ -11688,7 +11817,7 @@ exit 00a06c shindengen electric mfg. co., ltd. 00a06d mannesmann tally corporation 00a06e austron, inc. - 00a06f the appcon group, inc. + 00a06f color sentinel systems, llc 00a070 coastcom 00a071 video lottery technologies,inc 00a072 ovation systems ltd. @@ -11705,12 +11834,12 @@ exit 00a07d seeq technology, inc. 00a07e avid technology, inc. 00a07f gsm-syntel, ltd. - 00a080 tattile srl + 00a080 tattile srl 00a081 alcatel data networks 00a082 nkt elektronik a/s 00a083 asimmphony turkey 00a084 dataplex pty ltd - 00a085 + 00a085 private 00a086 amber wave systems, inc. 00a087 microsemi corporation 00a088 essential communications @@ -11727,7 +11856,7 @@ exit 00a093 b/e aerospace, inc. 00a094 comsat corporation 00a095 acacia networks, inc. - 00a096 mitsumi electric co., ltd. + 00a096 mitsumi electric co.,ltd. 00a097 jc information systems 00a098 netapp 00a099 k-net ltd. @@ -11741,7 +11870,7 @@ exit 00a0a1 epic data inc. 00a0a2 digicom s.p.a. 00a0a3 reliable power meters - 00a0a4 micros systems, inc. + 00a0a4 oracle corporation 00a0a5 teknor microsysteme, inc. 00a0a6 m.i. systems, k.k. 00a0a7 vorax corporation @@ -11753,7 +11882,7 @@ exit 00a0ad marconi spa 00a0ae nucom systems, inc. 00a0af wms industries - 00a0b0 i-o data device, inc. + 00a0b0 i-o data device,inc. 00a0b1 first virtual corporation 00a0b2 shima seiki 00a0b3 zykronix @@ -11761,7 +11890,7 @@ exit 00a0b5 3h technology 00a0b6 sanritz automation co., ltd. 00a0b7 cordant, inc. - 00a0b8 symbios logic inc. + 00a0b8 netapp 00a0b9 eagle technology, inc. 00a0ba patton electronics co. 00a0bb hilan gmbh @@ -11774,11 +11903,11 @@ exit 00a0c2 r.a. systems co., ltd. 00a0c3 unicomputer gmbh 00a0c4 cristie electronics ltd. - 00a0c5 zyxel communication - 00a0c6 qualcomm incorporated + 00a0c5 zyxel communications corporation + 00a0c6 qualcomm inc. 00a0c7 tadiran telecommunications - 00a0c8 adtran inc. - 00a0c9 intel corporation - hf1-06 + 00a0c8 adtran inc + 00a0c9 intel corporation 00a0ca fujitsu denso ltd. 00a0cb ark telecommunications, inc. 00a0cc lite-on communications, inc. @@ -11790,7 +11919,7 @@ exit 00a0d2 allied telesis international corporation 00a0d3 instem computer systems, ltd. 00a0d4 radiolan, inc. - 00a0d5 sierra wireless inc. + 00a0d5 sierra wireless 00a0d6 sbe, inc. 00a0d7 kasten chase applied research 00a0d8 spectra - tek @@ -11825,41 +11954,59 @@ exit 00a0f5 radguard ltd. 00a0f6 autogas systems inc. 00a0f7 v.i computer corp. - 00a0f8 symbol technologies, inc. + 00a0f8 zebra technologies inc 00a0f9 bintec communications gmbh 00a0fa marconi communication gmbh - 00a0fb toray engineering co., ltd. + 00a0fb toray engineering d solutions co., ltd. 00a0fc image sciences, inc. 00a0fd scitex digital printing, inc. 00a0fe boston technology, inc. 00a0ff tellabs operations, inc. 00a1de shenzhen shihua technology co.,ltd + 00a289 cisco systems, inc 00a2da inat gmbh + 00a2ee cisco systems, inc + 00a2f5 guangzhou yuanyun network technology co.,ltd 00a2ff abatec group ag + 00a38e cisco systems, inc + 00a3d1 cisco systems, inc + 00a509 wigwag inc. + 00a5bf cisco systems, inc + 00a6ca cisco systems, inc + 00a742 cisco systems, inc + 00a784 itx security 00aa00 intel corporation 00aa01 intel corporation 00aa02 intel corporation 00aa3c olivetti telecom spa (olteco) - 00aa70 lg electronics + 00aa6e cisco systems, inc + 00aa70 lg electronics (mobile communications) + 00ab48 eero inc. 00ace0 arris group, inc. - 00b009 grass valley group + 00ad24 d-link international + 00ad63 dedicated micros malta ltd + 00add5 huawei device co., ltd. + 00aecd pensando systems + 00aefa murata manufacturing co., ltd. + 00af1f cisco systems, inc + 00b009 grass valley, a belden brand 00b017 infogear technology corp. 00b019 utc ccs 00b01c westport technologies 00b01e rantic labs, inc. 00b02a orsys gmbh 00b02d viagate technologies, inc. - 00b033 oao "izhevskiy radiozavod" + 00b033 oao izhevskiy radiozavod 00b03b hiq networks 00b048 marconi communications inc. - 00b04a cisco systems, inc. + 00b04a cisco systems, inc 00b052 atheros communications - 00b064 cisco systems, inc. + 00b064 cisco systems, inc 00b069 honewell oy 00b06d jones futurex inc. 00b080 mannesmann ipulsys b.v. 00b086 locsoft limited - 00b08e cisco systems, inc. + 00b08e cisco systems, inc 00b091 transmeta corp. 00b094 alaris, inc. 00b09a morrow technologies corp. @@ -11867,34 +12014,60 @@ exit 00b0ac siae-microelettronica s.p.a. 00b0ae symmetricom 00b0b3 xstreamis plc - 00b0c2 cisco systems, inc. + 00b0c2 cisco systems, inc 00b0c7 tellabs operations, inc. - 00b0ce technology rescue - 00b0d0 dell computer corp. + 00b0ce viveris technologies + 00b0d0 dell inc. 00b0db nextcell, inc. 00b0df starboard storage systems + 00b0e1 cisco systems, inc 00b0e7 british federal ltd. 00b0ec eacem 00b0ee ajile systems, inc. 00b0f0 caly networks 00b0f5 networth technologies, inc. - 00b338 kontron design manufacturing services (m) sdn. bhd + 00b1e3 cisco systems, inc + 00b338 kontron asia pacific design sdn. bhd 00b342 macrosan technologies co., ltd. + 00b362 apple, inc. + 00b4f5 dongguan siyoto electronics co., ltd 00b56d david electronics co., ltd. + 00b5d0 samsung electronics co.,ltd 00b5d6 omnibit inc. + 00b600 voim co., ltd. + 00b670 cisco systems, inc + 00b69f latch + 00b771 cisco systems, inc 00b78d nanjing shining electric automation co., ltd + 00b7a8 heinzinger electronic gmbh + 00b810 yichip microelectronics (hangzhou) co.,ltd + 00b881 new platforms llc + 00b8b3 cisco systems, inc + 00b8b6 motorola mobility llc, a lenovo company + 00b8c2 heights telecom t ltd 00b9f6 shenzhen super rich electronics co.,ltd 00bac0 biometric access company 00bb01 octothorpe corp. - 00bb3a + 00bb1c huawei device co., ltd. + 00bb3a amazon technologies inc. + 00bb60 intel corporate 00bb8e hme co., ltd. + 00bbc1 canon inc. 00bbf0 ungermann-bass inc. + 00bc60 cisco systems, inc 00bd27 exar corp. 00bd3a nokia corporation + 00bd82 shenzhen youhua technology co., ltd + 00be3b huawei technologies co.,ltd + 00be75 cisco systems, inc + 00be9e fiberhome telecommunication technologies co.,ltd + 00bed5 new h3c technologies co., ltd 00bf15 genetec inc. + 00bf61 samsung electronics co.,ltd + 00bf77 cisco systems, inc 00c000 lanoptics, ltd. 00c001 diatek patient managment - 00c002 sercomm corporation + 00c002 sercomm corporation. 00c003 globalnet communications 00c004 japan business computer co.ltd 00c005 livingston enterprises, inc. @@ -11915,7 +12088,7 @@ exit 00c014 telematics calabasas int'l,inc 00c015 new media corporation 00c016 electronic theatre controls - 00c017 fluke corporation + 00c017 netally 00c018 lanart corporation 00c019 leap technology, inc. 00c01a corometrics medical systems @@ -11971,7 +12144,7 @@ exit 00c04c department of foreign affairs 00c04d mitec, inc. 00c04e comtrol corporation - 00c04f dell computer corporation + 00c04f dell inc. 00c050 toyo denki seizo k.k. 00c051 advanced integration research 00c052 burr-brown @@ -11992,13 +12165,13 @@ exit 00c061 solectek corporation 00c062 impulse technology 00c063 morning star technologies, inc - 00c064 general datacomm ind. inc. + 00c064 general datacomm llc 00c065 scope communications, inc. 00c066 docupoint, inc. 00c067 united barcode industries 00c068 hme clear-com ltd. 00c069 axxcelera broadband wireless - 00c06a zahner-elektrik gmbh & co. kg + 00c06a zahner-elektrik ingeborg zahner-schiller gmbh & co. kg. 00c06b osi plus corporation 00c06c svec computer corp. 00c06d boca research, inc. @@ -12041,7 +12214,7 @@ exit 00c092 mennen medical inc. 00c093 alta research corp. 00c094 vmx inc. - 00c095 znyx + 00c095 znyx networks, inc. 00c096 tamura corporation 00c097 archipel sa 00c098 chuntex electronic co., ltd. @@ -12051,7 +12224,7 @@ exit 00c09c hioki e.e. corporation 00c09d distributed systems int'l, inc 00c09e cache computers, inc. - 00c09f quanta computer, inc. + 00c09f quanta computer inc. 00c0a0 advance micro research, inc. 00c0a1 tokyo denshi sekei co. 00c0a2 intermedium a/s @@ -12063,7 +12236,7 @@ exit 00c0a8 gvc corporation 00c0a9 barron mccann ltd. 00c0aa silicon valley computer - 00c0ab telco systems, inc. + 00c0ab telco systems, inc. 00c0ac gambit computer communications 00c0ad marben communication systems 00c0ae towercom co. inc. dba pc house @@ -12074,7 +12247,7 @@ exit 00c0b3 comstat datacomm corporation 00c0b4 myson technology, inc. 00c0b5 corporate network systems,inc. - 00c0b6 overland storage, inc. + 00c0b6 hve, inc. 00c0b7 american power conversion corp 00c0b8 fraser's hill ltd. 00c0b9 funk software, inc. @@ -12130,9 +12303,9 @@ exit 00c0eb seh computertechnik gmbh 00c0ec dauphin technology 00c0ed us army electronic - 00c0ee kyocera corporation + 00c0ee kyocera display corporation 00c0ef abit corporation - 00c0f0 kingston technology corp. + 00c0f0 kingston technology company, inc. 00c0f1 shinko electric co., ltd. 00c0f2 transition networks 00c0f3 network communications corp. @@ -12141,27 +12314,42 @@ exit 00c0f6 celan technology inc. 00c0f7 engage communication, inc. 00c0f8 about computing inc. - 00c0f9 emerson network power + 00c0f9 artesyn embedded technologies 00c0fa canary communications, inc. 00c0fb advanced technology labs 00c0fc elastic reality, inc. 00c0fd prosum 00c0fe aptec computer systems, inc. - 00c0ff dot hill systems corporation + 00c0ff seagate cloud systems inc 00c14f ddl co,.ltd. + 00c164 cisco systems, inc + 00c1b1 cisco systems, inc 00c2c6 intel corporate + 00c343 e-t-a circuit breakers ltd + 00c3f4 samsung electronics co.,ltd + 00c52c juniper networks 00c5db datatech sistemas digitales avanzados sl - 00c610 apple - 00cbbd cambridge broadband networks ltd. + 00c610 apple, inc. + 00c88b cisco systems, inc + 00cae5 cisco systems, inc + 00cb00 private + 00cb51 sagemcom broadband sas + 00cbb4 shenzhen ateko photoelectricity co.,ltd + 00cbbd cambridge broadband networks group + 00cc34 juniper networks + 00cc3f universal electronics, inc. + 00ccfc cisco systems, inc 00cd90 mas elektronik ag - 00cf1c communication machinery corp. + 00cdfe apple, inc. + 00cf1c communication machinery corporation + 00cfc0 china mobile group device co.,ltd. 00d000 ferran scientific, inc. 00d001 vst technologies, inc. 00d002 ditech corporation 00d003 comda enterprises corp. 00d004 pentacom ltd. 00d005 zhs zeitmanagementsysteme - 00d006 cisco systems, inc. + 00d006 cisco systems, inc 00d007 mic associates, inc. 00d008 mactell corporation 00d009 hsing tech. enterprise co. ltd @@ -12186,7 +12374,7 @@ exit 00d01c sbs technologies, 00d01d furuno electric co., ltd. 00d01e pingtel corp. - 00d01f ctam pty. ltd. + 00d01f senetas corporation ltd 00d020 aim system, inc. 00d021 regent electronics corp. 00d022 incredible technologies, inc. @@ -12200,7 +12388,7 @@ exit 00d02a voxent systems ltd. 00d02b jetcell, inc. 00d02c campbell scientific, inc. - 00d02d ademco + 00d02d resideo 00d02e communication automation corp. 00d02f vlsi technology inc. 00d030 safetran systems corp @@ -12210,7 +12398,7 @@ exit 00d034 ormec systems corp. 00d035 behavior tech. computer corp. 00d036 technology atlanta corp. - 00d037 pace france + 00d037 arris group, inc. 00d038 fivemere, ltd. 00d039 utilicom, inc. 00d03a zoneworx, inc. @@ -12235,7 +12423,7 @@ exit 00d04d div of research & statistics 00d04e logibag 00d04f bitronics, inc. - 00d050 iskratel + 00d050 iskratel d.o.o. 00d051 o2 micro, inc. 00d052 ascend communications, inc. 00d053 connected systems @@ -12243,18 +12431,18 @@ exit 00d055 kathrein-werke kg 00d056 somat corporation 00d057 ultrak, inc. - 00d058 cisco systems, inc. + 00d058 cisco systems, inc 00d059 ambit microsystems corp. 00d05a symbionics, ltd. 00d05b acroloop motion control - 00d05c technotrend systemtechnik gmbh + 00d05c kathrein technotrend gmbh 00d05d intelliworxx, inc. 00d05e stratabeam technology, inc. 00d05f valcom, inc. 00d060 panasonic europe ltd. 00d061 tremon enterprises co., ltd. 00d062 digigram - 00d063 cisco systems, inc. + 00d063 cisco systems, inc 00d064 multitel 00d065 toko electric 00d066 wintriss engineering corp. @@ -12276,7 +12464,7 @@ exit 00d076 bank of america 00d077 lucent technologies 00d078 eltex of sweden ab - 00d079 cisco systems, inc. + 00d079 cisco systems, inc 00d07a amaquest computer corp. 00d07b comcam international inc 00d07c koyo electronics inc. co.,ltd. @@ -12297,23 +12485,23 @@ exit 00d08b adva optical networking ltd. 00d08c genoa technology, inc. 00d08d phoenix group, inc. - 00d08e nvision inc. + 00d08e grass valley, a belden brand 00d08f ardent technologies, inc. - 00d090 cisco systems, inc. + 00d090 cisco systems, inc 00d091 smartsan systems, inc. 00d092 glenayre western multiplex 00d093 tq - components gmbh - 00d094 timeline vista, inc. - 00d095 alcatel-lucent, enterprise business group - 00d096 3com europe ltd. - 00d097 cisco systems, inc. + 00d094 seeion control llc + 00d095 alcatel-lucent enterprise + 00d096 3com europe ltd + 00d097 cisco systems, inc 00d098 photon dynamics canada inc. 00d099 elcard wireless systems oy 00d09a filanet corporation 00d09b spectel ltd. 00d09c kapadia communications 00d09d veris industries - 00d09e 2wire, inc. + 00d09e 2wire inc 00d09f novtek test systems 00d0a0 mips denmark 00d0a1 oskar vierling gmbh + co. kg @@ -12327,7 +12515,7 @@ exit 00d0a9 shinano kenshi co., ltd. 00d0aa chase communications 00d0ab deltakabel telecom cv - 00d0ac grayson wireless + 00d0ac commscope, inc 00d0ad tl industries 00d0ae oresis communications, inc. 00d0af cutler-hammer, inc. @@ -12341,13 +12529,13 @@ exit 00d0b7 intel corporation 00d0b8 iomega corporation 00d0b9 microtek international, inc. - 00d0ba cisco systems, inc. - 00d0bb cisco systems, inc. - 00d0bc cisco systems, inc. - 00d0bd silicon image gmbh + 00d0ba cisco systems, inc + 00d0bb cisco systems, inc + 00d0bc cisco systems, inc + 00d0bd lattice semiconductor corp. (lpa) 00d0be emutec inc. 00d0bf pivotal technologies - 00d0c0 cisco systems, inc. + 00d0c0 cisco systems, inc 00d0c1 harmonic data systems, ltd. 00d0c2 balthazar technology ab 00d0c3 vivid technology pte, ltd. @@ -12361,17 +12549,17 @@ exit 00d0cb dasan co., ltd. 00d0cc technologies lyre inc. 00d0cd atan technology inc. - 00d0ce asyst electronic + 00d0ce isystem labs 00d0cf moreton bay 00d0d0 zhongxing telecom ltd. 00d0d1 sycamore networks 00d0d2 epilog corporation - 00d0d3 cisco systems, inc. + 00d0d3 cisco systems, inc 00d0d4 v-bits, inc. 00d0d5 grundig ag 00d0d6 aethra telecomunicazioni 00d0d7 b2c2, inc. - 00d0d8 3com corporation + 00d0d8 3com 00d0d9 dedicated microcomputers 00d0da taicom data systems co., ltd. 00d0db mcquay international @@ -12383,7 +12571,7 @@ exit 00d0e1 avionitek israel inc. 00d0e2 mrt micro, inc. 00d0e3 ele-chem engineering co., ltd. - 00d0e4 cisco systems, inc. + 00d0e4 cisco systems, inc 00d0e5 solidum systems corp. 00d0e6 ibond inc. 00d0e7 vcon telecommunication ltd. @@ -12391,7 +12579,7 @@ exit 00d0e9 advantage century telecommunication corp. 00d0ea nextone communications, inc. 00d0eb lightera networks, inc. - 00d0ec nakayo telecommunications, inc + 00d0ec nakayo inc 00d0ed xiox 00d0ee dictaphone corporation 00d0ef igt @@ -12401,7 +12589,7 @@ exit 00d0f3 solari di udine spa 00d0f4 carinthian tech institute 00d0f5 orange micro, inc. - 00d0f6 alcatel canada + 00d0f6 nokia 00d0f7 next nets corporation 00d0f8 fujian star terminal 00d0f9 acute communications corp. @@ -12410,13 +12598,23 @@ exit 00d0fc granite microsystems 00d0fd optima tele.com, inc. 00d0fe astral point - 00d0ff cisco systems, inc. + 00d0ff cisco systems, inc 00d11c acetel + 00d279 vingroup joint stock company + 00d2b1 tpv display technology (xiamen) co.,ltd. + 00d318 spg controls 00d38d hotel technology next generation 00d632 ge energy + 00d6fe cisco systems, inc + 00d78f cisco systems, inc + 00d861 micro-star intl co., ltd. + 00d9d1 sony interactive entertainment inc. + 00da55 cisco systems, inc 00db1e albedo telecom sl 00db45 thamway co.,ltd. + 00db70 apple, inc. 00dbdf intel corporate + 00dcb2 extreme networks, inc. 00dd00 ungermann-bass inc. 00dd01 ungermann-bass inc. 00dd02 ungermann-bass inc. @@ -12433,7 +12631,8 @@ exit 00dd0d ungermann-bass inc. 00dd0e ungermann-bass inc. 00dd0f ungermann-bass inc. - 00defb cisco systems, inc. + 00dd25 shenzhen hechengdong technology co., ltd + 00defb cisco systems, inc 00e000 fujitsu limited 00e001 strand lighting limited 00e002 crossroads systems, inc. @@ -12443,18 +12642,18 @@ exit 00e006 silicon integrated sys. corp. 00e007 avaya ecs ltd 00e008 amazing controls! inc. - 00e009 marathon technologies corp. + 00e009 stratus technologies 00e00a diba, inc. 00e00b rooftop communications corp. 00e00c motorola 00e00d radiant systems 00e00e avalon imaging systems, inc. - 00e00f shanghai baud data + 00e00f shanghai baud data communication co.,ltd. 00e010 hess sb-automatenbau gmbh 00e011 uniden corporation 00e012 pluto technologies international inc. 00e013 eastern electronic co., ltd. - 00e014 cisco systems, inc. + 00e014 cisco systems, inc 00e015 heiwa corporation 00e016 rapid city communications 00e017 exxact gmbh @@ -12464,11 +12663,11 @@ exit 00e01b sphere communications, inc. 00e01c cradlepoint, inc 00e01d webtv networks, inc. - 00e01e cisco systems, inc. + 00e01e cisco systems, inc 00e01f avidia systems, inc. 00e020 tecnomen oy 00e021 freegate corp. - 00e022 analog devices inc. + 00e022 analog devices, inc. 00e023 telrad 00e024 gadzoox networks 00e025 dit co., ltd. @@ -12477,7 +12676,7 @@ exit 00e028 aptix corporation 00e029 standard microsystems corp. 00e02a tandberg television as - 00e02b extreme networks + 00e02b extreme networks, inc. 00e02c ast computer 00e02d innomedialogic, inc. 00e02e spc electronics corporation @@ -12486,8 +12685,8 @@ exit 00e031 hagiwara electric co., ltd. 00e032 misys financial systems, ltd. 00e033 e.e.p.d. gmbh - 00e034 cisco systems, inc. - 00e035 emerson network power + 00e034 cisco systems, inc + 00e035 artesyn embedded technologies 00e036 pioneer corporation 00e037 century corporation 00e038 proxima corporation @@ -12508,15 +12707,15 @@ exit 00e047 infocus corporation 00e048 sdl communications, inc. 00e049 microwi electronic gmbh - 00e04a enhanced messaging systems, inc + 00e04a zx technologies, inc 00e04b jump industrielle computertechnik gmbh 00e04c realtek semiconductor corp. 00e04d internet initiative japan, inc 00e04e sanyo denki co., ltd. - 00e04f cisco systems, inc. + 00e04f cisco systems, inc 00e050 executone information systems, inc. 00e051 talx corporation - 00e052 brocade communications systems, inc + 00e052 brocade communications systems llc 00e053 cellport labs, inc. 00e054 kodai hitec co., ltd. 00e055 ingenieria electronica comercial inelcom s.a. @@ -12526,14 +12725,14 @@ exit 00e059 controlled environments, ltd. 00e05a galea network security 00e05b west end systems corp. - 00e05c matsushita kotobuki electronics industries, ltd. + 00e05c phc corporation 00e05d unitec co., ltd. 00e05e japan aviation electronics industry, ltd. 00e05f e-net, inc. 00e060 sherwood 00e061 edgepoint networks, inc. 00e062 host engineering - 00e063 cabletron - yago systems, inc. + 00e063 cabletron systems, inc. 00e064 samsung electronics 00e065 optical access international 00e066 promax systems, inc. @@ -12542,7 +12741,7 @@ exit 00e069 jaycor 00e06a kapsch ag 00e06b w&g special products - 00e06c ultra electronics limited (aep networks) + 00e06c ultra electronics command & control systems 00e06d compuware corporation 00e06e far systems s.p.a. 00e06f arris group, inc. @@ -12573,20 +12772,20 @@ exit 00e088 ltx-credence corporation 00e089 ion networks, inc. 00e08a gec avery, ltd. - 00e08b qlogic corp. + 00e08b qlogic corporation 00e08c neoparadigm labs, inc. 00e08d pressure systems, inc. 00e08e utstarcom - 00e08f cisco systems, inc. + 00e08f cisco systems, inc 00e090 beckman lab. automation div. - 00e091 lg electronics, inc. + 00e091 lg electronics 00e092 admtek incorporated 00e093 ackfin networks 00e094 osai srl 00e095 advanced-vision technolgies corp. 00e096 shimadzu corporation 00e097 carrier access corporation - 00e098 abocom systems, inc. + 00e098 abocom 00e099 samson ag 00e09a positron inc. 00e09b engage networks, inc. @@ -12597,7 +12796,7 @@ exit 00e0a0 wiltron co. 00e0a1 hima paul hildebrandt gmbh co. kg 00e0a2 microslate inc. - 00e0a3 cisco systems, inc. + 00e0a3 cisco systems, inc 00e0a4 esaote s.p.a. 00e0a5 comcore semiconductor, inc. 00e0a6 telogy networks, inc. @@ -12610,14 +12809,14 @@ exit 00e0ad ees technology, ltd. 00e0ae xaqti corporation 00e0af general dynamics information systems - 00e0b0 cisco systems, inc. - 00e0b1 alcatel-lucent, enterprise business group + 00e0b0 cisco systems, inc + 00e0b1 alcatel-lucent enterprise 00e0b2 telmax communications corp. 00e0b3 etherwan systems, inc. 00e0b4 techno scope co., ltd. 00e0b5 ardent communications corp. 00e0b6 entrada networks - 00e0b7 pi group, ltd. + 00e0b7 cosworth electronics ltd 00e0b8 gateway 2000 00e0b9 byas systems 00e0ba berghof automationstechnik gmbh @@ -12641,7 +12840,7 @@ exit 00e0cc hero systems, ltd. 00e0cd saab sensis corporation 00e0ce arn - 00e0cf integrated device technology, inc. + 00e0cf integrated device 00e0d0 netspeed, inc. 00e0d1 telsis limited 00e0d2 versanet communications, inc. @@ -12652,19 +12851,19 @@ exit 00e0d7 sunshine electronics, inc. 00e0d8 lanbit computer, inc. 00e0d9 tazmo co., ltd. - 00e0da alcatel north america esd + 00e0da alcatel-lucent enterprise 00e0db viavideo communications, inc. 00e0dc nexware corp. 00e0dd zenith electronics corporation 00e0de datax nv - 00e0df keymile gmbh + 00e0df dzs gmbh 00e0e0 si electronics, ltd. 00e0e1 g2 networks, inc. 00e0e2 innova corp. 00e0e3 sk-elektronik gmbh 00e0e4 fanuc robotics north america, inc. 00e0e5 cinco networks, inc. - 00e0e6 incaa datacom b.v. + 00e0e6 incaa computers 00e0e7 raytheon e-systems, inc. 00e0e8 gretacoder data systems ag 00e0e9 data labs, inc. @@ -12681,143 +12880,346 @@ exit 00e0f4 inside technology a/s 00e0f5 teles ag 00e0f6 decision europe - 00e0f7 cisco systems, inc. + 00e0f7 cisco systems, inc 00e0f8 dicna control ab - 00e0f9 cisco systems, inc. + 00e0f9 cisco systems, inc 00e0fa trl technology, ltd. 00e0fb leightronix, inc. - 00e0fc huawei technologies co., ltd. + 00e0fc huawei technologies co.,ltd 00e0fd a-trend technology co., ltd. - 00e0fe cisco systems, inc. + 00e0fe cisco systems, inc 00e0ff security dynamics technologies, inc. + 00e16d cisco systems, inc 00e175 ak-systems ltd + 00e18c intel corporate + 00e22c china mobile group device co.,ltd. 00e3b2 samsung electronics co.,ltd + 00e400 sichuan changhong electric ltd. + 00e406 huawei technologies co.,ltd + 00e421 sony interactive entertainment inc. + 00e5e4 sichuan tianyi comheart telecom co., ltd. 00e666 arima communications corp. 00e6d3 nixdorf computer corp. + 00e6e8 netzin technology corporation,.ltd. 00e8ab meggitt training systems, inc. - 00eb2d sony mobile communications ab + 00e93a azurewave technology inc. + 00eabd cisco systems, inc + 00eb2d sony mobile communications inc + 00ebd5 cisco systems, inc + 00ec0a xiaomi communications co ltd + 00edb8 kyocera corporation + 00eeab cisco systems, inc 00eebd htc corporation 00f051 kwb gmbh + 00f22c shanghai b-star technology co.,ltd. + 00f28b cisco systems, inc + 00f361 amazon technologies inc. + 00f3db woo sports 00f403 orbis systems oy - 00f4b9 apple + 00f46f samsung electronics co.,ltd + 00f48d liteon technology corporation + 00f4b9 apple, inc. + 00f620 google, inc. + 00f663 cisco systems, inc + 00f76f apple, inc. + 00f81c huawei technologies co.,ltd + 00f82c cisco systems, inc 00f860 pt. panggung electric citrabuana + 00f871 dgs denmark a/s + 00fa21 samsung electronics co.,ltd 00fa3b cloos electronic gmbh 00fc58 websilicon ltd. 00fc70 intrepid control systems, inc. + 00fc8b amazon technologies inc. + 00fc8d hitron technologies. inc + 00fcba cisco systems, inc + 00fd22 cisco systems, inc + 00fd45 hewlett packard enterprise 00fd4c nevatec + 00fec8 cisco systems, inc 020701 racal-datacom 021c7c perq systems corporation 026086 logic replacement tech. ltd. - 02608c 3com corporation + 02608c 3com 027001 racal-datacom 0270b0 m/a-com inc. companies - 0270b3 data recall ltd - 029d8e cardiac recorders inc. + 0270b3 data recall ltd. + 029d8e cardiac recorders, inc. 02aa3c olivetti telecomm spa (olteco) 02bb01 octothorpe corp. - 02c08c 3com corporation - 02cf1c communication machinery corp. - 02e6d3 nixdorf computer corporation + 02c08c 3com + 02cf1c communication machinery corporation + 02e6d3 nixdorf computer corp. + 04021f huawei technologies co.,ltd + 0402ca shenzhen vtsonic co.,ltd + 0403d6 nintendo co.,ltd + 0404ea valens semiconductor ltd. + 0405dd shenzhen cultraview digital technology co., ltd + 04072e vtech electronics ltd. + 040973 hewlett packard enterprise + 0409a5 hfr, inc. 040a83 alcatel-lucent 040ae0 xmit ag computer networks - 040cce apple + 040cce apple, inc. + 040e3c hp inc. 040ec2 viewsonic mobile china limited - 041552 apple + 041119 ieee registration authority + 041552 apple, inc. + 0415d9 viwone 04180f samsung electronics co.,ltd - 0418b6 - 0418d6 ubiquiti networks + 0418b6 private + 0418d6 ubiquiti networks inc. + 04197f grasphere japan 041a04 waveip + 041b6d lg electronics (mobile communications) 041b94 host mobility ab 041bba samsung electronics co.,ltd 041d10 dream ware inc. - 041e64 apple - 04209a panasonic avc networks company + 041dc7 zte corporation + 041e64 apple, inc. + 041e7a dspworks + 041efa bissell homecare, inc. + 04209a panasonic corporation avc networks company + 042144 sunitec enterprise co.,ltd + 04214c insight energy ventures llc 042234 wireless standard extensions + 0425c5 huawei technologies co.,ltd + 0425e0 taicang t&w electronics 042605 gfr gesellschaft für regelungstechnik und energieeinsparung mbh - 042665 apple + 042665 apple, inc. + 042728 microsoft corporation + 042758 huawei technologies co.,ltd + 042ae2 cisco systems, inc 042bbb picocela, inc. + 042db4 first property (beijing) co., ltd modern moma branch 042f56 atocs (shenzhen) ltd + 043110 inspur group co., ltd. 0432f4 partron + 043385 nanchang blackshark co.,ltd. + 043389 huawei technologies co.,ltd + 0433c2 intel corporate 043604 gyeyoung i&t + 043a0d sm optics s.r.l. 043d98 chongqing qingjia electronics co.,ltd + 043f72 mellanox technologies, inc. + 0440a9 new h3c technologies co., ltd + 044169 gopro 0444a1 telecon galicia,s.a. + 044562 andra sp. z o. o. + 0445a1 nirit- xinwei telecom technology co., ltd. 044665 murata manufacturing co., ltd. - 04489a apple + 0446cf beijing venustech cybervision co.,ltd. + 04489a apple, inc. + 04495d huawei device co., ltd. 044a50 ramaxel technology (shenzhen) limited company + 044a6c huawei technologies co.,ltd + 044ac6 aipon electronics co., ltd + 044bed apple, inc. 044bff guangzhou hedy digital technology co., ltd 044cef fujian sanao technology co.,ltd 044e06 ericsson ab + 044e5a arris group, inc. + 044eaf lg innotek + 044f17 humax co., ltd. + 044f4c huawei technologies co.,ltd 044f8b adapteva, inc. 044faa ruckus wireless - 045453 apple + 0450da qiku internet network scientific (shenzhen) co., ltd + 0452c7 bose corporation + 0452f3 apple, inc. + 0453d5 sysorex global holdings + 045453 apple, inc. 0455ca briview (xiamen) corp. + 045604 gionee communication equipment co.,ltd. + 0456e5 intel corporate 04572f sertel electronics uk ltd 04586f sichuan whayer information industry co.,ltd 045a95 nokia corporation 045c06 zmodo technology corporation + 045c6c juniper networks + 045c8e gosund group co.,ltd + 045d4b sony corporation 045d56 camtron industrial inc. + 045ea4 shenzhen netis technology co.,ltd 045fa7 shenzhen yichen technology development co.,ltd + 045fb9 cisco systems, inc + 046169 media global links co., ltd. + 046273 cisco systems, inc 0462d7 alstom hydro france 0463e0 nome oy + 046565 testop + 046785 scemtec hard- und software fuer mess- und steuerungstechnik gmbh + 0469f8 apple, inc. + 046b1b sysdine co., ltd. + 046b25 sichuan tianyi comheart telecom co.,ltd + 046c59 intel corporate + 046c9d cisco systems, inc 046d42 bryston ltd. + 046e02 openrtls group 046e49 taiyear electronic technology (suzhou) co., ltd 0470bc globalstar inc. + 04714b ieee registration authority + 047295 apple, inc. 0474a1 aligera equipamentos digitais ltda + 047503 huawei technologies co.,ltd 0475f5 csst - 04766e alps co,. ltd. + 04766e alpsalpine co,.ltd + 0476b0 cisco systems, inc + 047863 shanghai mxchip information technology co., ltd. + 047970 huawei technologies co.,ltd + 047975 honor device co., ltd. + 0479b7 texas instruments + 047a0b beijing xiaomi electronics co., ltd. + 047bcb universal global scientific industrial co., ltd. + 047d50 shenzhen kang ying technology co.ltd. 047d7b quanta computer inc. + 047e23 china mobile iot company limited + 047e4a moobox co., ltd. + 047f0e barrot technology limited + 04819b bskyb ltd 0481ae clack corporation 04848a 7inova technology limited + 04885f huawei technologies co.,ltd 04888c eifelwerk butler systeme gmbh 0488e2 beats electronics llc - 048a15 avaya, inc - 048b42 skspruce technology limited + 048a15 avaya inc + 048ae1 flextronics manufacturing(zhuhai)co.,ltd. + 048b42 skspruce technologies 048c03 thinpad technology (shenzhen)co.,ltd + 048c16 huawei technologies co.,ltd + 048c9a huawei device co., ltd. 048d38 netcore technology inc. + 049081 pensando systems, inc. + 049162 microchip technology inc. + 049226 asustek computer inc. + 0492ee iway ag + 04946b tecno mobile limited 0494a1 catch the wind inc - 0498f3 alps electric co,. ltd. + 049573 zte corporation + 0495e6 tenda technology co.,ltd.dongguan branch + 049645 wuxi sky chip interconnection technology co.,ltd. + 049790 lartech telecom llc + 0498f3 alpsalpine co,.ltd + 0499e6 shenzhen yoostar technology co., ltd + 049b9c eadingcore intelligent technology co., ltd. 049c62 bmt medical technology s.r.o. + 049dfe hivesystem 049f06 smobile co., ltd. - 049f81 netscout systems, inc. - 04a151 netgear inc., + 049f81 netscout systems inc + 049fca huawei technologies co.,ltd + 04a151 netgear + 04a222 arcadyan corporation + 04a2f3 fiberhome telecommunication technologies co.,ltd + 04a316 texas instruments 04a3f3 emicon 04a82a nokia corporation + 04aae1 beijing microvision technology co.,ltd + 04ab18 elecom co.,ltd. + 04ab6a chun-il co.,ltd. + 04ac44 holtek semiconductor inc. + 04b0e7 huawei technologies co.,ltd + 04b167 xiaomi communications co ltd + 04b1a1 samsung electronics co.,ltd 04b3b6 seamap (uk) ltd + 04b429 samsung electronics co.,ltd 04b466 bsp co., ltd. + 04b648 zenner + 04ba1c huawei device co., ltd. + 04ba36 li seng technology ltd + 04ba8d samsung electronics co.,ltd + 04bbf9 pavilion data systems inc + 04bc87 shenzhen justlink technology co., ltd + 04bd70 huawei technologies co.,ltd + 04bd88 aruba, a hewlett packard enterprise company + 04bdbf samsung electronics co.,ltd + 04bf6d zyxel communications corporation 04bfa8 isb corporation 04c05b tigo energy - 04c06f shenzhen huawei communication technologies co., ltd - 04c1b9 fiberhome telecommunication tech.co.,ltd. - 04c5a4 cisco systems, inc. + 04c06f huawei technologies co.,ltd + 04c09c tellabs inc. + 04c103 clover network, inc. + 04c1b9 fiberhome telecommunication technologies co.,ltd + 04c1d8 huawei device co., ltd. + 04c23e htc corporation + 04c241 nokia + 04c29b aura home, inc. + 04c3e6 ieee registration authority + 04c5a4 cisco systems, inc + 04c807 xiaomi communications co ltd 04c880 samtec inc + 04c991 phistek inc. + 04c9d9 dish technologies corp 04cb1d traka plc + 04cb88 shenzhen jingxun software telecommunication technology co.,ltd 04ce14 wilocity ltd. + 04ce7e nxp france semiconductors france 04cf25 manycolors, inc. + 04cf8c xiaomi electronics,co.,ltd + 04d13a xiaomi communications co ltd + 04d16e ieee registration authority + 04d320 itel mobile limited + 04d395 motorola mobility llc, a lenovo company + 04d3b0 intel corporate + 04d3b5 huawei device co., ltd. + 04d3cf apple, inc. 04d437 znv + 04d4c4 asustek computer inc. + 04d590 fortinet, inc. + 04d60e funai electric co., ltd. + 04d6aa samsung electro-mechanics(thailand) + 04d6f4 gd midea air-conditioning equipment co.,ltd. 04d783 y&h e&c co.,ltd. - 04dad2 cisco + 04d7a5 new h3c technologies co., ltd + 04d9f5 asustek computer inc. + 04dad2 cisco systems, inc 04db56 apple, inc. 04db8a suntech international ltd. 04dd4c velocytech + 04dedb rockport networks inc + 04def2 shenzhen ecom technology co. ltd 04df69 car connectivity consortium + 04e0b0 shenzhen youhua technology co., ltd 04e0c4 triumph-adler ag 04e1c8 ims soluções em energia ltda. + 04e229 qingdao haier technology co.,ltd 04e2f8 aep ticketing solutions srl 04e451 texas instruments - 04e536 apple + 04e536 apple, inc. 04e548 cohda wireless pty ltd + 04e56e thub co., ltd. + 04e598 xiaomi communications co ltd 04e662 acroname inc. + 04e676 ampak technology, inc. + 04e77e we corporation inc. + 04e795 huawei technologies co.,ltd 04e9e5 pjrc.com, llc + 04ea56 intel corporate + 04eb40 cisco systems, inc + 04ecbb fiberhome telecommunication technologies co.,ltd + 04ed33 intel corporate + 04ee03 texas instruments 04ee91 x-fabric gmbh 04f021 compex systems pte ltd - 04f13e apple + 04f03e huawei device co., ltd. + 04f128 hmd global oy + 04f13e apple, inc. + 04f169 huawei device co., ltd. 04f17d tarana wireless + 04f352 huawei technologies co.,ltd 04f4bc xena networks - 04f7e4 apple + 04f5f4 proxim wireless + 04f7e4 apple, inc. 04f8c2 flaircomm microelectronics, inc. + 04f8f8 edgecore networks corporation 04f938 huawei technologies co.,ltd + 04f993 infinix mobility limited + 04f9d9 speaker electronic(jiashan) co.,ltd + 04fa3f opticore inc. + 04fa83 qingdao haier technology co.,ltd 04fe31 samsung electronics co.,ltd - 04fe7f cisco systems, inc. + 04fe7f cisco systems, inc + 04fe8d huawei technologies co.,ltd + 04fea1 fihonest communication co.,ltd 04ff51 novamedia innovision sp. z o.o. 080001 computervision corporation 080002 bridge communications inc. @@ -12825,13 +13227,13 @@ exit 080004 cromemco incorporated 080005 symbolics inc. 080006 siemens ag - 080007 apple + 080007 apple, inc. 080008 bolt beranek and newman inc. 080009 hewlett packard 08000a nestar systems incorporated 08000b unisys corporation 08000c miklyn development co. - 08000d international computers ltd. + 08000d international computers, ltd 08000e ncr corporation 08000f mitel corporation 080011 tektronix inc. @@ -12844,7 +13246,7 @@ exit 080018 pirelli focom networks 080019 general electric corporation 08001a tiara/ 10net - 08001b emc corporation + 08001b dell emc 08001c kdd-kokusai debnsin denwa co. 08001d able communications inc. 08001e apollo computer inc. @@ -12856,7 +13258,7 @@ exit 080024 10net communications/dca 080025 control data 080026 norsk data a.s. - 080027 cadmus computer systems + 080027 pcs systemtechnik gmbh 080028 texas instruments 080029 megatek corporation 08002a mosaic technologies inc. @@ -12865,8 +13267,8 @@ exit 08002d lan-tec inc. 08002e metaphor computer systems 08002f prime computer inc. - 080030 network research corporation 080030 cern + 080030 network research corporation 080030 royal melbourne inst of tech 080031 little machines inc. 080032 tigan incorporated @@ -12897,7 +13299,7 @@ exit 08004b planning research corp. 08004c hydra computer systems inc. 08004d corvus systems inc. - 08004e 3com europe ltd. + 08004e 3com europe ltd 08004f cygnet systems 080050 daisy systems corp. 080051 experdata @@ -12923,14 +13325,14 @@ exit 080066 agfa corporation 080067 comdesign 080068 ridge computers - 080069 silicon graphics inc. - 08006a att bell laboratories + 080069 silicon graphics + 08006a at&t 08006b accel technologies inc. 08006c suntek technology int'l 08006d whitechapel computer works 08006e masscomp 08006f philips apeldoorn b.v. - 080070 mitsubishi electric corp. + 080070 mitsubishi precision co.,ltd. 080071 matra (dsie) 080072 xerox corp univ grant program 080073 tecmar inc. @@ -12952,8 +13354,8 @@ exit 080084 tomen electronics corp. 080085 elxsi 080086 konica minolta holdings, inc. - 080087 xyplex - 080088 brocade communications systems, inc. + 080087 xyplex, inc. + 080088 brocade communications systems llc 080089 kinetics 08008a perftech, inc. 08008b pyramid technology corp. @@ -12962,180 +13364,442 @@ exit 08008e tandem computers 08008f chipcom corporation 080090 sonoma systems + 08010f sichuan tianyi comheart telecomco.,ltd + 08028e netgear + 080342 palo alto networks 080371 krg corporate + 080581 roku, inc. 0805cd dongguang enmai electronic product co.ltd. - 0808c2 samsung electronics + 0808c2 samsung electronics co.,ltd 0808ea amsc + 0809b6 masimo corp + 0809c7 zhuhai unitech power technology co., ltd. + 080a4e planet bingo® — 3rd rock gaming® 080c0b sysmik gmbh dresden 080cc9 mission technology group, dba magma 080d84 geco, inc. 080ea8 velex s.r.l. 080ffa ksp inc. + 081086 nec platforms, ltd. + 08115e bitel co., ltd. 081196 intel corporate + 0812a5 amazon technologies inc. 081443 unibrain s.a. + 08152f samsung electronics co., ltd. artik 081651 shenzhen sea star technology co.,ltd - 081735 cisco systems, inc. + 081735 cisco systems, inc 0817f4 ibm corp 08181a zte corporation 08184c a. s. thomas, inc. 0819a6 huawei technologies co.,ltd + 081dc4 thermo fisher scientific messtechnik gmbh 081dfb shanghai mexon communication technology co.,ltd 081f3f wondalink inc. - 081ff3 cisco systems, inc. + 081f71 tp-link technologies co.,ltd. + 081feb bincube + 081ff3 cisco systems, inc + 0821ef samsung electronics co.,ltd + 0823b2 vivo mobile communication co., ltd. 082522 advansee + 082525 xiaomi communications co ltd + 082697 zyxel communications corporation 082719 aps systems/electronic ag + 0827ce nagano keiki co., ltd. 082ad0 srd innovations inc. + 082cb0 network instruments + 082cb6 apple, inc. + 082ced technity solutions inc. + 082e36 huawei device co., ltd. 082e5f hewlett packard + 082fe9 huawei technologies co.,ltd + 08306b palo alto networks + 08318b huawei technologies co.,ltd + 0831a4 huawei device co., ltd. + 08351b shenzhen jialihua electronic technology co., ltd 083571 caswell inc. + 0835b2 coreedge networks co., ltd + 0836c9 netgear 08373d samsung electronics co.,ltd 08379c topaz co. ltd. + 083869 hong kong amobile intelligent corp. limited taiwan branch 0838a5 funkwerk plettac electronic gmbh + 0838e6 motorola (wuhan) mobility technologies communication co., ltd. + 083a2f guangzhou juan intelligent tech joint stock co.,ltd + 083a38 new h3c technologies co., ltd + 083a5c junilab, inc. + 083a88 universal global scientific industrial co., ltd. 083ab8 shinoda plasma co., ltd. + 083af2 espressif inc. + 083d88 samsung electronics co.,ltd 083e0c arris group, inc. - 083e8e hon hai precision ind.co.ltd + 083e5d sagemcom broadband sas + 083e8e hon hai precision ind. co.,ltd. 083f3e wsh gmbh 083f76 intellian technologies, inc. + 083fbc zte corporation 084027 gridstore inc. + 0840f3 tenda technology co.,ltd.dongguan branch + 084296 mobile technology solutions llc + 084656 veo-labs + 08474c nokia + 0847d0 nokia shanghai bell co., ltd. 08482c raycore taiwan co., ltd. - 084929 cybati + 084acf guangdong oppo mobile telecommunications corp.,ltd 084e1c h2a systems, llc - 084ebf broad net mux corporation + 084ebf sumitomo electric industries, ltd + 084f0a huawei technologies co.,ltd + 084fa9 cisco systems, inc + 084ff9 cisco systems, inc + 085114 qingdao topscomm communication co., ltd 08512e orion diagnostica oy 085240 ebv elektronikbau- und vertriebs gmbh + 0854bb shenzhen chuangwei-rgb electronics co.,ltd + 085531 routerboard.com 085700 tp-link technologies co.,ltd. + 0858a5 beijing vrv software corpoaration limited. 085ae0 recovision technology co., ltd. 085b0e fortinet, inc. + 085bd6 intel corporate + 085bda clinicare ltd 085ddd mercury corporation 08606e asustek computer inc. - 086361 huawei technologies co., ltd + 086083 zte corporation + 086195 rockwell automation + 086266 asustek computer inc. + 086361 huawei technologies co.,ltd + 0865f0 jm zengge co., ltd + 08661f palo alto networks + 086698 apple, inc. + 08674e hisense broadband multimedia technology co.,ltd + 08688d new h3c technologies co., ltd 0868d0 japan system design 0868ea eito electronics co., ltd. + 086a0a askey computer corp + 086ac5 intel corporate + 086bd1 shenzhen superelectron technology co.,ltd. + 086bd7 silicon laboratories + 086d41 apple, inc. 086df2 shenzhen mimowave technology co.,ltd - 087045 apple + 087045 apple, inc. + 087190 intel corporate + 087402 apple, inc. 0874f6 winterhalter gastronom gmbh 087572 obelux oy 087618 vie technologies sdn. bhd. 087695 auto industrial co., ltd. 0876ff thomson telecom belgium + 087808 samsung electronics co.,ltd + 08798c huawei technologies co.,ltd 087999 aim gmbh - 087a4c huawei technologies co., ltd + 087a4c huawei technologies co.,ltd 087baa svyazkomplektservice, llc + 087c39 amazon technologies inc. 087cbe quintic corp. 087d21 altasec technology corporation + 087e64 technicolor ch usa inc. + 087f98 vivo mobile communication co., ltd. 088039 cisco spvtg + 0881b2 logitech (china) technology co., ltd + 0881bc hongkong ipro technology co., limited 0881f4 juniper networks - 08863b belkin international, inc. + 088466 novartis pharma ag + 08849d amazon technologies inc. + 088620 tecno mobile limited + 08863b belkin international inc. + 0887c6 ingram micro services + 088c2c samsung electronics co.,ltd 088dc8 ryowa electronics co.,ltd 088e4f sf software solutions - 088f2c hills sound vision & lighting + 088f2c amber technology ltd. + 0890ba danlaw inc + 089356 huawei technologies co.,ltd + 0894ef wistron infocomm (zhongshan) corporation + 08952a technicolor ch usa inc. + 0896ad cisco systems, inc 0896d7 avm gmbh + 089734 hewlett packard enterprise 089758 shenzhen strong rising electronics co.,ltd dongguan subsidiary + 089798 compal information (kunshan) co., ltd. + 089ac7 zte corporation + 089b4b ikuai networks + 089bb9 nokia solutions and networks gmbh & co. kg + 089c86 nokia shanghai bell co., ltd. 089e01 quanta computer inc. + 089e08 google, inc. 089f97 leroy automation 08a12b shenzhen ezl technology co., ltd - 08a95a azurewave + 08a189 hangzhou hikvision digital technology co.,ltd. + 08a5c8 sunnovo international limited + 08a6bc amazon technologies inc. + 08a7c0 technicolor ch usa inc. + 08a8a1 cyclotronics power concepts, inc + 08a95a azurewave technology inc. + 08aa55 motorola mobility llc, a lenovo company + 08aa89 zte corporation 08aca5 benu video, inc. + 08acc4 fmtech + 08aed6 samsung electronics co.,ltd 08af78 totus solutions, inc. + 08b055 askey computer corp + 08b0a7 truebeyond co., ltd + 08b258 juniper networks 08b2a3 cynny italia s.r.l. + 08b3af vivo mobile communication co., ltd. + 08b4b1 google, inc. 08b4cf abicom international 08b738 lite-on technogy corp. 08b7ec wireless seismic + 08ba22 swaive corporation + 08ba5f qingdao hisense electronics co.,ltd. + 08bb3c flextronics tech.(ind) pvt ltd 08bbcc ak-nord edv vertriebsges. mbh - 08bd43 netgear inc., + 08bc20 hangzhou royal cloud technology co., ltd + 08bd43 netgear 08be09 astrol electronic ag + 08be77 green electronics + 08beac edimax technology co. ltd. + 08bfa0 samsung electronics co.,ltd + 08c021 huawei technologies co.,ltd + 08c0eb mellanox technologies, inc. + 08c5e1 samsung electro-mechanics(thailand) + 08c6b3 qtech llc 08ca45 toyou feiji electronics co., ltd. - 08cc68 cisco - 08d09f cisco systems, inc. + 08cbe5 r3 - reliable realtime radio communications gmbh + 08cc27 motorola mobility llc, a lenovo company + 08cc68 cisco systems, inc + 08cca7 cisco systems, inc + 08cd9b samtec automotive electronics & software gmbh + 08d09f cisco systems, inc + 08d0b7 qingdao hisense communications co.,ltd. + 08d23e intel corporate 08d29a proformatique + 08d34b techman electronics (changshu) co., ltd. 08d40c intel corporate - 08d42b samsung electronics + 08d42b samsung electronics co.,ltd + 08d46a lg electronics (mobile communications) + 08d59d sagemcom broadband sas 08d5c0 seers technology co., ltd - 08d833 shenzhen rf technology co,.ltd - 08e5da nanjing fujitsu computer products co.,ltd. + 08d833 shenzhen rf technology co., ltd + 08df1f bose corporation + 08dfcb systrome networks + 08e5da nanjing fujitsu computer products co.,ltd. 08e672 jebsee electronics co.,ltd. - 08ea44 aerohive networks, inc. - 08eb74 humax + 08e689 apple, inc. + 08e84f huawei technologies co.,ltd + 08e9f6 ampak technology,inc. + 08ea40 shenzhen bilian electronic co.,ltd + 08ea44 extreme networks, inc. + 08eb29 jiangsu huitong group co.,ltd. + 08eb74 humax co., ltd. 08ebed world elite technology co.,ltd + 08eca9 samsung electronics co.,ltd + 08ecf5 cisco systems, inc + 08ed02 ieee registration authority + 08ed9d tecno mobile limited 08edb9 hon hai precision ind. co.,ltd. + 08eded zhejiang dahua technology co., ltd. + 08ee8b samsung electronics co.,ltd 08ef3b mcs logic inc. + 08efab sayme wireless sensor network 08f1b7 towerstream corpration + 08f1ea hewlett packard enterprise 08f2f4 net one partners co.,ltd. + 08f458 huawei device co., ltd. + 08f4ab apple, inc. + 08f606 zte corporation + 08f69c apple, inc. 08f6f8 get engineering + 08f728 globo multimedia sp. z o.o. sp.k. + 08f7e9 hrcp research and development partnership + 08f8bc apple, inc. + 08fa79 vivo mobile communication co., ltd. 08fae0 fohhn audio ag + 08fbea ampak technology,inc. 08fc52 openxs bv 08fc88 samsung electronics co.,ltd 08fd0e samsung electronics co.,ltd + 08ff24 shenzhen skyworth digital technology co., ltd + 0c01db infinix mobility limited + 0c0227 technicolor ch usa inc. 0c0400 jantar d.o.o. 0c0535 juniper systems - 0c1105 ringslink (xiamen) network communication technologies co., ltd + 0c08b4 humax co., ltd. + 0c1105 akuvox (xiamen) networks co., ltd + 0c1167 cisco systems, inc 0c1262 zte corporation 0c130b uniqoteq ltd. 0c1420 samsung electronics co.,ltd + 0c14d2 china mobile group device co.,ltd. + 0c1539 apple, inc. 0c15c5 sdtec co., ltd. + 0c1773 huawei device co., ltd. 0c17f1 telecsys 0c191f inform electronik + 0c19f8 apple, inc. + 0c1a10 acoustic stream + 0c1c19 longconn electronics(shenzhen) co.,ltd + 0c1c20 kakao corp + 0c1c57 texas instruments + 0c1daf xiaomi communications co ltd 0c1dc2 seah networks 0c2026 noax technologies ag - 0c2724 cisco + 0c20d3 vivo mobile communication co., ltd. + 0c2138 hengstler gmbh + 0c2369 honeywell sps + 0c2576 longcheer telecommunication limited + 0c2724 cisco systems, inc 0c2755 valuable techologies limited + 0c29ef dell inc. 0c2a69 electric imp, incorporated + 0c2a86 fiberhome telecommunication technologies co.,ltd 0c2ae7 beijing general research institute of mining and metallurgy + 0c2c54 huawei technologies co.,ltd 0c2d89 qiiq communications inc. - 0c3021 apple - 0c37dc huawei technologies co., ltd + 0c2fb0 samsung electronics co.,ltd + 0c3021 apple, inc. + 0c31dc huawei technologies co.,ltd + 0c354f nokia + 0c35fe fiberhome telecommunication technologies co.,ltd + 0c3747 zte corporation + 0c3796 bizlink technology, inc. + 0c37dc huawei technologies co.,ltd + 0c383e fanvil technology co., ltd. 0c3956 observator instruments + 0c3afa new h3c technologies co., ltd + 0c3b50 apple, inc. 0c3c65 dome imaging inc - 0c3e9f apple, inc + 0c3ccd universal global scientific industrial co., ltd. + 0c3e9f apple, inc. + 0c4101 ruichi auto technology (guangzhou) co., ltd. + 0c413e microsoft corporation + 0c41e9 huawei technologies co.,ltd + 0c42a1 mellanox technologies, inc. + 0c45ba huawei technologies co.,ltd 0c469d ms sedco 0c473d hitron technologies. inc - 0c4c39 mitrastar technology - 0c4de9 apple + 0c47c9 amazon technologies inc. + 0c4885 lg electronics (mobile communications) + 0c48c6 celestica inc. + 0c4933 sichuan jiuzhou electronic technology co., ltd. + 0c4b54 tp-link technologies co.,ltd. + 0c4c39 mitrastar technology corp. + 0c4de9 apple, inc. 0c4f5a asa-rt s.r.l. + 0c5101 apple, inc. 0c51f7 chauvin arnoux + 0c5203 agm group limited + 0c5331 eth zurich + 0c5415 intel corporate 0c54a5 pegatron corporation + 0c54b9 nokia 0c5521 axiros gmbh 0c565c hybroad vision (hong kong) technology co ltd 0c57eb mueller systems + 0c5842 dme micro + 0c599c juniper networks 0c5a19 axtion sdn bhd + 0c5a9e wi-sun alliance + 0c5cb5 ieee registration authority 0c5cd8 doli elektronik gmbh + 0c5f35 niagara video corporation 0c6076 hon hai precision ind. co.,ltd. + 0c6111 anda technologies sac + 0c6127 actiontec electronics, inc + 0c61cf texas instruments + 0c62a6 hui zhou gaoshengda technology co.,ltd 0c63fc nanjing signway technology co., ltd - 0c6803 cisco + 0c6803 cisco systems, inc + 0c6abc fiberhome telecommunication technologies co.,ltd + 0c6ae6 stanley security solutions 0c6e4f primevolt co., ltd. + 0c6f9c shaw communications inc. + 0c704a huawei technologies co.,ltd 0c715d samsung electronics co.,ltd 0c722c tp-link technologies co.,ltd. - 0c74c2 apple + 0c72d9 zte corporation + 0c7329 sercomm corporation. + 0c73be dongguan haimai electronie technology co.,ltd + 0c73eb ieee registration authority + 0c74c2 apple, inc. + 0c7512 shenzhen kunlun tongtai technology co.,ltd. 0c7523 beijing gehua catv network co.,ltd - 0c771a apple + 0c756c anaren microwave, inc. + 0c75bd cisco systems, inc + 0c771a apple, inc. + 0c7a15 intel corporate + 0c7c28 nokia solutions and networks gmbh & co. kg 0c7d7c kexiang information technology co, ltd. - 0c8112 + 0c8063 tp-link technologies co.,ltd. + 0c8112 private + 0c8126 juniper networks + 0c817d eep elektro-elektronik pranjic gmbh 0c8230 shenzhen magnus technologies co.,ltd 0c8268 tp-link technologies co.,ltd. 0c826a wuhan huagong genuine optics technology co., ltd + 0c839a huawei device co., ltd. + 0c83cc alpha networks inc. 0c8411 a.o. smith water products + 0c8447 fiberhome telecommunication technologies co.,ltd 0c8484 zenovia electronics inc. 0c84dc hon hai precision ind. co.,ltd. - 0c8525 cisco systems, inc. + 0c8525 cisco systems, inc + 0c8610 juniper networks 0c8910 samsung electronics co.,ltd + 0c8a87 aglogica holdings, inc + 0c8b7d vizio, inc + 0c8bd3 itel mobile limited 0c8bfd intel corporate + 0c8c24 shenzhen bilian electronic co.,ltd + 0c8c69 shenzhen elink smart co., ltd + 0c8c8f kamo technology limited 0c8cdc suunto oy 0c8d98 top eight ind corp + 0c8ddb cisco meraki + 0c8e29 arcadyan corporation + 0c8fff huawei technologies co.,ltd + 0c9160 hui zhou gaoshengda technology co.,ltd 0c924e rice lake weighing systems 0c9301 pt. prasimax inovasi teknologi + 0c938f guangdong oppo mobile telecommunications corp.,ltd 0c93fb bns solutions - 0c96bf huawei technologies co., ltd + 0c9541 chipsea technologies (shenzhen) corp. + 0c96bf huawei technologies co.,ltd + 0c96cd mercury corporation + 0c96e6 cloud network technology (samoa) limited + 0c9838 xiaomi communications co ltd + 0c9a42 fn-link technology limited 0c9b13 shanghai magic mobile telecommunication co.ltd. 0c9d56 consort controls ltd + 0c9d92 asustek computer inc. 0c9e91 sankosha corporation + 0ca06c industrial cyber sensing inc. 0ca138 blinq wireless inc. 0ca2f4 chameleon technology (uk) limited - 0ca402 alcatel lucent ipd + 0ca402 alcatel-lucent ipd 0ca42a ob telecom electronic technology co., ltd 0ca694 sunitec enterprise co.,ltd + 0ca8a7 samsung electronics co.,ltd + 0cac05 unitend technologies inc. + 0cae7d texas instruments 0caf5a genus power infrastructures limited + 0cb2b7 texas instruments + 0cb319 samsung electronics co.,ltd + 0cb34f shenzhen xiaoqi intelligent technology co., ltd. + 0cb459 marketech international corp. + 0cb4a4 xintai automobile intelligent network technology 0cb4ef digience co.,ltd. - 0cbd51 tct mobile limited - 0cbf15 genetec + 0cb527 huawei technologies co.,ltd + 0cb5de alcatel lucent + 0cb6d2 d-link international + 0cb771 arris group, inc. + 0cb789 honor device co., ltd. + 0cb912 jm-data gmbh + 0cb937 ubee interactive co., limited + 0cbc9f apple, inc. + 0cbd51 tct mobile ltd + 0cbf15 genetec inc. + 0cbf3f shenzhen lencotion technology co.,ltd + 0cbf74 morse micro 0cc0c0 magneti marelli sistemas electronicos mexico 0cc3a7 meritec 0cc47a super micro computer, inc. @@ -13143,948 +13807,2575 @@ exit 0cc655 wuxi ysten technology co.,ltd. 0cc66a nokia corporation 0cc6ac dags + 0cc6cc huawei technologies co.,ltd + 0cc731 currant, inc. 0cc81f summer infant, inc. + 0cc844 cambridge mobile telematics, inc. 0cc9c6 samwin hong kong limited + 0ccb0c isys rts gmbh + 0ccb85 motorola mobility llc, a lenovo company 0ccb8d asco numatics gmbh + 0ccc26 airenetworks 0ccdd3 eastriver technology co., ltd. 0ccdfb edic systems inc. + 0ccef6 guizhou fortuneship technology co., ltd + 0ccf89 shenzhen bilian electronic co.,ltd + 0ccfd1 springwave co., ltd + 0cd0f8 cisco systems, inc 0cd292 intel corporate 0cd2b5 binatone telecommunication pvt. ltd - 0cd502 westell + 0cd502 westell technologies inc. 0cd696 amimon ltd + 0cd6bd huawei technologies co.,ltd + 0cd746 apple, inc. 0cd7c2 axium technologies, inc. - 0cd996 cisco systems, inc. - 0cd9c1 johnson controls-asg + 0cd86c shenzhen fast technologies co.,ltd + 0cd996 cisco systems, inc + 0cd9c1 visteon corporation 0cda41 hangzhou h3c technologies co., limited + 0cdc7e espressif inc. 0cdccc inala technologies + 0cdd24 intel corporate 0cddef nokia corporation 0cdfa4 samsung electronics co.,ltd - 0ce0e4 plantronics, inc + 0ce041 idruide + 0ce0dc samsung electronics co.,ltd + 0ce0e4 plantronics, inc. + 0ce441 apple, inc. + 0ce4a0 huawei device co., ltd. 0ce5d3 dh electronics gmbh 0ce709 fox crypto b.v. + 0ce725 microsoft corporation 0ce82f bonfiglioli vectron gmbh 0ce936 elimos srl + 0ce99a atls altec + 0ceac9 arris group, inc. + 0cec80 texas instruments + 0cec84 shenzhen tinno mobile technology corp. + 0cec8d motorola mobility llc, a lenovo company + 0cee99 amazon technologies inc. 0ceee6 hon hai precision ind. co.,ltd. 0cef7c anacom inc + 0cefaf ieee registration authority 0cf019 malgn technology co., ltd. 0cf0b4 globalsat international technology ltd + 0cf346 xiaomi communications co ltd 0cf361 java information 0cf3ee em microelectronic 0cf405 beijing signalway technologies co.,ltd + 0cf475 zliide technologies aps + 0cf4d5 ruckus wireless + 0cf5a4 cisco systems, inc 0cf893 arris group, inc. + 0cf9c0 bskyb ltd 0cfc83 airoha technology corp., - 100000 + 0cfd37 suse linux gmbh + 0cfe45 sony interactive entertainment inc. + 0cfe5d ieee registration authority + 100000 private 10005a ibm corp 1000e8 national semiconductor 1000fd laonpeople + 100177 huawei technologies co.,ltd 1001ca ashley butterworth + 1002b5 intel corporate + 100501 pegatron corporation + 1005b1 arris group, inc. + 1005ca cisco systems, inc + 1005e1 nokia + 100645 sagemcom broadband sas + 100723 ieee registration authority + 1007b6 samsung electronics co.,ltd + 10082c texas instruments + 1008b1 hon hai precision ind. co.,ltd. 10090c janome sewing machine co., ltd. 100ba9 intel corporate 100c24 pomdevices, llc + 100c6b netgear 100d2f online security pty. ltd. 100d32 embedian, inc. - 100d7f netgear inc., + 100d7f netgear 100e2b nec casio mobile communications 100e7e juniper networks 100f18 fu gang electronic(kunshan)co.,ltd + 101081 zte corporation 1010b6 mccain inc 101212 vivo international corporation pty ltd + 101218 korins inc. 101248 itg, inc. + 101250 integrated device technology (malaysia) sdn. bhd. + 1012b4 sichuan tianyi comheart telecom co.,ltd + 1012fb hangzhou hikvision digital technology co.,ltd. + 101331 technicolor 1013ee justec international technology inc. 10189e elmo motion control + 101965 new h3c technologies co., ltd 101b54 huawei technologies co.,ltd - 101c0c apple - 101d51 on-q llc dba on-q mesh networks + 101c0c apple, inc. + 101d51 8mesh networks limited 101dc0 samsung electronics co.,ltd - 101f74 hewlett-packard company + 101f74 hewlett packard 102279 zerodesktop, inc. + 102779 sadel s.p.a. 1027be tvip + 1027f5 tp-link corporation limited 102831 morion inc. + 102959 apple, inc. + 1029ab samsung electronics co.,ltd + 102ab3 xiaomi communications co ltd + 102b41 samsung electronics co.,ltd + 102c6b ampak technology, inc. + 102c83 ximea + 102d31 shenzhen americas trading company llc + 102d41 sichuan ai-link technology co., ltd. 102d96 looxcie inc. 102eaf texas instruments + 102f6b microsoft corporation + 102fa3 shenzhen uvision-tech technology co.ltd + 103025 apple, inc. + 103034 cara systems + 103047 samsung electronics co.,ltd + 10327e huawei device co., ltd. 103378 flectron co., ltd + 1033bf technicolor ch usa inc. + 10341b spacelink + 10364a boston dynamics 103711 simlink as + 10381f sichuan ai-link technology co., ltd. + 103917 samsung electronics co.,ltd + 10394e hisense broadband multimedia technology co.,ltd + 1039e9 juniper networks 103b59 samsung electronics co.,ltd + 103d0a hui zhou gaoshengda technology co.,ltd + 103d1c intel corporate + 103d3e china mobile group device co.,ltd. 103dea hfc technology (beijing) ltd. co. - 1040f3 apple - 104369 soundmax electronic limited + 103f44 xiaomi communications co ltd + 1040f3 apple, inc. + 10417f apple, inc. + 104369 soundmax electronic limited + 104400 huawei technologies co.,ltd 10445a shaanxi hitech electronic co., ltd 1045be norphonic as 1045f8 lnt-automation gmbh + 1046b4 formericaoe 104780 huawei technologies co.,ltd 1048b1 beijing duokan technology limited + 104963 harting k.k. + 104a7d intel corporate + 104b46 mitsubishi electric corporation 104d77 innovative computer engineering + 104e07 shanghai genvision industries co.,ltd + 104e89 garmin international + 104f58 aruba, a hewlett packard enterprise company + 104fa8 sony corporation + 105072 sercomm corporation. + 105107 intel corporate + 105172 huawei technologies co.,ltd + 10521c espressif inc. + 105611 arris group, inc. 1056ca peplink international ltd. + 105887 fiberhome telecommunication technologies co.,ltd + 105917 tonal + 105932 roku, inc + 105af7 adb italia + 105bad mega well limited 105c3b perma-pipe, inc. 105cbf durobyte inc + 105ddc huawei device co., ltd. 105f06 actiontec electronics, inc 105f49 cisco spvtg + 105fd4 tendyron corporation 10604b hewlett packard 1062c9 adatis gmbh & co. kg + 1062d0 technicolor ch usa inc. + 1062e5 hewlett packard + 1062eb d-link international + 1063c8 liteon technology corporation 1064e2 adfweb.com s.r.l. - 1065a3 core brands llc + 106530 dell inc. + 1065a3 panamax llc 1065cf iqsim - 106682 nec accesstechnica, ltd. - 10683f lg electronics - 106f3f buffalo inc. + 106682 nec platforms, ltd. + 10683f lg electronics (mobile communications) + 106f3f buffalo.inc 106fef ad-sol nissin corp + 1070fd mellanox technologies, inc. + 107100 huawei device co., ltd. 1071f9 cloud telecomputers, llc + 107223 tellescom industria e comercio em telecomunicacao + 10746f motorola solutions malaysia sdn. bhd. 10768a eocell + 107717 shenzhen chuangwei-rgb electronics co.,ltd + 1077b0 fiberhome telecommunication technologies co.,ltd 1077b1 samsung electronics co.,ltd + 10785b actiontec electronics, inc + 107873 shenzhen jinkeyi communication co., ltd. 1078ce hanvit si, inc. - 1078d2 elitegroup computer system co., ltd. + 1078d2 elitegroup computer systems co.,ltd. 107a86 u&u engineering inc. - 107bef zyxel communications corp + 107b44 asustek computer inc. + 107ba4 olive & dove co.,ltd. + 107bef zyxel communications corporation + 107d1a dell inc. + 1081b4 hunan greatwall galaxy science and technology co.,ltd. + 108286 luxshare precision industry co.,ltd 1083d2 microseven systems, llc + 10868c arris group, inc. 10880f daruma telecomunicações e informática s.a. - 1088ce fiberhome telecommunication tech.co.,ltd. - 108ccf cisco systems, inc. - 1093e9 apple + 1088ce fiberhome telecommunication technologies co.,ltd + 1089fb samsung electronics co.,ltd + 108a1b raonix inc. + 108b6a antailiye technology co.,ltd + 108ccf cisco systems, inc + 108eba molekule + 108ee0 samsung electronics co.,ltd + 108ffe huawei technologies co.,ltd + 109266 samsung electronics co.,ltd + 109397 arris group, inc. + 1093e9 apple, inc. + 109497 logitech hong kong + 1094bb apple, inc. + 10954b megabyte ltd. + 109693 amazon technologies inc. + 109836 dell inc. + 1098c3 murata manufacturing co., ltd. 109ab9 tosibox oy - 109add apple + 109add apple, inc. + 109c70 prusa research s.r.o. + 109d7a huawei device co., ltd. + 109e3a zhejiang tmall technology co., ltd. 109fa9 actiontec electronics, inc 10a13b fujikura rubber ltd. - 10a5d0 murata manufacturing co.,ltd. + 10a24e gold3link electronics co., ltd + 10a3b8 iskratel d.o.o. + 10a4b9 baidu online network technology (beijing) co., ltd + 10a4be shenzhen bilian electronic co.,ltd + 10a4da huawei technologies co.,ltd + 10a5d0 murata manufacturing co., ltd. + 10a659 mobile create co.,ltd. 10a743 sk mtek limited 10a932 beijing cyber cloud technology co. ,ltd. - 10ae60 + 10ae60 private + 10af78 shenzhen atue technology co., ltd + 10b1f8 huawei technologies co.,ltd 10b26b base co.,ltd. - 10b713 + 10b36f bowei technology company limited + 10b3c6 cisco systems, inc + 10b3d5 cisco systems, inc + 10b3d6 cisco systems, inc + 10b713 private 10b7f6 plastoform industries ltd. + 10b9f7 niko-servodan 10b9fe lika srl 10baa5 gana i&c co., ltd - 10bd18 cisco systems, inc. + 10bc97 vivo mobile communication co., ltd. + 10bd18 cisco systems, inc + 10bd55 q-lab corporation + 10bef5 d-link international 10bf48 asustek computer inc. + 10c07c blu-ray disc association + 10c172 huawei technologies co.,ltd + 10c22f china entropy co., ltd. + 10c25a technicolor ch usa inc. 10c2ba utt co., ltd. + 10c37b asustek computer inc. + 10c3ab huawei technologies co.,ltd 10c586 bio sound lab co., ltd. - 10c61f huawei technologies co., ltd + 10c595 lenovo + 10c60c domino uk ltd + 10c61f huawei technologies co.,ltd + 10c65e adapt-ip + 10c67e shenzhen juchin technology co., ltd 10c6fc garmin international 10c73f midas klark teknik ltd + 10c753 qingdao intelligent&precise electronics co.,ltd. + 10c9ca ace technology corp. 10ca81 precia + 10cc1b liverock technologies,inc 10ccdb aximum produits electroniques + 10cd6e fisys + 10cdae avaya inc + 10cdb6 essential products, inc. + 10ce45 miromico ag + 10cea9 texas instruments + 10cee9 apple, inc. + 10d07a ampak technology, inc. + 10d0ab zte corporation 10d1dc instar deutschland gmbh + 10d38a samsung electronics co.,ltd 10d542 samsung electronics co.,ltd - 10ddb1 apple + 10d561 tuya smart inc. + 10d7b0 sagemcom broadband sas + 10da43 netgear + 10dc4a fiberhome telecommunication technologies co.,ltd + 10dcb6 ieee registration authority + 10ddb1 apple, inc. 10ddf4 maxway electronics co.,ltd 10dee4 automationnext gmbh + 10df8b shenzhen caredear communication technology co.,ltd + 10dffc siemens ag 10e2d5 qi hardware inc. 10e3c7 seohwa telecom 10e4af apr, llc + 10e68f kwangsung electronics korea co.,ltd. 10e6ae source technologies, llc + 10e77a stmicrolectronics international nv + 10e7c6 hewlett packard + 10e878 nokia 10e8ee phasespace + 10e953 huawei device co., ltd. 10ea59 cisco spvtg + 10ec81 samsung electronics co.,ltd 10eed9 canoga perkins corporation - 10f311 cisco + 10f005 intel corporate + 10f163 tnk co.,ltd + 10f1f2 lg electronics (mobile communications) + 10f311 cisco systems, inc 10f3db gridco systems, inc. 10f49a t3 innovation - 10f96f lg electronics + 10f681 vivo mobile communication co., ltd. + 10f920 cisco systems, inc + 10f96f lg electronics (mobile communications) + 10f9eb industria fueguina de relojería electrónica s.a. 10f9ee nokia corporation + 10face reacheng communication technology co.,ltd 10fbf0 kangsheng ltd. - 10fc54 shany electronic co., ltd. - 10feed tp-link technologies co., ltd. - 1100aa - 140708 + 10fc54 shany electronic co., ltd. + 10fcb6 mirusystems co.,ltd + 10feed tp-link technologies co.,ltd. + 1100aa private + 111111 private + 14007d zte corporation + 140152 samsung electronics co.,ltd + 1402ec hewlett packard enterprise + 140467 snk technologies co.,ltd. + 140708 private 1407e0 abrantix ag + 1409b4 zte corporation + 1409dc huawei technologies co.,ltd + 140ac5 amazon technologies inc. + 140c5b plnetworks 140c76 freebox sas 140d4f flextronics international - 14109f apple + 140f42 nokia + 14109f apple, inc. + 141114 tecno mobile limited + 14115d skyworth digital technology(shenzhen) co.,ltd 141330 anakreon uk llp - 14144b fujian star-net communication co.,ltd + 141333 azurewave technology inc. + 141346 skyworth digital technology(shenzhen) co.,ltd + 141357 atp electronics, inc. + 1413fb huawei technologies co.,ltd + 14144b ruijie networks co.,ltd + 141459 vodafone italia s.p.a. + 1414e6 ningbo sanhe digital co.,ltd + 14157c tokyo cosmos electric co.,ltd. + 14169d cisco systems, inc + 14169e wingtech group (hongkong)limited + 141877 dell inc. + 1418c3 intel corporate 141a51 treetech sistemas digitais + 141aa3 motorola mobility llc, a lenovo company + 141b30 shenzhen yipingfang network technology co., ltd. 141bbd volex inc. 141bf0 intellimedia systems ltd + 141f78 samsung electronics co.,ltd + 141fba ieee registration authority + 14205e apple, inc. + 142233 fiberhome telecommunication technologies co.,ltd + 1422db eero inc. + 14230a huawei technologies co.,ltd 1423d7 eutronix co., ltd. + 142475 4dreplay, inc + 142882 midicom electronics co.ltd + 142971 nemoa electronics (hk) co. ltd + 142a14 shenzhen selenview digital technology co.,ltd 142bd2 armtel ltd. + 142bd6 guangdong appscomm co.,ltd + 142c78 goowi wireless technology co., limited 142d27 hon hai precision ind. co.,ltd. 142d8b incipio technologies, inc 142df5 amphitech + 142e5e sercomm corporation. + 142ffd lt security inc + 143004 huawei technologies co.,ltd 14307a avermetrics + 1430c6 motorola mobility llc, a lenovo company + 1432d1 samsung electronics co.,ltd + 143365 tem mobile limited 14358b mediabridge products, llc. 1435b3 future designs, inc. 143605 nokia corporation + 1436c6 lenovo mobile communication technology ltd. + 143719 pt prakarsa visi valutama 14373b procom systems 143aea dynapower company llc + 143b42 realfit(shenzhen) intelligent technology co., ltd + 143cc3 huawei technologies co.,ltd 143df2 beijing shidai hongyuan network communication co.,ltd - 143e60 alcatel-lucent + 143e60 nokia + 143ebf zte corporation + 143f27 noccela oy + 143fa6 sony home entertainment&sound products inc + 143fc3 snapav + 144146 honeywell (china) co., ltd 1441e2 monaco enterprises, inc. + 1442fc texas instruments 144319 creative&link technology limited + 14444a apollo seiko ltd. + 144658 huawei technologies co.,ltd 1446e4 avistel + 14472d guangdong oppo mobile telecommunications corp.,ltd + 144802 the yeolrim co.,ltd. + 14488b shenzhen doov technology co.,ltd 144978 digital control incorporated - 1449e0 samsung electro mechanics co.,ltd. + 1449bc draytek corp. + 1449e0 samsung electro-mechanics(thailand) 144c1a max communication gmbh + 144d67 zioncom electronics (shenzhen) ltd. + 144e2a ciena corporation + 144e34 remote solution + 144f8a intel corporate + 144fd7 ieee registration authority + 145051 sharp corporation + 145120 huawei device co., ltd. + 14517e new h3c technologies co., ltd + 145290 kns group llc (yadro company) 145412 entis co., ltd. + 14563a huawei device co., ltd. 145645 savitech corp. - 145a05 apple + 14568e samsung electronics co.,ltd + 14579f huawei technologies co.,ltd + 1458d0 hewlett packard + 1459c0 netgear + 1459c3 creative chips gmbh + 145a05 apple, inc. + 145a83 logi-d inc + 145afc liteon technology corporation 145bd1 arris group, inc. + 145be1 nyantec gmbh + 145e45 bamboo systems group + 145e69 guangdong oppo mobile telecommunications corp.,ltd + 145f94 huawei technologies co.,ltd 146080 zte corporation + 1460cb apple, inc. + 146102 alpine electronics, inc. + 14612f avaya inc 146308 jabil circuit (shanghai) ltd. + 1469a2 sichuan tianyi comheart telecom co.,ltd 146a0b cypress electronics limited - 146e0a + 146b72 shenzhen fortune ship technology co., ltd. + 146b9a zte corporation + 146b9c shenzhen bilian electronic co.,ltd + 146e0a private 147373 tubitak uekae 147411 rim + 147590 tp-link technologies co.,ltd. + 147740 huawei device co., ltd. + 14780b varex imaging deutschland ag + 1479f3 china mobile group device co.,ltd. + 147bac nokia + 147d05 sercomm philippines inc 147db3 joa telecom.co.,ltd 147dc5 murata manufacturing co., ltd. - 14825b hefei radio communication technology co., ltd + 147dda apple, inc. + 14825b hefei radio communication technology co., ltd + 148430 mitac computing technology corporation + 14857f intel corporate 148692 tp-link technologies co.,ltd. - 1489fd samsung electronics + 14876a apple, inc. + 1488e6 apple, inc. + 14893e vixtel technologies limted + 1489cb huawei technologies co.,ltd + 1489fd samsung electronics co.,ltd 148a70 ads gmbh - 148fc6 apple + 148f21 garmin international + 148fc6 apple, inc. 149090 kongtop industrial(shen zhen)co.,ltd + 149138 amazon technologies inc. + 149182 belkin international inc. + 149346 pni sensor corporation + 14942f usys co.,ltd. 149448 blu castle s.a. - 1499e2 apple, inc + 1495ce apple, inc. + 1496e5 samsung electronics co.,ltd + 149877 apple, inc. + 14987d technicolor ch usa inc. + 1499e2 apple, inc. + 149a10 microsoft corporation + 149b2f jiangsu zhongxie intelligent technology co., ltd + 149d09 huawei technologies co.,ltd + 149d99 apple, inc. + 149ecf dell inc. + 149f3c samsung electronics co.,ltd + 149fb6 guangdong genius technology co., ltd. 149fe8 lenovo mobile communication technology ltd. + 14a0f8 huawei technologies co.,ltd + 14a1bf assa abloy korea co., ltd unilock + 14a2a0 cisco systems, inc + 14a32f huawei device co., ltd. + 14a364 samsung electronics co.,ltd + 14a3b4 huawei device co., ltd. + 14a51a huawei technologies co.,ltd 14a62c s.m. dezac s.a. + 14a72b currentoptronics pvt.ltd + 14a78b zhejiang dahua technology co., ltd. 14a86b shenzhen telacom science&technology co., ltd + 14a9d0 f5 networks, inc. 14a9e3 mst corporation + 14ab02 huawei technologies co.,ltd + 14ab56 wuxi funide digital co.,ltd + 14abc5 intel corporate 14abf0 arris group, inc. + 14adca china mobile iot limited company + 14ae85 ieee registration authority + 14aedb vtech telecommunications ltd. 14b126 industrial software co 14b1c8 infiniwing, inc. + 14b2e5 shenzhen icomm semiconductor co.,ltd + 14b31f dell inc. + 14b370 gigaset digital technology (shenzhen) co., ltd. + 14b457 silicon laboratories + 14b484 samsung electronics co.,ltd 14b73d archean technologies - 14b968 huawei technologies co., ltd + 14b7f8 technicolor ch usa inc. + 14b837 shenzhen youhua technology co., ltd + 14b968 huawei technologies co.,ltd + 14bb6e samsung electronics co.,ltd + 14bd61 apple, inc. + 14c03e arris group, inc. 14c089 dune hd ltd + 14c126 nokia corporation + 14c14e google, inc. + 14c1ff shenzhen qianhai comlan communication co.,ltd + 14c213 apple, inc. 14c21d sabtech industries - 14cc20 tp-link technologies co.,ltd - 14cf8d ohsung electronics co., ltd. - 14cf92 tp-link technologies co., ltd. + 14c3c2 k.a. schmersal gmbh & co. kg + 14c697 guangdong oppo mobile telecommunications corp.,ltd + 14c88b apple, inc. + 14c913 lg electronics + 14caa0 hu&co + 14cb19 hp inc. + 14cc20 tp-link technologies co.,ltd. + 14ccb3 ao gk nateks + 14cf8d ohsung + 14cf92 tp-link technologies co.,ltd. 14cfe2 arris group, inc. - 14d4fe pace plc + 14d00d apple, inc. + 14d11f huawei technologies co.,ltd + 14d169 huawei technologies co.,ltd + 14d19e apple, inc. + 14d4fe arris group, inc. 14d64d d-link international 14d76e conch electronic co.,ltd 14dae9 asustek computer inc. 14db85 s net media + 14dd9c vivo mobile communication co., ltd. + 14dda9 asustek computer inc. + 14dde5 mpmkvvcl + 14de39 huawei device co., ltd. 14e4ec mlogic llc - 14e6e4 tp-link technologies co., ltd. + 14e6e4 tp-link technologies co.,ltd. + 14e7c8 integrated device technology (malaysia) sdn. bhd. + 14e9b2 fiberhome telecommunication technologies co.,ltd + 14eb08 huawei technologies co.,ltd 14eb33 bsmediasoft co., ltd. 14eda5 wächter gmbh sicherheitssysteme + 14edbb 2wire inc + 14ede4 kaiam corporation 14ee9d airnav systems llc + 14efcf schreder 14f0c5 xtremio ltd. 14f28e shenyang zhongke-allwin technology co.ltd - 14f42a samsung electronics + 14f42a samsung electronics co.,ltd + 14f65a xiaomi communications co ltd + 14f6d8 intel corporate + 14f893 wuhan fiberhome digital technology co.,ltd. 14feaf sagittar limited - 14feb5 dell inc - 18002d sony mobile communications ab + 14feb5 dell inc. + 18002d sony mobile communications inc 1800db fitbit inc. - 1801e3 elektrobit wireless communications ltd - 180373 dell inc + 18017d harbin arteor technology co., ltd + 1801e3 bittium wireless ltd + 1801f1 xiaomi communications co ltd + 18022d huawei technologies co.,ltd + 1802ae vivo mobile communication co., ltd. + 180373 dell inc. 1803fa ibt interfaces + 1804ed texas instruments 180675 dilax intelcom gmbh + 1806f5 rad data communications, ltd. + 1806ff acer computer(shanghai) limited. 180b52 nanotron technologies gmbh 180c14 isonea limited 180c77 westinghouse electric company, llc 180cac canon inc. + 180d2c intelbras + 180f76 d-link international 18104e cedint-upm + 181171 guangzhou doctorpai education & technology co.,ltd + 181212 cepton technologies + 18132d zte corporation 181420 teb sas 181456 nokia corporation + 18146c zhejiang tmall technology co., ltd. + 1816c9 samsung electronics co.,ltd 181714 daewoois 181725 cameo communications, inc. + 18188b fujitsu connected technologies limited 18193f tamtron oy + 1819d6 samsung electronics co.,ltd 181beb actiontec electronics, inc + 181dea intel corporate + 181e78 sagemcom broadband sas + 181e95 auverte 181eb0 samsung electronics co.,ltd 182012 aztech associates inc. - 182032 apple + 182032 apple, inc. + 18204c kummler+matter ag 1820a6 sage co., ltd. + 1820d5 arris group, inc. + 182195 samsung electronics co.,ltd + 18227e samsung electronics co.,ltd + 182649 intel corporate 182666 samsung electronics co.,ltd 182861 airties wireless networks + 182a44 hirose electronic system + 182a57 huawei technologies co.,ltd 182a7b nintendo co., ltd. + 182ad3 juniper networks 182b05 8d technologies 182c91 concept development, inc. + 182cb4 nectarsoft co., ltd. + 182d98 jinwoo industrial system + 183009 woojin industrial systems co., ltd. + 18300c hisense electric co.,ltd + 1831bf asustek computer inc. + 183219 em microelectronic 1832a2 laon technology co., ltd. - 18339d cisco systems, inc. - 183451 apple + 18339d cisco systems, inc + 183451 apple, inc. + 1835d1 arris group, inc. + 183672 shaoxing shunchuang technology co.,ltd 1836fc elecsys international corporation 183825 wuhan lingjiu high-tech co.,ltd. + 183864 cap-tech international co., ltd. + 1838ae conspin solution 183919 unicoi systems + 18396e sunsea telecommunications co.,ltd. + 18399c skorpios technologies + 183a2d samsung electronics co.,ltd + 183a48 vostronet 183bd2 byd precision manufacture company ltd. + 183cb7 huawei device co., ltd. + 183d5e huawei technologies co.,ltd 183da2 intel corporate + 183eef apple, inc. 183f47 samsung electronics co.,ltd - 18421d + 1840a4 shenzhen trylong smart science and technology co., ltd. + 1841fe digital 14 + 18421d private 18422f alcatel lucent + 1842d4 wuhan hosan telecommunication technology co.,ltd 184462 riava networks, inc. - 184617 samsung electronics + 1844e6 zte corporation + 184516 texas instruments + 184593 taicang t&w electronics + 184617 samsung electronics co.,ltd + 184644 home control singapore pte ltd + 18473d chongqing fugui electronics co.,ltd. + 184859 castlenet technology inc. + 1848ca murata manufacturing co., ltd. 1848d8 fastback networks + 184a6f alcatel-lucent shanghai bell co., ltd + 184b0d ruckus wireless + 184bdf caavo inc + 184c08 rockwell automation + 184cae continental + 184e16 samsung electronics co.,ltd 184e94 messoa technologies inc. + 184ecb samsung electronics co.,ltd + 184f32 hon hai precision ind. co.,ltd. + 184f5d jrc mobility inc. + 18502a soarnex + 185207 sichuan tianyi comheart telecomco., ltd 185253 pixord corporation + 185282 fiberhome telecommunication technologies co.,ltd 1853e0 hanyang digitech co.ltd + 1854cf samsung electronics co.,ltd 18550f cisco spvtg + 1855e3 apple, inc. + 185644 huawei technologies co.,ltd + 185680 intel corporate + 185869 sailer electronic co., ltd 185933 cisco spvtg + 185936 xiaomi communications co ltd + 185a58 dell inc. 185ae8 zenotech.co.,ltd - 18622c sagemcom sas - 186472 aruba networks + 185bb3 samsung electronics co.,ltd + 185d9a bobjgear llc + 185e0f intel corporate + 186024 hewlett packard + 1861c7 lemonbeat gmbh + 18622c sagemcom broadband sas + 1862e4 texas instruments + 186472 aruba, a hewlett packard enterprise company + 186571 top victory electronics (taiwan) co., ltd. + 186590 apple, inc. + 1866c7 shenzhen libre technology co., ltd + 1866da dell inc. 1866e3 veros systems, inc. 18673f hanover displays limited 186751 komeg industrielle messtechnik gmbh 1867b0 samsung electronics co.,ltd + 18686a zte corporation + 186882 beward r&d co., ltd. + 1868cb hangzhou hikvision digital technology co.,ltd. + 1869d8 tuya smart inc. + 1869da china mobile group device co.,ltd. 186d99 adanis inc. + 186f2d shenzhen sundray technologies company limited + 18703b huawei device co., ltd. + 187117 eta plus electronic gmbh + 1871d5 hazens automotive electronics(sz)co.,ltd. + 18742e amazon technologies inc. + 187532 sichuan tianyi comheart telecomco., ltd + 1878d4 verizon 1879a2 gmj electric limited 187a93 amiccom electronics corporation + 187c0b ruckus wireless 187c81 valeo vision systems + 187eb9 apple, inc. 187ed5 shenzhen kaism technology co. ltd + 188090 cisco systems, inc 1880ce barberry solutions ltd 1880f5 alcatel-lucent shanghai bell co., ltd + 18810e apple, inc. + 188219 alibaba cloud computing ltd. + 18828c arcadyan corporation 188331 samsung electronics co.,ltd + 1883bf arcadyan technology corporation 188410 coretrust inc. 18863a digital art system 1886ac nokia danmark a/s + 188740 xiaomi communications co ltd 188796 htc corporation 188857 beijing jinhong xi-dian information technology corp. + 18895b samsung electronics co.,ltd + 1889a0 wuhan funshion online technologies co.,ltd 1889df cerebrex inc. + 188a6a avpro global hldgs + 188b15 shenzhen zhongruijing technology co.,ltd + 188b45 cisco systems, inc + 188b9d cisco systems, inc 188ed5 tp vision belgium n.v. - innovation site brugge + 188ef9 g2c co. ltd. + 189088 eero inc. + 1890d8 sagemcom broadband sas 18922c virtual instruments + 1892a4 ciena corporation + 18937f ampak technology, inc. + 1893d7 texas instruments + 1894c6 shenzhen chenyee technology co., ltd. + 189552 1more 1897ff techfaith wireless technology limited + 1899f5 sichuan changhong electric ltd. 189a67 cse-servelec limited - 189c5d cisco - 189efc apple - 18a905 hewlett-packard company - 18a99b dell inc + 189ba5 ieee registration authority + 189c27 arris group, inc. + 189c5d cisco systems, inc + 189e2c huawei device co., ltd. + 189efc apple, inc. + 18a28a essel-t co., ltd + 18a3e8 fiberhome telecommunication technologies co.,ltd + 18a4a9 vanu inc. + 18a6f7 tp-link technologies co.,ltd. + 18a7f1 qingdao haier technology co.,ltd + 18a905 hewlett packard + 18a958 provision thai co., ltd. + 18a99b dell inc. + 18aa0f huawei device co., ltd. 18aa45 fon technology - 18abf5 ultra electronics - electrics + 18aaca sichuan tianyi kanghe communications co., ltd + 18ab1d samsung electronics co.,ltd + 18abf5 ultra electronics electrics + 18ac9e itel mobile limited 18ad4d polostar technology corporation 18aebb siemens convergence creators gmbh&co.kg - 18af61 apple, inc - 18af8f apple + 18af61 apple, inc. + 18af8f apple, inc. 18af9f digitronic automationsanlagen gmbh + 18b169 sonicwall 18b209 torrey pines logic, inc 18b3ba netlogic ab 18b430 nest labs inc. 18b591 i-storm + 18b6cc we corporation inc. + 18b6f7 new pos technology limited 18b79e invoxia - 18c086 broadcom corporation + 18b81f arris group, inc. + 18b905 hong kong bouffalo lab limited + 18bb26 fn-link technology limited + 18bb41 huawei device co., ltd. + 18bc5a zhejiang tmall technology co., ltd. + 18bdad l-tech corporation + 18be92 delta networks, inc. + 18bf1c jiangsu huitong group co.,ltd. + 18bfb3 samsung electronics co., ltd., memory division + 18c04d giga-byte technology co.,ltd. + 18c086 broadcom + 18c19d integrated device technology (malaysia) sdn. bhd. + 18c241 sonicwall + 18c2bf buffalo.inc 18c451 tucson embedded systems + 18c501 shenzhen gongjin electronics co.,lt + 18c58a huawei technologies co.,ltd 18c8e7 shenzhen hualistone technology co.,ltd + 18cc18 intel corporate 18cc23 philio technology corporation - 18d071 dasan smc, inc. + 18cc88 hitachi johnson controls air + 18ce94 samsung electronics co.,ltd + 18cf24 huawei technologies co.,ltd + 18cf5e liteon technology corporation + 18d071 dasan co., ltd. + 18d0c5 guangdong oppo mobile telecommunications corp.,ltd + 18d225 fiberhome telecommunication technologies co.,ltd + 18d276 huawei technologies co.,ltd + 18d5b6 smg holdings llc + 18d61c shenzhen tinno mobile technology corp. 18d66a inmarsat + 18d6c7 tp-link technologies co.,ltd. 18d6cf kurth electronic gmbh + 18d717 guangdong oppo mobile telecommunications corp.,ltd 18d949 qvis labs, llc - 18dc56 yulong computer telecommunication scientific(shenzhen)co.,lt + 18d98f huawei device co., ltd. + 18d9ef shuttle inc. + 18dbf2 dell inc. + 18dc56 yulong computer telecommunication scientific (shenzhen) co.,ltd + 18ded7 huawei technologies co.,ltd + 18dfb4 bosung powertec co.,ltd. + 18dfc1 aetheros + 18e1ca wanze 18e288 stt condigi - 18e2c2 samsung electronics - 18e728 cisco - 18e7f4 apple + 18e29f vivo mobile communication co., ltd. + 18e2c2 samsung electronics co.,ltd + 18e3bc tct mobile ltd + 18e728 cisco systems, inc + 18e777 vivo mobile communication co., ltd. + 18e7f4 apple, inc. 18e80f viking electronics inc. + 18e829 ubiquiti networks inc. 18e8dd moduletek - 18ef63 cisco systems, inc. + 18ece7 buffalo.inc + 18ee69 apple, inc. + 18ee86 novatel wireless solutions, inc. + 18ef63 cisco systems, inc + 18f0e4 xiaomi communications co ltd + 18f145 netcomm wireless limited + 18f18e chiper technology co. ltd + 18f1d8 apple, inc. + 18f292 shannon systems 18f46a hon hai precision ind. co.,ltd. + 18f643 apple, inc. 18f650 multimedia pacific limited + 18f76b zhejiang winsight technology co.,ltd 18f87a i3 international inc. + 18f9c4 bae systems 18fa6f isc applied systems corp - 18fb7b dell inc + 18fb7b dell inc. 18fc9f changhe electronics co., ltd. + 18fdcb ieee registration authority 18fe34 espressif inc. + 18ff0f intel corporate 18ff2e shenzhen rui ying da technology co., ltd + 1c0042 nari technology co., ltd. + 1c012d ficer technology + 1c0219 guangdong oppo mobile telecommunications corp.,ltd + 1c05b7 chongqing trantor technology co., ltd. 1c0656 idy corporation 1c08c1 lg innotek 1c0b52 epicom s.a + 1c0faf lucid vision labs 1c0fcf sypro optics gmbh + 1c1161 ciena corporation 1c11e1 wartsila finland oy - 1c129d ieee pes psrc/sub + 1c129d ieee pes psrc/sub + 1c12b0 amazon technologies inc. + 1c1338 kimball electronics group, llc + 1c1386 huawei device co., ltd. 1c1448 arris group, inc. - 1c17d3 cisco systems, inc. + 1c14b3 airwire technologies + 1c151f huawei technologies co.,ltd + 1c17d3 cisco systems, inc 1c184a shenzhen richerlink technologies co.,ltd 1c19de eyevis gmbh - 1c1ac0 apple + 1c1ac0 apple, inc. + 1c1adf microsoft corporation + 1c1b0d giga-byte technology co.,ltd. 1c1b68 arris group, inc. + 1c1bb5 intel corporate 1c1cfd dalian hi-think computer technology, corp - 1c1d67 shenzhen huawei communication technologies co., ltd - 1c1d86 cisco + 1c1d67 huawei technologies co.,ltd + 1c1d86 cisco systems, inc + 1c1e38 pccw global, inc. + 1c1ee3 hui zhou gaoshengda technology co.,ltd + 1c1fd4 lifebeam technologies ltd + 1c1ff1 huawei device co., ltd. + 1c20db huawei technologies co.,ltd + 1c21d1 ieee registration authority + 1c232c samsung electronics co.,ltd + 1c234f edmi europe ltd + 1c24cd askey computer corp. + 1c24eb burlywood + 1c25e1 china mobile iot company limited + 1c2704 zte corporation + 1c27dd datang gohighsec(zhejiang)information technology co.,ltd. + 1c28af aruba, a hewlett packard enterprise company + 1c2aa3 shenzhen hongrui optical technology co., ltd. + 1c2e1b suzhou tremenet communication technology co., ltd. + 1c3008 hui zhou gaoshengda technology co.,ltd + 1c330e pernixdata 1c334d its telecom 1c3477 innovation wireless + 1c34da mellanox technologies, inc. 1c35f1 new lift neue elektronische wege steuerungsbau gmbh + 1c36bb apple, inc. 1c37bf cloudium systems ltd. + 1c3929 ohsung + 1c3947 compal information (kunshan) co., ltd. + 1c398a fiberhome telecommunication technologies co.,ltd 1c3a4f accuspec electronics, llc + 1c3a60 ruckus wireless + 1c3ade samsung electronics co.,ltd + 1c3b8f selve gmbh & co. kg + 1c3bf3 tp-link technologies co.,ltd. + 1c3d2f huawei technologies co.,ltd 1c3de7 sigma koki co.,ltd. 1c3e84 hon hai precision ind. co.,ltd. + 1c4024 dell inc. + 1c40e8 shenzhen progress&win technology co.,ltd 1c4158 gemalto m2m gmbh + 1c4176 china mobile group device co.,ltd. + 1c427d guangdong oppo mobile telecommunications corp.,ltd + 1c4363 huawei technologies co.,ltd 1c43ec japan circuit co.,ltd + 1c4419 tp-link technologies co.,ltd. + 1c4455 sieb & meyer ag 1c4593 texas instruments + 1c45c2 huizhou city sunsin lntelligent technology co.,ltd + 1c472f huawei device co., ltd. + 1c4840 ims messsysteme gmbh + 1c48ce guangdong oppo mobile telecommunications corp.,ltd 1c48f9 gn netcom a/s + 1c497b gemtek technology co., ltd. 1c4af7 amon inc 1c4bb9 smg enterprise, llc - 1c4bd6 azurewave + 1c4bd6 azurewave technology inc. + 1c4c48 itel mobile limited + 1c4d66 amazon technologies inc. + 1c4d70 intel corporate + 1c501e sunplus technology co., ltd. 1c51b5 techaya ltd + 1c5216 dongguan hele electronics co., ltd 1c52d6 flat display technology corporation - 1c5a3e samsung eletronics co., ltd (visual display divison) + 1c549e universal electronics, inc. + 1c553a qiangua corp. + 1c56fe motorola mobility llc, a lenovo company + 1c57d8 kraftway corporation plc + 1c599b huawei technologies co.,ltd + 1c5a0b tegile systems + 1c5a3e samsung electronics co.,ltd 1c5a6b philips electronics nederland bv 1c5c55 prima cinema, inc 1c5c60 shenzhen belzon technology co.,ltd. + 1c5cf2 apple, inc. + 1c5d80 mitubishi hitachi power systems industries co., ltd. + 1c5f2b d-link international 1c5fff beijing ereneben information technology co.,ltd shenzhen branch + 1c60d2 fiberhome telecommunication technologies co.,ltd + 1c60de mercury communication technologies co.,ltd. 1c62b8 samsung electronics co.,ltd 1c63b7 openproducts 237 ab + 1c63bf shenzhen broadtel telecom co.,ltd + 1c6499 comtrend corporation 1c659d liteon technology corporation - 1c666d hon hai precision ind.co.ltd - 1c66aa samsung electronics - 1c69a5 research in motion + 1c666d hon hai precision ind. co.,ltd. + 1c66aa samsung electronics co.,ltd + 1c6758 huawei technologies co.,ltd + 1c687e shenzhen qihu intelligent technology company limited + 1c697a elitegroup computer systems co., ltd + 1c69a5 blackberry rts + 1c6a7a cisco systems, inc 1c6bca mitsunami co., ltd. + 1c6e4c logistic service & engineering co.,ltd + 1c6e76 quarion technology inc + 1c6ee6 nhnetworks 1c6f65 giga-byte technology co.,ltd. - 1c7508 compal information (kunshan) co., ltd. + 1c7022 murata manufacturing co., ltd. + 1c721d dell inc. + 1c7328 connected home + 1c7370 neotech + 1c740d zyxel communications corporation + 1c7508 compal information (kunshan) co., ltd. 1c76ca terasic technologies inc. + 1c77f6 guangdong oppo mobile telecommunications corp.,ltd 1c7839 shenzhen tencent computer system co., ltd. - 1c7b21 sony mobile communications ab - 1c7c11 eid + 1c784e china mobile iot limited company + 1c7b21 sony mobile communications inc + 1c7b23 qingdao hisense communications co.,ltd. + 1c7c11 eid 1c7c45 vitek industrial video products, inc. 1c7cc7 coriant gmbh + 1c7d22 fuji xerox co., ltd. + 1c7e51 3bumen.com 1c7ee5 d-link international + 1c7f2c huawei technologies co.,ltd + 1c8259 ieee registration authority + 1c8341 hefei bitland information technology co.ltd 1c83b0 linked ip gmbh 1c8464 formosa wireless communication corp. 1c86ad mct co., ltd. + 1c872c asustek computer inc. + 1c87e3 tecno mobile limited + 1c8e5c huawei technologies co.,ltd 1c8e8e db communication & systems co., ltd. 1c8f8a phase motion control spa + 1c90be ericsson ab + 1c9148 apple, inc. 1c9179 integrated system technologies ltd + 1c9180 apple, inc. + 1c919d dongguan liesheng electronic co., ltd. + 1c937c arris group, inc. 1c9492 ruag schweiz ag 1c955d i-lax electronics inc. 1c959f veethree electronics and marine llc + 1c965a weifang goertek electronics co.,ltd 1c973d pricom design - 1c994c murata manufactuaring co.,ltd. - 1ca770 shenzhen chuangwei-rgb electronics co.,lt - 1caa07 cisco systems, inc. + 1c97c5 ynomia pty ltd + 1c98c1 cloud network technology singapore pte. ltd. + 1c98ec hewlett packard enterprise + 1c994c murata manufacturing co., ltd. + 1c9957 intel corporate + 1c9c26 zoovel technologies + 1c9c8c juniper networks + 1c9d3e integrated device technology (malaysia) sdn. bhd. + 1c9e46 apple, inc. + 1c9ecb beijing nari smartchip microelectronics company limited + 1c9f4e coosea group (hk) company limited + 1ca0b8 hon hai precision ind. co., ltd. + 1ca0d3 ieee registration authority + 1ca0ef ieee registration authority + 1ca2b1 ruwido austria gmbh + 1ca532 shenzhen gongjin electronics co.,lt + 1ca681 huawei technologies co.,ltd + 1ca770 shenzhen chuangwei-rgb electronics co.,ltd + 1ca852 sensaio pte ltd + 1caa07 cisco systems, inc 1cab01 innovolt - 1caba7 apple + 1cab34 new h3c technologies co., ltd + 1caba7 apple, inc. + 1cabc0 hitron technologies. inc + 1cadd1 bosung electronics co., ltd. + 1caecb huawei technologies co.,ltd 1caf05 samsung electronics co.,ltd - 1caff7 d-link international pte limited + 1caff7 d-link international + 1cb044 askey computer corp 1cb094 htc corporation - 1cb17f nec accesstechnica, ltd. + 1cb17f nec platforms, ltd. 1cb243 tdc a/s + 1cb3e9 shenzhen zhongke united communication technology + 1cb72c asustek computer inc. + 1cb796 huawei technologies co.,ltd + 1cb857 becon technologies co,.ltd. + 1cb9c4 ruckus wireless 1cba8c texas instruments - 1cbba8 ojsc "ufimskiy zavod "promsvyaz" + 1cbba8 ojsc ufimskiy zavod promsvyaz 1cbd0e amplified engineering pty ltd - 1cbdb9 d-link international pte limited + 1cbdb9 d-link international + 1cbfc0 chongqing fugui electronics co.,ltd. + 1cbfce shenzhen century xinyang technology co., ltd + 1cc035 planex communications inc. + 1cc0e1 ieee registration authority 1cc11a wavetronix - 1cc1de hewlett-packard company + 1cc1bc yichip microelectronics (hangzhou) co.,ltd + 1cc1de hewlett packard 1cc316 milesight technology co., ltd. + 1cc3eb guangdong oppo mobile telecommunications corp.,ltd + 1cc586 absolute acoustics 1cc63c arcadyan technology corporation + 1cc72d shenzhen huapu digital co.,ltd + 1ccae3 ieee registration authority + 1ccb99 tct mobile ltd + 1cccd6 xiaomi communications co ltd + 1ccde5 shanghai wind technologies co.,ltd + 1cd107 realme chongqing mobile telecommunications corp.,ltd. + 1cd1ba fiberhome telecommunication technologies co.,ltd + 1cd1e0 cisco systems, inc 1cd40c kriwan industrie-elektronik gmbh - 1cdf0f cisco systems, inc. + 1cd5e2 shenzhen youhua technology co., ltd + 1cd6bd leedarson lighting co., ltd. + 1cd6be wistron neweb corporation + 1cda27 vivo mobile communication co., ltd. + 1cddea guangdong oppo mobile telecommunications corp.,ltd + 1cde57 fiberhome telecommunication technologies co.,ltd + 1cdea7 cisco systems, inc + 1cdf0f cisco systems, inc + 1cdf52 texas instruments 1ce165 marshal corporation 1ce192 qisda corporation 1ce2cc texas instruments - 1ce62b apple - 1ce6c7 cisco + 1ce57f samsung electronics co.,ltd + 1ce61d samsung electronics co.,ltd + 1ce62b apple, inc. + 1ce6ad huawei device co., ltd. + 1ce6c7 cisco systems, inc + 1ce85d cisco systems, inc + 1cea0b edgecore networks corporation + 1cea1b nokia + 1cec72 allradio co., ltd + 1ceec9 elo touch solutions 1ceee8 ilshin elecom + 1cefce bebro electronic gmbh + 1cf03e wearhaus inc. 1cf061 scaps gmbh - 1cf4ca + 1cf29a google, inc. + 1cf4ca private 1cf5e7 turtle industry co., ltd. 1cfa68 tp-link technologies co.,ltd. 1cfcbb realfiction aps + 1cfd08 ieee registration authority + 1cfe2b amazon technologies inc. 1cfea7 identytech solutins ltd. + 1cff59 sichuan tianyi comheart telecom co., ltd. 20014f linea research ltd - 2002af murata manufactuaring co.,ltd. + 2002af murata manufacturing co., ltd. + 20040f dell inc. 200505 radmax communication private limited 2005e8 ooo inpromedia - 2008ed huawei technologies co., ltd - 200a5e xiangshan giant eagle technology developing co.,ltd + 2008ed huawei technologies co.,ltd + 200a0d ieee registration authority + 200a5e xiangshan giant eagle technology developing co., ltd. 200bc7 huawei technologies co.,ltd - 200cc8 netgear inc., + 200bcf nintendo co.,ltd + 200cc8 netgear + 200db0 shenzhen four seas global link network technology co., ltd. 200e95 iec – tc9 wg43 + 200f70 foxtech 20107a gemtek technology co., ltd. + 20114e metersit s.r.l. 201257 most lucky trading ltd + 2012d5 scientech materials corporation 2013e0 samsung electronics co.,ltd + 20163d integrated device technology (malaysia) sdn. bhd. + 2016b9 intel corporate 2016d8 liteon technology corporation + 201742 lg electronics 20180e shenzhen sunchip technology co., ltd - 201a06 compal information (kunshan) co., ltd. + 201a06 compal information (kunshan) co., ltd. + 201b88 dongguan liesheng electronic co., ltd. + 201bc9 juniper networks 201d03 elatec gmbh - 2021a5 lg electronics inc + 201e88 intel corporate + 201f31 inteno broadband technology ab + 2021a5 lg electronics (mobile communications) 202564 pegatron corporation 202598 teleview - 202bc1 shenzhen huawei communication technologies co., ltd + 2025d2 fiberhome telecommunication technologies co.,ltd + 202681 tecno mobile limited + 20283e huawei technologies co.,ltd + 2028bc visionscape co,. ltd. + 202ac5 petite-en + 202bc1 huawei technologies co.,ltd 202cb7 kong yue electronics & information industry (xinhui) ltd. - 203706 cisco systems, inc. + 202d07 samsung electronics co.,ltd + 202d23 collinear networks inc. + 202df8 digital media cartridge ltd. + 20311c vivo mobile communication co., ltd. + 2031eb hdsn + 203233 shenzhen bilian electronic co.,ltd + 20326c samsung electronics co.,ltd + 2034fb xiaomi communications co ltd + 20365b megafone limited + 2036d7 shanghai reacheng communication technology co.,ltd + 203706 cisco systems, inc 2037bc kuipers electronic engineering bv - 203a07 cisco + 203956 hmd global oy + 203a07 cisco systems, inc + 203aef sivantos gmbh + 203b69 vivo mobile communication co., ltd. + 203cae apple, inc. + 203d66 arris group, inc. + 203db2 huawei technologies co.,ltd + 203dbd lg innotek 204005 feno gmbh 20415a smarteh d.o.o. 20443a schneider electric asia pacific ltd + 204441 remote solution 2046a1 vecow co., ltd 2046f9 advanced network devices (dba:and) + 204747 dell inc. + 2047da xiaomi communications co ltd + 2047ed bskyb ltd 204aaa hanscan spain s.a. + 204c03 aruba, a hewlett packard enterprise company 204c6d hugo brennenstuhl gmbh & co. kg. + 204c9e cisco systems, inc 204e6b axxana(israel) ltd + 204e71 juniper networks 204e7f netgear - 205476 sony mobile communications ab + 204ef6 azurewave technology inc. + 2050e7 ampak technology,inc. + 2053ca risk technology ltd + 205476 sony mobile communications inc + 2054fa huawei technologies co.,ltd + 205531 samsung electronics co.,ltd + 205532 gotech international technology limited 205721 salix technology co., ltd. + 2057af shenzhen fh-net optoelectronics co.,ltd + 205869 ruckus wireless 2059a0 paragon technologies inc. 205a00 coval - 205b2a + 205b2a private 205b5e shenzhen wonhe technology co., ltd - 206432 samsung electro mechanics co.,ltd. + 205cfa yangzhou changlian network technology co,ltd. + 205d47 vivo mobile communication co., ltd. + 205e64 huawei device co., ltd. + 205ef7 samsung electronics co.,ltd + 205f3d cambridge communication systems ltd + 206274 microsoft corporation + 20635f abeeway + 206432 samsung electro mechanics co., ltd. + 2064cb guangdong oppo mobile telecommunications corp.,ltd + 20658e huawei technologies co.,ltd + 2066cf freebox sas + 20677c hewlett packard enterprise 2067b1 pluto inc. 20689d liteon technology corporation - 206a8a wistron infocomm manufacturing(kunshan)co.,ltd. + 206980 apple, inc. + 206a8a wistron infocomm (zhongshan) corporation + 206a94 hitron technologies. inc 206aff atlas elektronik uk limited + 206be7 tp-link technologies co.,ltd. + 206c8a extreme networks, inc. + 206d31 firewalla inc + 206e9c samsung electronics co.,ltd 206fec braemac ca llc + 20719e sf technology co.,ltd 207355 arris group, inc. + 207454 vivo mobile communication co., ltd. 2074cf shenzhen voxtech co.,ltd 207600 actiontec electronics, inc + 20768f apple, inc. + 207693 lenovo (beijing) limited. + 207759 optical network video technologies (shenzhen) co., ltd. + 20780b delta faucet company + 207852 nokia solutions and networks gmbh & co. kg + 2078f0 apple, inc. + 207918 intel corporate 207c8f quanta microsystems,inc. - 207d74 apple + 207d74 apple, inc. + 208058 ciena corporation + 20826a guangdong oppo mobile telecommunications corp.,ltd + 2082c0 xiaomi communications co ltd + 2083f8 advanced digital broadcast sa 20858c assa + 208593 ieee registration authority + 208756 siemens ag 2087ac aes motomation - 208984 compal information (kunshan) co., ltd + 2087ec huawei technologies co.,ltd + 20896f fiberhome telecommunication technologies co.,ltd + 208984 compal information (kunshan) co., ltd. 208986 zte corporation + 208b37 skyworth digital technology(shenzhen) co.,ltd + 20906f shenzhen tencent computer system co., ltd. + 209148 texas instruments 20918a profalux 2091d9 i'm spa + 20934d fujian star-net communication co.,ltd + 20968a china mobile (hangzhou) information technology co., ltd. + 2098d8 shenzhen yingdakang technology co., ltd + 209a7d sagemcom broadband sas 209ae9 volacomm co., ltd 209ba5 jiaxing glead electronics co.,ltd + 209bcd apple, inc. + 209e79 universal electronics, inc. + 209ef7 extreme networks, inc. + 20a171 amazon technologies inc. + 20a2e4 apple, inc. 20a2e7 lee-dickens ltd + 20a60c xiaomi communications co ltd + 20a680 huawei technologies co.,ltd + 20a6cd hewlett packard enterprise + 20a783 micontrol gmbh 20a787 bointec taiwan corporation limited + 20a7f9 shenzhen olanboa technology co., ltd + 20a8b9 siemens ag + 20a90e tct mobile ltd + 20a99b microsoft corporation 20aa25 ip-net llc 20aa4b cisco-linksys, llc + 20ab37 apple, inc. + 20ab48 huawei technologies co.,ltd + 20ac9c china telecom corporation limited + 20ad56 continental automotive systems inc. + 20b001 technicolor 20b0f7 enclustra gmbh 20b399 enterasys 20b5c6 mimosa networks + 20b730 tecongroup, inc + 20b780 toshiba visual solutions corporation co.,ltd 20b7c0 omicron electronics gmbh - 20bbc0 cisco + 20bb76 col giovanni paolo spa + 20bbc0 cisco systems, inc 20bbc6 jabil circuit hungary ltd. 20bfdb dvl + 20c047 verizon + 20c06d shenzhen spacetek technology co.,ltd 20c1af i wit digital co., limited + 20c38f texas instruments + 20c3a4 retailnext 20c60d shanghai annijie information technology co.,ltd 20c6eb panasonic corporation avc networks company + 20c74f sensorpush 20c8b3 shenzhen bul-tech co.,ltd. - 20c9d0 apple - 20cd39 texas instruments, inc + 20c9d0 apple, inc. + 20cd39 texas instruments + 20cd6e realme chongqing mobile telecommunications corp.,ltd. + 20ce2a ieee registration authority 20cec4 peraso technologies 20cf30 asustek computer inc. + 20d160 private 20d21f wincal technology corp. + 20d25f smartcap technologies 20d390 samsung electronics co.,ltd 20d5ab korea infocom co.,ltd. - 20d5bf samsung eletronics co., ltd + 20d5bf samsung electronics co.,ltd 20d607 nokia corporation + 20d75a posh mobile limited + 20d80b juniper networks 20d906 iota, inc. + 20da22 huawei technologies co.,ltd + 20dbab samsung electronics co., ltd. 20dc93 cheetah hi-tech, inc. - 20dce6 tp-link technologies co., ltd. + 20dce6 tp-link technologies co.,ltd. + 20dcfd huawei device co., ltd. + 20de88 ic realtime llc 20df3f nanjing sac power grid automation co., ltd. - 20e52a netgear inc., + 20dfb9 google, inc. + 20e09c nokia + 20e2a8 apple, inc. + 20e407 spark srl + 20e52a netgear 20e564 arris group, inc. 20e791 siemens healthcare diagnostics, inc + 20e874 apple, inc. + 20e882 zte corporation 20eac7 shenzhen riopine electronics co., ltd + 20ed74 ability enterprise co.,ltd. + 20ee28 apple, inc. 20eec6 elefirst science & tech co ., ltd + 20efbd roku, inc 20f002 mtdata developments pty. ltd. - 20f3a3 huawei technologies co., ltd + 20f17c huawei technologies co.,ltd + 20f19e arris group, inc. + 20f375 arris group, inc. + 20f3a3 huawei technologies co.,ltd + 20f41b shenzhen bilian electronic co.,ltd + 20f44f nokia + 20f452 shanghai iuv software development co. ltd + 20f478 xiaomi communications co ltd + 20f510 codex digital limited + 20f543 hui zhou gaoshengda technology co.,ltd + 20f77c vivo mobile communication co., ltd. 20f85e delta electronics 20fabb cambridge executive limited 20fdf1 3com europe ltd 20fecd system in frontier inc. 20fedb m2m solution s.a.s. - 2401c7 cisco + 20ff36 iflytek co.,ltd. + 2400ba huawei technologies co.,ltd + 2400fa china mobile (hangzhou) information technology co., ltd + 24016f huawei device co., ltd. + 2401c7 cisco systems, inc 24050f mtn electronic co. ltd + 240588 google, inc. + 2405f5 integrated device technology (malaysia) sdn. bhd. + 2406aa guangdong oppo mobile telecommunications corp.,ltd 240917 devlin electronics limited - 240a11 tct mobile limited - 240a64 azurewavetechnologies,inc + 240995 huawei technologies co.,ltd + 240a11 tct mobile ltd + 240a63 arris group, inc. + 240a64 azurewave technology inc. + 240ac4 espressif inc. + 240b0a palo alto networks 240b2a viettel group - 240bb1 kostal industrie elektrik gmbh + 240b88 taicang t&w electronics + 240bb1 kostal industrie elektrik gmbh + 240d65 shenzhen vsun communication technology co., ltd. + 240d6c smnd + 240dc2 tct mobile ltd 241064 shenzhen ecsino tecnical co. ltd 241125 hutek co., ltd. + 241145 xiaomi communications co ltd 241148 entropix, llc 2411d0 chongqing ehs science and technology development co.,ltd. + 241407 xiamen sigmastar technology ltd. + 241510 ieee registration authority + 24166d huawei technologies co.,ltd + 24169d cisco systems, inc + 24181d samsung electro-mechanics(thailand) + 2418c6 hunan fn-link technology limited 241a8c squarehead technology as + 241ae6 huawei device co., ltd. 241b13 shanghai nutshell electronic co., ltd. + 241b44 hangzhou tuners electronics co., ltd + 241b7a apple, inc. + 241c04 shenzhen jehe technology development co., ltd. + 241eeb apple, inc. 241f2c calsys, inc. - 2421ab sony ericsson mobile communications + 241fa0 huawei technologies co.,ltd + 2420c7 sagemcom broadband sas + 242124 nokia + 2421ab sony mobile communications inc + 24240e apple, inc. 242642 sharp corporation. + 2429fe kyocera corporation + 242e02 huawei technologies co.,ltd + 242e90 palit microsystems, ltd 242ffa toshiba global commerce solutions - 24336c + 2430f8 huawei device co., ltd. + 243154 huawei technologies co.,ltd + 243184 sharp corporation + 24336c private + 2435cc zhongshan scinan internet of things co.,ltd. 24374c cisco spvtg 2437ef emc electronic media communication sa + 243a82 irts 243c20 dynamode group + 243f30 oxygen broadband s.a. + 2440ae niic technology co., ltd. + 24418c intel corporate + 2442bc alinco,incorporated + 2443e2 dasan network solutions + 244427 huawei technologies co.,ltd + 24456b huawei device co., ltd. 244597 gemue gebr. mueller apparatebau + 2446c8 motorola mobility llc, a lenovo company 24470e pentronicab 24497b innovative converged devices inc - 245fdf kyocera corporation + 244b03 samsung electronics co.,ltd + 244b81 samsung electronics co.,ltd + 244bfe asustek computer inc. + 244c07 huawei technologies co.,ltd + 244ce3 amazon technologies inc. + 244e7b ieee registration authority + 244f1d irule llc + 24526a zhejiang dahua technology co., ltd. + 2453bf enernet + 24586e zte corporation + 245880 vizeo + 24590b white sky inc. limited + 245a4c ubiquiti networks inc. + 245ab5 samsung electronics co.,ltd + 245b83 renesas electronics (penang) sdn. bhd. + 245ba7 apple, inc. + 245bf0 liteon, inc. + 245cbf ncse + 245ccb axie consortium, inc. + 245dfc ieee registration authority + 245ebe qnap systems, inc. + 245f9f huawei device co., ltd. + 245fdf kyocera corporation + 246081 razberi technologies + 24615a china mobile group device co.,ltd. 246278 sysmocom - systems for mobile communications gmbh + 2462ab espressif inc. + 2462ce aruba, a hewlett packard enterprise company + 24649f huawei device co., ltd. 2464ef cyg sunri co.,ltd. 246511 avm gmbh + 246880 braveridge.co.,ltd. + 2468b0 samsung electronics co.,ltd + 24693e innodisk corporation 24694a jasmine systems inc. - 2469a5 huawei technologies co., ltd + 246968 tp-link technologies co.,ltd. + 2469a5 huawei technologies co.,ltd 246aab it-is international + 246c8a yukai engineering + 246e96 dell inc. + 246f28 espressif inc. + 246f8c huawei device co., ltd. + 247152 dell inc. + 247189 texas instruments + 247260 iottech corp + 2474f7 gopro + 247625 texas instruments + 247656 shanghai net miles fiber optics technology co., ltd. 24767d cisco spvtg 247703 intel corporate + 24792a ruckus wireless + 2479ef greenpacket berhad, taiwan + 2479f3 guangdong oppo mobile telecommunications corp.,ltd + 2479f8 kupson spol. s r.o. + 247c4c herman miller + 247d4d texas instruments + 247e12 cisco systems, inc + 247e51 zte corporation + 247f20 sagemcom broadband sas + 247f3c huawei technologies co.,ltd 248000 westcontrol as 2481aa ksh international co., ltd. + 2481c7 huawei device co., ltd. 24828a prowave technologies ltd. + 248498 beijing jiaoda microunion tech.co.,ltd. 2486f4 ctek, inc. 248707 senergy corporation - 2493ca voxtronic technology computer-systeme gmbh + 248894 shenzhen lensun communication technology ltd + 248a07 mellanox technologies, inc. + 248be0 sichuan tianyi comheart telecomco., ltd + 2491bb huawei technologies co.,ltd + 24920e samsung electronics co.,ltd + 2493ca voxtronic austria 249442 open road solutions , inc. + 249493 fibrsol global network limited + 249494 hong kong bouffalo lab limited + 2494cb arris group, inc. 249504 sfr - 24a2e1 apple, inc + 2497ed techvision intelligent technology limited + 249ad8 yealink(xiamen) network technology co.,ltd. + 249eab huawei technologies co.,ltd + 249f89 texas instruments + 24a074 apple, inc. + 24a160 espressif inc. + 24a2e1 apple, inc. 24a42c koukaam a.s. - 24a43c ubiquiti networks, inc + 24a43c ubiquiti networks inc. + 24a487 huawei device co., ltd. 24a495 thales canada inc. + 24a52c huawei technologies co.,ltd + 24a534 syntrust tech international ltd. + 24a65e zte corporation + 24a7dc bskyb ltd 24a87d panasonic automotive systems asia pacific(thailand)co.,ltd. 24a937 pure storage - 24ab81 apple - 24af4a alcatel-lucent-ipd + 24ab81 apple, inc. + 24af4a alcatel-lucent ipd 24af54 nexgen mediatech inc. - 24b657 cisco systems, inc. + 24b0a9 shanghai mobiletek communication ltd. + 24b105 prama hikvision india private limited + 24b209 avaya inc + 24b2de espressif inc. + 24b657 cisco systems, inc 24b6b8 friem spa - 24b6fd dell inc + 24b6fd dell inc. 24b88c crenus co.,ltd. 24b8d2 opzoon technology co.,ltd. + 24ba13 riso kagaku corporation 24ba30 technical consumer products, inc. 24bbc1 absolute analysis 24bc82 dali wireless, inc. + 24bcf8 huawei technologies co.,ltd 24be05 hewlett packard - 24bf74 + 24be18 dadoutek company limited + 24bf74 private 24c0b3 rsf + 24c17a beijing iactive network co.,ltd + 24c1bd crrc dalian r&d co.,ltd. + 24c3f9 securitas direct ab + 24c42f philips lifeline + 24c44a zte corporation 24c696 samsung electronics co.,ltd - 24c848 mywerk system gmbh + 24c848 mywerk portal gmbh 24c86e chaney instrument co. + 24c8d3 mcwane india pvt ltd 24c9a1 ruckus wireless 24c9de genoray + 24cacb fiberhome telecommunication technologies co.,ltd 24cbe7 myk, inc. 24cf21 shenzhen state micro technology co., ltd + 24d0df apple, inc. + 24d13f mexus co.,ltd 24d2cc smartdrive systems inc. - 24d921 avaya, inc + 24d3f2 zte corporation + 24d51c zhongtian broadband technology co., ltd + 24d76b syntronic ab + 24d921 avaya inc + 24da11 no nda inc + 24da33 huawei technologies co.,ltd + 24da9b motorola mobility llc, a lenovo company 24dab6 sistemas de gestión energética s.a. de c.v - 24dbac shenzhen huawei communication technologies co., ltd + 24dbac huawei technologies co.,ltd 24dbad shoppertrak rct corporation 24dbed samsung electronics co.,ltd - 24dec6 aruba networks - 24e271 qingdao hisense communications co.,ltd + 24dec6 aruba, a hewlett packard enterprise company + 24df6a huawei technologies co.,ltd + 24dfa7 hangzhou broadlink technology co.,ltd + 24e124 xiamen ursalink technology co., ltd. + 24e271 qingdao hisense communications co.,ltd. + 24e314 apple, inc. + 24e43f wenzhou kunmei communication technology co.,ltd. + 24e4c8 fiberhome telecommunication technologies co.,ltd + 24e5aa philips oral healthcare, inc. 24e6ba jsc zavod im. kozitsky - 24e9b3 cisco - 24ea40 systeme helmholz gmbh + 24e853 lg innotek + 24e927 tomtom international bv + 24e9b3 cisco systems, inc + 24e9ca huawei device co., ltd. + 24ea40 helmholz gmbh & co. kg 24eb65 saet i.s. s.r.l. + 24ec51 adf technologies sdn bhd 24ec99 askey computer corp 24ecd6 csg science & technology co.,ltd.hefei + 24edfd siemens canada limited 24ee3a chengdu yingji electronic hi-tech co ltd + 24ee9a intel corporate + 24f094 apple, inc. 24f0ff ght co., ltd. + 24f128 telstra + 24f150 guangzhou qi'an technology co., ltd. + 24f27f hewlett packard enterprise 24f2dd radiant zemax llc + 24f57e hwh co., ltd. + 24f5a2 belkin international inc. 24f5aa samsung electronics co.,ltd + 24f677 apple, inc. + 24faf3 shanghai flexem technology co.,ltd. + 24fb65 huawei technologies co.,ltd + 24fce5 samsung electronics co.,ltd + 24fd0d intelbras 24fd52 liteon technology corporation + 24fd5b smartthings, inc. + 280245 konze system technology co.,ltd. + 2802d8 samsung electronics co.,ltd 2804e0 fermax electronica s.a.u. + 28052e dematic corp 28061e ningbo global useful electric co.,ltd 28068d itl, llc - 280b5c apple + 28070d guangzhou winsound information technology co.,ltd. + 280b5c apple, inc. + 280c28 unigen datastorage corporation 280cb8 mikrosay yazilim ve elektronik a.s. - 280dfc sony computer entertainment inc. + 280dfc sony interactive entertainment inc. + 280e8b beijing spirit technology development co., ltd. + 280fc5 beijing leadsec technology co., ltd. + 28101b magnacom 28107b d-link international + 2811a5 bose corporation + 2811ec huawei technologies co.,ltd 281471 lantis co., ltd. - 28162e 2wire + 28162e 2wire inc + 28167f xiaomi communications co ltd + 2816a8 microsoft corporation + 2816ad intel corporate 2817ce omnisense ltd 281878 microsoft corporation 2818fd aditya infotech ltd. + 281b04 zalliant llc 282246 beijing sinoix communication co., ltd + 282373 digita + 2823f5 china mobile (hangzhou) information technology co., ltd. + 2824ff wistron neweb corporation + 282536 shenzhen holatek co.,ltd 2826a6 pbr electronics gmbh + 2827bf samsung electronics co.,ltd 28285d zyxel communications corporation + 282986 apc by schneider electric + 2829cc corsa technology incorporated 2829d9 globalbeiming technology (beijing)co. ltd + 282b96 huawei device co., ltd. + 282c02 ieee registration authority 282cb2 tp-link technologies co.,ltd. + 282fc2 automotive data solutions + 2830ac frontiir co. ltd. 283152 huawei technologies co.,ltd + 283166 vivo mobile communication co., ltd. + 28317e hongkong nano ic technologies co., ltd + 2832c5 humax co., ltd. + 283334 huawei device co., ltd. 283410 enigma diagnostics limited - 2834a2 cisco - 283737 apple + 2834a2 cisco systems, inc + 283545 shenzhen chuangwei-rgb electronics co.,ltd + 283638 ieee registration authority + 283713 shenzhen 3nod digital technology co., ltd. + 283737 apple, inc. + 28385c flextronics 2838cf gen2wave + 283926 cybertan technology inc. + 28395e samsung electronics co.,ltd 2839e7 preceno technology pte.ltd. + 283a4d cloud network technology (samoa) limited + 283b82 d-link international 283b96 cool control ltd - 283ce4 huawei technologies co., ltd + 283ce4 huawei technologies co.,ltd + 283e76 common networks + 283f69 sony mobile communications inc 28401a c8 medisensors, inc. 284121 optisense network, llc + 2841c6 huawei technologies co.,ltd + 2841ec huawei technologies co.,ltd 284430 genesistechnical systems (uk) ltd 2847aa nokia corporation 284846 gridcentric inc. + 2848e7 huawei device co., ltd. 284c53 intune networks 284d92 luminator + 284ed7 outsmart power systems, inc. 284fce liaoning wontel science and technology development co.,ltd. 285132 shenzhen prayfly technology co.,ltd - 285767 echostar technologies corp - 285fdb shenzhen huawei communication technologies co., ltd + 285261 cisco systems, inc + 2852e0 layon international electronic & telecom co.,ltd + 2852f9 zhongxin intelligent times (shenzhen) co., ltd. + 28534e huawei technologies co.,ltd + 285471 huawei device co., ltd. + 28565a hon hai precision ind. co.,ltd. + 2856c1 harman/becker automotive systems gmbh + 285767 dish technologies corp + 2857be hangzhou hikvision digital technology co.,ltd. + 285aeb apple, inc. + 285b0c sichuan jiuzhou electronic technology co., ltd. + 285f2f rnware co.,ltd. + 285fdb huawei technologies co.,ltd 286046 lantech communications global, inc. 286094 capelec - 286336 siemens ag - industrial automation - ewa + 286336 siemens ag + 2863bd aptiv services us, llc + 2864b0 huawei device co., ltd. 28656b keystone microtech corporation - 286ab8 apple - 286aba apple + 2866e3 azurewave technology inc. + 2868d2 huawei technologies co.,ltd + 286ab8 apple, inc. + 286aba apple, inc. + 286c07 xiaomi electronics,co.,ltd 286d97 samjin co., ltd. + 286dcd beijing winner microelectronics co.,ltd. 286ed4 huawei technologies co.,ltd + 286f7f cisco systems, inc 287184 spire payments 2872c5 smartmatic corp 2872f0 athena + 2875d8 fujian star-net communication co.,ltd + 287610 ignitenet + 2876cd funshion online technologies co.,ltd + 2877f1 apple, inc. 287994 realplay digital technology(shenzhen) co.,ltd + 287aee arris group, inc. + 287b09 zte corporation + 287cdb hefei toycloud technology co.,ltd + 287fcf intel corporate + 288023 hewlett packard + 288088 netgear + 2880a2 novatel wireless solutions, inc. + 288335 samsung electronics co.,ltd + 28840e silicon valley immigration service + 2884fa sharp corporation 28852d touch networks 288915 cashguard sverige ab 288a1c juniper networks + 288cb8 zte corporation 2891d0 stage tec entwicklungsgesellschaft für professionelle audiotechnik mbh 28924a hewlett packard - 2893fe cisco systems, inc. - 28940f cisco systems, inc. + 2893fe cisco systems, inc + 28940f cisco systems, inc 2894af samhwa telecom 28987b samsung electronics co.,ltd + 28993a arista networks + 2899c7 lindsay broadband inc 289a4b steelseries aps - 289afa tct mobile limited + 289af7 adva optical networking ltd. + 289afa tct mobile ltd + 289e97 huawei technologies co.,ltd 289edf danfoss turbocor compressors, inc + 289efc sagemcom broadband sas + 28a02b apple, inc. + 28a183 alpsalpine co,.ltd 28a186 enblink 28a192 gerp solution 28a1eb etek technology (shenzhen) co.,ltd 28a241 exlar corp + 28a24b juniper networks 28a574 miller electric mfg. co. + 28a5ee shenzhen sdgi catv co., ltd + 28a6ac seca gmbh & co. kg + 28a6db huawei technologies co.,ltd + 28ac67 mach power, rappresentanze internazionali s.r.l. + 28ac9e cisco systems, inc + 28ad18 hui zhou gaoshengda technology co.,ltd + 28ad3e shenzhen tong bo wei technology co.,ltd 28af0a sirius xm radio inc + 28affd cisco systems, inc 28b0cc xenya d.o.o. 28b2bd intel corporate + 28b371 ruckus wireless 28b3ab genmark automation + 28b448 huawei technologies co.,ltd + 28b4fb sprocomm technologies co.,ltd. + 28b77c ieee registration authority + 28b9d9 radisys corporation 28ba18 nextnav, llc 28bab5 samsung electronics co.,ltd 28bb59 rnet technologies, inc. - 28be9b technicolor usa inc. + 28bc18 sourcingoverseas co. ltd + 28bc56 emac, inc. + 28bd89 google, inc. + 28be03 tct mobile ltd + 28be9b technicolor ch usa inc. + 28bf89 fiberhome telecommunication technologies co.,ltd 28c0da juniper networks + 28c13c hon hai precision ind. co., ltd. + 28c21f samsung electro-mechanics(thailand) + 28c2dd azurewave technology inc. + 28c63f intel corporate 28c671 yota devices oy - 28c68e netgear inc., + 28c68e netgear + 28c709 apple, inc. 28c718 altierre + 28c7ce cisco systems, inc 28c825 dellking industrial co., ltd + 28c87a arris group, inc. + 28c87c zte corporation 28c914 taimag corporation + 28ca09 thyssenkrupp elevators (shanghai) co.,ltd 28cbeb one 28cc01 samsung electronics co.,ltd 28ccff corporacion empresarial altra sl 28cd1c espotel oy 28cd4c individual computers gmbh 28cd9c shenzhen dynamax software development co.,ltd. - 28cfda apple - 28cfe9 apple + 28cdc4 chongqing fugui electronics co.,ltd. + 28cf08 essys + 28cfda apple, inc. + 28cfe9 apple, inc. + 28d044 shenzhen xinyin technology company + 28d0cb cambridge communication systems ltd + 28d0ea intel corporate + 28d127 beijing xiaomi mobile software co., ltd 28d1af nokia corporation + 28d1b7 shenzhen youhua technology co., ltd 28d244 lcfc(hefei) electronics technology co., ltd. + 28d3ea huawei device co., ltd. + 28d436 jiangsu dewosi electric co., ltd 28d576 premier wireless, inc. 28d93e telecor inc. + 28d98a hangzhou konke technology co.,ltd. 28d997 yuduan mobile co., ltd. 28db81 shanghai guao electronic technology co., ltd + 28de65 aruba, a hewlett packard enterprise company + 28dee5 huawei technologies co.,ltd 28def6 biomerieux inc. - 28e02c apple + 28e02c apple, inc. 28e14c apple, inc. 28e297 shanghai infotm microelectronics co.,ltd. + 28e31f xiaomi communications co ltd 28e347 liteon technology corporation + 28e34e huawei technologies co.,ltd + 28e476 pi-coral + 28e5b0 huawei technologies co.,ltd 28e608 tokheim + 28e6e9 sis sat internet services gmbh 28e794 microtime computer inc. - 28e7cf apple + 28e7cf apple, inc. + 28e98e mitsubishi electric corporation + 28ec95 apple, inc. + 28ec9a texas instruments 28ed58 jag jakob ag + 28ed6a apple, inc. + 28ede0 ampak technology, inc. 28ee2c frontline test equipment - 28ef01 + 28ee52 tp-link technologies co.,ltd. + 28eed3 shenzhen super d technology co., ltd + 28ef01 amazon technologies inc. + 28f033 apple, inc. + 28f076 apple, inc. + 28f10e dell inc. 28f358 2c - trifonov & co + 28f366 shenzhen bilian electronic co.,ltd + 28f49b leetek 28f532 add-engineering bv + 28f537 ieee registration authority 28f606 syes srl + 28fa7a zhejiang tmall technology co., ltd. + 28faa0 vivo mobile communication co., ltd. 28fbd3 ragentek technology group 28fc51 the electric controller and manufacturing co., llc + 28fcf6 shenzhen xin kingbrand enterprises co.,ltd + 28fd80 ieee registration authority + 28fe65 dongguan siyoto electronics co., ltd + 28fecd lemobile information technology (beijing) co., ltd. + 28fede comesta, inc. + 28ff3c apple, inc. + 28ff3e zte corporation + 28ffb2 toshiba corp. 2c002c unowhy 2c0033 econtrols, llc + 2c00ab arris group, inc. 2c00f7 xos + 2c010b nascent technology, llc - remkon + 2c01b5 cisco systems, inc + 2c029f 3alogics 2c0623 win leader inc. 2c073c devline limited + 2c0786 huawei device co., ltd. + 2c081c ovh + 2c0823 sercomm france sarl + 2c088c humax co., ltd. + 2c094d raptor engineering, llc + 2c09cb cobs ab + 2c0be9 cisco systems, inc + 2c0e3d samsung electro-mechanics(thailand) 2c10c1 nintendo co., ltd. + 2c15e1 phicomm (shanghai) co., ltd. + 2c16bd ieee registration authority + 2c17e0 systemes et technologies identification (stid) + 2c1875 skyworth digital technology(shenzhen) co.,ltd 2c18ae trend electronics co., ltd. 2c1984 idn telecom, inc. + 2c1a01 huawei technologies co.,ltd + 2c1a31 electronics company limited + 2c1bc8 hunan topview network system co.,ltd + 2c1cf6 alien green llc + 2c1db8 arris group, inc. + 2c1e4f chengdu qianli network technology co., ltd. 2c1eea aerodev + 2c1f23 apple, inc. + 2c200b apple, inc. + 2c2131 juniper networks 2c2172 juniper networks + 2c21d7 imax corporation + 2c228b ctr srl + 2c233a hewlett packard 2c245f babolat vs + 2c2617 oculus vr, llc + 2c265f ieee registration authority 2c26c5 zte corporation - 2c27d7 hewlett-packard company - 2c282d bbk communicatiao technology co.,ltd. + 2c279e ieee registration authority + 2c27d7 hewlett packard + 2c282d bbk educational electronics corp.,ltd. + 2c28b7 hangzhou ruiying technology co., ltd + 2c2997 microsoft corporation + 2c2bf9 lg innotek 2c2d48 bct electronic gesmbh + 2c3033 netgear 2c3068 pantech co.,ltd + 2c3124 cisco systems, inc + 2c3311 cisco systems, inc + 2c3361 apple, inc. + 2c337a hon hai precision ind. co.,ltd. 2c3427 erco & gener 2c3557 elliy power co..ltd 2c36a0 capisco limited - 2c36f8 cisco systems, inc. - 2c3731 shenzhen yifang digital technology co.,ltd - 2c3996 sagemcom + 2c36f8 cisco systems, inc + 2c3731 shenzhen yifang digital technology co.,ltd. + 2c3796 cybo co.,ltd. + 2c37c5 qingdao haier intelligent home appliance technology co.,ltd + 2c3996 sagemcom broadband sas 2c39c1 ciena corporation 2c3a28 fagor electrónica + 2c3ae8 espressif inc. + 2c3afd avm audiovisuelles marketing und computersysteme gmbh 2c3bfd netstor technology co., ltd. - 2c3ecf cisco - 2c3f38 cisco systems, inc. + 2c3ecf cisco systems, inc + 2c3f0b cisco meraki + 2c3f38 cisco systems, inc 2c3f3e alge-timing gmbh - 2c4138 hewlett-packard company + 2c402b smart iblue technology limited + 2c4053 samsung electronics co.,ltd + 2c4138 hewlett packard + 2c41a1 bose corporation + 2c4205 lytx + 2c431a shenzhen youhua technology co., ltd + 2c43be sunnovo international limited 2c4401 samsung electronics co.,ltd 2c441b spectrum medical limited 2c44fd hewlett packard + 2c4759 beijing mega preponderance science & technology co. ltd + 2c4835 ieee registration authority + 2c4a11 ciena corporation + 2c4cc6 murata manufacturing co., ltd. + 2c4d54 asustek computer inc. + 2c4d79 weifang goertek electronics co.,ltd + 2c4e7d chunghua intelligent network equipment inc. + 2c4f52 cisco systems, inc + 2c5089 shenzhen kaixuan visual technology co.,limited + 2c52af huawei technologies co.,ltd 2c534a shenzhen winyao electronic limited - 2c542d cisco systems, inc. + 2c542d cisco systems, inc + 2c5491 microsoft corporation + 2c54cf lg electronics (mobile communications) 2c553c gainspeed, inc. + 2c557c shenzhen youhua technology co., ltd + 2c55d3 huawei technologies co.,ltd + 2c56dc asustek computer inc. + 2c5731 wingtech group (hongkong)limited + 2c5741 cisco systems, inc + 2c584f arris group, inc. + 2c58e8 huawei technologies co.,ltd + 2c598a lg electronics (mobile communications) 2c59e5 hewlett packard 2c5a05 nokia corporation + 2c5a0f cisco systems, inc + 2c5a8d systronik elektronik u. systemtechnik gmbh 2c5aa3 promate electronic co.ltd + 2c5bb8 guangdong oppo mobile telecommunications corp.,ltd + 2c5be1 centripetal networks, inc + 2c5d34 guangdong oppo mobile telecommunications corp.,ltd 2c5d93 ruckus wireless 2c5ff3 pertronic industries + 2c600c quanta computer inc. + 2c6104 shenzhen fenglian technology co., ltd. + 2c61f6 apple, inc. 2c625a finest security systems co., ltd 2c6289 regenersis (glenrothes) ltd + 2c6373 sichuan tianyi comheart telecomco., ltd + 2c641f vizio, inc + 2c6798 intaltech ltd. 2c67fb shenzhen zhengjili electronics co., ltd 2c69ba rf controls, llc + 2c6a6f ieee registration authority + 2c6b7d texas instruments 2c6bf5 juniper networks + 2c6e85 intel corporate + 2c6f51 herospeed digital technology limited + 2c6fc9 hon hai precision ind. co.,ltd. 2c7155 hivemotion + 2c71ff amazon technologies inc. 2c72c3 soundmatters + 2c7360 earda technologies co ltd + 2c73a0 cisco systems, inc 2c750f shanghai dongzhou-lawton communication technology co. ltd. - 2c768a hewlett-packard company + 2c768a hewlett packard + 2c780e huawei device co., ltd. + 2c793d boditech med + 2c79d7 sagemcom broadband sas 2c7b5a milper ltd 2c7b84 ooo petr telegin + 2c7ce4 wuhan tianyu information industry co., ltd. + 2c7e81 arris group, inc. 2c7ecf onzo ltd 2c8065 harting inc. of north america - 2c8158 hon hai precision ind. co.,ltd + 2c8158 hon hai precision ind. co.,ltd. + 2c86d2 cisco systems, inc + 2c8a72 htc corporation 2c8bf2 hitachi metals america ltd + 2c8db1 intel corporate 2c9127 eintechno corporation + 2c91ab avm audiovisuelles marketing und computersysteme gmbh 2c922c kishu giken kogyou company ltd,. 2c9464 cincoze co., ltd. + 2c9569 arris group, inc. 2c957f zte corporation + 2c9662 invenit bv 2c9717 i.c.y. b.v. - 2c9aa4 ngi spa + 2c97b1 huawei technologies co.,ltd + 2c97ed sony imaging products & solutions inc. + 2c9924 arris group, inc. + 2c9aa4 eolo spa + 2c9d1e huawei technologies co.,ltd 2c9e5f arris group, inc. + 2c9eec jabil circuit penang 2c9efc canon inc. + 2c9ffb wistron neweb corporation + 2ca02f veroguard systems pty ltd + 2ca042 huawei device co., ltd. 2ca157 acromate, inc. + 2ca17d arris group, inc. + 2ca2b4 fortify technologies, llc + 2ca30e power dragon development limited + 2ca539 parallel wireless, inc + 2ca59c hangzhou hikvision digital technology co.,ltd. 2ca780 true technologies inc. 2ca835 rim - 2cab25 shenzhen gongjin electronics co.,ltd + 2ca89c creatz inc. + 2ca9f0 guangdong oppo mobile telecommunications corp.,ltd + 2caa8e wyze labs inc + 2cab00 huawei technologies co.,ltd + 2cab25 shenzhen gongjin electronics co.,lt + 2cab33 texas instruments + 2caba4 cisco spvtg + 2cabeb cisco systems, inc + 2cac44 conextop + 2cad13 shenzhen zhilu technology co.,ltd + 2cae2b samsung electronics co.,ltd 2cb05d netgear 2cb0df soliton technologies pvt ltd - 2cb43a apple + 2cb115 integrated device technology (malaysia) sdn. bhd. + 2cb21a phicomm (shanghai) co., ltd. + 2cb43a apple, inc. 2cb693 radware 2cb69d red digital cinema + 2cb8ed sonicwall + 2cbaba samsung electronics co.,ltd + 2cbe08 apple, inc. 2cbe97 ingenieurbuero bickele und buehler gmbh - 2cc260 ravello systems + 2cbeeb nothing technology limited + 2cc260 oracle corporation + 2cc407 machineq + 2cc546 huawei device co., ltd. + 2cc548 iadea corporation + 2cc5d3 ruckus wireless + 2cc81b routerboard.com + 2cca0c withus planet 2ccc15 nokia corporation + 2ccc44 sony interactive entertainment inc. + 2ccce6 skyworth digital technology(shenzhen) co.,ltd 2ccd27 precor inc 2ccd43 summit technology group 2ccd69 aqavi.com + 2cce1e cloudtronics pty ltd + 2ccf58 huawei technologies co.,ltd + 2cd02d cisco systems, inc 2cd05a liteon technology corporation + 2cd066 xiaomi communications co ltd + 2cd141 ieee registration authority 2cd1da sanjole, inc. + 2cd26b fn-link technology limited + 2cd2e3 guangzhou aoshi electronic co.,ltd 2cd2e7 nokia corporation 2cd444 fujitsu limited + 2cd974 hui zhou gaoshengda technology co.,ltd + 2cdb07 intel corporate + 2cdcad wistron neweb corporation + 2cdcd7 azurewave technology inc. 2cdd0c discovergy gmbh + 2cdd95 taicang t&w electronics + 2cdda3 point grey research inc. 2ce2a8 devicedesign - 2ce412 sagemcom sas + 2ce310 stratacache + 2ce412 sagemcom broadband sas 2ce6cc ruckus wireless 2ce871 alert metalguard aps + 2cea7f dell inc. 2cedeb alpheus digital company limited 2cee26 petroleum geo-services + 2cf05d micro-star intl co., ltd. + 2cf0a2 apple, inc. + 2cf0ee apple, inc. 2cf203 emko elektronik san ve tic as - 2cf4c5 avaya, inc + 2cf432 espressif inc. + 2cf4c5 avaya inc + 2cf7f1 seeed technology inc. + 2cf89b cisco systems, inc + 2cfaa2 alcatel-lucent enterprise + 2cfce4 ctek sweden ab + 2cfd37 blue calypso, inc. + 2cfda1 asustek computer inc. + 2cfdab motorola (wuhan) mobility technologies communication co., ltd. + 2cfdb3 tcl technoly electronics(huizhou).,ltd + 2cff65 oki electric industry co., ltd. + 2cffee vivo mobile communication co., ltd. + 30053f jti co.,ltd. 30055c brother industries, ltd. + 30074d samsung electro-mechanics(thailand) + 3009f9 ieee registration authority + 300a60 ieee registration authority + 300ac5 ruio telecommunication technologies co., limited 300b9c delta mobile systems, inc. - 300ed5 hon hai precision ind.co.ltd + 300c23 zte corporation + 300d2a zhejiang wellcom technology co.,ltd. + 300d43 microsoft mobile oy + 300d9e ruijie networks co.,ltd + 300ed5 hon hai precision ind. co.,ltd. + 300ee3 aquantia corporation + 3010b3 liteon technology corporation 3010e4 apple, inc. + 301389 siemens ag, automations & drives, 30142d piciorgros gmbh - 30144a wistron neweb corp. + 30144a wistron neweb corporation 301518 ubiquitous communication co. ltd. 30168d prolon - 3017c8 sony ericsson mobile communications ab + 3017c8 sony mobile communications inc 3018cf deos control systems gmbh 301966 samsung electronics co.,ltd 301a28 mako networks ltd + 301b97 lierda science & technology group co.,ltd + 301f9a ieee registration authority 30215b shenzhen ostar display electronic co.,ltd + 302303 belkin international inc. + 302432 intel corporate + 302478 sagemcom broadband sas + 3024a9 hp inc. + 3027cf private + 302952 hillstone networks inc + 3029be shanghai mrdcom co.,ltd 302de8 jda, llc (jda systems) + 30317d hosiden corporation + 303235 qingdao intelligent&precise electronics co.,ltd. 303294 w-ie-ne-r plein & baus gmbh 3032d4 hanilstm co., ltd. - 3037a6 cisco systems, inc. + 303335 boosty + 3034d2 availink, inc. + 3035ad apple, inc. + 3037a6 cisco systems, inc + 3037b3 huawei technologies co.,ltd 303855 nokia corporation - 303926 sony ericsson mobile communications ab + 303926 sony mobile communications inc 303955 shenzhen jinhengjia electronic co., ltd. 3039f2 adb broadband italia 303a64 intel corporate + 303aba guangzhou baolun electronics co., ltd 303d08 glintt tes s.a. 303ead sonavox canada inc 304174 altec lansing llc + 304225 burg-wÄchter kg + 304240 zte corporation + 3042a1 ilumisys inc. dba toggled 304449 plath gmbh + 304487 hefei radio communication technology co., ltd + 3044a1 shanghai nanchao information technology + 304511 texas instruments + 304596 huawei technologies co.,ltd 30469a netgear 30493b nanjing z-com wireless co.,ltd + 304950 ieee registration authority + 304a26 shenzhen trolink technology co, ltd + 304b07 motorola mobility llc, a lenovo company 304c7e panasonic electric works automation controls techno co.,ltd. + 304e1b huawei device co., ltd. 304ec3 tianjin techua technology co., ltd. + 304f75 dasan network solutions + 305075 gn audio a/s + 3050fd skyworth digital technology(shenzhen) co.,ltd 3051f8 byk-gardner gmbh 30525a nst co., ltd + 3052cb liteon technology corporation 3055ed trex network llc + 305684 shenzhen yunji intelligent technology co.,ltd + 305714 apple, inc. + 30578e eero inc. 3057ac irlab ltd. + 305890 frontier silicon ltd + 30595b streamnow ag 3059b7 microsoft - 305d38 beissbarth + 305a3a asustek computer inc. + 305d38 beissbarth + 305da6 advaly system inc. 306023 arris group, inc. 306112 pav gmbh 306118 paradom inc. + 30636b apple, inc. 3065ec wistron (chongqing) + 3066d0 huawei device co., ltd. 30688c reach technology inc. 30694b rim + 306a85 samsung electronics co.,ltd 306cbe skymotion technology (hk) limited 306e5c validus technologies + 306f07 nations technologies inc. 3071b2 hangzhou prevail optoelectronic equipment co.,ltd. - 30766f lg electronics + 307350 inpeco sa + 307496 huawei technologies co.,ltd + 307512 sony mobile communications inc + 30766f lg electronics (mobile communications) + 3077cb maike industry(shenzhen)co.,ltd + 30785c partow tamas novin (parman) 30786b tianjin golden pentagon electronics co., ltd. - 3078c2 innowireless, co. ltd. + 3078c2 innowireless / qucell networks + 3078d3 virgilant technologies ltd. + 307bac new h3c technologies co., ltd 307c30 rim + 307c4a huawei device co., ltd. + 307c5e juniper networks + 307cb2 anov france 307ecb sfr - 3085a9 asustek computer inc - 308730 shenzhen huawei communication technologies co., ltd + 30809b new h3c technologies co., ltd + 308398 espressif inc. + 308454 guangdong oppo mobile telecommunications corp.,ltd + 3085a9 asustek computer inc. + 3085eb fiberhome telecommunication technologies co.,ltd + 30862d arista network, inc. + 308730 huawei technologies co.,ltd + 3087d9 ruckus wireless + 308841 sichuan ai-link technology co., ltd. + 308944 deva broadcast ltd. + 308976 dalian lamba technology co.,ltd 308999 guangdong east power co., + 3089d3 hongkong ucloudlink network technology limited + 308af7 huawei device co., ltd. + 308bb2 cisco systems, inc 308cfb dropcam - 3090ab apple + 308d99 hewlett packard + 308e7a shenzhen icomm semiconductor co.,ltd + 309048 apple, inc. + 3090ab apple, inc. + 309176 skyworth digital technology(shenzhen) co.,ltd 30918f technicolor 3092f6 shanghai sunmon communication technogy co.,ltd - 309bad bbk electronics corp., ltd., - 30a8db sony mobile communications ab + 3093bc sagemcom broadband sas + 309435 vivo mobile communication co., ltd. + 309587 hunan fn-link technology limited + 3095e3 shanghai simcom limited + 309610 huawei device co., ltd. + 3096fb samsung electronics co.,ltd + 309935 zte corporation + 309bad bbk educational electronics corp.,ltd. + 309c23 micro-star intl co., ltd. + 309e1d ohsung + 309ffb ardomus networks corporation + 30a023 rock path s.r.l + 30a1fa huawei technologies co.,ltd + 30a220 arg telecom + 30a243 shenzhen prifox innovation technology co., ltd. + 30a2c2 huawei device co., ltd. + 30a452 arrival elements bv + 30a612 shenzhen hugsun technology co.,ltd. + 30a889 decimator design + 30a8db sony mobile communications inc + 30a998 huawei device co., ltd. + 30a9de lg innotek 30aabd shanghai reallytek information technology co.,ltd + 30aae4 huawei device co., ltd. + 30ab6a samsung electro-mechanics(thailand) 30ae7b deqing dusun electron co., ltd + 30aea4 espressif inc. 30aef6 radio mobile access - 30b216 hytec geraetebau gmbh + 30afce vivo mobile communication co., ltd. + 30b164 power electronics international inc. + 30b1b5 arcadyan corporation + 30b216 hitachi abb power grids – grid automation + 30b237 gd midea air-conditioning equipment co.,ltd. 30b3a2 shenzhen heguang measurement & control technology co.,ltd + 30b49e tp-link technologies co.,ltd. + 30b4b8 lg electronics 30b5c2 tp-link technologies co.,ltd. + 30b5f1 aitexin technology co., ltd + 30b62d mojo networks, inc. + 30b64f juniper networks + 30b7d4 hitron technologies. inc + 30b9b0 intracom asia co., ltd + 30be3b mitsubishi electric corporation + 30c01b shenzhen jingxun software telecommunication technology co.,ltd + 30c3d9 alpsalpine co,.ltd + 30c507 eci telecom ltd. + 30c50f huawei technologies co.,ltd 30c750 mic technology group - 30c82a wi-next s.r.l. - 30cda7 samsung electronics its, printer division + 30c7ae samsung electronics co.,ltd + 30c82a wi-biz srl + 30c9ab cloud network technology singapore pte. ltd. + 30cbf8 samsung electronics co.,ltd + 30cc21 zte corporation + 30cda7 samsung electronics co.,ltd + 30d042 dell inc. + 30d16b liteon technology corporation + 30d17e huawei technologies co.,ltd + 30d32d devolo ag 30d357 logosol, inc. + 30d386 zte corporation 30d46a autosales incorporated + 30d587 samsung electronics co.,ltd + 30d659 merging technologies sa 30d6c9 samsung electronics co.,ltd + 30d941 raydium semiconductor corp. + 30d9d9 apple, inc. 30de86 cedac software s.r.l. + 30df8d shenzhen gongjin electronics co.,lt + 30e090 linctronix ltd, + 30e171 hewlett packard + 30e283 texas instruments + 30e37a intel corporate + 30e396 huawei device co., ltd. + 30e3d6 spotify usa inc. 30e48e vodafone uk - 30e4db cisco systems, inc. + 30e4db cisco systems, inc + 30e98e huawei technologies co.,ltd + 30ea26 sycada bv + 30eb1f skylab m&c technology co.,ltd 30eb25 intek digital + 30eb5a landis + gyr 30efd1 alstom strongwish (shenzhen) co., ltd. 30f31d zte corporation + 30f335 huawei technologies co.,ltd 30f33a +plugg srl 30f42f esp - 30f70d cisco systems - 30f7c5 apple + 30f6b9 ecocentric energy + 30f70d cisco systems, inc + 30f772 hon hai precision ind. co.,ltd. + 30f77f s mobile devices limited + 30f7c5 apple, inc. + 30f7d7 thread technology co., ltd + 30f94b universal electronics, inc. 30f9ed sony corporation + 30fab7 tunai creative + 30fb94 shanghai fangzhiwei information technology co.,ltd. + 30fbb8 huawei technologies co.,ltd + 30fc68 tp-link technologies co.,ltd. + 30fceb lg electronics (mobile communications) 30fd11 macrotech (usa) inc. + 30fd38 google, inc. + 30fd65 huawei technologies co.,ltd + 30fe31 nokia + 30fff6 hangzhou kuoheng technology co.,ltd + 34008a ieee registration authority + 3400a3 huawei technologies co.,ltd + 340286 intel corporate + 34029b plexonics technologies limited + 3403de texas instruments + 34049e ieee registration authority + 34074f accelstor, inc. 3407fb ericsson ab 340804 d-link corporation + 3408bc apple, inc. + 340a22 top-access electronics co ltd + 340a33 d-link international + 340a98 huawei technologies co.,ltd + 340aff qingdao hisense communications co.,ltd. + 340b40 mios elettronica srl + 340ced moduel ab + 340f66 web sensing llc + 341290 treeview co.,ltd. + 341298 apple, inc. + 3412f9 huawei technologies co.,ltd 3413a8 mediplan limited 3413e8 intel corporate - 34159e apple - 3417eb dell inc + 34145f samsung electronics co.,ltd + 3414b5 texas instruments + 341513 texas instruments + 34159e apple, inc. + 3417eb dell inc. + 341a35 fiberhome telecommunication technologies co.,ltd 341a4c shenzhen weibu electronics co.,ltd. 341b22 grandbeing technology co., ltd + 341cf0 xiaomi communications co ltd + 341e6b huawei technologies co.,ltd + 341fe4 arris group, inc. + 342003 shenzhen feitengyun technology co.,ltd + 3420e3 ruckus wireless 342109 jensen scandinavia as 342387 hon hai precision ind. co.,ltd. - 3423ba samsung electro mechanics co.,ltd. + 3423ba samsung electro-mechanics(thailand) 34255d shenzhen loadcom technology co.,ltd + 342606 carepredict, inc. + 342792 freebox sas + 3428f0 atn international limited + 342912 huawei technologies co.,ltd + 34298f ieee registration authority 3429ea mcd electronics sp. z o.o. + 342af1 texas instruments + 342b70 arris + 342cc4 compal broadband networks, inc. + 342d0d samsung electronics co.,ltd + 342eb6 huawei technologies co.,ltd + 342eb7 intel corporate 342f6e anywire corporation + 342fbd nintendo co.,ltd 343111 samsung electronics co.,ltd + 34318f apple, inc. + 3431c4 avm gmbh + 3432e6 panasonic industrial devices europe gmbh + 34363b apple, inc. + 343654 zte corporation + 343759 zte corporation + 343794 hamee corp. + 3438af inlab software gmbh + 3438b7 humax co., ltd. + 343d98 jinqianmao technology co.,ltd. + 343dc4 buffalo.inc + 343ea4 ring llc 3440b5 ibm + 34415d intel corporate + 3441a8 er-telecom + 344262 apple, inc. 34466f hitem engineering - 344b3d fiberhome telecommunication tech.co.,ltd. + 3446ec huawei device co., ltd. + 3448ed dell inc. + 34495b sagemcom broadband sas + 344ac3 hunan zikun information technology co., ltd + 344b3d fiberhome telecommunication technologies co.,ltd 344b50 zte corporation + 344ca4 amazipoint technology ltd. + 344cc8 echodyne corp + 344dea zte corporation + 344df7 lg electronics (mobile communications) 344f3f io-power technology co., ltd. 344f5c r&m ag 344f69 ekinops sas + 345180 tcl king electrical appliances (huizhou) co., ltd 3451aa jid global - 3451c9 apple + 3451c9 apple, inc. + 34543c takaoka toko co.,ltd. + 345594 fujian star-net communication co.,ltd + 3456fe cisco meraki + 345760 mitrastar technology corp. + 345840 huawei technologies co.,ltd + 34587c mirae information technology co., ltd. + 345a06 sharp corporation + 345aba tcloud intelligence 345b11 evi heat ab + 345bbb gd midea air-conditioning equipment co.,ltd. 345c40 cargt holdings llc 345d10 wytek 346178 the boeing company + 346288 cisco systems, inc + 3463d4 bionix supplychain technologies slu + 3464a9 hewlett packard + 3466ea vertu international corporation limited 34684a teraworks co., ltd. - 346bd3 huawei technologies co., ltd + 346893 tecnovideo srl + 346895 hon hai precision ind. co.,ltd. + 346987 zte corporation + 346ac2 huawei technologies co.,ltd + 346b46 sagemcom broadband sas + 346b5b new h3c technologies co., ltd + 346bd3 huawei technologies co.,ltd + 346c0f pramod telecom pvt. ltd + 346d9c carrier corporation 346e8a ecosense + 346e9d ericsson ab + 346f90 cisco systems, inc 346f92 white rodgers division - 3475c7 avaya, inc - 3476c5 i-o data device, inc. - 347877 o-net communications(shenzhen) limited + 346fed enovation controls + 347146 huawei device co., ltd. + 34732d cisco systems, inc + 34735a dell inc. + 347563 shenzhen rf-link technology co.,ltd. + 3475c7 avaya inc + 3476c5 i-o data device,inc. + 347839 zte corporation + 347877 o-net communications (shenzhen) limited + 3478d7 gionee communication equipment co.,ltd. + 347916 huawei technologies co.,ltd + 347a60 arris group, inc. + 347c25 apple, inc. + 347df6 intel corporate + 347e00 huawei device co., ltd. 347e39 nokia danmark a/s + 347e5c sonos, inc. + 347eca nextwill + 34800d cavium inc + 3480b3 xiaomi communications co ltd 348137 unicard sa 3481c4 avm gmbh - 3482de kayo technology, inc. + 3481f4 sst taiwan ltd. + 3482c5 samsung electronics co.,ltd + 3482de kiio inc 348302 iforcom co., ltd 348446 ericsson ab + 348584 extreme networks, inc. 34862a heinz lackmann gmbh & co kg + 34865d espressif inc. + 34873d quectel wireless solutions co., ltd. 34885d logitech far east - 348aae sagemcom sas + 348a12 aruba, a hewlett packard enterprise company + 348a7b samsung electronics co.,ltd + 348aae sagemcom broadband sas + 348b75 lava international(h.k) limited + 348f27 ruckus wireless + 34916f usergate ltd. + 349342 tte corporation 3495db logitec corporation + 349672 tp-link technologies co.,ltd. + 3497f6 asustek computer inc. 3497fb advanced rf technologies inc 34996f vpi engineering + 349971 quanta storage inc. 3499d7 universal flow monitors, inc. 349a0d zbd displays ltd + 349b5b maquet gmbh 349d90 heinzmann gmbh & co. kg + 349e34 evervictory electronic co.ltd + 349f7b canon inc. 34a183 aware, inc + 34a2a2 huawei technologies co.,ltd + 34a395 apple, inc. 34a3bf terewave. inc. 34a55d technosoft international srl 34a5e1 sensorist aps @@ -14092,803 +16383,2234 @@ exit 34a709 trevil srl 34a7ba fischer international systems corporation 34a843 kyocera display corporation - 34a84e cisco + 34a84e cisco systems, inc + 34a8eb apple, inc. 34aa8b samsung electronics co.,ltd - 34aa99 alcatel-lucent + 34aa99 nokia 34aaee mikrovisatos servisas uab + 34ab37 apple, inc. + 34ab95 espressif inc. 34ade4 shanghai chint power systems co., ltd. 34af2c nintendo co., ltd. + 34afb3 amazon technologies inc. 34b1f7 texas instruments + 34b20a huawei device co., ltd. + 34b354 huawei technologies co.,ltd 34b571 plds + 34b5a3 cig shanghai co ltd + 34b7fd guangzhou younghead electronic technology co.,ltd + 34ba38 pal mohan electronics pvt ltd 34ba51 se-kure controls, inc. + 34ba75 everest networks, inc 34ba9a asiatelco technologies co. - 34bb1f research in motion + 34bb1f blackberry rts + 34bb26 motorola mobility llc, a lenovo company 34bca6 beijing ding qing technology, ltd. - 34bdc8 cisco systems + 34bdc8 cisco systems, inc 34bdf9 shanghai wdk industrial co.,ltd. 34bdfa cisco spvtg 34be00 samsung electronics co.,ltd - 34bf90 fiberhome telecommunication tech.co.,ltd. - 34c059 apple - 34c3ac samsung electronics + 34bf90 fiberhome telecommunication technologies co.,ltd + 34c059 apple, inc. + 34c0f9 rockwell automation + 34c103 hangzhou huamu technology co.,ltd. + 34c3ac samsung electronics co.,ltd + 34c3d2 fn-link technology limited + 34c5d0 hagleitner hygiene international gmbh 34c69a enecsys ltd - 34c731 alps co,. ltd. + 34c731 alpsalpine co,.ltd 34c803 nokia corporation + 34c93d intel corporate 34c99d eidolon communications technology co. ltd. + 34c9f0 lm technologies ltd + 34cb1a procter & gamble company + 34cc28 nexpring co. ltd., 34cd6d commsky technologies - 34cdbe huawei technologies co., ltd + 34cdbe huawei technologies co.,ltd + 34ce00 xiaomi electronics,co.,ltd 34ce94 parsec (pty) ltd + 34cff6 intel corporate 34d09b mobilmax technology inc. + 34d0b8 ieee registration authority + 34d262 sz dji technology co.,ltd + 34d270 amazon technologies inc. 34d2c4 rena gmbh print systeme + 34d693 huawei device co., ltd. + 34d712 smartisan digital co., ltd + 34d772 xiamen yudian automation technology co., ltd 34d7b4 tributary systems, inc. - 34dbfd cisco + 34d954 wibotic inc. + 34dab7 zte corporation + 34dac1 sae technologies development(dongguan) co., ltd. + 34db9c sagemcom broadband sas + 34dbfd cisco systems, inc + 34dd7e umeox innovations co.,ltd 34de1a intel corporate 34de34 zte corporation 34df2a fujikon industrial co.,limited 34e0cf zte corporation 34e0d7 dongguan qisheng electronics industrial co., ltd - 34e2fd apple + 34e12d intel corporate + 34e1d1 ieee registration authority + 34e2fd apple, inc. + 34e380 genexis b.v. + 34e3da hoval aktiengesellschaft 34e42a automatic bar controls inc. - 34ef44 2wire + 34e5ec palo alto networks + 34e6ad intel corporate + 34e6d7 dell inc. + 34e70b han networks co., ltd + 34e71c shenzhen youhua technology co., ltd + 34e894 tp-link technologies co.,ltd. + 34e911 vivo mobile communication co., ltd. + 34e9fe metis co., ltd. + 34ea34 hangzhou gubei electronics technology co.,ltd + 34eae7 shanghai high-flying electronics technology co., ltd + 34ed0b shanghai xz-com.co.,ltd. + 34ed1b cisco systems, inc + 34ef44 2wire inc 34ef8b ntt communications corporation + 34efb6 edgecore networks corporation + 34f0ca shenzhen linghangyuan digital technology co.,ltd. + 34f150 hui zhou gaoshengda technology co.,ltd + 34f39a intel corporate 34f39b wizlan ltd. 34f62d sharp corporation + 34f64b intel corporate + 34f6d2 panasonic taiwan co.,ltd. + 34f716 tp-link technologies co.,ltd. + 34f8e7 cisco systems, inc 34f968 atek products, llc 34fa40 guangzhou robustel technologies co., limited + 34fa9f ruckus wireless 34fc6f alcea - 380197 toshiba samsung storage technolgoy korea corporation + 34fcb9 hewlett packard enterprise + 34fcef lg electronics (mobile communications) + 34fd6a apple, inc. + 34fec5 shenzhen sunwoda intelligent hardware co.,ltd + 380025 intel corporate + 380118 ulvac,inc. + 380146 shenzhen bilian electronic co.,ltd + 380195 samsung electronics co.,ltd + 380197 tsst global,inc + 38019f shenzhen fast technologies co.,ltd + 3802de sercomm corporation. + 380546 foctek photonics, inc. + 3805ac piller group gmbh 3806b4 a.d.c. gmbh + 3807d4 zeppelin systems gmbh + 3808fd silca spa + 3809a4 firefly integrations 380a0a sky-city communication and electronics limited company 380a94 samsung electronics co.,ltd + 380aab formlabs + 380b3c texas instruments 380b40 samsung electronics co.,ltd 380dd4 primax electronics ltd. - 380f4a apple + 380e4d cisco systems, inc + 380e7b v.p.s. thai co., ltd + 380f4a apple, inc. 380fe4 dedicated network partners oy + 3810d5 avm audiovisuelles marketing und computersysteme gmbh + 3810f0 aruba, a hewlett packard enterprise company + 38144e fiberhome telecommunication technologies co.,ltd 3816d1 samsung electronics co.,ltd + 381730 ulrich lippert gmbh & co kg 381766 promzakaz ltd. + 3817c3 hewlett packard enterprise + 3817e1 technicolor ch usa inc. + 38184c sony home entertainment&sound products inc 38192f nokia corporation + 381a52 seiko epson corporation + 381c1a cisco systems, inc + 381c23 hilan technology co.,ltd 381c4a simcom wireless solutions co.,ltd. - 38229d pirelli tyre s.p.a. - 3822d6 h3c technologies co., limited + 381d14 skydio inc. + 381dd9 fn-link technology limited + 382028 huawei technologies co.,ltd + 382056 cisco systems, inc + 3820a8 colortokens, inc. + 382187 midea group co., ltd. + 3821c7 aruba, a hewlett packard enterprise company + 38229d adb broadband italia + 3822d6 hangzhou h3c technologies co., limited + 3822e2 hp inc. + 38256b microsoft mobile oy + 38262b utran technology 3826cd andtek 3828ea fujian netcom technology co., ltd + 38295a guangdong oppo mobile telecommunications corp.,ltd + 3829dd onvocal inc + 382a19 technica engineering gmbh + 382b78 eco plugs enterprise co., ltd + 382c4a asustek computer inc. + 382dd1 samsung electronics co.,ltd + 382de8 samsung electronics co.,ltd + 3830f9 lg electronics (mobile communications) 3831ac weg + 3835fb sagemcom broadband sas + 38378b huawei technologies co.,ltd + 383a21 ieee registration authority + 383b26 jiangsu qinheng co., ltd. + 383bc8 2wire inc + 383c9c fujian newland payment technology co.,ltd. + 383d5b fiberhome telecommunication technologies co.,ltd 383f10 dbl technology ltd. + 383fb3 technicolor ch usa inc. + 38420b sonos, inc. 384233 wildeboer bauteile gmbh 3842a6 ingenieurbuero stahlkopf 384369 patrol products consortium llc + 38437d compal broadband networks, inc. + 3843e5 grotech inc + 38454c light labs, inc. 38458c mycloud technology corporation 384608 zte corporation - 38484c apple - 384ff0 azurewave technologies, inc. - 38521a alcatel-lucent 7705 + 3847bc huawei technologies co.,ltd + 38484c apple, inc. + 384b5b ztron technology limited + 384b76 airtame aps + 384c4f huawei technologies co.,ltd + 384c90 arris group, inc. + 384f49 juniper networks + 384ff0 azurewave technology inc. + 38521a nokia + 385247 huawei device co., ltd. + 38539c apple, inc. + 38549b zte corporation + 385610 candy house, inc. + 3856b5 peerbridge health inc 38580c panaccess systems gmbh 3859f8 mindmade sp. z o.o. 3859f9 hon hai precision ind. co.,ltd. 385aa8 beijing zhongdun security technology development co. + 385f66 cisco spvtg 385fc3 yu jeong system, co.ltd 386077 pegatron corporation + 3863bb hewlett packard 3863f6 3nod multimedia(shenzhen)co.,ltd 386645 oosic technology co.,ltd + 3866f0 apple, inc. 386793 asia optical co., inc. + 386893 intel corporate + 3868a4 samsung electronics co.,ltd + 3868dd inventec corporation + 386a77 samsung electronics co.,ltd + 386b1c shenzhen mercury communication technologies co.,ltd. 386bbb arris group, inc. 386c9b ivy biomedical 386e21 wasion group ltd. - 3872c0 comtrend + 386e88 zte corporation + 386ea2 vivo mobile communication co., ltd. + 38700c arris group, inc. + 3871de apple, inc. + 3872c0 comtrend corporation + 3873ea ieee registration authority + 3876ca shenzhen smart intelligent technology co.ltd + 3876d1 euronda spa + 387862 sony mobile communications inc + 387a3c fiberhome telecommunication technologies co.,ltd 387b47 akela, inc. - 388345 tp-link technologies co., ltd. + 3880df motorola mobility llc, a lenovo company + 3881d7 texas instruments + 388345 tp-link technologies co.,ltd. + 38839a shenzhen rf-link technology co.,ltd. + 388479 cisco meraki + 388602 flexoptix gmbh + 3887d5 intel corporate + 38881e huawei technologies co.,ltd + 38892c apple, inc. 3889dc opticon sensors europe b.v. 388ab7 itc networks + 388abe guangdong oppo mobile telecommunications corp.,ltd + 388b59 google, inc. + 388c50 lg electronics + 388e7a autoit 388ee7 fanhattan llc + 389052 huawei technologies co.,ltd + 3890a5 cisco systems, inc + 3891d5 hangzhou h3c technologies co., limited 3891fb xenox holding bv + 389496 samsung electronics co.,ltd + 3894e0 syrotech networks. ltd. + 3894ed netgear 389592 beijing tendyron corporation + 3897a4 elecom co.,ltd. + 3897d6 hangzhou h3c technologies co., limited + 3898d8 meritech co.,ltd + 3898e9 huawei device co., ltd. + 389af6 samsung electronics co.,ltd + 389d92 seiko epson corporation + 389f5a c-kur tv inc. 389f83 otn systems n.v. - 38a53c veenstra instruments + 38a067 nokia solutions and networks gmbh & co. kg + 38a28c shenzhen rf-link technology co.,ltd. + 38a4ed xiaomi communications co ltd + 38a53c comecer netherlands 38a5b6 shenzhen megmeet electrical co.,ltd + 38a6ce bskyb ltd 38a851 moog, ing 38a86b orga bv 38a95f actifio inc - 38aa3c samsung electro-mechanics + 38aa3c samsung electro mechanics co., ltd. + 38ac3d nephos inc + 38ad8e new h3c technologies co., ltd + 38adbe new h3c technologies co., ltd + 38af29 zhejiang dahua technology co., ltd. + 38afd0 nevro + 38afd7 fujitsu limited 38b12d sonotronic nagel gmbh + 38b19e ieee registration authority + 38b1db hon hai precision ind. co.,ltd. + 38b3f7 huawei device co., ltd. + 38b4d3 bsh hausgeraete gmbh + 38b54d apple, inc. 38b5bd e.g.o. elektro-ger + 38b5d3 secuworks + 38b725 wistron infocomm (zhongshan) corporation 38b74d fijowave limited + 38b8eb ieee registration authority + 38bab0 broadcom + 38baf8 intel corporate 38bb23 ozvision america llc - 38bc1a meizu technology co.,ltd + 38bb3c avaya inc + 38bc01 huawei technologies co.,ltd + 38bc1a meizu technology co., ltd. 38bf2f espec corp. 38bf33 nec casio mobile communications - 38c096 alps electric co.,ltd. + 38c096 alpsalpine co,.ltd + 38c2ba cctv neotech + 38c4e8 nss sp. z o.o. + 38c70a wifisong 38c7ba cs services co.,ltd. 38c85c cisco spvtg + 38c986 apple, inc. 38c9a9 smart high reliability solutions, inc. + 38ca73 shenzhen miaoming intelligent technology co.,ltd 38ca97 contour design llc + 38cada apple, inc. + 38cd07 beijing facecam technology co., ltd. 38d135 easyio corporation sdn. bhd. + 38d269 texas instruments + 38d2ca zhejiang tmall technology co., ltd. + 38d40b samsung electronics co.,ltd + 38d547 asustek computer inc. + 38d620 limidea concept pte. ltd. + 38d7ca 7hugs labs + 38d82f zte corporation + 38d9a5 mikotek information inc. 38dbbb sunbow telecom co., ltd. 38de60 mohlenhoff gmbh + 38dead intel corporate 38e08e mitsubishi electric corporation - 38e595 shenzhen gongjin electronics co.,ltd + 38e1aa zte corporation + 38e26e shenzhen sweet rain electronics co.,ltd. + 38e2dd zte corporation + 38e3c5 taicang t&w electronics + 38e595 shenzhen gongjin electronics co.,lt + 38e60a xiaomi communications co ltd 38e7d8 htc corporation 38e8df b gmbh medien + datenbanken + 38e8ee nanjing youkuo electric technology co., ltd 38e98c reco s.p.a. 38eaa7 hewlett packard + 38eb47 huawei technologies co.,ltd + 38ec0d apple, inc. 38ec11 novatek microelectronics corp. - 38ece4 samsung electronics + 38ece4 samsung electronics co.,ltd + 38ed18 cisco systems, inc 38ee9d anedo ltd. + 38efe3 ingenico terminals sas 38f098 vapor stone rail systems + 38f0c8 mevo inc. + 38f135 sensortec-canada + 38f23e microsoft mobile oy + 38f32e skullcandy + 38f33f tatsuno corporation + 38f3ab lcfc(hefei) electronics technology co., ltd + 38f3fb asperiq + 38f554 hisense electric co.,ltd + 38f557 jolata, inc. 38f597 home2net gmbh + 38f601 solid state storage technology corporation 38f708 national resource management, inc. + 38f73d amazon technologies inc. + 38f7b2 seojun electric + 38f7cd ieee registration authority + 38f85e humax co., ltd. + 38f889 huawei technologies co.,ltd 38f8b7 v2com participacoes s.a. + 38f8ca owin inc. + 38f9d3 apple, inc. + 38faca skyworth digital technology(shenzhen) co.,ltd + 38fb14 huawei technologies co.,ltd + 38fc98 intel corporate + 38fdfe ieee registration authority 38fec5 ellips b.v. + 38ff36 ruckus wireless + 3c01ef sony mobile communications inc 3c02b1 creation technologies lp + 3c0461 arris group, inc. 3c04bf pravis systems co.ltd., + 3c0518 samsung electronics co.,ltd 3c05ab product creation studio - 3c0754 apple + 3c0630 apple, inc. + 3c06a7 tp-link technologies co.,ltd. + 3c0754 apple, inc. 3c0771 sony corporation 3c081e beijing yupont electric power technology co.,ltd - 3c08f6 cisco + 3c08f6 cisco systems, inc 3c096d powerhouse dynamics 3c0c48 servergy, inc. - 3c0e23 cisco + 3c0c7d tiny mesh as + 3c0cdb unionman technology co.,ltd + 3c0e23 cisco systems, inc 3c0fc1 kbc networks 3c1040 daesung network - 3c106f albahith technologies - 3c15c2 apple + 3c106f albahith technologies + 3c10e6 phazr inc. + 3c11b2 fraunhofer fit + 3c13cc cisco systems, inc + 3c1512 shenzhen huanhu technology co.,ltd + 3c15c2 apple, inc. 3c15ea tescom co., ltd. - 3c18a0 luxshare precision industry co.,ltd. + 3c15fb huawei technologies co.,ltd + 3c1710 sagemcom broadband sas + 3c189f nokia corporation + 3c18a0 luxshare precision industry company limited 3c1915 gfi chrono time 3c197d ericsson ab + 3c1a0f clearsky data 3c1a57 cardiopulmonary corp 3c1a79 huayuan technology co.,ltd + 3c1a9e vitalthings as 3c1cbe jadak llc + 3c1e04 d-link international + 3c1e13 hangzhou sunrise technology co., ltd + 3c2093 gd midea air-conditioning equipment co.,ltd. + 3c20f6 samsung electronics co.,ltd + 3c22fb apple, inc. + 3c24f0 ieee registration authority 3c25d7 nokia corporation 3c26d5 sotera wireless 3c2763 sle quality engineering gmbh & co. kg + 3c286d google, inc. + 3c28a6 alcatel-lucent enterprise (china) + 3c2af4 brother industries, ltd. + 3c2c30 dell inc. + 3c2c94 杭州德澜科技有限公司(hangzhou delan technology co.,ltd) + 3c2c99 edgecore networks corporation 3c2db7 texas instruments + 3c2ef9 apple, inc. + 3c2eff apple, inc. 3c2f3a sforzato corp. 3c300c dewar electronics pty ltd + 3c306f huawei technologies co.,ltd + 3c3178 qolsys inc. + 3c3300 shenzhen bilian electronic co.,ltd + 3c3556 cognitec systems gmbh 3c363d nokia corporation 3c36e4 arris group, inc. + 3c3712 avm audiovisuelles marketing und computersysteme gmbh + 3c3786 netgear 3c3888 connectquest, llc 3c39c3 jw electronics co., ltd. - 3c3a73 avaya, inc - 3c404f guangdong pisen electronics co. ltd. + 3c39e7 ieee registration authority + 3c3a73 avaya inc + 3c3f51 2crsi + 3c404f guangdong pisen electronics co.,ltd + 3c410e cisco systems, inc + 3c427e ieee registration authority 3c438e arris group, inc. - 3c4a92 hewlett-packard company + 3c46d8 tp-link technologies co.,ltd. + 3c4711 huawei technologies co.,ltd + 3c479b theissen training systems, inc. + 3c4937 assmann electronic gmbh + 3c4a92 hewlett packard 3c4c69 infinity system s.l. + 3c4cd0 ceragon networks + 3c4dbe apple, inc. 3c4e47 etronic a/s + 3c510e cisco systems, inc + 3c5282 hewlett packard + 3c53d7 cedes ag + 3c5447 huawei technologies co.,ltd + 3c5731 cisco systems, inc + 3c574f china mobile group device co.,ltd. + 3c576c samsung electronics co.,ltd 3c57bd kessler crane inc. 3c57d5 fiveco - 3c5a37 samsung electronics + 3c58c2 intel corporate + 3c591e tcl king electrical appliances (huizhou) co., ltd + 3c5a37 samsung electronics co.,ltd + 3c5ab4 google, inc. + 3c5cc3 shenzhen first blue chip technology ltd + 3c5cc4 amazon technologies inc. + 3c5cf1 eero inc. + 3c5ec3 cisco systems, inc 3c5f01 synerchip co., ltd. 3c6104 juniper networks - 3c6200 samsung electronics co., ltd + 3c6105 espressif inc. + 3c6200 samsung electronics co.,ltd 3c6278 shenzhen jetnet technology co.,ltd. + 3c6716 lily robotics 3c672c sciovid inc. + 3c678c huawei technologies co.,ltd + 3c6816 vxi corporation + 3c6a2c ieee registration authority 3c6a7d niigata power systems co., ltd. + 3c6a9d dexatek technology ltd. + 3c6aa7 intel corporate 3c6e63 mitron oy 3c6f45 fiberpro inc. + 3c6fea panasonic india pvt. ltd. 3c6ff7 entek systems, inc. 3c7059 makerbot industries + 3c71bf espressif inc. 3c7437 rim 3c754a arris group, inc. 3c77e6 hon hai precision ind. co.,ltd. + 3c7843 huawei technologies co.,ltd + 3c7873 airsonics + 3c7a8a arris group, inc. + 3c7aaa china dragon technology limited + 3c7ac4 chemtronics + 3c7c3f asustek computer inc. + 3c7d0a apple, inc. 3c7db1 texas instruments - 3c81d8 sagemcom sas + 3c7f6f telechips, inc. + 3c806b hunan voc acoustics technology co., ltd. + 3c80aa ransnet singapore pte ltd + 3c81d8 sagemcom broadband sas + 3c831e ckd corporation + 3c8375 microsoft corporation 3c83b5 advance vision electronics co. ltd. + 3c846a tp-link technologies co.,ltd. 3c86a8 sangshin elecom .co,, ltd + 3c86d1 vivo mobile communication co., ltd. + 3c894d dr. ing. h.c. f. porsche ag + 3c8970 neosfar + 3c8994 bskyb ltd 3c89a6 kapelse 3c8ab0 juniper networks 3c8ae5 tensun information technology(hangzhou) co.,ltd - 3c8bfe samsung electronics - 3c9157 hangzhou yulong conmunication co.,ltd + 3c8bcd alcatel-lucent shanghai bell co., ltd + 3c8bfe samsung electronics co.,ltd + 3c8c40 hangzhou h3c technologies co., limited + 3c8c93 juniper networks + 3c8cf8 trendnet, inc. + 3c8d20 google, inc. + 3c8f06 shenzhen libtor technology co.,ltd + 3c9066 smartrg, inc. + 3c912b vexata inc + 3c9157 yulong computer telecommunication scientific (shenzhen) co.,ltd 3c9174 along communication technology + 3c9180 liteon technology corporation + 3c92dc octopod technology co. ltd. 3c94d5 juniper networks + 3c9509 liteon technology corporation 3c970e wistron infocomm(kunshan)co.,ltd. 3c977e ips technology limited + 3c9872 sercomm corporation. 3c98bf quest controls, inc. 3c99f7 lansentechnology ab + 3c9a77 technicolor ch usa inc. + 3c9bc6 huawei device co., ltd. + 3c9bd6 vizio, inc + 3c9c0f intel corporate + 3c9d56 huawei technologies co.,ltd 3c9f81 shenzhen catic bit communications technology co.,ltd + 3ca067 liteon technology corporation + 3ca10d samsung electronics co.,ltd + 3ca308 texas instruments 3ca315 bless information & communications co., ltd + 3ca31a oilfind international llc + 3ca348 vivo mobile communication co., ltd. + 3ca37e huawei technologies co.,ltd + 3ca581 vivo mobile communication co., ltd. + 3ca616 vivo mobile communication co., ltd. + 3ca62f avm audiovisuelles marketing und computersysteme gmbh 3ca72b mrv communications (networks) ltd + 3ca82a hewlett packard + 3ca8ed smart light technology 3ca9f4 intel corporate - 3cab8e apple - 3cb15b avaya, inc + 3caa3f ikey, ltd. + 3cab8e apple, inc. + 3cae69 esa elektroschaltanlagen grimma gmbh + 3cb15b avaya inc 3cb17f wattwatchers pty ld - 3cb87a + 3cb233 huawei device co., ltd. + 3cb53d hunan goke microelectronics co.,ltd + 3cb6b7 vivo mobile communication co., ltd. + 3cb72b plumgrid inc + 3cb74b technicolor ch usa inc. + 3cb792 hitachi maxell, ltd., optronics division + 3cb87a private 3cb9a6 belden deutschland gmbh + 3cbb73 shenzhen xinguodu technology co., ltd. + 3cbbfd samsung electronics co.,ltd + 3cbd3e beijing xiaomi electronics co., ltd. + 3cbdc5 arcadyan corporation 3cbdd8 lg electronics inc + 3cbee1 nikon corporation + 3cbf60 apple, inc. + 3cc079 shenzhen one-nine intelligent electronic science and technology co., ltd 3cc0c6 d&b audiotechnik gmbh 3cc12c aes corporation 3cc1f6 melange systems pvt. ltd. 3cc243 nokia corporation + 3cc2e1 xinhua control engineering co.,ltd + 3cc786 dongguan huarong communication technologies co.,ltd. 3cc99e huiyang technology co., ltd 3cca87 iders incorporated + 3ccb7c tct mobile ltd + 3ccd36 apple, inc. + 3ccd5a technische alternative gmbh + 3ccd5d huawei technologies co.,ltd 3ccd93 lg electronics inc - 3cce73 cisco systems, inc. - 3cd0f8 apple + 3cce15 mercedes-benz usa, llc + 3cce73 cisco systems, inc + 3ccf5b icomm hk limited + 3cd0f8 apple, inc. 3cd16e telepower communication co., ltd + 3cd2e5 new h3c technologies co., ltd 3cd4d6 wirelesswerx, inc 3cd7da sk mtek microelectronics(shenzhen)limited - 3cd92b hewlett-packard company - 3cdf1e cisco systems, inc. - 3cdfbd huawei technologies co., ltd - 3ce072 apple - 3ce5a6 hangzhou h3c technologies co., ltd. + 3cd92b hewlett packard + 3cd9ce eclipse wifi + 3cda2a zte corporation + 3cda6d tiandy technologies co.,ltd + 3cdcbc samsung electronics co.,ltd + 3cdd89 somo holdings & tech. co.,ltd. + 3cdf1e cisco systems, inc + 3cdfa9 arris group, inc. + 3cdfbd huawei technologies co.,ltd + 3ce038 plumeria networks, inc. + 3ce072 apple, inc. + 3ce1a1 universal global scientific industrial co., ltd. + 3ce36b zhejiang dahua technology co., ltd. + 3ce3e7 china mobile group device co.,ltd. + 3ce5a6 hangzhou h3c technologies co., limited 3ce5b4 kidasen industria e comercio de antenas ltda - 3ce624 lg display - 3cea4f 2wire + 3ce624 lg display + 3ce824 huawei technologies co.,ltd + 3cea4f 2wire inc + 3ceaf9 jubixcoltd 3ceafb nse ag + 3cecef super micro computer, inc. + 3cef8c zhejiang dahua technology co., ltd. + 3cf011 intel corporate 3cf392 virtualtek. co. ltd + 3cf4f9 moda-innochips 3cf52c dspecialists gmbh + 3cf591 guangdong oppo mobile telecommunications corp.,ltd + 3cf5cc new h3c technologies co., ltd + 3cf652 zte corporation 3cf72a nokia corporation 3cf748 shenzhen linsn technology development co.,ltd + 3cf7a4 samsung electronics co.,ltd + 3cf808 huawei technologies co.,ltd + 3cf862 intel corporate + 3cfa43 huawei technologies co.,ltd + 3cfad3 ieee registration authority + 3cfb5c fiberhome telecommunication technologies co.,ltd 3cfb96 emcraft systems llc + 3cfdfe intel corporate + 3cffd8 huawei technologies co.,ltd + 4000e0 derek(shaoguan)limited 400107 arista corp + 40017a cisco systems, inc 4001c6 3com europe ltd 40040c a&t + 400589 t-mobile, usa + 400634 huawei device co., ltd. + 4006a0 texas instruments 4007c0 railtec systems gmbh + 400d10 arris group, inc. 400e67 tremol ltd. - 400e85 samsung electro mechanics co.,ltd. + 400e85 samsung electro-mechanics(thailand) + 401175 ieee registration authority + 4011dc sonance 4012e4 compass-eos 4013d9 global es + 4014ad huawei device co., ltd. 401597 protect america, inc. + 40163b samsung electronics co.,ltd 40167e asustek computer inc. - 40169f tp-link technologies co., ltd. + 40169f tp-link technologies co.,ltd. 4016fa ekm metering - 4018b1 aerohive networks inc. - 4018d7 wyle telemetry and data systems + 4017e2 intai technology corp. + 4018b1 extreme networks, inc. + 4018d7 smartronix, inc. + 401920 movon corporation + 401b5f weifang goertek electronics co.,ltd + 401c83 intel corporate 401d59 biometric associates, lp 4022ed digital projection ltd + 402343 chongqing fugui electronics co.,ltd. + 4024b2 sichuan ai-link technology co., ltd. 4025c2 intel corporate + 402619 apple, inc. 40270b mobileeco co., ltd - 402ba1 sony ericsson mobile communications ab + 402814 rfi engineering + 402b50 arris group, inc. + 402b69 kumho electric inc. + 402ba1 sony mobile communications inc + 402c76 ieee registration authority 402cf4 universal global scientific industrial co., ltd. - 403004 apple + 402e28 mixtelematics + 402e71 texas instruments + 402f86 lg innotek + 403004 apple, inc. 403067 conlog (pty) ltd + 40313c xiaomi electronics,co.,ltd + 40331a apple, inc. 40336c godrej & boyce mfg. co. ltd 4037ad macro image technology, inc. - 403cfc apple + 403cfc apple, inc. + 403dec humax co., ltd. + 403f8c tp-link technologies co.,ltd. 404022 ziv + 404028 ziv 40406b icomera + 4040a7 sony mobile communications inc + 404101 rockwell automation + 404229 layer3tv, inc + 4044fd realme chongqing mobile telecommunications corp.,ltd. 4045da spreadtrum communications (shanghai) co., ltd. + 40476a astro gaming + 4048fd ieee registration authority + 40490f hon hai precision ind. co.,ltd. + 40498a synapticon gmbh 404a03 zyxel communications corporation 404a18 addrek smart solutions - 404d8e shenzhen huawei communication technologies co., ltd + 404ad4 widex a/s + 404c77 arris group, inc. + 404d7f apple, inc. + 404d8e huawei technologies co.,ltd + 404e36 htc corporation + 404eeb higher way electronic co., ltd. + 4050b5 shenzhen new species technology co., ltd. 4050e0 milton security group llc 40516c grandex international corporation 40520d pico technology - 405539 cisco systems, inc. + 4054e4 wearsafe labs inc + 405539 cisco systems, inc + 405582 nokia 40560c in home displays ltd + 40562d smartron india pvt ltd + 405662 guotengshenghua electronics ltd. 405a9b anovo + 405bd8 chongqing fugui electronics co.,ltd. + 405cfd dell inc. + 405d82 netgear + 405ee1 shenzhen h&t intelligent control co.,ltd. 405fbe rim 405fc2 texas instruments 40605a hawkeye tech co. ltd 406186 micro-star int'l co.,ltd 40618e stella-green co + 406231 gifa + 406234 telink semiconductor (shanghai) co., ltd. + 4062b6 tele system communication + 4062ea china mobile group device co.,ltd. + 4064a4 the furukawa electric co., ltd + 4065a3 sagemcom broadband sas 40667a mediola - connected living ag 406826 thales uk limited + 406a8e hangzhou puwell oe tech ltd. 406aab rim - 406c8f apple - 406f2a research in motion + 406c8f apple, inc. + 406f2a blackberry rts 407009 arris group, inc. 40704a power idea technology limited 407074 life technology (china) co., ltd + 4070f5 apple, inc. + 407183 juniper networks 407496 afun technology inc. + 4074e0 intel corporate + 4077a9 new h3c technologies co., ltd + 40786a motorola mobility llc, a lenovo company 407875 imbel - industria de material belico do brasil 407a80 nokia corporation 407b1b mettle networks inc. - 4083de motorola + 407c7d nokia + 407d0f huawei technologies co.,ltd + 407fe0 glory star technics (shenzhen) limited + 408256 continental automotive gmbh + 40831d apple, inc. + 4083de zebra technologies inc 408493 clavister ab + 40862e jdm mobile internet solution co., ltd. + 408805 motorola mobility llc, a lenovo company + 40882f extreme networks, inc. 4088e0 beijing ereneben information technology limited shenzhen branch + 4089a8 wirediq, llc 408a9a titeng co., ltd. 408b07 actiontec electronics, inc - 408bf6 shenzhen tcl new technology co; ltd. + 408bf6 shenzhen tcl new technology co., ltd + 408c1f guangdong oppo mobile telecommunications corp.,ltd + 408c4c shenzhen miaoming intelligent technology co.,ltd + 408d5c giga-byte technology co.,ltd. + 408f9d juniper networks + 409505 acoinfo technology co.,ltd 409558 aisino corporation + 4095bd ntmore.co.,ltd 4097d1 bk electronics cc 40984c casacom solutions ag 40984e texas instruments 40987b aisino corporation + 4098ad apple, inc. + 409922 azurewave technology inc. + 409b0d shenzhen yourf kwan industrial co., ltd + 409bcd d-link international + 409c28 apple, inc. + 409f38 azurewave technology inc. + 409f87 jide technology (hong kong) limited 409fc7 baekchun i&c co., ltd. + 40a108 motorola (wuhan) mobility technologies communication co., ltd. + 40a2db amazon technologies inc. + 40a3cc intel corporate + 40a5ef shenzhen four seas global link network technology co., ltd. + 40a677 juniper networks 40a6a4 passivsystems ltd - 40a6d9 apple + 40a6b7 intel corporate + 40a6d9 apple, inc. + 40a6e8 cisco systems, inc 40a8f0 hewlett packard + 40a93f pivotal commware, inc. + 40a9cf amazon technologies inc. + 40aa56 china dragon technology limited 40ac8d data management, inc. - 40b0fa lg electronics + 40b034 hewlett packard + 40b076 asustek computer inc. + 40b0fa lg electronics (mobile communications) 40b2c8 nortel networks - 40b395 apple + 40b30e integrated device technology (malaysia) sdn. bhd. + 40b31e universal electronics, inc. + 40b395 apple, inc. 40b3cd chiyoda electronics co.,ltd. - 40b3fc logital co. limited + 40b3fc logital co. limited + 40b4cd amazon technologies inc. 40b4f0 juniper networks + 40b5c1 cisco systems, inc + 40b688 legic identsystems ag 40b6b1 sungsam co,.ltd + 40b6e7 huawei device co., ltd. 40b7f3 arris group, inc. + 40b837 sony mobile communications inc + 40b89a hon hai precision ind. co.,ltd. + 40b93c hewlett packard enterprise 40ba61 arima communications corp. + 40bc60 apple, inc. + 40bc68 wuhan funshion online technologies co.,ltd 40bc73 cronoplast s.l. 40bc8b itelio gmbh + 40bd32 texas instruments 40bd9e physio-control, inc + 40beee shenzhen yunding information technology co.,ltd 40bf17 digistar telecom. sa 40c245 shenzhen hexicom technology co., ltd. + 40c3c6 snaproute 40c4d6 chongqing camyu technology development co.,ltd. + 40c62a shanghai jing ren electronic technology co., ltd. + 40c711 apple, inc. + 40c729 sagemcom broadband sas 40c7c9 naviit inc. - 40cba8 huawei technologies co., ltd + 40c81f shenzhen xinguodu technology co., ltd. + 40c8cb am telecom co., ltd. + 40cba8 huawei technologies co.,ltd + 40cbc0 apple, inc. 40cd3a z3 technology - 40d32d apple + 40cd7a qingdao hisense communications co.,ltd. + 40ce24 cisco systems, inc + 40d25f itel mobile limited + 40d28a nintendo co., ltd. + 40d32d apple, inc. + 40d357 ison technology co., ltd. + 40d3ae samsung electronics co.,ltd 40d40e biodata ltd + 40d4bd sk networks service co., ltd. 40d559 micro s.e.r.i. + 40d63c equitech industrial(dongguan)co.,ltd 40d855 ieee registration authority + 40dc9d hajen + 40dca5 huawei device co., ltd. + 40ddd1 beautiful card corporation + 40de17 shenzhen lanfeng times industrial co.,ltd. + 40dead juniper networks + 40df02 line biz plus + 40e230 azurewave technology inc. + 40e3d6 aruba, a hewlett packard enterprise company + 40e64b apple, inc. 40e730 dey storage systems, inc. 40e793 shenzhen siviton technology co.,ltd + 40eace founder broadband network service co.,ltd + 40ec99 intel corporate 40ecf8 siemens ag + 40ed98 ieee registration authority + 40ee15 zioncom electronics (shenzhen) ltd. + 40eedd huawei technologies co.,ltd 40ef4c fihonest communication co.,ltd 40f02f liteon technology corporation + 40f04e integrated device technology (malaysia) sdn. bhd. + 40f078 cisco systems, inc 40f14c ise europe sprl + 40f201 sagemcom broadband sas + 40f21c dasan zhone solutions 40f2e9 ibm - 40f308 murata manufactuaring co.,ltd. + 40f308 murata manufacturing co., ltd. + 40f385 ieee registration authority 40f407 nintendo co., ltd. - 40f4ec cisco systems, inc. + 40f413 rubezh + 40f420 sichuan tianyi comheart telecomco.,ltd + 40f4ec cisco systems, inc + 40f520 espressif inc. 40f52e leica microsystems (schweiz) ag + 40f946 apple, inc. + 40f9d5 tecore networks + 40fa7f preh car connect gmbh 40fc89 arris group, inc. - 4403a7 cisco + 40fe0d maxio + 440010 apple, inc. + 440049 amazon technologies inc. + 44004d huawei technologies co.,ltd + 4401bb shenzhen bilian electronic co.,ltd + 44032c intel corporate + 440377 ieee registration authority + 4403a7 cisco systems, inc + 440444 guangdong oppo mobile telecommunications corp.,ltd + 44070b google, inc. + 4409b8 salcomp (shenzhen) co., ltd. 440cfd netman co., ltd. + 4410fe huizhou foryou general electronics co., ltd. + 441102 edmi europe ltd 4411c2 telegartner karl gartner gmbh 441319 wkk technology ltd. + 4413d0 zte corporation + 441441 audiocontrol inc. + 441622 microsoft corporation + 441847 hunan scrown electronic information tech.co.,ltd 44184f fitview + 4418fd apple, inc. 4419b6 hangzhou hikvision digital technology co.,ltd. + 441afa new h3c technologies co., ltd + 441c12 technicolor ch usa inc. + 441c7f motorola mobility llc, a lenovo company + 441ca8 hon hai precision ind. co.,ltd. 441e91 arvida intelligent electronics technology co.,ltd. - 441ea1 hewlett-packard company + 441e98 ruckus wireless + 441ea1 hewlett packard + 44227c huawei technologies co.,ltd + 442295 china mobile iot limited company + 4422f1 s.fac, inc + 44237c beijing xiaomi mobile software co., ltd 4423aa farmage co., ltd. 4425bb bamboo entertainment corporation + 4427f3 70mai co.,ltd. + 4428a3 jiangsu fulian communication technology co., ltd. 442938 nietzsche enterprise co.ltd. - 442a60 apple + 442a60 apple, inc. 442aff e3 technology, inc. - 442b03 cisco systems, inc. + 442b03 cisco systems, inc + 442c05 ampak technology, inc. 443192 hewlett packard - 44322a avaya, inc - 4432c8 technicolor usa inc. + 44322a avaya inc + 4432c8 technicolor ch usa inc. 44334c shenzhen bilian electronic co.,ltd 44348f mxt industrial ltda + 4434a7 arris group, inc. + 44356f neterix + 443583 apple, inc. + 443708 mrv comunications 443719 2 save energy ltd 44376f young electric sign co - 4437e6 hon hai precision ind.co.ltd + 4437e6 hon hai precision ind. co.,ltd. 443839 cumulus networks, inc - 4439c4 universal global scientific industrial co.,ltd + 4439c4 universal global scientific industrial co., ltd. + 443b32 intelbras + 443c88 ficosa maroc international 443c9c pintsch tiefenbach gmbh 443d21 nuvolt + 443e07 electrolux 443eb2 deotron co., ltd. + 44422f testop co.,ltd. + 444450 ottoq + 444687 realme chongqing mobiletelecommunications corp ltd + 4447cc hangzhou hikvision digital technology co.,ltd. 444891 hdmi licensing, llc + 4448c1 hewlett packard enterprise 444a65 silverflare ltd. - 444c0c apple + 444ab0 zhejiang moorgen intelligence technology co., ltd + 444adb apple, inc. + 444b5d ge healthcare + 444b7e fiberhome telecommunication technologies co.,ltd + 444c0c apple, inc. + 444ca8 arista networks 444e1a samsung electronics co.,ltd + 444e6d avm audiovisuelles marketing und computersysteme gmbh 444f5e pan studios co.,ltd. 4451db raytheon bbn technologies 4454c0 thompson aerospace + 4455b1 huawei technologies co.,ltd + 4455c4 huawei device co., ltd. 44568d pnc technologies co., ltd. 4456b7 spawn labs, inc + 4456e2 sichuan tianyi comheart telecom co., ltd. 445829 cisco spvtg + 445943 zte corporation 44599f criticare systems, inc + 4459e3 huawei technologies co.,ltd + 445ce9 samsung electronics co.,ltd + 445d5e shenzhen coolkit technology co.,ltd + 445ecd razer inc 445ef3 tonalite holding b.v. 445f7a shihlin electric & engineering corp. + 445f8c intercel group limited 446132 ecobee inc 44619c fonsystem co. ltd. + 446246 comat ag + 44650d amazon technologies inc. + 44656a mega video electronic(hk) industry co., ltd + 44657f calix inc. + 44666e ip-line + 4466fc guangdong oppo mobile telecommunications corp.,ltd + 446747 huawei technologies co.,ltd 446755 orbit irrigation + 44680c wacom co.,ltd. 4468ab juin company, limited + 446a2e huawei technologies co.,ltd + 446ab7 arris group, inc. 446c24 reallin electronic co.,ltd 446d57 liteon technology corporation + 446d6c samsung electronics co.,ltd + 446ee5 huawei technologies co.,ltd + 446fd8 ieee registration authority + 446ff8 dyson limited 44700b iffu 447098 ming hong technology (shen zhen) limited + 4473d6 logitech + 44746c sony mobile communications inc + 447654 huawei technologies co.,ltd + 44783e samsung electronics co.,ltd + 447bbb shenzhen youhua technology co., ltd 447bc4 dualshine technology(sz)co.,ltd 447c7f innolight technology corporation 447da5 vtion information technology (fujian) co.,ltd 447e76 trek technology (s) pte ltd 447e95 alpha and omega, inc + 447f77 connected home + 4480eb motorola mobility llc, a lenovo company + 4482e5 huawei technologies co.,ltd 448312 star-net 448500 intel corporate - 4487fc elitegroup computer system co., ltd. + 4486c1 siemens low voltage & products + 448723 hoya service corporation + 4487db tymphany acoustic technology (huizhou) co., ltd. + 4487fc elitegroup computer systems co.,ltd. + 4488cb camco technologies nv 448a5b micro-star int'l co., ltd. 448c52 ktis co., ltd + 448dbf rhino mobility llc 448e12 dt research, inc. 448e81 vig + 448f17 samsung electronics co., ltd. artik + 4490bb apple, inc. + 449160 murata manufacturing co., ltd. + 44917c hmd global oy 4491db shanghai huaqin telecom technology co.,ltd - 4494fc netgear inc., + 4494fc netgear 4495fa qingdao santong digital technology co.ltd + 44962b aidon oy + 44975a shenzhen fast technologies co.,ltd 449b78 the now factory + 449bc1 huawei technologies co.,ltd 449cb5 alcomp, inc - 44a42d tct mobile limited + 449ef9 vivo mobile communication co., ltd. + 449f7f datacore software corporation + 44a191 huawei technologies co.,ltd + 44a42d tct mobile ltd + 44a466 groupe ldlc + 44a54e qorvo international pte. ltd. + 44a56e netgear + 44a61e ingram micro services 44a689 promax electronica sa + 44a6e5 thinking technology co.,ltd 44a7cf murata manufacturing co., ltd. + 44a842 dell inc. 44a8c2 sewoo tech co., ltd + 44a8fc apple, inc. 44aa27 udworks co., ltd. + 44aa50 juniper networks 44aae8 nanotec electronic gmbh & co. kg - 44add9 cisco + 44aaf5 arris group, inc. + 44ad19 xingfei (h.k)limited + 44adb1 sagemcom broadband sas + 44add9 cisco systems, inc + 44ae25 cisco systems, inc + 44aeab guangdong oppo mobile telecommunications corp.,ltd + 44af28 intel corporate + 44b295 sichuan ai-link technology co., ltd. + 44b32d tp-link technologies co.,ltd. 44b382 kuang-chi institute of advanced technology + 44b412 sius ag + 44b433 tide.co.,ltd + 44b462 flextronics tech.(ind) pvt ltd + 44b6be cisco systems, inc + 44b994 douglas lighting controls + 44ba46 sichuan tianyi comheart telecomco.,ltd + 44bb3b google, inc. + 44bdde bhtc gmbh + 44bfe3 shenzhen longtech electronics co.,ltd 44c15c texas instruments 44c233 guangzhou comet technology development co.ltd 44c306 sifrom inc. + 44c346 huawei technologies co.,ltd 44c39b ooo rubezh npo 44c4a9 opticom communication, llc 44c56f ngn easy satfinder (tianjin) electronic co., ltd + 44c65d apple, inc. + 44c69b wuhan feng tian information network co.,ltd + 44c7fc huawei device co., ltd. + 44c874 china mobile group device co.,ltd. 44c9a2 greenwald industries + 44cb8b lg innotek + 44cd0e flextronics manufacturing(zhuhai)co.,ltd. + 44ce3a jiangsu huacun electronic technology co., ltd. + 44ce7d sfr 44d15e shanghai kingto information technology ltd + 44d1fa shenzhen yunlink technology co., ltd + 44d244 seiko epson corporation 44d2ca anvia tv oy - 44d3ca cisco systems, inc. + 44d3ad shenzhen tinno mobile technology corp. + 44d3ca cisco systems, inc + 44d437 inteno broadband technology ab + 44d453 sagemcom broadband sas + 44d4e0 sony mobile communications inc + 44d5a5 addon computer + 44d5f2 ieee registration authority 44d63d talari networks - 44d832 azurewave technologies, inc. - 44d884 apple + 44d6e1 snuza international pty. ltd. + 44d791 huawei technologies co.,ltd + 44d832 azurewave technology inc. + 44d878 hui zhou gaoshengda technology co.,ltd + 44d884 apple, inc. + 44d9e7 ubiquiti networks inc. + 44dc4e itel mobile limited 44dc91 planex communications inc. 44dccb semindia systems pvt ltd 44e08e cisco spvtg + 44e137 arris group, inc. 44e49a omnitronics pty ltd - 44e4d9 cisco systems, inc. + 44e4d9 cisco systems, inc + 44e4ee wistron neweb corporation + 44e66e apple, inc. + 44e6b0 china mobile iot company limited 44e8a5 myreka technologies sdn. bhd. + 44e968 huawei technologies co.,ltd + 44e9dd sagemcom broadband sas + 44ea4b actlas inc. + 44ead8 texas instruments + 44ecce juniper networks 44ed57 longicorn, inc. + 44ee02 mti ltd. 44ee30 budelmann elektronik gmbh - 44f459 samsung electronics + 44efbf china dragon technology limited + 44efcf ugene solution inc. + 44f034 kaonmedia co., ltd. + 44f21b apple, inc. + 44f436 zte corporation + 44f459 samsung electronics co.,ltd + 44f477 juniper networks + 44f4e7 cohesity inc 44f849 union pacific railroad - 44fb42 apple + 44f971 shenzhen mercury communication technologies co.,ltd. + 44fb42 apple, inc. + 44fb5a zte corporation + 44fda3 everysight ltd. + 44fe3b arcadyan corporation + 44ffba zte corporation + 480031 huawei technologies co.,ltd + 480033 technicolor ch usa inc. + 48007d dts elektronik san. tic. ltd. sti. + 4801c5 oneplus technology (shenzhen) co., ltd 48022a b-link electronic limited 480362 desay electronics(huizhou)co.,ltd + 48049f elecom co., ltd + 4805e2 huawei device co., ltd. + 48066a tempered networks, inc. + 480bb2 ieee registration authority + 480c49 nakayo inc + 480eec tp-link technologies co.,ltd. + 480fcf hewlett packard + 481063 ntt innovation institute, inc. 481249 luxcom technologies inc. - 4813f3 bbk electronics corp., ltd. + 481258 huawei technologies co.,ltd + 48137e samsung electronics co.,ltd + 4813f3 bbk educational electronics corp.,ltd. + 481693 lear corporation gmbh 48174c micropower technologies 481842 shanghai winaas co. equipment co. ltd. + 4818fa nocsys + 481a84 pointer telocation ltd 481bd2 intron scientific co., ltd. + 481d70 cisco spvtg + 481f2d shenzhen jie shi lian industrial co.,ltd + 48210b pegatron corporation + 48216c china mobile iot company limited + 482335 dialog semiconductor hellas sa + 482567 poly + 48262c apple, inc. + 4826e8 tek-air systems, inc. + 482759 levven electronics ltd. + 4827ea samsung electronics co.,ltd 48282f zte corporation + 482952 sagemcom broadband sas + 4829e4 zao npk rotek + 482ae3 wistron infocomm(kunshan)co.,ltd. + 482ca0 xiaomi communications co ltd + 482cd0 huawei technologies co.,ltd 482cea motorola inc business light radios 4833dd zennio avance y tecnologia, s.l. 48343d iep gmbh + 48352e shenzhen wolck network product co.,ltd + 48365f wintecronics ltd. + 483871 huawei device co., ltd. + 483974 proware technologies co., ltd. + 483b38 apple, inc. + 483c0c huawei technologies co.,ltd 483d32 syscor controls & automation + 483fda espressif inc. + 483fe9 huawei technologies co.,ltd + 48435a huawei technologies co.,ltd + 48437c apple, inc. + 4843dd amazon technologies inc. 484487 cisco spvtg - 4844f7 samsung electronics co., ltd + 4844f7 samsung electronics co.,ltd + 484520 intel corporate + 4846c1 fn-link technology limited 4846f1 uros oy 4846fb huawei technologies co.,ltd + 4849c7 samsung electronics co.,ltd + 484a30 george robotics limited + 484ae9 hewlett packard enterprise + 484baa apple, inc. + 484bd4 technicolor ch usa inc. + 484c29 huawei technologies co.,ltd + 484c86 huawei device co., ltd. + 484d7e dell inc. + 484efc arris group, inc. + 485073 microsoft corporation + 485169 samsung electronics co.,ltd + 4851b7 intel corporate + 4851c5 intel corporate + 4851cf intelbras 485261 soreel + 485415 net rules tecnologia eireli + 48555c wu qi technologies,inc. + 48555f fiberhome telecommunication technologies co.,ltd + 485702 huawei technologies co.,ltd + 4857dd facebook inc + 485929 lg electronics (mobile communications) + 4859a4 zte corporation 485a3f wisol 485ab6 hon hai precision ind. co.,ltd. 485b39 asustek computer inc. - 485d60 azurewave technologies, inc. - 4860bc apple - 4861a3 concern "axion" jsc + 485d36 verizon + 485d60 azurewave technology inc. + 485deb just add power + 485f99 cloud network technology (samoa) limited + 48605f lg electronics (mobile communications) + 4860bc apple, inc. + 4861a3 concern axion jsc 486276 huawei technologies co.,ltd + 4865ee ieee registration authority + 486834 silicon motion, inc. + 48684a intel corporate + 486b2c bbk educational electronics corp.,ltd. 486b91 fleetwood group inc. + 486dbb vestel elektronik san ve tic. a.Ş. + 486e70 zhejiang tmall technology co., ltd. 486e73 pica8, inc. + 486efb davit system technology co., ltd. 486fd2 storsimple inc + 48701e texas instruments 487119 sgb group ltd. - 48746e apple - 487604 + 48746e apple, inc. + 487583 intellion ag + 487604 private + 487746 calix inc. + 48785e amazon technologies inc. + 48794d samsung electronics co.,ltd + 487a55 ale international + 487ada hangzhou h3c technologies co., limited + 487af6 ncs electrical sdn bhd + 487aff essys + 487b5e smt telecomm hk + 487b6b huawei technologies co.,ltd + 487d2e tp-link technologies co.,ltd. + 487e48 earda technologies co ltd + 488244 life fitness / div. of brunswick + 4882f2 appel elektronik gmbh + 4883b4 guangdong oppo mobile telecommunications corp.,ltd + 4883c7 sagemcom broadband sas + 4886e8 microsoft corporation + 48872d shen zhen da xia long que technology co.,ltd + 488764 vivo mobile communication co., ltd. + 488803 mantechnology inc. + 48881e ethoswitch llc + 488899 shenzhen superelectron technology co.,ltd. + 4888ca motorola (wuhan) mobility technologies communication co., ltd. + 4889e7 intel corporate + 488ad2 mercury communication technologies co.,ltd. + 488b0a cisco systems, inc + 488c63 huawei device co., ltd. + 488d36 arcadyan corporation 488e42 digalog gmbh + 488eef huawei technologies co.,ltd + 488f5a routerboard.com + 48902f lg electronics (mobile communications) 489153 weinmann geräte für medizin gmbh + co. kg 4891f6 shenzhen reach software technology co.,ltd + 489507 guangdong oppo mobile telecommunications corp.,ltd + 4898ca sichuan ai-link technology co., ltd. + 489a42 technomate ltd + 489bd5 extreme networks, inc. 489be2 sci innovations ltd - 489d24 research in motion + 489d18 flashbay limited + 489d24 blackberry rts + 489dd1 samsung electronics co.,ltd + 48a0f8 fiberhome telecommunication technologies co.,ltd + 48a195 apple, inc. 48a22d shenzhen huaxuchang telecom technology co.,ltd 48a2b7 kodofon jsc + 48a2b8 chengdu vision-zenith tech.co,.ltd + 48a2e6 resideo + 48a380 gionee communication equipment co.,ltd. + 48a472 intel corporate + 48a493 taiyo yuden co.,ltd + 48a516 huawei device co., ltd. + 48a5e7 nintendo co.,ltd + 48a6b8 sonos, inc. 48a6d2 gjsun optical science and tech co.,ltd. + 48a73c sichuan tianyi kanghe communications co., ltd + 48a74e zte corporation + 48a91c apple, inc. + 48a9d2 wistron neweb corporation 48aa5d store electronic systems + 48ad08 huawei technologies co.,ltd + 48b02d nvidia corporation 48b253 marketaxess corporation + 48b25d huawei technologies co.,ltd 48b5a7 glory horse industries ltd. + 48b620 roli ltd. + 48b8a3 apple, inc. 48b8de homewins technology co.,ltd. 48b977 pulseon oy 48b9c2 teletics inc. + 48ba4e hewlett packard + 48bca6 ​asung techno co.,ltd + 48bd0e quanta storage inc. + 48bd3d new h3c technologies co., ltd 48be2d symanitron + 48bf6b apple, inc. + 48bf74 baicells technologies co.,ltd + 48c049 broad telecom sa + 48c093 xirrus, inc. 48c1ac plantronics, inc. + 48c3b0 pharos co.ltd + 48c58d lear corporation gmbh + 48c663 gto access systems llc + 48c796 samsung electronics co.,ltd 48c862 simo wireless,inc. 48c8b6 systec gmbh 48cb6e cello electronics (uk) ltd 48d0cf universal electronics, inc. 48d18e metis communication co.,ltd 48d224 liteon technology corporation + 48d24f sagemcom broadband sas + 48d343 arris group, inc. + 48d35d private + 48d539 huawei technologies co.,ltd 48d54c jeda networks + 48d6d5 google, inc. + 48d705 apple, inc. 48d7ff blankom antennentechnik gmbh + 48d845 shenzhen mainuoke electronics co., ltd + 48d855 telvent + 48d875 china transinfo technology co., ltd + 48d890 fn-link technology limited 48d8fe claridy solutions, inc. + 48da96 eddy smart home solutions inc. + 48db50 huawei technologies co.,ltd + 48dc2d huawei technologies co.,ltd 48dcfb nokia corporation + 48dd0c eero inc. + 48dd9d itel mobile limited 48df1c wuhan nec fibre optic communications industry co. ltd + 48df37 hewlett packard enterprise 48e1af vity + 48e1e9 chengdu meross technology co., ltd. + 48e244 hon hai precision ind. co.,ltd. + 48e3c3 jenoptik advanced systems gmbh + 48e695 insigma inc + 48e6c0 simcom wireless solutions co.,ltd. + 48e9f1 apple, inc. 48ea63 zhejiang uniview technologies co., ltd. 48eb30 eterna technology, inc. + 48eb62 murata manufacturing co., ltd. + 48ec5b nokia solutions and networks gmbh & co. kg 48ed80 daesung eltec 48ee07 silver palm technologies llc + 48ee0c d-link international 48ee86 utstarcom (china) co.,ltd + 48ef61 huawei device co., ltd. + 48f027 chengdu newifi co.,ltd + 48f07b alpsalpine co,.ltd + 48f17f intel corporate 48f230 ubizcore co.,ltd - 48f317 + 48f317 private 48f47d techvision holding internation limited - 48f7f1 alcatel-lucent + 48f7c0 technicolor ch usa inc. + 48f7f1 nokia 48f8b3 cisco-linksys, llc - 48f8e1 alcatel lucent wt + 48f8db huawei technologies co.,ltd + 48f8e1 nokia 48f925 maestronic + 48f97c fiberhome telecommunication technologies co.,ltd + 48fcb6 lava international(h.k) limited 48fcb8 woodstream corporation + 48fd8e huawei technologies co.,ltd + 48fda3 xiaomi communications co ltd 48feea homa b.v. - 4c0082 cisco + 4c0082 cisco systems, inc + 4c0143 eero inc. + 4c0220 xiaomi communications co ltd 4c022e cmr korea co., ltd 4c0289 lex computech co., ltd 4c068a basler electric company 4c07c9 computer office co.,ltd. 4c09b4 zte corporation - 4c0b3a tct mobile limited + 4c09d4 arcadyan technology corporation + 4c0a3d adnacom inc. + 4c0b3a tct mobile ltd + 4c0bbe microsoft 4c0dee jabil circuit (shanghai) ltd. 4c0f6e hon hai precision ind. co.,ltd. - 4c0fc7 earda electronics co.,ltd + 4c0fc7 earda technologies co ltd + 4c1154 mobiwire mobiles (ningbo) co., ltd + 4c1159 vision information & communications + 4c11ae espressif inc. + 4c11bf zhejiang dahua technology co., ltd. + 4c1265 arris group, inc. + 4c1365 emplus technologies 4c1480 noregon systems, inc 4c14a3 tcl technoly electronics (huizhou) co., ltd. - 4c17eb sagemcom + 4c1694 shenzhen sibituo technology co., ltd + 4c16f1 zte corporation + 4c16fc juniper networks + 4c1744 amazon technologies inc. + 4c17eb sagemcom broadband sas + 4c189a guangdong oppo mobile telecommunications corp.,ltd 4c1a3a prima research and production enterprise ltd. + 4c1a3d guangdong oppo mobile telecommunications corp.,ltd 4c1a95 novakon co., ltd. + 4c1b86 arcadyan corporation + 4c1d96 intel corporate 4c1fcc huawei technologies co.,ltd - 4c21d0 sony mobile communications ab + 4c20b8 apple, inc. + 4c2113 nokia shanghai bell co., ltd. + 4c218c panasonic india private limited + 4c21d0 sony mobile communications inc + 4c2219 yuanfudao hk limted 4c2258 cozybit, inc. + 4c2498 texas instruments 4c2578 nokia corporation - 4c2c80 beijing skyway technologies co.,ltd + 4c26e7 welgate co., ltd. + 4c2c80 beijing skyway technologies co.,ltd + 4c2c83 zhejiang kanong network technology co.,ltd. + 4c2efe shenzhen comnect technology co.,ltd 4c2f9d icm controls 4c3089 thales transportation systems gmbh 4c322d teledata networks + 4c3275 apple, inc. 4c32d9 m rutty holdings pty. ltd. + 4c3329 sweroam + 4c334e hightech + 4c3488 intel corporate + 4c364e panasonic corporation connected solutions company + 4c38d5 mitac computing technology corporation + 4c38d8 arris group, inc. + 4c3909 hpl electric & power private limited 4c3910 newtek electronics co., ltd. 4c3b74 vogtec(h.k.) co., ltd + 4c3bdf microsoft corporation 4c3c16 samsung electronics co.,ltd - 4c4b68 mobile device, inc. - 4c4e35 cisco + 4c3fd3 texas instruments + 4c4088 sanshin electronics co.,ltd. + 4c4576 china mobile(hangzhou) information technology co.,ltd. + 4c48da beijing autelan technology co.,ltd + 4c494f zte corporation + 4c49e3 xiaomi communications co ltd + 4c4b68 mobile device, inc. + 4c4bf9 ieee registration authority + 4c4d66 nanjing jiahao technology co., ltd. + 4c4e03 tct mobile ltd + 4c4e35 cisco systems, inc + 4c4fee oneplus technology (shenzhen) co., ltd + 4c5077 huawei device co., ltd. + 4c5262 fujitsu technology solutions gmbh + 4c52ec solarwatt gmbh 4c5427 linepro sp. z o.o. - 4c5499 shenzhen huawei communication technologies co., ltd + 4c5499 huawei technologies co.,ltd 4c5585 hamilton systems 4c55b8 turkcell teknoloji - 4c55cc ackme networks pty ltd + 4c55cc zentri pty ltd + 4c569d apple, inc. + 4c56df targus us llc + 4c57ca apple, inc. + 4c5d3c cisco systems, inc 4c5dcd oy finnish electric vehicle technologies ltd 4c5e0c routerboard.com 4c5fd2 alcatel-lucent 4c60d5 airpointe of new hampshire 4c60de netgear + 4c617e huawei device co., ltd. 4c6255 sanmina-sci system de mexico s.a. de c.v. + 4c6371 xiaomi communications co ltd 4c63eb application solutions (electronics and vision) ltd 4c64d9 guangdong leawin group co., ltd + 4c65a8 ieee registration authority + 4c6641 samsung electro-mechanics(thailand) + 4c6af6 hmd global oy + 4c6be8 apple, inc. + 4c6c13 iot company solucoes tecnologicas ltda + 4c6d58 juniper networks + 4c6e6e comnect technology co.,ltd + 4c6f9c guangdong oppo mobile telecommunications corp.,ltd + 4c710c cisco systems, inc + 4c710d cisco systems, inc 4c72b9 pegatron corporation 4c7367 genius bytes software solutions gmbh 4c73a5 kove - 4c774f embedded wireless labs + 4c7403 bq + 4c7487 leader phone communication technology co., ltd. + 4c74bf apple, inc. + 4c7525 espressif inc. + 4c7625 dell inc. + 4c774f embedded wireless labs + 4c7766 shenzhen mercury communication technologies co.,ltd. + 4c776d cisco systems, inc + 4c7872 cav. uff. giacomo cimberio s.p.a. 4c7897 arrowhead alarm products ltd + 4c796e intel corporate 4c79ba intel corporate + 4c7a48 nippon seiki (europe) b.v. + 4c7c5f apple, inc. + 4c7cd9 apple, inc. 4c7f62 nokia corporation 4c804f armstrong monitoring corp 4c8093 intel corporate - 4c82cf echostar technologies + 4c80ba wuhan tianyu information industry co., ltd. + 4c8120 taicang t&w electronics + 4c82cf dish technologies corp + 4c83de cisco spvtg + 4c875d bose corporation 4c8b30 actiontec electronics, inc 4c8b55 grupo digicon - 4c8bef huawei technologies co., ltd - 4c8d79 apple + 4c8bef huawei technologies co.,ltd + 4c8d79 apple, inc. + 4c8ecc silkan sa 4c8fa5 jastec + 4c90db jl audio + 4c910c lanix internacional, s.a. de c.v. + 4c9157 fujian landi commercial equipment co.,ltd + 4c917a ieee registration authority + 4c93a6 ieee registration authority 4c9614 juniper networks + 4c962d fresh ab 4c98ef zeo 4c9e80 kyokko electric co., ltd. 4c9ee4 hanyang navicom co.,ltd. + 4c9eff zyxel communications corporation + 4ca003 vitec + 4ca161 rain bird corporation + 4ca515 baikal electronics jsc 4ca56d samsung electronics co.,ltd + 4ca64d cisco systems, inc 4ca74b alcatel lucent + 4ca928 insensi 4caa16 azurewave technologies (shanghai) inc. 4cab33 kst technology + 4cabfc zte corporation 4cac0a zte corporation + 4cada8 panoptics corp. + 4cae13 huawei technologies co.,ltd + 4cae1c sainxt technologies llp + 4cae31 shenghai electronics (shenzhen) ltd + 4caea3 hewlett packard enterprise + 4caeec guangzhou limee technology co.,ltd + 4cb008 shenzhen gwelltimes technology co.,ltd + 4cb0e8 beijing rongzhi xinghua technology co., ltd 4cb16c huawei technologies co.,ltd - 4cb199 apple + 4cb199 apple, inc. + 4cb1cd ruckus wireless + 4cb21c maxphotonics co.,ltd + 4cb44a nanowave technologies inc. 4cb4ea hrd (s) pte., ltd. + 4cb76d novi security 4cb81c sam electronics gmbh + 4cb82c cambridge mobile telematics, inc. + 4cb8b5 shenzhen youhua technology co., ltd + 4cb910 apple, inc. + 4cb911 raisecom technology co.,ltd + 4cb99b weifang goertek electronics co.,ltd 4cb9c8 conet co., ltd. 4cbaa3 bison electronics inc. + 4cbb58 chicony electronics co., ltd. + 4cbc42 shenzhen hangsheng electronics co.,ltd. + 4cbc48 cisco systems, inc + 4cbc72 primex wireless + 4cbc98 ieee registration authority 4cbca5 samsung electronics co.,ltd + 4cbcb4 abb spa - din rail + 4cbd8f hangzhou hikvision digital technology co.,ltd. + 4cc00a vivo mobile communication co., ltd. + 4cc206 somfy 4cc452 shang hai tyd. electon technology ltd. + 4cc53e zyxel communications corporation 4cc602 radios, inc. - 4cc94f alcatel-lucent + 4cc681 shenzhen aisat electronic co., ltd. + 4cc7d6 flextronics manufacturing(zhuhai)co.,ltd. + 4cc8a1 cisco meraki + 4cc94f nokia + 4cc95e samsung electronics co.,ltd 4cca53 skyera, inc. 4ccbf5 zte corporation 4ccc34 motorola solutions inc. + 4ccc6a micro-star intl co., ltd. + 4cce2d danlaw inc + 4cd08a humax co., ltd. + 4cd0cb huawei technologies co.,ltd + 4cd1a1 huawei technologies co.,ltd 4cd637 qsono electronics co., ltd 4cd7b6 helmer scientific + 4cd98f dell inc. 4cd9c4 magneti marelli automotive electronics (guangzhou) co. ltd + 4cdc0d coral telecom limited + 4cdd31 samsung electronics co.,ltd + 4cdd7d lhp telematics llc 4cdf3d team engineers advance technologies india pvt ltd + 4ce173 ieee registration authority + 4ce175 cisco systems, inc + 4ce176 cisco systems, inc + 4ce19e tecno mobile limited 4ce1bb zhuhai hifocus technology co., ltd. - 4ce676 buffalo inc. + 4ce2f1 sclak srl + 4ce5ae tianjin beebox intelligent technology co.,ltd. + 4ce676 buffalo.inc + 4ce933 railcomm, llc + 4ce9e4 new h3c technologies co., ltd 4ceb42 intel corporate + 4cebbd chongqing fugui electronics co.,ltd. + 4cecef soraa, inc. 4cedde askey computer corp + 4cedfb asustek computer inc. + 4ceeb0 shc netzwerktechnik gmbh + 4cef56 shenzhen sundray technologies company limited + 4cefc0 amazon technologies inc. 4cf02e vifa denmark a/s + 4cf19e groupe atlantic + 4cf202 xiaomi communications co ltd + 4cf2bf cambridge industries(group) co.,ltd. 4cf45b blue clover devices + 4cf55b huawei technologies co.,ltd + 4cf5a0 scalable network technologies inc 4cf737 samji electronics co., ltd + 4cf95d huawei technologies co.,ltd + 4cfaca cambridge industries(group) co.,ltd. + 4cfb45 huawei technologies co.,ltd + 4cfbf4 optimal audio ltd + 4cfbfe sercomm japan corporation + 4cfcaa tesla,inc. + 4cff12 fuze entertainment co., ltd + 500084 siemens canada 50008c hong kong telecommunications (hkt) limited - 5001bb samsung electronics + 50016b huawei technologies co.,ltd + 5001bb samsung electronics co.,ltd + 5001d9 huawei technologies co.,ltd + 500291 espressif inc. + 5004b8 huawei technologies co.,ltd 50053d cywee group ltd - 500604 cisco + 500604 cisco systems, inc + 5006ab cisco systems, inc + 500959 technicolor ch usa inc. 500b32 foxda technology industrial(shenzhen)co.,ltd + 500b91 ieee registration authority 500e6d trafficcast international + 500f80 cisco systems, inc + 500ff5 tenda technology co.,ltd.dongguan branch 5011eb silvernet ltd - 5017ff cisco + 501395 sichuan ai-link technology co., ltd. + 501408 ainet + 501479 irobot corporation + 5014b5 richfit information technology co., ltd + 5017ff cisco systems, inc + 50184c platina systems inc. + 501aa5 gn netcom a/s 501ac5 microsoft - 501cbf cisco + 501b32 taicang t&w electronics + 501cb0 cisco systems, inc + 501cbf cisco systems, inc + 501d93 huawei technologies co.,ltd + 501e2d streamunlimited engineering gmbh + 501fc6 apple, inc. 50206b emerson climate technologies transportation solutions + 5021ec huawei device co., ltd. 502267 pixelink 50252b nethra imaging incorporated 502690 fujitsu limited 5027c7 technart co.,ltd + 502873 huawei device co., ltd. + 50294d nanjing iot sensor technology co,ltd + 5029f5 guangdong oppo mobile telecommunications corp.,ltd 502a7e smart electronic gmbh 502a8b telekom research and development sdn bhd + 502b73 tenda technology co.,ltd.dongguan branch + 502b98 es-tech international + 502cc6 gree electric appliances, inc. of zhuhai 502d1d nokia corporation 502da2 intel corporate + 502dbb gd midea air-conditioning equipment co.,ltd. 502df4 phytec messtechnik gmbh + 502dfb igshare co., ltd. 502e5c htc corporation 502ece asahi electronics co.,ltd + 502f9b intel corporate + 502fa8 cisco systems, inc + 5031ad abb global industries and services private limited + 503237 apple, inc. 503275 samsung electronics co.,ltd + 50338b texas instruments + 5033f0 yichen (shenzhen) technology co.ltd + 50382f ase group chung-li 503955 cisco spvtg + 503a7d alphatech plc int’l co., ltd. + 503aa0 shenzhen mercury communication technologies co.,ltd. 503cc4 lenovo mobile communication technology ltd. - 503de5 cisco systems, inc. + 503cea guangdong oppo mobile telecommunications corp.,ltd + 503da1 samsung electronics co.,ltd + 503dc6 xiaomi communications co ltd + 503de5 cisco systems, inc + 503e7c leishen intelligent system co.ltd + 503eaa tp-link technologies co.,ltd. 503f56 syncmold enterprise corp + 503f98 cmitech + 504061 nokia + 5041b9 i-o data device,inc. + 504348 thingsmatrix inc. + 5043b9 oktoinform rus + 5045f7 liuhe intelligence technology ltd. + 50464a huawei technologies co.,ltd 50465d asustek computer inc. 5048eb beijing haihejinsheng network technology co. ltd. 504a5e masimo corporation - 504a6e netgear inc., + 504a6e netgear + 504b5b controltronic gmbh + 504c7e the 41st institute of cetc + 504edc ping communication 504f94 loxone electronics gmbh + 50502a egardia + 505065 takt corporation + 5050a4 samsung electronics co.,ltd + 5050ce hangzhou dianyixia communication technology co. ltd. + 5051a9 texas instruments + 50523b nokia + 5052d2 hangzhou telin technologies co., limited + 505527 lg electronics (mobile communications) + 50558d china mobile iot company limited 505663 texas instruments 5056a8 jolla ltd 5056bf samsung electronics co.,ltd - 5057a8 cisco systems, inc. + 50579c seiko epson corporation + 5057a8 cisco systems, inc 505800 wytec international, inc. + 50584f waytotec,inc. + 505967 intent solutions inc 505ac6 guangdong super telecom co.,ltd. + 505bc2 liteon technology corporation + 505dac huawei technologies co.,ltd + 505fb5 askey computer corp. 506028 xirrus inc. - 506184 avaya, inc + 506184 avaya inc + 5061bf cisco systems, inc 5061d6 indu-sol gmbh + 5061f6 universal electronics, inc. + 506255 ieee registration authority 506313 hon hai precision ind. co.,ltd. + 50642b xiaomi electronics,co.,ltd 506441 greenlee + 506583 texas instruments + 5065f3 hewlett packard + 506787 planet networks + 5067ae cisco systems, inc 5067f0 zyxel communications corporation + 50680a huawei technologies co.,ltd + 506a03 netgear + 506b4b mellanox technologies, inc. + 506b8d nutanix + 506cbe innosilicontechnology ltd + 506e92 innocent technology co., ltd. + 506f77 huawei technologies co.,ltd + 506f98 sehaj synergy technologies private limited 506f9a wi-fi alliance + 507043 bskyb ltd 5070e5 he shan world fair electronics technology limited + 507224 texas instruments 50724d beg brueck electronic gmbh + 5075f1 arris group, inc. 507691 tekpea, inc. 5076a6 ecil informatica ind. com. ltda + 5076af intel corporate + 507705 samsung electronics co.,ltd + 5078b3 zte corporation 50795b interexport telecomunicaciones s.a. + 507a55 apple, inc. + 507ac5 apple, inc. + 507b9d lcfc(hefei) electronics technology co., ltd 507d02 biodit 507e5d arcadyan technology corporation + 50804a quectel wireless solutions co., ltd. + 5082d5 apple, inc. 508569 samsung electronics co.,ltd + 508789 cisco systems, inc 5087b8 nuvyyo inc + 508965 shenzhen mercury communication technologies co.,ltd. + 508a0f shenzhen fise technology holding co.,ltd. 508a42 uptmate technology co., ltd 508acb shenzhen maxmade technology co., ltd. 508c77 dirmeier schanktechnik gmbh &co kg + 508cb1 texas instruments + 508cf5 china mobile group device co.,ltd. 508d6f chahoo limited + 508e49 xiaomi communications co ltd + 508f4c xiaomi communications co ltd + 5092b9 samsung electronics co.,ltd 50934f gradual tecnologia ltda. + 509551 arris group, inc. + 509707 xiamen paperang technology co.,ltd. + 509744 integrated device technology (malaysia) sdn. bhd. 509772 westinghouse digital + 509839 xiaomi communications co ltd 509871 inventum technologies private limited - 509f27 huawei technologies co., ltd + 5098b8 new h3c technologies co., ltd + 5098f3 rheem australia pty ltd + 509a46 safetrust inc + 509a4c dell inc. + 509ea7 samsung electronics co.,ltd + 509f27 huawei technologies co.,ltd + 509f3b oi electric co.,ltd + 50a009 xiaomi communications co ltd 50a054 actineon + 50a0a4 nokia 50a0bf alba fiber systems inc. + 50a132 shenzhen miaoming intelligent technology co.,ltd 50a4c8 samsung electronics co.,ltd + 50a4d0 ieee registration authority + 50a5dc arris group, inc. + 50a67f apple, inc. 50a6e3 david clark company 50a715 aboundi, inc. + 50a72b huawei technologies co.,ltd 50a733 ruckus wireless + 50a83a s mobile devices limited + 50a9de smartcom - bulgaria ad + 50ab3e qibixx ag 50abbf hoseo telecom + 50ad71 tessolve semiconductor private limited + 50ad92 nx technologies + 50add5 dynalec corporation + 50ae86 linkintec co., ltd + 50af4d zte corporation 50af73 shenzhen bitland information technology co., ltd. + 50b363 digitron da amazonia s/a 50b695 micropoint biotechnologies,inc. - 50b7c3 samsung electronics co., ltd + 50b7c3 samsung electronics co.,ltd 50b888 wi2be tecnologia s/a 50b8a2 imtech technologies llc, + 50bc96 apple, inc. + 50bd5f tp-link technologies co.,ltd. 50c006 carmanah signs 50c271 securetech inc + 50c2ed gn audio a/s + 50c3a2 nfore technology co.,ltd. + 50c4dd buffalo.inc 50c58d juniper networks + 50c68e biwin semiconductor (hk) company limted + 50c6ad fiberhome telecommunication technologies co.,ltd + 50c709 juniper networks 50c7bf tp-link technologies co.,ltd. + 50c8e5 samsung electronics co.,ltd 50c971 gn netcom a/s - 50c9a0 skipper electronics as - 50ccf8 samsung electro mechanics + 50c9a0 skipper as + 50ccf8 samsung electro mechanics co., ltd. + 50cd22 avaya inc 50cd32 nanjing chaoran science & technology co.,ltd. - 50ce75 measy electronics ltd + 50ce75 measy electronics co., ltd. + 50cee3 gigafirm.co.ltd + 50d213 cvilux corporation 50d274 steffes corporation + 50d2f5 beijing xiaomi mobile software co., ltd + 50d37f yu fly mikly way science and technology co., ltd. + 50d4f7 tp-link technologies co.,ltd. + 50d59c thai habel industrial co., ltd. 50d6d7 takahata precision + 50d753 conelcom gmbh + 50da00 hangzhou h3c technologies co., limited + 50db3f shenzhen gongjin electronics co.,lt + 50dce7 amazon technologies inc. + 50dcfc ecocom + 50dd4f automation components, inc + 50de06 apple, inc. + 50df95 lytx + 50e039 zyxel communications corporation + 50e085 intel corporate 50e0c7 turcontrolsystme ag - 50e14a + 50e0ef nokia + 50e14a private + 50e24e zte corporation 50e549 giga-byte technology co.,ltd. - 50ead6 apple - 50eb1a brocade communications systems, inc. + 50e666 shenzhen techtion electronics co., ltd. + 50e971 jibo, inc. + 50ead6 apple, inc. + 50eb1a brocade communications systems llc + 50eb71 intel corporate + 50ec50 beijing xiaomi mobile software co., ltd + 50ed3c apple, inc. 50ed78 changzhou yongse infotech co.,ltd 50ed94 egatel sl 50f003 open stack, inc. + 50f0d3 samsung electronics co.,ltd + 50f14a texas instruments + 50f43c leeo inc + 50f4eb apple, inc. 50f520 samsung electronics co.,ltd + 50f5da amazon technologies inc. 50f61a kunshan jade technologies co., ltd. + 50f722 cisco systems, inc + 50f7ed huawei device co., ltd. + 50f8a5 ewbm co., ltd. + 50f958 huawei device co., ltd. + 50fa84 tp-link technologies co.,ltd. 50faab l-tek d.o.o. + 50fb19 chipsea technologies (shenzhen) corp. 50fc30 treehouse labs 50fc9f samsung electronics co.,ltd + 50fef2 sify technologies ltd + 50ff20 keenetic limited + 50ff99 ieee registration authority + 540237 teltronic ag + 540384 hongkong nano ic technologies co., ltd 5403f5 ebn technology corp. 540496 gigawave ltd 5404a6 asustek computer inc. 540536 vivago oy 54055f alcatel lucent + 540593 woori elec co.,ltd + 5405db lcfc(hefei) electronics technology co., ltd + 54068b ningbo deli kebei technology co.ltd + 540764 huawei device co., ltd. + 540910 apple, inc. + 540955 zte corporation + 54098d deister electronic gmbh + 540df9 huawei device co., ltd. + 540e2d vivo mobile communication co., ltd. + 540e58 guangdong oppo mobile telecommunications corp.,ltd + 541031 smarto + 5410ec microchip technology inc. 54112f sulzer pump solutions finland oy 54115f atamo pty ltd + 541310 huawei technologies co.,ltd + 541379 hon hai precision ind. co.,ltd. + 541473 wingtech group (hongkong)limited + 5414f3 intel corporate + 5414fd orbbec 3d technology international + 541589 mcs logic inc. + 5419c8 vivo mobile communication co., ltd. 541b5d techno-innov 541dfb freestyle energy ltd + 541e56 juniper networks 541fd5 advantage electronics 542018 tely labs - 542160 resolution products + 54211d huawei device co., ltd. + 542160 alula + 54219d samsung electronics co.,ltd 5422f8 zte corporation - 542696 apple - 54271e azurewave technonloies, inc. + 5425ea huawei technologies co.,ltd + 542696 apple, inc. + 54271e azurewave technology inc. + 542758 motorola (wuhan) mobility technologies communication co., ltd. + 54276c jiangsu houge technology corp. + 54278d nxp (china) management ltd. + 542a1b sonos, inc. 542a9c lsy defense, llc. + 542aa2 alpha networks inc. + 542b57 night owl sp + 542b8d apple, inc. + 542bde new h3c technologies co., ltd 542cea protectron 542f89 euclid laboratories, inc. + 542f8a tellescom industria e comercio em telecomunicacao 543131 raster vision ltd + 5433cb apple, inc. + 5434ef huawei technologies co.,ltd 543530 hon hai precision ind. co.,ltd. 5435df symeo gmbh + 54369b 1verge internet technology (beijing) co., ltd. 543968 edgewater networks inc 5439df huawei technologies co.,ltd + 543ad6 samsung electronics co.,ltd + 543b30 duagon ag 543d37 ruckus wireless + 543e64 fiberhome telecommunication technologies co.,ltd + 5440ad samsung electronics co.,ltd 544249 sony corporation 544408 nokia corporation - 54466b shenzhen cztic electronic technology co., ltd + 544617 zte corporation + 54466b shenzhen cztic electronic technology co., ltd + 544741 xcheng holding + 5447d3 tsat as + 544810 dell inc. + 54489c cdoubles electronics co. ltd. + 5448e6 beijing xiaomi mobile software co., ltd + 5449df peloton interactive, inc + 544a00 cisco systems, inc 544a05 wenglor sensoric gmbh 544a16 texas instruments + 544b8c juniper networks + 544e45 private + 544e90 apple, inc. + 54511b huawei technologies co.,ltd + 545146 amg systems ltd. 5453ed sony corporation 545414 digital rf corea, inc + 5454cf probedigital co.,ltd + 5455d5 huawei device co., ltd. + 545aa6 espressif inc. 545ebd nl technologies 545fa9 teracom limited + 546009 google, inc. + 546172 zodiac aerospace sas 5461ea zaplox ab - 54724f apple + 5462e2 apple, inc. + 5464d9 sagemcom broadband sas + 546503 quectel wireless solutions co., ltd. + 5465de arris group, inc. + 54666c shenzhen youhua technology co., ltd + 546751 compal broadband networks, inc. + 5467e6 shenzhen mtc co ltd + 546ad8 elster water metering + 546c0e texas instruments + 546d52 topview optronics corp. + 5471dd huawei device co., ltd. + 54724f apple, inc. + 54725e unionman technology co.,ltd 547398 toyo electronics corporation 5474e6 webtech wireless - 5475d0 cisco systems, inc. - 54781a cisco + 547595 tp-link technologies co.,ltd. + 5475d0 cisco systems, inc + 54778a hewlett packard enterprise + 54781a cisco systems, inc 547975 nokia corporation + 547a52 cte international srl + 547c69 cisco systems, inc + 547dcd texas instruments 547f54 ingenico 547fa8 telco systems, s.r.o. - 547fee cisco systems, inc. + 547fbc iodyne + 547fee cisco systems, inc + 548028 hewlett packard enterprise + 54812d pax computer technology(shenzhen) ltd. 5481ad eagle research corporation + 54833a zyxel communications corporation 54847b digital devices gmbh - 54880e samsung electro mechanics co., ltd. + 5484dc zte corporation + 5486bc cisco systems, inc + 54880e samsung electro-mechanics(thailand) + 5488de cisco systems, inc 548922 zelfy inc 548998 huawei technologies co.,ltd + 548aba cisco systems, inc + 548ca0 liteon technology corporation + 548d5a intel corporate + 549209 huawei technologies co.,ltd 5492be samsung electronics co.,ltd 549359 shenzhen twowing technologies co.,ltd. 549478 silvershore technology partners + 549963 apple, inc. + 549a11 ieee registration authority 549a16 uzushio electric co.,ltd. - 549b12 samsung electronics + 549a4c guangdong homecare technology co.,ltd. + 549b12 samsung electronics co.,ltd + 549b72 ericsson ab + 549c27 plasma cloud limited 549d85 eneraccess inc + 549f13 apple, inc. + 549f35 dell inc. + 549fae ibase gaming inc + 549fc6 cisco systems, inc 54a04f t-mac technologies ltd + 54a050 asustek computer inc. + 54a274 cisco systems, inc 54a31b shenzhen linkworld technology co,.ltd - 54a51b shenzhen huawei communication technologies co., ltd + 54a3fa bqt solutions (australia)pty ltd + 54a493 ieee registration authority + 54a51b huawei technologies co.,ltd 54a54b nsc communications siberia ltd 54a619 alcatel-lucent shanghai bell co., ltd + 54a65c technicolor ch usa inc. + 54a6db huawei device co., ltd. + 54a703 tp-link technologies co.,ltd. 54a9d4 minibar systems - 54ae27 apple + 54ab3a quanta computer inc. + 54ae27 apple, inc. + 54aed0 dasan networks, inc. + 54b121 huawei technologies co.,ltd + 54b203 pegatron corporation + 54b56c xi'an novastar tech co., ltd 54b620 suhdol e&c co.ltd. + 54b753 hunan fenghui yinjia science and technology co.,ltd + 54b7e5 rayson technology co., ltd. + 54b802 samsung electronics co.,ltd + 54b80a d-link international + 54bad6 huawei technologies co.,ltd + 54bd79 samsung electronics co.,ltd + 54be53 zte corporation 54bef7 pegatron corporation + 54bf64 dell inc. + 54c33e ciena corporation + 54c415 hangzhou hikvision digital technology co.,ltd. + 54c57a sunnovo international limited 54c80f tp-link technologies co.,ltd. + 54c9df fn-link technology limited + 54cd10 panasonic mobile communications co.,ltd. 54cda7 fujian shenzhou electronic co.,ltd 54cdee shenzhen apexis electronic co.,ltd + 54ce69 hikari trading co.,ltd. + 54d0b4 xiamen four-faith communication technology co.,ltd 54d0ed axim communications 54d163 max-tech,inc 54d1b0 universal laser systems, inc + 54d272 nuki home solutions gmbh 54d46f cisco spvtg + 54d751 proximus + 54d9c6 huawei device co., ltd. + 54d9e4 brilliantts co., ltd + 54dba2 fibrain + 54dc1d yulong computer telecommunication scientific (shenzhen) co.,ltd + 54ded0 sevio srl + 54df00 ulterius technologies, llc + 54df24 fiberhome telecommunication technologies co.,ltd 54df63 intrakey technologies gmbh + 54e019 ring llc 54e032 juniper networks - 54e2e0 pace plc + 54e061 sichuan tianyi comheart telecomco., ltd + 54e140 ingenico + 54e1ad lcfc(hefei) electronics technology co., ltd + 54e2c8 dongguan aoyuan electronics technology co., ltd + 54e2e0 arris group, inc. 54e3b0 jvl industri elektronik + 54e3f6 alcatel-lucent 54e43a apple, inc. + 54e4a9 bhr tech gmbh + 54e4bd fn-link technology limited + 54e61b apple, inc. 54e63f shenzhen lingkeweier technology co., ltd. - 54e6fc tp-link technologies co., ltd. + 54e6fc tp-link technologies co.,ltd. + 54e7d5 sun cupid technology (hk) ltd 54eaa8 apple, inc. + 54ec2f ruckus wireless + 54eda3 navdy, inc. 54ee75 wistron infocomm(kunshan)co.,ltd. + 54ef44 lumi united technology co., ltd 54ef92 shenzhen elink technology co., ltd + 54effe fullpower technologies, inc. + 54f15f sichuan ai-link technology co., ltd. + 54f201 samsung electronics co.,ltd + 54f294 huawei device co., ltd. 54f5b6 oriental pacific international limited + 54f607 huawei device co., ltd. 54f666 berthold technologies gmbh and co.kg + 54f6c5 fujian star-net communication co.,ltd + 54f6e2 huawei technologies co.,ltd + 54f876 abb ag + 54fa3e samsung electronics co.,ltd + 54fa96 nokia solutions and networks gmbh & co. kg 54fb58 wiseware, lda + 54fcf0 samsung electronics co.,ltd 54fdbf scheidt & bachmann gmbh + 54ff82 davit solution co. + 54ffcf mopria alliance + 5800bb juniper networks + 5800e3 liteon technology corporation + 5803fb hangzhou hikvision digital technology co.,ltd. + 580454 icomm hk limited + 5804cb tianjin huisun technology co.,ltd. 580528 labris networks 580556 elettronica gf s.r.l. 5808fa fiber optic & telecommunication inc. - 580943 + 580943 private 5809e5 kivic inc. - 580a20 cisco + 580a20 cisco systems, inc + 58108c intelbras + 5810b7 infinix mobility limited 581243 acsip technology corp. - 581626 avaya, inc - 58170c sony ericsson mobile communications ab + 581626 avaya inc + 5816d7 alpsalpine co,.ltd + 58170c sony mobile communications inc + 5819f8 arris group, inc. 581cbd affinegy 581d91 advanced mobile telecom co.,ltd. - 581faa apple + 581f28 huawei technologies co.,ltd + 581f67 open-m technology limited + 581faa apple, inc. 581fef tuttnaer ltd + 582059 xiaomi communications co ltd + 58208a ieee registration authority + 5820b1 hewlett packard + 582136 kmb systems, s.r.o. + 5821e9 twpi + 58238c technicolor ch usa inc. + 582429 google, inc. + 582575 huawei technologies co.,ltd + 58278c buffalo.inc + 582af7 huawei technologies co.,ltd + 582bdb pax ab + 582d34 qingping electronics (suzhou) co., ltd 582efe lighting science group + 582f40 nintendo co.,ltd 582f42 universal electric corporation + 583112 drust + 583277 reliance communications llc 58343b glovast technology ltd. - 5835d9 cisco systems, inc. + 583526 deeplet technology corp + 58356b tecno mobile limited + 5835d9 cisco systems, inc + 583879 ricoh company, ltd. + 583bd9 fiberhome telecommunication technologies co.,ltd 583cc6 omneality ltd. - 5842e4 sigma international general medical apparatus, llc. + 583f54 lg electronics (mobile communications) + 58404e apple, inc. + 584120 tp-link technologies co.,ltd. + 5842e4 baxter international inc + 584498 xiaomi communications co ltd + 58454c ericsson ab 58468f koncar electronics and informatics - 5846e1 baxter healthcare + 5846e1 baxter international inc + 584704 shenzhen webridge technology co.,ltd + 584822 sony mobile communications inc 5848c0 coflec + 584925 e3 enterprise 58493b palo alto networks 5849ba chitai electronic corp. 584c19 chongqing guohong technology development company limited @@ -14896,293 +18618,768 @@ exit 585076 linear equipamentos eletronicos sa 5850ab tls corporation 5850e6 best buy corporation - 5855ca apple + 5850ed hangzhou hikvision digital technology co.,ltd. + 58528a mitsubishi electric corporation + 5853c0 beijing guang runtong technology development company co.,ltd + 5855ca apple, inc. + 5856c2 huawei technologies co.,ltd 5856e8 arris group, inc. 58570d danfoss solar inverters + 5859c2 extreme networks, inc. + 585ff6 zte corporation + 58605f huawei technologies co.,ltd + 5860d8 arris group, inc. + 586163 quantum networks (sg) pte. ltd. + 586356 fn-link technology limited 58639a tpl systemes - 5865e6 infomark co., ltd. + 5865e6 infomark 5866ba hangzhou h3c technologies co., limited - 58671a barnes&noble.com + 58671a barnes&noble 58677f clare controls inc. - 58696c fujian ruijie networks co, ltd + 58685d tempo australia pty ltd + 58696c ruijie networks co.,ltd 5869f9 fusion transactive ltd. + 586ab1 hangzhou h3c technologies co., limited + 586b14 apple, inc. + 586c25 intel corporate 586d8f cisco-linksys, llc - 586ed6 + 586ed6 private + 5870c6 shanghai xiaoyi technology co., ltd. 587521 cjsc rtsoft 587675 beijing echo technologies co.,ltd + 5876c5 digi i's ltd 587a4d stonesoft corporation - 587e61 hisense electric co., ltd + 587a62 texas instruments + 587a6a guangdong oppo mobile telecommunications corp.,ltd + 587be9 airpro technology india pvt. ltd + 587e61 qingdao hisense communications co.,ltd. + 587f57 apple, inc. + 587f66 huawei technologies co.,ltd + 587fb7 sonar industrial co., ltd. 587fc8 s2m + 58821d h. schomäcker gmbh + 5882a8 microsoft 5884e4 ip500 alliance e.v. + 58856e qsc ag + 5885a2 realme chongqing mobiletelecommunications corp ltd + 5885e9 realme chongqing mobiletelecommunications corp ltd + 588694 efm networks 58874c lite-on clean energy technology corp. 5887e2 shenzhen coship electronics co., ltd. - 588d09 cisco systems, inc. + 588a5a dell inc. + 588bf3 zyxel communications corporation + 588d09 cisco systems, inc + 588d64 xi'an clevbee technology co.,ltd + 588e81 silicon laboratories + 589043 sagemcom broadband sas 5891cf intel corporate 58920d kinetic avionics limited 589396 ruckus wireless + 5893d8 texas instruments 58946b intel corporate + 5894a2 ketek gmbh + 5894ae huawei device co., ltd. + 5894b2 brainco 5894cf vertex standard lmr, inc. - 58971e cisco + 5895d8 ieee registration authority + 58961d intel corporate + 589630 technicolor ch usa inc. + 58971e cisco systems, inc + 5897bd cisco systems, inc 589835 technicolor 58986f revolution display + 589b0b shineway technologies, inc. 589cfc freebsd foundation - 58a2b5 lg electronics + 589ec6 gigaset communications gmbh + 58a023 intel corporate + 58a0cb tracknet, inc + 58a2b5 lg electronics (mobile communications) + 58a48e pixart imaging inc. + 58a639 samsung electronics co.,ltd 58a76f id corporation - 58b035 apple + 58a839 intel corporate + 58a87b fitbit, inc. + 58ac78 cisco systems, inc + 58ae2b huawei device co., ltd. + 58aea8 huawei technologies co.,ltd + 58aef1 fiberhome telecommunication technologies co.,ltd + 58b035 apple, inc. 58b0d4 zunidata systems inc. + 58b0fe team eps gmbh + 58b10f samsung electronics co.,ltd + 58b3fc shenzhen rf-link technology co.,ltd. + 58b42d ysten technology co.,ltd + 58b568 securitas direct espaÑa, sau + 58b623 beijing xiaomi mobile software co., ltd + 58b633 ruckus wireless 58b961 solem electronique 58b9e1 crystalfontz america, inc. - 58bc27 cisco systems, inc. + 58bad4 huawei technologies co.,ltd + 58bc27 cisco systems, inc + 58bc8f cognitive systems corp. 58bda3 nintendo co., ltd. 58bdf9 sigrand - 58bfea cisco systems, inc. + 58be72 huawei technologies co.,ltd + 58bfea cisco systems, inc + 58c17a cambium networks limited 58c232 nec corporation - 58c38b samsung electronics + 58c38b samsung electronics co.,ltd + 58c583 itel mobile limited + 58c5cb samsung electronics co.,ltd + 58c6f0 guangdong oppo mobile telecommunications corp.,ltd + 58c876 china mobile (hangzhou) information technology co., ltd. + 58c935 chiun mai communication systems, inc + 58cb52 google, inc. 58cf4b lufkin industries + 58d061 huawei technologies co.,ltd 58d071 bw broadcast 58d08f ieee 1904.1 working group + 58d349 apple, inc. + 58d391 quectel wireless solutions co., ltd. + 58d50a murata manufacturing co., ltd. + 58d56e d-link international + 58d67a tcplink 58d6d3 dairy cheq inc + 58d759 huawei technologies co.,ltd + 58d9c3 motorola mobility llc, a lenovo company + 58d9d5 tenda technology co.,ltd.dongguan branch + 58db15 tecno mobile limited 58db8d fast co., ltd. + 58dc6d exceptional innovation, inc. 58e02c micro technic a/s + 58e16c ying hua information technology (shanghai)co., ltd + 58e28f apple, inc. 58e326 compass technologies inc. 58e476 centron communications technologies fujian co.,ltd 58e636 evrsafe technologies + 58e6ba apple, inc. 58e747 deltanet ag 58e808 autonics corporation + 58e873 hangzhou dangbei network tech.co.,ltd + 58e876 ieee registration authority + 58eafc ell-iot inc 58eb14 proteus digital health 58ece1 newport corporation + 58eced integrated device technology (malaysia) sdn. bhd. 58eece icon time systems + 58ef68 belkin international inc. + 58f102 blu products inc. + 58f2fc huawei device co., ltd. 58f387 hccp + 58f39c cisco systems, inc + 58f496 source chain 58f67b xia men unioncore technology ltd. 58f6bf kyoto university + 58f987 huawei technologies co.,ltd 58f98e secudos gmbh - 58fd20 bravida sakerhet ab + 58fb84 intel corporate + 58fb96 ruckus wireless + 58fc20 altice labs s.a. + 58fc73 arria live media, inc. + 58fcdb ieee registration authority + 58fd20 systemhouse solutions ab + 58fdb1 lg electronics + 58fdbe shenzhen taikaida technology co., ltd + 5c0038 viasat group s.p.a. 5c026a applied vision corporation + 5c0272 silicon laboratories + 5c0339 huawei technologies co.,ltd 5c076f thought creator - 5c0a5b samsung electro-mechanics co., ltd. + 5c0947 apple, inc. + 5c0979 huawei technologies co.,ltd + 5c0a5b samsung electro mechanics co., ltd. + 5c0bca tunstall nordic ab + 5c0c0e guizhou huaxintong semiconductor technology co ltd 5c0cbb celizion inc. - 5c0e8b motorola + 5c0e8b extreme networks, inc. + 5c0ffb amino communications ltd + 5c10c5 samsung electronics co.,ltd 5c1193 seal one ag 5c1437 thyssenkrupp aufzugswerke gmbh + 5c1515 advan 5c15e1 aidc technology (s) pte ltd 5c16c7 big switch networks + 5c1720 huawei device co., ltd. 5c1737 i-view now, llc. - 5c17d3 lge + 5c17cf oneplus technology (shenzhen) co., ltd + 5c17d3 lge 5c18b5 talon communications + 5c1a6f cambridge industries(group) co.,ltd. + 5c1cb9 vivo mobile communication co., ltd. + 5c1dd9 apple, inc. 5c20d0 asoni communication co., ltd. 5c22c4 dae eun eletronics co., ltd + 5c2316 squirrels research labs llc + 5c2443 o-sung telecom co., ltd. 5c2479 baltech ag 5c254c avire global pte ltd 5c260a dell inc. - 5c2aef open access pty ltd + 5c2623 wavelynx technologies corporation + 5c27d4 shenzhen qihu intelligent technology company limited + 5c2aef r2p asia-pacific pty ltd + 5c2bf5 vivint wireless inc. + 5c2e59 samsung electronics co.,ltd + 5c2ed2 abc(xisheng) electronics co.,ltd 5c313e texas instruments + 5c32c5 teracom ltd. 5c3327 spazio italia srl 5c335c swissphone telecom ag - 5c338e alpha networkc inc. - 5c353b compal broadband networks inc. + 5c338e alpha networks inc. + 5c3400 hisense electric co.,ltd + 5c353b compal broadband networks, inc. 5c35da there corporation oy - 5c36b8 tcl king electrical appliances (huizhou) ltd. + 5c36b8 tcl king electrical appliances (huizhou) co., ltd 5c38e0 shanghai super electronics technology co.,ltd + 5c3a3d zte corporation + 5c3a45 chongqing fugui electronics co.,ltd. + 5c3b35 gehirn inc. 5c3c27 samsung electronics co.,ltd 5c4058 jefferson audio video systems, inc. + 5c415a amazon.com, llc + 5c41e7 wiatec international ltd. 5c43d2 hazemeyer + 5c443e skullcandy + 5c4527 juniper networks + 5c4979 avm audiovisuelles marketing und computersysteme gmbh + 5c497d samsung electronics co.,ltd + 5c4a1f sichuan tianyi comheart telecomco., ltd 5c4a26 enguity technology corp - 5c4ca9 shenzhen huawei communication technologies co., ltd - 5c5015 cisco systems, inc. + 5c4ca9 huawei technologies co.,ltd + 5c5015 cisco systems, inc 5c514f intel corporate + 5c5181 samsung electronics co.,ltd + 5c5188 motorola mobility llc, a lenovo company + 5c521e nintendo co.,ltd + 5c546d huawei technologies co.,ltd + 5c5578 iryx corp + 5c56a4 wanan hongsheng electronic co.ltd 5c56ed 3pleplay electronics private limited 5c571a arris group, inc. 5c57c8 nokia corporation - 5c5948 apple + 5c5819 jingsheng technology co., ltd. + 5c5948 apple, inc. + 5c5ac7 cisco systems, inc + 5c5aea ford + 5c5b35 mist systems, inc. + 5c5bc2 yik corporation 5c5eab juniper networks - 5c63bf tp-link technologies co., ltd. + 5c5f67 intel corporate + 5c6199 cloud network technology singapore pte. ltd. + 5c625a canon inc. + 5c63bf tp-link technologies co.,ltd. + 5c63c9 intellithings ltd. + 5c647a huawei technologies co.,ltd + 5c648e zyxel communications corporation + 5c666c guangdong oppo mobile telecommunications corp.,ltd + 5c6776 ids imaging development systems gmbh + 5c68d0 aurora innovation inc. 5c6984 nuvico - 5c6a7d kentkart ege elektronik san. ve tic. ltd. sti. + 5c6a7d kentkart ege elektronik san. ve tic. ltd. sti. + 5c6a80 zyxel communications corporation 5c6b32 texas instruments + 5c6b4f hello inc. + 5c6bd7 foshan viomi electric appliance technology co. ltd. 5c6d20 hon hai precision ind. co.,ltd. 5c6f4f s.a. sistel + 5c6f69 broadcom limited + 5c7017 apple, inc. + 5c70a3 lg electronics (mobile communications) + 5c710d cisco systems, inc + 5c75af fitbit, inc. + 5c7695 technicolor ch usa inc. 5c7757 haivision network video - 5c7d5e huawei technologies co., ltd + 5c7776 tct mobile ltd + 5c78f8 huawei device co., ltd. + 5c7d5e huawei technologies co.,ltd + 5c7d7d technicolor ch usa inc. + 5c80b6 intel corporate + 5c81a7 network devices pty ltd + 5c838f cisco systems, inc 5c8486 brightsource industries israel ltd + 5c857e ieee registration authority + 5c85f8 shenzhen kaifa technology co.,ltd. + 5c8613 beijing zhoenet technology co., ltd 5c864a secret labs llc + 5c865c samsung electronics co.,ltd + 5c86c1 dongguan solum electronics co.,ltd + 5c8730 apple, inc. 5c8778 cybertelbridge co.,ltd + 5c879c intel corporate + 5c8816 rockwell automation + 5c899a tp-link technologies co.,ltd. 5c89d4 beijing banner electric co.,ltd - 5c95ae apple - 5c969d apple + 5c8a38 hewlett packard + 5c8d2d shanghai wellpay information technology co., ltd + 5c8d4e apple, inc. + 5c8fe0 arris group, inc. + 5c9012 owl cyber defense solutions, llc + 5c9157 huawei technologies co.,ltd + 5c91fd jaewoncnc + 5c925e zioncom electronics (shenzhen) ltd. + 5c93a2 liteon technology corporation + 5c95ae apple, inc. + 5c9656 azurewave technology inc. + 5c966a rtnet + 5c969d apple, inc. + 5c97f3 apple, inc. + 5c9960 samsung electronics co.,ltd + 5c9aa1 huawei device co., ltd. 5c9ad8 fujitsu limited - 5ca39d samsung electro-mechanics co., ltd. + 5ca176 sichuan tianyi comheart telecomco., ltd + 5ca178 tabletop media (dba ziosk) + 5ca1e0 embedway technologies + 5ca39d samsung electro mechanics co., ltd. 5ca3eb lokel s.r.o. - 5ca48a cisco + 5ca48a cisco systems, inc + 5ca4a4 fiberhome telecommunication technologies co.,ltd + 5ca5bc eero inc. + 5ca62d cisco systems, inc + 5ca86a huawei technologies co.,ltd + 5ca933 luma home + 5caafd sonos, inc. 5cac4c hon hai precision ind. co.,ltd. - 5cb524 sony ericsson mobile communications ab + 5cad76 shenzhen tcl new technology co., ltd + 5cadcf apple, inc. + 5caf06 lg electronics (mobile communications) + 5cb00a huawei technologies co.,ltd + 5cb066 arris group, inc. + 5cb13e sagemcom broadband sas + 5cb15f oceanblue cloud technology limited + 5cb29e asco power technologies + 5cb395 huawei technologies co.,ltd + 5cb3f6 human, incorporated + 5cb43e huawei technologies co.,ltd + 5cb4e2 inspur software group ltd. + 5cb524 sony mobile communications inc + 5cb559 cnex labs + 5cb6cc novacomm technologies inc. + 5cb8cb allis communications + 5cb901 hewlett packard + 5cba2c hewlett packard enterprise + 5cba37 microsoft corporation + 5cbaef chongqing fugui electronics co.,ltd. + 5cbd9a huawei device co., ltd. 5cbd9e hongkong miracle eagle technology(group) limited + 5cc0a0 huawei technologies co.,ltd + 5cc1d7 samsung electronics co.,ltd 5cc213 fr. sauter ag + 5cc307 huawei technologies co.,ltd + 5cc336 ittim 5cc5d4 intel corporate - 5cc6d0 skyworth digital technology(shenzhen)co.ltd. + 5cc6d0 skyworth digital technology(shenzhen) co.,ltd + 5cc6e9 edifier international + 5cc7d7 azroad technology company limited + 5cc8e3 shintec hozumi co.ltd. + 5cc999 new h3c technologies co., ltd 5cc9d3 palladium energy eletronica da amazonia ltda + 5cca1a microsoft mobile oy 5cca32 theben ag + 5ccad3 chipsea technologies (shenzhen) corp. + 5ccb99 samsung electronics co.,ltd + 5ccbca fujian star-net communication co.,ltd + 5ccca0 gridwiz inc. + 5cccff techroutes network pvt ltd + 5ccd5b intel corporate + 5ccd7c meizu technology co.,ltd. 5ccead cdyne corporation + 5ccf7f espressif inc. 5cd135 xtreme power systems + 5cd20b yytek co., ltd. 5cd2e4 intel corporate 5cd41b uczoon technology co., ltd 5cd4ab zektor + 5cd5b5 shenzhen wisiyilink technology co.,ltd 5cd61f qardio, inc + 5cd89e huawei device co., ltd. 5cd998 d-link corporation 5cdad4 murata manufacturing co., ltd. + 5cdc96 arcadyan technology corporation 5cdd70 hangzhou h3c technologies co., limited + 5cde34 shenzhen mercury communication technologies co.,ltd. + 5ce0c5 intel corporate 5ce0ca feitian united (beijing) system technology co., ltd. 5ce0f6 nic.br- nucleo de informacao e coordenacao do ponto br + 5ce176 cisco systems, inc 5ce223 delphin technology ag 5ce286 nortel networks + 5ce28c zyxel communications corporation 5ce2f4 acsip technology corp. + 5ce30e arris group, inc. + 5ce3b6 fiberhome telecommunication technologies co.,ltd + 5ce50c beijing xiaomi mobile software co., ltd + 5ce747 huawei technologies co.,ltd + 5ce7a0 nokia 5ce7bf new singularity international technical development co.,ltd - 5ce8eb samsung electronics + 5ce883 huawei technologies co.,ltd + 5ce8b7 oraimo technology limited + 5ce8eb samsung electronics co.,ltd + 5cea1d hon hai precision ind. co.,ltd. 5ceb4e r. stahl hmi systems gmbh + 5ceb68 cheerstar technology co., ltd + 5ced8c hewlett packard enterprise 5cee79 global digitech co ltd 5cf207 speco technologies + 5cf286 ieee registration authority 5cf370 cc&c technologies, inc 5cf3fc ibm corp - 5cf4ab zyxel communications corp + 5cf4ab zyxel communications corporation 5cf50d institute of microelectronic applications + 5cf5da apple, inc. 5cf6dc samsung electronics co.,ltd - 5cf8a1 murata manufactuaring co.,ltd. - 5cf938 apple, inc - 5cf9dd dell inc + 5cf7c3 syntech (hk) technology limited + 5cf7e6 apple, inc. + 5cf821 texas instruments + 5cf8a1 murata manufacturing co., ltd. + 5cf938 apple, inc. + 5cf96a huawei technologies co.,ltd + 5cf9dd dell inc. + 5cf9f0 atomos engineering p/l + 5cf9fd taicang t&w electronics + 5cfafb acubit + 5cfb3a chongqing fugui electronics co.,ltd. + 5cfb7c shenzhen jingxun software telecommunication technology co.,ltd + 5cfc66 cisco systems, inc + 5cfe9e wiwynn corporation tainan branch 5cff35 wistron corporation 5cffff shenzhen kezhonglong optoelectronic technology co., ltd - 6002b4 wistron neweb corp. - 600308 apple + 600194 espressif inc. + 600292 pegatron corporation + 6002b4 wistron neweb corporation + 600308 apple, inc. 600347 billion electric co. ltd. + 6003a6 inteno broadband technology ab + 600417 posbank co.,ltd + 60058a hitachi metals, ltd. + 60077c jala group + 600810 huawei technologies co.,ltd + 600837 ivvi scientific(nanchang)co.ltd + 6009c3 u-blox ag + 600b03 hangzhou h3c technologies co., limited 600f77 silverplus, inc + 6010a2 crompton instruments 601199 siama systems inc - 601283 soluciones tecnologicas para la salud y el bienestar sa + 60123c huawei technologies co.,ltd + 601283 tsb real time location systems s.l. + 60128b canon inc. + 601466 zte corporation + 6014b3 cybertan technology inc. + 601592 ieee registration authority 6015c7 idatech + 601803 daikin air-conditioning (shanghai) co., ltd. + 60182e shenzhen protruly electronic ltd co. + 601888 zte corporation + 601895 dell inc. 60190c rramac 601929 voltronic power technology(shenzhen) corp. + 601970 huizhou qiaoxing electronics technology co., ltd. + 601971 arris group, inc. 601d0f midnite solar + 601d91 motorola mobility llc, a lenovo company + 601d9d sichuan ai-link technology co., ltd. 601e02 eltexalatau - 602103 stcube.inc - 6021c0 murata manufactuaring co.,ltd. + 602101 guangdong oppo mobile telecommunications corp.,ltd + 602103 i4vine, inc + 6021c0 murata manufacturing co., ltd. + 6023a4 sichuan ai-link technology co., ltd. 6024c1 jiangsu zhongxun electronic technology co., ltd + 60271c videor e. hartig gmbh + 6029d5 davolink inc. 602a54 cardiotek b.v. 602ad0 cisco spvtg + 602e20 huawei technologies co.,ltd + 6030d4 apple, inc. + 60313b sunnovo international limited + 603197 zyxel communications corporation + 6032b1 tp-link technologies co.,ltd. 6032f0 mplus technology - 60334b apple + 60334b apple, inc. 603553 buwon technology + 603573 earda technologies co ltd + 6035c0 sfr + 603696 the sapling company 6036dd intel corporate - 60380e alps electric co., + 60380e alpsalpine co,.ltd + 6038e0 belkin international inc. 60391f abb ltd + 603a7c tp-link technologies co.,ltd. + 603cee lg electronics (mobile communications) + 603d26 technicolor ch usa inc. + 603e7b gafachi, inc. + 603eca cambridge medical robotics ltd 603fc5 cox co., ltd + 60427f shenzhen chuangwei-rgb electronics co.,ltd + 60447a water-i.d. gmbh 6044f5 easy digital ltd. 60455e liptel s.r.o. 6045bd microsoft + 6045cb asustek computer inc. 604616 xiamen vann intelligent co., ltd + 604762 beijing sensoro technology co.,ltd. 6047d4 forics electronic technology co., ltd. + 604826 newbridge technologies int. ltd. + 6049c1 avaya inc 604a1c suyin corporation - 6052d0 facts engineering + 604baa magic leap, inc. + 6050c1 kinetek sports + 60512c tct mobile ltd + 6052d0 facts engineering + 605317 sandstone technologies 605464 eyedro green solutions inc. + 6055f9 espressif inc. + 605661 ixecloud tech 605718 intel corporate + 60577d eero inc. + 605bb4 azurewave technology inc. + 605e4f huawei device co., ltd. + 605f8d eero inc. 60601f sz dji technology co.,ltd + 6061df z-meta research llc + 60634c d-link international + 6063f9 ciholas, inc. 6063fd transcend communication beijing co.,ltd. + 606405 texas instruments + 606453 aod co.,ltd. 6064a1 radiflow ltd. 606720 intel corporate - 606944 apple, inc + 60684e samsung electronics co.,ltd + 606944 apple, inc. 60699b isepos gmbh - 606bbd samsung electronics co., ltd + 606bbd samsung electronics co.,ltd + 606bff nintendo co.,ltd + 606c63 hitron technologies. inc 606c66 intel corporate - 60735c cisco + 606d3c luxshare precision industry company limited + 606dc7 hon hai precision ind. co.,ltd. + 606ed0 seal ag + 607072 shenzhen hongde smart link technology co., ltd + 6070c0 apple, inc. + 60720b blu products inc + 60735c cisco systems, inc + 6073bc zte corporation 60748d atmaca elektronik 607688 velodyne - 60812b custom control concepts + 607771 texas instruments + 6077e2 samsung electronics co.,ltd + 607ea4 shanghai imilab technology co.ltd + 607ec9 apple, inc. + 607ecd huawei technologies co.,ltd + 607edd microsoft mobile oy + 60812b astronics custom control concepts + 6081f9 helium systems, inc + 608334 huawei technologies co.,ltd + 608373 apple, inc. 6083b2 gkware e.k. 60843b soladigm, inc. + 6084bd buffalo.inc 608645 avery weigh-tronix, llc 60893c thermo fisher scientific p.o.a. 6089b1 key digital systems 6089b7 kael mÜhendİslİk elektronİk tİcaret sanayİ lİmİted Şİrketİ + 608b0e apple, inc. 608c2b hanson technology + 608c4a apple, inc. + 608cdf private + 608ce6 arris group, inc. 608d17 sentrus government systems division, inc + 608d26 arcadyan corporation + 608e08 samsung electronics co.,ltd + 608f5c samsung electronics co.,ltd 609084 dssd inc - 609217 apple - 609620 + 6091f3 vivo mobile communication co., ltd. + 609217 apple, inc. + 6092f5 arris group, inc. + 6095ce ieee registration authority + 609620 private + 6097dd microsys electronics gmbh + 609813 shanghai visking digital technology co. ltd + 609866 texas instruments + 6099d1 vuzix / lenovo 609aa4 gvi security inc. + 609ac1 apple, inc. + 609b2d jmacs japan co., ltd. + 609bc8 hipad intelligent technology co., ltd. + 609c9f brocade communications systems llc 609e64 vivonic gmbh 609f9d cloudswitch 60a10a samsung electronics co.,ltd + 60a11e wuhan maxsine electric co.,ltd. + 60a37d apple, inc. + 60a423 silicon laboratories 60a44c asustek computer inc. + 60a4b7 tp-link corporation limited + 60a4d0 samsung electronics co.,ltd + 60a730 shenzhen yipinfang internet technology co.,ltd + 60a751 huawei device co., ltd. + 60a8fe nokia solutions and networks gmbh & co. kg 60a9b0 merchandising technologies, inc + 60aaef huawei device co., ltd. + 60ab14 lg innotek + 60ab67 xiaomi communications co ltd + 60abd2 bose corporation + 60acc8 kunteng inc. + 60af6d samsung electronics co.,ltd 60b185 ath system + 60b387 synergics technologies gmbh 60b3c4 elber srl + 60b4f7 plume design inc 60b606 phorus - 60b617 fiberhome telecommunication tech.co.,ltd. + 60b617 fiberhome telecommunication technologies co.,ltd + 60b76e google, inc. 60b933 deutron electronics corp. 60b982 ro.ve.r. laboratories s.p.a. + 60ba18 nextlap gmbh 60bb0c beijing huaqinworld technology co,ltd 60bc4c ewm hightec welding gmbh 60bd91 move innovation - 60beb5 motorola mobility llc + 60beb5 motorola mobility llc, a lenovo company + 60bec4 apple, inc. + 60c0bf on semiconductor + 60c1cb fujian great power plc equipment co.,ltd 60c397 2wire inc - 60c547 apple + 60c547 apple, inc. 60c5a8 beijing lt honway technology co.,ltd + 60c5ad samsung electronics co.,ltd + 60c5e6 skullcandy + 60c658 phytronix co.,ltd. + 60c798 verifone 60c980 trymus 60cbfb airscape inc. + 60cda9 abloomy 60cdc5 taiwan carol electronics., ltd + 60ce86 sercomm corporation. + 60ce92 the refined industry company limited + 60d02c ruckus wireless 60d0a9 samsung electronics co.,ltd 60d1aa vishal telecommunications pvt ltd + 60d21c sunnovo international limited + 60d248 arris group, inc. + 60d262 tzukuri pty ltd 60d2b9 realand bio co., ltd. + 60d2dd shenzhen baitong putian technology co.,ltd. 60d30a quatius limited + 60d4e9 guangdong oppo mobile telecommunications corp.,ltd + 60d755 huawei technologies co.,ltd + 60d7e3 ieee registration authority 60d819 hon hai precision ind. co.,ltd. - 60d9c7 apple + 60d89c hmd global oy + 60d9a0 lenovo mobile communication technology ltd. + 60d9c7 apple, inc. 60da23 estech co.,ltd + 60da83 hangzhou h3c technologies co., limited 60db2a hns + 60db98 calix inc. + 60de35 gitsn, inc. 60de44 huawei technologies co.,ltd + 60def3 huawei technologies co.,ltd 60e00e shinsei electronics co ltd 60e327 tp-link technologies co.,ltd. + 60e3ac lg electronics (mobile communications) + 60e6bc sino-telecom technology co.,ltd. + 60e701 huawei technologies co.,ltd + 60e78a unisem 60e956 ayla networks, inc + 60eb5a asterfusion data technologies co.,ltd 60eb69 quanta computer inc. + 60ee5c shenzhen fast technologies co.,ltd + 60efc6 shenzhen chima technologies co limited 60f13d jablocom s.r.o. + 60f189 murata manufacturing co., ltd. + 60f18a huawei technologies co.,ltd + 60f262 intel corporate 60f281 tranwo technology co., ltd. 60f2ef visionvera international co., ltd. 60f3da logic way gmbh + 60f43a edifier international + 60f445 apple, inc. 60f494 hon hai precision ind. co.,ltd. 60f59c cru-dataport 60f673 terumo corporation - 60facd apple - 60fb42 apple + 60f677 intel corporate + 60f81d apple, inc. + 60fa9d huawei technologies co.,ltd + 60facd apple, inc. + 60fb42 apple, inc. + 60fd56 woorisystems co., ltd 60fe1e china palms telecom.ltd - 60fe20 2 wire - 60fec5 apple + 60fe20 2wire inc + 60fec5 apple, inc. 60fef9 thomas & betts 60ffdd c.e. electronics, inc - 6400f1 cisco systems, inc. + 64002d powerlinq co., ltd + 64006a dell inc. + 6400f1 cisco systems, inc + 6402cb arris group, inc. + 64037f samsung electronics co.,ltd 6405be new light led + 6405e4 alpsalpine co .,ltd + 6405e9 shenzhen wayos technology crop., ltd. + 6407f6 samsung electronics co.,ltd 64094c beijing superbee wireless technology co.,ltd + 640980 xiaomi communications co ltd + 6409ac tct mobile ltd 640b4a digital telecom technology limited + 640bd7 apple, inc. + 640d22 lg electronics (mobile communications) + 640dce shenzhen mercury communication technologies co.,ltd. + 640de6 petra systems 640e36 taztag 640e94 pluribus networks, inc. - 640f28 2wire + 640f28 2wire inc 641084 hexium technical development co., ltd. - 64168d cisco systems, inc. - 6416f0 shehzhen huawei communication technologies co., ltd. - 641a22 heliospectra/woodhill investments + 641225 cisco systems, inc + 641236 technicolor ch usa inc. + 641269 arris group, inc. + 641331 bosch car multimedia (wuhu) co. ltd. + 64136c zte corporation + 6413ab huawei technologies co.,ltd + 641666 nest labs inc. + 64167f polycom + 64168d cisco systems, inc + 6416f0 huawei technologies co.,ltd + 641759 intellivision holdings, llc + 641a22 heliospectra ab 641c67 digibras industria do brasils/a + 641cae samsung electronics co.,ltd + 641cb0 samsung electronics co.,ltd 641e81 dowslake microsystems - 64200c apple + 64200c apple, inc. + 64209f tilgin ab + 6420e0 t3 technology co., ltd. 642184 nippon denki kagaku co.,ltd 642216 shandong taixin electronic co.,ltd + 642315 huawei device co., ltd. 642400 xorcom ltd. + 64255e observint technologies, inc. + 642656 shenzhen fanweitai technology service co.,ltd 642737 hon hai precision ind. co.,ltd. + 642753 huawei device co., ltd. + 6429ed ao pkk milandr + 642b8a all best industrial co., ltd. + 642c0f vivo mobile communication co., ltd. + 642cac huawei technologies co.,ltd 642db7 seungil electronics - 643150 hewlett-packard company + 643139 ieee registration authority + 643150 hewlett packard 64317e dexin corporation + 6432a8 intel corporate + 6433db texas instruments 643409 bitwave pte ltd + 64351c e-con systems india pvt ltd + 643ab1 sichuan tianyi comheart telecomco.,ltd + 643aea cisco systems, inc + 643e8c huawei technologies co.,ltd 643f5f exablaze 644214 swisscom energy solutions ag 644346 guangdong quick network computer co.,ltd + 6447e0 feitian technologies co., ltd 644bc3 shanghai woasis telecommunications ltd., co. 644bf0 caldigit, inc + 644c36 intel corporate 644d70 dspace gmbh + 644f42 jetter co., ltd. 644f74 lenus co., ltd. + 644fb0 hyunjin.com + 645106 hewlett packard 64517e long ben (dongguan) electronic technology co.,ltd. 645299 the chamberlain group, inc 64535d frauscher sensortechnik @@ -15190,1544 +19387,4051 @@ exit 645563 intelight inc. 64557f nsfocus information technology co., ltd. 6455b1 arris group, inc. - 645601 tp-link technologies co.,ltd + 645601 tp-link technologies co.,ltd. + 6458ad china mobile iot company limited + 6459f8 vodafone omnitel b.v. 645a04 chicony electronics co., ltd. - 645dd7 shenzhen lifesense medical electronics co., ltd. + 645aed apple, inc. + 645cf3 parantek inc. + 645d86 intel corporate + 645d92 sichuan tianyi comheart telecomco.,ltd + 645dd7 shenzhen lifesense medical electronics co., ltd. + 645e10 huawei technologies co.,ltd + 645e2c iray technology co., ltd. 645ebe yahoo! japan 645fff nicolet neuro + 646038 hirschmann automation and control gmbh + 646184 velux 646223 cellient co., ltd. + 646266 ieee registration authority + 64628a evon gmbh + 64644a beijing xiaomi mobile software co., ltd + 64649b juniper networks 6465c0 nuvon, inc - 6466b3 tp-link technologies co., ltd. + 646624 sagemcom broadband sas + 6466b3 tp-link technologies co.,ltd. 646707 beijing omnific technology, ltd. - 64680c comtrend + 64680c comtrend corporation + 64694e texas instruments 6469bc hytera communications co .,ltd + 646a52 avaya inc + 646a74 auth-servers, llc + 646c80 chongqing fugui electronics co.,ltd. + 646cb2 samsung electronics co.,ltd + 646d6c huawei technologies co.,ltd + 646e69 liteon technology corporation 646e6c radio datacom llc + 646e97 tp-link technologies co.,ltd. + 646ee0 intel corporate 646eea iskratel d.o.o. - 647002 tp-link technologies co., ltd. + 647002 tp-link technologies co.,ltd. + 647033 apple, inc. 6472d8 goowi technology co.,limited + 647366 shenzhen siera technology ltd 6473e2 arbiter systems, inc. + 6474f6 shooter detection systems 647657 innovative security designs - 6476ba apple + 6476ba apple, inc. + 64777d hitron technologies. inc 647791 samsung electronics co.,ltd + 647924 huawei device co., ltd. + 6479a7 phison electronics corp. + 6479f0 intel corporate + 647bce samsung electronics co.,ltd 647bd4 texas instruments - 647c34 ubee interactive corp. + 647c34 ubee interactive co., limited 647d81 yokota industrial co,.ltd 647fda tektelic communications inc. 64808b vg controls, inc. 648099 intel corporate 648125 alphatron marine bv 648788 juniper networks - 6487d7 pirelli tyre s.p.a. + 6487d7 adb broadband italia 6488ff sichuan changhong electric ltd. + 64899a lg electronics (mobile communications) + 6489f1 samsung electronics co.,ltd 648d9e ivt electronic co.,ltd - 64995d lge + 6490c1 beijing xiaomi mobile software co., ltd + 64956c lg electronics + 649714 eero inc. + 649829 integrated device technology (malaysia) sdn. bhd. + 64995d lge 649968 elentec 6499a0 ag elektronik ab + 649a08 shenzhen superelectron technology co.,ltd + 649a12 p2 mobile technologies limited + 649abe apple, inc. 649b24 v technology co., ltd. - 649c81 qualcomm iskoot, inc. + 649c81 qualcomm inc. 649c8e texas instruments - 649ef3 cisco systems, inc. + 649d99 fs com inc + 649ef3 cisco systems, inc 649ff7 kone oyj - 64a0e7 cisco systems, inc. + 64a0e7 cisco systems, inc + 64a198 huawei device co., ltd. + 64a200 xiaomi communications co ltd 64a232 ooo samlight + 64a28a huawei device co., ltd. + 64a2f9 oneplus technology (shenzhen) co., ltd 64a341 wonderlan (beijing) technology co., ltd. - 64a3cb apple + 64a3cb apple, inc. + 64a5c3 apple, inc. + 64a651 huawei technologies co.,ltd + 64a68f zhongshan readboy electronics co.,ltd 64a769 htc corporation + 64a7dd avaya inc 64a837 juni korea co., ltd - 64ae0c cisco systems, inc. + 64a965 linkflow co., ltd. + 64ae0c cisco systems, inc 64ae88 polytec gmbh + 64aef1 qingdao hisense electronics co.,ltd. + 64b0a6 apple, inc. + 64b0e8 huawei device co., ltd. + 64b21d chengdu phycom tech co., ltd. 64b310 samsung electronics co.,ltd - 64b370 powercomm solutons llc + 64b370 powercomm solutions llc + 64b473 xiaomi communications co ltd + 64b5c6 nintendo co.,ltd + 64b623 ccs care communication solutions gmbh 64b64a vivotech, inc. - 64b9e8 apple + 64b853 samsung electronics co.,ltd + 64b9e8 apple, inc. 64babd sdj technologies, inc. + 64bc0c lg electronics (mobile communications) 64bc11 combiq ab + 64bc58 intel corporate + 64c2de lg electronics (mobile communications) + 64c354 avaya inc + 64c3d6 juniper networks 64c5aa south african broadcasting corporation 64c667 barnes&noble 64c6af axerra networks ltd + 64c753 apple, inc. + 64c901 inventec corporation 64c944 lark technologies, inc + 64cb5d sia teleset + 64cb9f tecno mobile limited + 64cba3 pointmobile + 64cc22 arcadyan corporation + 64cc2e xiaomi communications co ltd + 64ce6e sierra wireless + 64cfd9 texas instruments 64d02d next generation integration (ngi) + 64d154 routerboard.com 64d1a3 sitecom europe bv 64d241 keith & koep gmbh - 64d4bd alps electric co.,ltd. + 64d2c4 apple, inc. + 64d4bd alpsalpine co,.ltd 64d4da intel corporate - 64d814 cisco systems, inc. + 64d7c0 huawei device co., ltd. + 64d814 cisco systems, inc 64d912 solidica, inc. - 64d989 cisco systems, inc. + 64d954 taicang t&w electronics + 64d989 cisco systems, inc + 64daa0 robert bosch smart home gmbh 64db18 openpattern + 64db43 motorola (wuhan) mobility technologies communication co., ltd. + 64db81 syszone co., ltd. + 64db8b hangzhou hikvision digital technology co.,ltd. + 64dba0 select comfort 64dc01 static systems group plc + 64dde9 xiaomi communications co ltd 64de1c kingnetic pte ltd + 64df10 jinglue semiconductor(sh) ltd. + 64dfe9 ateme + 64e003 hui zhou gaoshengda technology co.,ltd + 64e0ab unionman technology co.,ltd 64e161 dep corp. + 64e172 shenzhen qihoo intelligent technology co.,ltd 64e599 efm networks 64e625 woxu wireless co., ltd - 64e682 apple + 64e682 apple, inc. + 64e7d8 samsung electronics co.,ltd 64e84f serialway communication technology co. ltd + 64e881 aruba, a hewlett packard enterprise company 64e892 morio denki co., ltd. 64e8e6 global moisture management system - 64e950 cisco + 64e950 cisco systems, inc + 64eac5 sibotech automation co., ltd. 64eb8c seiko epson corporation 64ed57 arris group, inc. 64ed62 woori systems co., ltd + 64eeb7 netcore technology inc 64f242 gerdes aktiengesellschaft + 64f2fb hangzhou ezviz software co.,ltd. 64f50e kinion technology company limited + 64f54e em microelectronic + 64f69d cisco systems, inc + 64f6bb fibocom wireless inc. + 64f6f7 anhui dynamic power co., ltd. + 64f81c huawei technologies co., ltd. + 64f88a china mobile iot company limited + 64f947 senscomm semiconductor co., ltd. 64f970 kenade electronics technology co.,ltd. 64f987 avvasi inc. + 64f9c0 analog devices + 64fb50 roomready/zdi, inc. + 64fb81 ieee registration authority + 64fb92 ppc broadband inc. 64fc8c zonar systems + 64ff0a wistron neweb corporation + 680235 konten networks inc. + 6802b8 compal broadband networks, inc. + 680571 samsung electronics co.,ltd 6805ca intel corporate - 680927 apple + 68070a tpvision europe b.v + 680715 intel corporate + 680927 apple, inc. 680ad7 yancheng kecheng optoelectronic technology co., ltd + 680ae2 silicon laboratories 68122d special instrument development co., ltd. - 681590 sagemcom sas + 681295 lupine lighting systems gmbh + 681324 huawei device co., ltd. + 681401 hon hai precision ind. co.,ltd. + 681590 sagemcom broadband sas 6815d3 zaklady elektroniki i mechaniki precyzyjnej r&g s.a. 681605 systems and electronic development fzco 681729 intel corporate 68193f digital airways + 6819ac guangzhou xianyou intelligent technogoly co., ltd 681ab2 zte corporation 681ca2 rosewill inc. 681d64 sunwave communications co., ltd + 681def shenzhen cyx technology co., ltd. 681e8b infosight corporation - 681fd8 advanced telemetry + 681f40 blu wireless technology ltd + 681fd8 siemens industry, inc. + 68215f edgecore networks corporation 68234b nihon dengyo kousaku + 68262a sichuan tianyi comheart telecomco., ltd + 682719 microchip technology inc. + 682737 samsung electronics co.,ltd 6828ba dejai + 6828f6 vubiq networks, inc. + 6829dc ficosa electronics s.l.u. + 682c7b cisco systems, inc + 682d83 shenzhen dinghe communication company 682ddc wuhan changjiang electro-communication equipment co.,ltd + 682f67 apple, inc. + 6831fe teladin co.,ltd. + 68332c kenstel networks limited + 683489 lea professional + 683563 shenzhen liown electronics co.,ltd. + 6836b5 drivescale, inc. + 6837e9 amazon technologies inc. + 683943 ittim + 683a1e cisco meraki 683b1e countwise ltd + 683b78 cisco systems, inc + 683c7d magic intelligence technology limited + 683e02 siemens ag, digital factory, motion control system + 683e26 intel corporate + 683e34 meizu technology co., ltd. 683eec ereca + 683f1e effect photonics b.v. + 683f7d ingram micro services 684352 bhuu limited + 6843d7 agilecom photonics solutions guangdong limited + 684571 huawei device co., ltd. + 6845f1 toshiba client solutions co., ltd. + 684749 texas instruments 684898 samsung electronics co.,ltd + 6849b2 carlo gavazzi ltd + 684a76 eero inc. + 684aae huawei technologies co.,ltd 684b88 galtronics telemetry inc. 684ca8 shenzhen herotel tech. co., ltd. + 684f64 dell inc. 6851b7 powercloud systems, inc. - 6854ed alcatel-lucent - nuage + 6852d6 ugame technology co.,ltd + 68536c spns co.,ltd + 685388 p&s technology + 68545a intel corporate + 6854c1 colortokens, inc. + 6854ed alcatel-lucent 6854f5 enlighted inc + 6854fd amazon technologies inc. + 68572d tuya smart inc. + 6858c5 zf trw automotive 68597f alcatel lucent - 685b35 apple + 685acf samsung electronics co.,ltd + 685b35 apple, inc. 685b36 powertech industrial co., ltd. 685d43 intel corporate 685e6b powerray co., ltd. + 686350 hella india automotive pvt ltd 686359 advanced digital broadcast sa + 68644b apple, inc. 68692e zycoo co.,ltd + 686975 angler labs inc + 6869ca hitachi, ltd. 6869f2 comap s.r.o. + 686dbc hangzhou hikvision digital technology co.,ltd. 686e23 wi3 inc. - 687251 ubiquiti networks - 68764f sony mobile communications ab + 686e48 prophet electronic technology corp.,ltd + 687251 ubiquiti networks inc. + 6872c3 samsung electronics co.,ltd + 6872dc cetory.tv company limited + 687627 zhuhai dingzhi electronic technology co., ltd + 68764f sony mobile communications inc 687848 westunitis co., ltd. 68784c nortel networks + 687912 ieee registration authority 687924 els-gmbh & co. kg 6879ed sharp corporation 687cc8 measurement systems s. de r.l. 687cd5 y soft corporation, a.s. + 687d6b samsung electronics co.,ltd + 687db4 cisco systems, inc 687f74 cisco-linksys, llc + 6882f2 grandcentrix gmbh 68831a pandora mobility corporation 688470 essys co.,ltd + 68847e fujitsu limited 688540 igi mobile, inc. 68856a outerlink corporation - 6886a7 cisco + 6886a7 cisco systems, inc 6886e7 orbotix, inc. 68876b inq mobile limited + 6888a1 universal electronics, inc. + 688975 nuoxc + 6889c1 huawei technologies co.,ltd 688ab5 edp servicos + 688af0 zte corporation + 688b0f china mobile iot company limited + 688db6 aetek inc. + 688f2e hitron technologies. inc + 688f84 huawei technologies co.,ltd + 688fc9 zhuolian (shenzhen) communication co., ltd + 6891d0 ieee registration authority 689234 ruckus wireless + 689320 new h3c technologies co., ltd + 689361 integrated device technology (malaysia) sdn. bhd. 689423 hon hai precision ind. co.,ltd. - 68967b apple + 68967b apple, inc. 68974b shenzhen costar electronics co. ltd. 6897e8 society of motion picture & television engineers + 689861 beacon inc + 6899cd cisco systems, inc + 689a87 amazon technologies inc. + 689ab7 atelier vision corporation 689c5e acsip technology corp. - 689c70 apple + 689c70 apple, inc. + 689ce2 cisco systems, inc + 689e0b cisco systems, inc + 689e19 texas instruments + 689e6a huawei device co., ltd. + 689ff0 zte corporation + 68a03e huawei technologies co.,ltd + 68a0f6 huawei technologies co.,ltd 68a1b7 honghao mingchuan technology (beijing) co.,ltd. + 68a378 freebox sas 68a3c4 liteon technology corporation - 68a40e bsh bosch and siemens home appliances gmbh - 68a86d apple + 68a40e bsh hausgeräte gmbh + 68a47d sun cupid technology (hk) ltd + 68a682 shenzhen youhua technology co., ltd + 68a828 huawei technologies co.,ltd + 68a86d apple, inc. + 68a8e1 wacom co.,ltd. 68aad2 datecs ltd., + 68ab09 nokia + 68ab1e apple, inc. 68ab8a rf ideas + 68abbc beijing xiaomi mobile software co., ltd + 68ae20 apple, inc. 68af13 futura mobility + 68afff shanghai cambricon information technology co., ltd. 68b094 inesa electron co.,ltd + 68b35e shenzhen neostra technology co.ltd 68b43a waterfurnace international, inc. - 68b599 hewlett-packard company + 68b599 hewlett packard 68b6fc hitron technologies. inc 68b8d9 act kde, inc. - 68bc0c cisco systems, inc. - 68bdab cisco systems, inc. + 68b983 b-plus gmbh + 68b9d3 shenzhen trolink technology co, ltd + 68bc0c cisco systems, inc + 68bdab cisco systems, inc + 68bfc4 samsung electronics co.,ltd + 68c44d motorola mobility llc, a lenovo company + 68c63a espressif inc. + 68c90b texas instruments 68ca00 octopus systems limited + 68cae4 cisco systems, inc + 68cc6e huawei technologies co.,ltd 68cc9c mine site technologies 68cd0f u tek company limited 68ce4e l-3 communications infrared products + 68d1ba shenzhen youhua technology co., ltd 68d1fd shenzhen trimax technology co.,ltd 68d247 portalis lc + 68d482 shenzhen gongjin electronics co.,lt + 68d48b hailo technologies ltd. + 68d6ed goowi wireless technology co., limited + 68d79a ubiquiti networks inc. 68d925 prosys development services - 68db67 nantong coship electronics co., ltd + 68d93c apple, inc. + 68db54 phicomm (shanghai) co., ltd. + 68db67 nantong coship electronics co., ltd. 68db96 opwill technologies co .,ltd + 68dbca apple, inc. + 68dbf5 amazon technologies inc. 68dce8 packetstorm communications - 68dfdd xiaomi inc. - 68e166 + 68dd26 shanghai focus vision security technology co.,ltd + 68dfdd xiaomi communications co ltd + 68e166 private + 68e209 huawei technologies co.,ltd 68e41f unglaube identech gmbh + 68e7c2 samsung electronics co.,ltd + 68e8eb linktel technologies co.,ltd 68ebae samsung electronics co.,ltd 68ebc5 angstrem telecom 68ec62 yodo technology corp. ltd. - 68ed43 research in motion + 68ecc5 intel corporate + 68ed43 blackberry rts + 68eda4 shenzhen seavo technology co.,ltd 68ee96 cisco spvtg - 68efbd cisco systems, inc. + 68ef43 apple, inc. + 68efbd cisco systems, inc + 68f06d along industrial co., limited + 68f0bc shenzhen liwifi technology co., ltd 68f125 data controls inc. + 68f728 lcfc(hefei) electronics technology co., ltd 68f895 redflow limited + 68f956 objetivos y servicio de valor añadido + 68fb7e apple, inc. 68fb95 generalplus technology inc. 68fcb3 next level security systems, inc. + 68feda fiberhome telecommunication technologies co.,ltd + 68fef7 apple, inc. + 68ff7b tp-link technologies co.,ltd. + 6c006b samsung electronics co.,ltd + 6c0273 shenzhen jin yun video equipment co., ltd. + 6c02e0 hp inc. + 6c0309 cisco systems, inc 6c0460 rbh access technologies inc. + 6c05d5 ethertronics inc + 6c06d6 huawei device co., ltd. + 6c090a gematica srl + 6c09bf fiberhome telecommunication technologies co.,ltd 6c09d6 digiquest electronics ltd - 6c0e0d sony ericsson mobile communications ab + 6c0b84 universal global scientific industrial co., ltd. + 6c0d34 nokia + 6c0dc4 beijing xiaomi electronics co., ltd. + 6c0de1 dongguan cannice precision manufacturing co., ltd. + 6c0e0d sony mobile communications inc + 6c0ee6 chengdu xiyida electronic technology co,.ltd 6c0f6a jdc tech co., ltd. + 6c13d5 cisco systems, inc + 6c1414 bujeon electronics co,.ltd + 6c146e huawei technologies co.,ltd 6c14f7 erhardt+leimer gmbh 6c15f9 nautronix limited + 6c160e shottracker + 6c1632 huawei technologies co.,ltd 6c1811 decatur electronics - 6c2056 cisco + 6c198f d-link international + 6c19c0 apple, inc. + 6c1a75 huawei device co., ltd. + 6c1b3f miraesignal co., ltd + 6c1c71 zhejiang dahua technology co., ltd. + 6c1deb u-blox ag + 6c1e70 guangzhou ybds it co.,ltd + 6c1e90 hansol technics co., ltd. + 6c1ed7 vivo mobile communication co., ltd. + 6c2056 cisco systems, inc + 6c21a2 ampak technology, inc. 6c22ab ainsworth game technology - 6c23b9 sony ericsson mobile communications ab + 6c23b9 sony mobile communications inc + 6c23cb wattty corporation + 6c2483 microsoft mobile oy + 6c24a6 vivo mobile communication co., ltd. + 6c25b9 bbk educational electronics corp.,ltd. + 6c2636 huawei technologies co.,ltd + 6c2779 microsoft mobile oy + 6c2990 wiz connected lighting company limited 6c2995 intel corporate + 6c2acb paxton access ltd + 6c2b59 dell inc. 6c2c06 ooo npp systemotechnika-nn + 6c2cdc skyworth digital technology(shenzhen) co.,ltd + 6c2d24 zhen shi information technology (shanghai) co., ltd. 6c2e33 accelink technologies co.,ltd. - 6c2e85 sagemcom + 6c2e72 b&b exporting limited + 6c2e85 sagemcom broadband sas + 6c2f2c samsung electronics co.,ltd + 6c2f8a samsung electronics co.,ltd + 6c310e cisco systems, inc 6c32de indieon technologies pvt. ltd. 6c33a9 magicjack lp + 6c3491 huawei technologies co.,ltd + 6c3838 marking system technology co., ltd. + 6c3845 fiberhome telecommunication technologies co.,ltd + 6c38a1 ubee interactive co., limited 6c391d beijing zhonghuahun network information center 6c3a84 shenzhen aero-startech. co.ltd + 6c3b6b routerboard.com 6c3be5 hewlett packard 6c3c53 soundhawk corp - 6c3e6d apple + 6c3e6d apple, inc. 6c3e9c ke knestel elektronik gmbh - 6c40c6 nimbus data systems, inc. - 6c416a cisco + 6c4008 apple, inc. + 6c40c6 nimbus data, inc. + 6c410e cisco systems, inc + 6c416a cisco systems, inc + 6c42ab subscriber networks, inc. + 6c4418 zappware + 6c442a huawei technologies co.,ltd + 6c4598 antex electronic corp. + 6c4760 sunitec enterprise co.,ltd + 6c49c1 o2ones co., ltd. + 6c4a39 bita + 6c4a74 aerodisk llc + 6c4a85 apple, inc. 6c4b7f vossloh-schwabe deutschland gmbh - 6c504d cisco systems, inc. + 6c4b90 liteon + 6c4d51 shenzhen ceres technology co., ltd. + 6c4d73 apple, inc. + 6c4e86 third millennium systems ltd. + 6c504d cisco systems, inc + 6c54cd lampex electronics limited + 6c55e8 technicolor ch usa inc. + 6c5640 blu products inc + 6c5697 amazon technologies inc. 6c5779 aclima, inc. + 6c5940 mercury communication technologies co.,ltd. + 6c5976 shanghai tricheer technology co.,ltd. 6c5a34 shenzhen haitianxiong electronic co., ltd. 6c5ab5 tcl technoly electronics (huizhou) co., ltd. + 6c5c14 guangdong oppo mobile telecommunications corp.,ltd + 6c5c3d ieee registration authority 6c5cde sunreports, inc. + 6c5d3a microsoft corporation 6c5d63 shenzhen rapoo technology co., ltd. + 6c5e3b cisco systems, inc 6c5e7a ubiquitous internet telecom co., ltd 6c5f1c lenovo mobile communication technology ltd. + 6c60eb zhi yuan electronics co., limited 6c6126 rinicom holdings + 6c61f4 sfr 6c626d micro-star int'l co., ltd + 6c639c arris group, inc. 6c641a penguin computing + 6c6a77 intel corporate + 6c6cd3 cisco systems, inc + 6c6d09 kyowa electronics co.,ltd. + 6c6efe core logic inc. 6c6f18 stereotaxis, inc. 6c7039 novar gmbh - 6c709f apple - 6c71d9 azurewave technologies, inc + 6c709f apple, inc. + 6c710d cisco systems, inc + 6c71bd ezelink telecom + 6c71d9 azurewave technology inc. + 6c7220 d-link international + 6c72e7 apple, inc. + 6c750d wifisong + 6c7637 huawei device co., ltd. + 6c7660 kyocera corporation 6c81fe mitsuba corporation 6c8336 samsung electronics co.,ltd 6c8366 nanjing sac power grid automation co., ltd. 6c8686 technonia 6c8814 intel corporate + 6c8aec nantong coship electronics co., ltd. 6c8b2f zte corporation + 6c8bd3 cisco systems, inc 6c8cdb otus technologies ltd 6c8d65 wireless glue networks, inc. + 6c8dc1 apple, inc. + 6c8fb5 microsoft mobile oy 6c90b1 sanlogic inc 6c92bf inspur electronic information industry co.,ltd. - 6c98eb xyne gmbh - 6c9989 cisco + 6c9354 yaojin technology (shenzhen) co., ltd. + 6c94f8 apple, inc. + 6c9522 scalys + 6c96cf apple, inc. + 6c98eb riverbed technology, inc. + 6c9961 sagemcom broadband sas + 6c9989 cisco systems, inc 6c9ac9 valentine research, inc. 6c9b02 nokia corporation + 6c9bc0 chemoptics inc. 6c9ce9 nimble storage - 6c9ced cisco systems, inc. + 6c9ced cisco systems, inc + 6c9e7c fiberhome telecommunication technologies co.,ltd + 6ca0b4 bskyb ltd + 6ca100 intel corporate + 6ca4d1 fiberhome telecommunication technologies co.,ltd + 6ca604 arris group, inc. 6ca682 edam information & communications + 6ca75f zte corporation 6ca780 nokia corporation + 6ca7fa youngbo engineering inc. + 6ca849 avaya inc + 6ca858 fiberhome telecommunication technologies co.,ltd 6ca906 telefield ltd + 6ca928 hmd global oy + 6ca936 displaylink (uk) ltd 6ca96f transpacket as 6caab3 ruckus wireless + 6cab05 cisco systems, inc + 6cab31 apple, inc. 6cab4d digital payment technologies 6cac60 venetex corp 6cad3f hubbell building automation, inc. - 6cadef kz broadband technologies, ltd. - 6cadf8 azurewave technologies, inc. + 6cadad chongqing fugui electronics co.,ltd. + 6cadef kz broadband technologies, ltd. + 6cadf8 azurewave technology inc. 6cae8b ibm corporation + 6caef6 eero inc. + 6caf15 webasto se + 6cb0ce netgear + 6cb227 sony video & sound products inc. + 6cb2ae cisco systems, inc 6cb311 shenzhen lianrui electronics co.,ltd 6cb350 anhui comhigher tech co.,ltd + 6cb4a7 landauer, inc. + 6cb56b humax co., ltd. + 6cb6ca divus gmbh + 6cb749 huawei technologies co.,ltd 6cb7f4 samsung electronics co.,ltd - 6cbee9 alcatel-lucent-ipd + 6cb881 zte corporation + 6cb9c5 delta networks, inc. + 6cbab8 sagemcom broadband sas + 6cbee9 alcatel-lucent ipd + 6cbfb5 noon technology co., ltd + 6cc147 xiamen hanin electronic technology co., ltd 6cc1d2 arris group, inc. - 6cc26b apple + 6cc217 hewlett packard + 6cc26b apple, inc. + 6cc374 texas instruments + 6cc4d5 hmd global oy + 6cc63b taicang t&w electronics + 6cc7ec samsung electro-mechanics(thailand) + 6cca08 arris group, inc. + 6ccdd6 netgear + 6cce44 1more 6cd032 lg electronics - 6cd146 smartek d.o.o. + 6cd146 framos gmbh 6cd1b0 wing sing electronics hong kong limited - 6cd68a lg electronics inc + 6cd2ba zte corporation + 6cd630 rootous system co.,ltd + 6cd68a lg electronics (mobile communications) + 6cd704 huawei technologies co.,ltd + 6cd71f guangdong oppo mobile telecommunications corp.,ltd + 6cd94c vivo mobile communication co., ltd. 6cdc6a promethean limited + 6cdd30 cisco systems, inc + 6cddbc samsung electronics co.,ltd + 6cdea9 cisco meraki + 6cdffb ieee registration authority + 6ce01e modcam ab 6ce0b0 sound4 + 6ce3b6 nera telecommunications ltd. 6ce4ce villiger security solutions ag - 6ce873 tp-link technologies co., ltd. + 6ce4da nec platforms, ltd. + 6ce5f7 new h3c technologies co., ltd + 6ce85c apple, inc. + 6ce873 tp-link technologies co.,ltd. + 6ce874 huawei technologies co.,ltd + 6ce8c6 earda technologies co ltd 6ce907 nokia corporation 6ce983 gastron co., ltd. + 6cebb2 dongguan sen donglv electronics co.,ltd + 6cebb6 huawei technologies co.,ltd + 6cec5a hon hai precision ind. co.,ltd. 6ceca1 shenzhen clou electronics co. ltd. 6ceceb texas instruments + 6ced51 nexcontrol co.,ltd + 6cefc6 shenzhen twowing technologies co.,ltd. 6cf049 giga-byte technology co.,ltd. + 6cf17e zhejiang uniview technologies co.,ltd. 6cf373 samsung electronics co.,ltd - 6cf37f aruba networks + 6cf37f aruba, a hewlett packard enterprise company + 6cf5e8 mooredoll inc. + 6cf712 nokia solutions and networks gmbh & co. kg 6cf97c nanoptix inc. - 6cfa58 avaya, inc - 6cfaa7 ampak technology inc. + 6cf9d2 chengdu povodo electronic technology co., ltd + 6cfa58 avaya inc + 6cfa89 cisco systems, inc + 6cfaa7 ampak technology, inc. 6cfdb9 proware technologies co ltd. + 6cfe54 intel corporate 6cffbe mpb communications inc. + 700136 fatek automation corporation + 7001b5 cisco systems, inc 700258 01db-metravib - 700514 lg electronics + 70037e technicolor ch usa inc. + 70039f espressif inc. + 700433 california things inc. + 700514 lg electronics (mobile communications) + 7006ac eastcompeace technology co., ltd + 700b01 sagemcom broadband sas + 700b4f cisco systems, inc 700bc0 dewav technology company + 700f6a cisco systems, inc + 700fc7 shenzhen ikinloop technology co.,ltd. 700fec poindus systems corp. - 70105c cisco - 701124 apple + 70105c cisco systems, inc + 70106f hewlett packard enterprise + 701124 apple, inc. + 7011ae music life ltd 701404 limited liability company + 7014a6 apple, inc. + 70169f ethercat technology group 70188b hon hai precision ind. co.,ltd. - 701a04 liteon tech corp. + 7018a7 cisco systems, inc + 70192f huawei technologies co.,ltd + 701a04 liteon technology corporation 701aed advas co., ltd. + 701bfb integrated device technology (malaysia) sdn. bhd. + 701ce7 intel corporate + 701d08 99iot shenzhen co.,ltd 701d7f comtech technology co., ltd. + 701dc4 northstar battery company, llc + 701e68 hanna instruments, inc. + 701f3c samsung electronics co.,ltd + 701f53 cisco systems, inc + 702084 hon hai precision ind. co., ltd. 702393 fos4x gmbh - 702526 alcatel-lucent - 702559 cybertan technology, inc. + 702526 nokia + 702559 cybertan technology inc. + 702605 sony visual products inc. + 70288b samsung electronics co.,ltd + 702900 shenzhen chiptrip technology co,ltd + 702a7d epspot ab + 702ad5 samsung electronics co.,ltd 702b1d e-domus international limited + 702c09 nintendo co.,ltd 702c1f wisol - 702f4b polyvision inc. + 702d84 i4c innovations + 702dd1 newings communication co., ltd. + 702e22 zte corporation + 702e80 diehl connectivity solutions + 702ed9 guangzhou shiyuan electronics co., ltd. + 702f35 huawei technologies co.,ltd + 702f4b steelcase inc. 702f97 aava mobile oy - 703018 avaya, inc + 703018 avaya inc 70305d ubiquoss inc 70305e nanjing zhongke menglian information technology co.,ltd 703187 acx gmbh 7032d5 athena wireless communications inc - 703811 invensys rail + 703509 cisco systems, inc + 703811 siemens mobility limited 7038b4 low tech solutions - 7038ee avaya, inc + 7038ee avaya inc + 703a0e aruba, a hewlett packard enterprise company + 703a2d shenzhen v-link technology co., ltd. + 703a51 xiaomi communications co ltd + 703a73 shenzhen sundray technologies company limited + 703aa6 new h3c technologies co., ltd + 703acb google, inc. 703ad8 shenzhen afoundry electronic co., ltd + 703c03 radiant co.,ltd 703c39 seawing kft + 703c69 apple, inc. + 703d15 hangzhou h3c technologies co., limited + 703eac apple, inc. + 7040ff huawei device co., ltd. 7041b7 edwards lifesciences llc + 70441c shenzhen kaifa technology co.,ltd. 704642 chyng hong electronic co., ltd. + 7047e9 vivo mobile communication co., ltd. + 70480f apple, inc. + 7048f7 nintendo co.,ltd + 704a0e ampak technology,inc. 704aae xstream flow (pty) ltd 704ae4 rinstrum pty ltd + 704ca5 fortinet, inc. 704ced tmrg, inc. + 704d7b asustek computer inc. 704e01 kwangwon tech co., ltd. - 7052c5 avaya, inc. + 704e66 shenzhen fast technologies co.,ltd + 704f08 shenzhen huisheng information technology co., ltd. + 704f57 tp-link technologies co.,ltd. + 704fb8 arris group, inc. + 7050af bskyb ltd + 7052c5 avaya inc 70533f alfa instrumentos eletronicos ltda. + 705425 arris group, inc. + 7054b4 vestel elektronik san ve tic. a.Ş. 7054d2 pegatron corporation 7054f5 huawei technologies co.,ltd - 705681 apple - 705812 panasonic avc networks company + 7055f8 cerebras systems inc + 705681 apple, inc. + 7057bf new h3c technologies co., ltd + 705812 panasonic corporation avc networks company + 705896 inshow technology 705957 medallion instrumentation systems 705986 ooo ttv - 705ab6 compal information (kunshan) co., ltd. + 705a0f hewlett packard + 705a9e technicolor ch usa inc. + 705aac samsung electronics co.,ltd + 705ab6 compal information (kunshan) co., ltd. + 705b2e m2communication inc. 705cad konami gaming inc + 705dcc efm networks + 705e55 realme chongqing mobiletelecommunications corp ltd 705eaa action target, inc. 7060de lavision gmbh 706173 calantec gmbh + 70617b cisco systems, inc + 7061be wistron neweb corporation + 7061ee sunwoda electronic co.,ltd 7062b8 d-link international 706417 orbis tecnologia electrica s.a. 706582 suzhou hanming technologies co., ltd. - 706f81 + 7065a3 kandao lightforge co., ltd. + 70661b sonova ag + 706655 azurewave technology inc. + 706879 saijo denki international co., ltd. + 70695a cisco systems, inc + 706979 ieee registration authority + 706bb9 cisco systems, inc + 706d15 cisco systems, inc + 706dec wifi-soft llc + 706e6d cisco systems, inc + 706f81 private + 70700d apple, inc. 70704c purple communications, inc + 70708b cisco systems, inc 7071b3 brain corporation 7071bc pegatron corporation - 70723c huawei technologies co., ltd + 70720d lenovo mobile communication technology ltd. + 70723c huawei technologies co.,ltd 7072cf edgecore networks - 7073cb apple - 707630 pace plc. - 7076dd oxyguard international a/s + 7073cb apple, inc. + 707414 murata manufacturing co., ltd. + 707630 arris group, inc. + 7076dd oxyguard internation a/s 7076f0 levelone communications (india) private limited + 7076ff kerlink + 707781 hon hai precision ind. co.,ltd. + 70788b vivo mobile communication co., ltd. + 707938 wuxi zhanrui electronic technology co.,ltd + 707990 huawei technologies co.,ltd + 7079b3 cisco systems, inc 707be8 huawei technologies co.,ltd 707c18 adata technology co., ltd + 707c69 avaya inc + 707d95 shenzhen city linwlantechnology co. ltd. + 707db9 cisco systems, inc 707e43 arris group, inc. 707ede nastec ltd. - 708105 cisco systems, inc. + 708105 cisco systems, inc + 7081eb apple, inc. 70820e as electronics gmbh 70828e oleumtech corporation - 7085c6 pace plc. + 708540 skyworth digital technology(shenzhen) co.,ltd + 7085c2 asrock incorporation + 7085c6 arris group, inc. + 7086c1 texas instruments + 70879e beken corporation + 70884d japan radio co., ltd. + 708976 tuya (hk) limietd + 7089cc china mobile group device co.,ltd. + 708a09 huawei technologies co.,ltd 708b78 citygrow technology co., ltd + 708bcd asustek computer inc. + 708cb6 huawei technologies co.,ltd + 708cbb mimodisplaykorea 708d09 nokia corporation + 708f47 vivo mobile communication co., ltd. + 7090b7 huawei device co., ltd. + 70918f weber-stephen products llc + 7091f3 universal electronics, inc. 709383 intelligent optical network high tech co.,ltd. 7093f8 space monkey, inc. 709756 happyelectronics co.,ltd + 70991c shenzhen honesty electronics co.,ltd 709a0b italian institute of technology 709ba5 shenzhen y&d electronics co.,ltd. 709bfc bryton inc. - 709e29 sony computer entertainment inc. + 709c8f nero ag + 709cd1 intel corporate + 709e29 sony interactive entertainment inc. 709e86 x6d limited + 709f2d zte corporation + 709fa9 tecno mobile limited 70a191 trendsetter medical, llc + 70a2b3 apple, inc. 70a41c advanced wireless dynamics s.l. 70a66a prox dynamics as + 70a84c monad., inc. 70a8e3 huawei technologies co.,ltd - 70aab2 research in motion + 70aab2 blackberry rts + 70acd7 shenzhen youhua technology co., ltd + 70ad54 malvern instruments ltd + 70af24 tp vision belgium nv + 70af25 nishiyama industry co.,ltd. + 70af6a shenzhen fenglian technology co., ltd. 70b035 shenzhen zowee technology co., ltd 70b08c shenou communication equipment co.,ltd - 70b14e pace plc + 70b13d samsung electronics co.,ltd + 70b14e arris group, inc. 70b265 hiltron s.r.l. - 70b3d5 ieee registration authority - please see oui36 public listing for more information. + 70b317 cisco systems, inc + 70b3d5 ieee registration authority 70b599 embedded technologies s.r.o. + 70b5e8 dell inc. + 70b7aa vivo mobile communication co., ltd. + 70b7e2 jiangsu miter technology co.,ltd. 70b921 fiberhome telecommunication technologies co.,ltd + 70baef hangzhou h3c technologies co., limited + 70bbe9 xiaomi communications co ltd + 70bc10 microsoft corporation + 70bf3e charles river laboratories + 70bf92 gn audio a/s 70c6ac bosch automotive aftermarket - 70ca9b cisco systems, inc. - 70cd60 apple + 70c76f inno s + 70c7f2 huawei technologies co.,ltd + 70c833 wirepas oy + 70c94e liteon technology corporation + 70c9c6 cisco systems, inc + 70ca4d shenzhen lnovance technology co.,ltd. + 70ca97 ruckus wireless + 70ca9b cisco systems, inc + 70cd60 apple, inc. + 70cd91 teracom telematica s.a + 70ce8c samsung electronics co.,ltd + 70cf49 intel corporate + 70d081 beijing netpower technologies inc. + 70d313 huawei technologies co.,ltd + 70d379 cisco systems, inc 70d4f2 rim 70d57e scalar corporation 70d5e7 wellcore corporation 70d6b6 metrum technologies 70d880 upos system sp. z o.o. + 70d923 vivo mobile communication co., ltd. + 70d931 cambridge industries(group) co.,ltd. + 70da9c tecsen + 70db98 cisco systems, inc 70dda1 tellabs - 70dee2 apple + 70dda8 guangdong oppo mobile telecommunications corp.,ltd + 70ddef huawei device co., ltd. + 70dee2 apple, inc. + 70def9 fai wah international (hong kong) limited + 70df2f cisco systems, inc + 70dff7 arris group, inc. 70e027 hongyu communication technology limited 70e139 3view ltd + 70e1fd flextronics 70e24c sae it-systems gmbh & co. kg - 70e284 wistron infocomm(zhongshan) corporation + 70e284 wistron infocomm (zhongshan) corporation + 70e422 cisco systems, inc + 70e56e texas instruments + 70e72c apple, inc. 70e843 beijing c&w optical communication technology co.,ltd. + 70ea1a cisco systems, inc + 70ea5a apple, inc. + 70ece4 apple, inc. 70ee50 netatmo + 70eea3 eoptolink technology inc. ltd, + 70ef00 apple, inc. + 70f087 apple, inc. + 70f088 nintendo co.,ltd + 70f096 cisco systems, inc + 70f11c shenzhen ogemray technology co.,ltd 70f176 data modul ag + 70f196 actiontec electronics, inc 70f1a1 liteon technology corporation 70f1e5 xetawave llc + 70f220 actiontec electronics, inc + 70f35a cisco systems, inc 70f395 universal global scientific industrial co., ltd. - 70f927 samsung electronics + 70f754 ampak technology,inc. + 70f82b dwnet technologies(suzhou) corporation + 70f8e7 ieee registration authority + 70f927 samsung electronics co.,ltd 70f96d hangzhou h3c technologies co., limited + 70fc8c oneaccess sa + 70fc8f freebox sas + 70fd45 huawei technologies co.,ltd + 70fd46 samsung electronics co.,ltd + 70ff5c cheerzing communication(xiamen)technology co.,ltd 70ff76 texas instruments - 740abc jsjs designs (europe) limited + 7403bd buffalo.inc + 74042b lenovo mobile communication (wuhan) company limited + 7404f0 mobiwire mobiles (ningbo) co., ltd + 7405a5 tp-link technologies co.,ltd. + 7409ac quext, llc + 740abc lightwaverf technology ltd + 740ae1 huawei device co., ltd. 740edb optowiz co., ltd + 7412b3 chongqing fugui electronics co.,ltd. + 7412bb fiberhome telecommunication technologies co.,ltd 741489 srt wireless + 741575 xiaomi communications co ltd 7415e2 tri-sen systems corporation - 7419f8 ieee registration authority - please see mam public listing for more information. - 741e93 fiberhome telecommunication tech.co.,ltd. + 741865 shanghai dareglobal technologies co.,ltd + 7419f8 ieee registration authority + 741ae0 ieee registration authority + 741bb2 apple, inc. + 741c27 itel mobile limited + 741e93 fiberhome telecommunication technologies co.,ltd + 741f4a hangzhou h3c technologies co., limited + 741f79 youngkook electronics co.,ltd + 7422bb huawei device co., ltd. + 742344 xiaomi communications co ltd 74258a hangzhou h3c technologies co., limited - 7426ac cisco + 7426ac cisco systems, inc 74273c changyang technology (nanjing) co., ltd - 7427ea elitegroup computer systems co., ltd. + 7427ea elitegroup computer systems co.,ltd. + 742857 mayfield robotics + 7429af hon hai precision ind. co.,ltd. 742b0f infinidat ltd. 742b62 fujitsu limited 742d0a norfolk elektronik ag - 742f68 azurewave technologies, inc. + 742edb perinet gmbh + 742efc directpacket research, inc, + 742f68 azurewave technology inc. 743170 arcadyan technology corporation 743256 nt-ware systemprg gmbh + 743400 mtg co., ltd. + 7434ae this is engineering inc. + 74366d vodafone italia s.p.a. 74372f tongfang shenzhen cloudcomputing technology co.,ltd + 74373b uninet co.,ltd. 743889 annax anzeigesysteme gmbh + 7438b7 canon inc. + 743a20 new h3c technologies co., ltd + 743a65 nec corporation + 743aef kaonmedia co., ltd. + 743c18 taicang t&w electronics + 743e2b ruckus wireless 743ecb gentrice tech + 7440bb hon hai precision ind. co.,ltd. + 7440be lg innotek + 74427f avm audiovisuelles marketing und computersysteme gmbh + 74428b apple, inc. 744401 netgear + 74452d huawei device co., ltd. 74458a samsung electronics co.,ltd + 7445ce cresyn 7446a0 hewlett packard + 744aa4 zte corporation 744be9 explorer hypertech co.,ltd + 744ca1 liteon technology corporation + 744d28 routerboard.com 744d79 arrive systems inc. + 74504e new h3c technologies co., ltd + 7451ba xiaomi communications co ltd 745327 commsen co., limited + 745427 shenzhen fast technologies co.,ltd + 74547d cisco spvtg 745612 arris group, inc. 745798 trumpf laser gmbh + co. kg + 7458f3 amazon technologies inc. + 745909 huawei technologies co.,ltd + 745933 danal entertainment + 745aaa huawei technologies co.,ltd + 745bc5 ieee registration authority + 745c4b gn audio a/s + 745c9f tct mobile ltd 745e1c pioneer corporation 745f00 samsung semiconductor inc. + 745f90 lam technologies 745fae tsl ppl + 7460fa huawei technologies co.,ltd + 74614b chongqing huijiatong information technology co., ltd. 7463df vts gmbh + 74650c apple, inc. 7465d1 atlinks 746630 t:mi ytti + 7467f7 extreme networks, inc. + 746a3a aperi corporation 746a89 rezolt corporation 746a8f vs vision systems gmbh - 746b82 movek + 746b82 movek + 746bab guangdong enok communication co., ltd + 746ee4 asia vital components co.,ltd. + 746f19 icarvisions (shenzhen) technology co., ltd. 746f3d contec gmbh + 746ff7 wistron neweb corporation + 7470fd intel corporate + 74721e edison labs inc. + 7472b0 guangzhou shiyuan electronics co., ltd. 7472f2 chipsip technology co., ltd. - 747818 serviceassure + 74731d ifm electronic gmbh + 747336 microdigtal inc + 747548 amazon technologies inc. + 747818 jurumani solutions + 747827 dell inc. + 747a90 murata manufacturing co., ltd. 747b7a eth inc. + 747d24 phicomm (shanghai) co., ltd. 747db6 aliwei communications, inc 747e1a red embedded design limited 747e2d beijing thomson citic digital technology co. ltd. - 74867a dell inc + 748114 apple, inc. + 74819a pt. hartono istana teknologi + 7483c2 ubiquiti networks inc. + 7483ef arista networks + 7484e1 dongguan haoyuan electronics co.,ltd + 74852a pegatron corporation + 7485c4 new h3c technologies co., ltd + 74860b cisco systems, inc + 74867a dell inc. + 7487a9 oct technology co., ltd. + 7487bb ciena corporation 74882a huawei technologies co.,ltd 74888b adb broadband italia + 7488bb cisco systems, inc + 748a0d arris group, inc. + 748a28 hmd global oy + 748a69 korea image technology co., ltd + 748b29 micobiomed + 748b34 shanghai smart system technology co., ltd + 748d08 apple, inc. 748e08 bestek corp. - 748ef8 brocade communications systems, inc. + 748ef8 brocade communications systems llc 748f1b masterimage 3d + 748f3c apple, inc. + 748f4d duagon germany gmbh + 74901f ragile networks inc. 749050 renesas electronics corporation 74911a ruckus wireless + 7491bd four systems co.,ltd. 7493a4 zebra technologies corp. 74943d agjunction + 7495ec alpsalpine co,.ltd + 749637 todaair electronic co., ltd + 749781 zte corporation 749975 ibm corporation + 749ac0 cachengo, inc. + 749be8 hitron technologies. inc 749c52 huizhou desay sv automotive co., ltd. - 749ddc 2wire + 749ce3 kodacloud canada, inc + 749d79 sercomm corporation. + 749d8f huawei technologies co.,ltd + 749ddc 2wire inc + 749ea5 ohsung + 749eaf apple, inc. + 749ef5 samsung electronics co.,ltd + 74a02f cisco systems, inc + 74a063 huawei technologies co.,ltd + 74a2e6 cisco systems, inc + 74a34a zimi corporation 74a4a7 qrs music technologies, inc. 74a4b5 powerleader science and technology co. ltd. - 74a722 lg electronics + 74a528 huawei technologies co.,ltd + 74a722 lg electronics (mobile communications) + 74a78e zte corporation + 74a7ea amazon technologies inc. + 74ab93 blink by amazon + 74ac5f qiku internet network scientific (shenzhen) co., ltd. + 74acb9 ubiquiti networks inc. + 74ad98 cisco systems, inc 74adb7 china mobile group device co.,ltd. 74ae76 inovo broadband, inc. 74b00c network video technologies, inc - 74b9eb fujian jinqianmao electronic technology co.,ltd + 74b472 ciesse + 74b57e zte corporation + 74b587 apple, inc. + 74b6b6 eero inc. + 74b7b3 shenzhen youhua technology co., ltd + 74b91e nanjing bestway automation system co., ltd + 74b9eb jinqianmao technology co.,ltd. + 74badb longconn electornics(shenzhen)co.,ltd + 74bbd3 shenzhen xeme communication co., ltd. 74be08 atek products, llc 74bfa1 hyunteck + 74bfb7 nusoft corporation + 74bfc0 canon inc. + 74c14f huawei technologies co.,ltd + 74c17d infinix mobility limited + 74c246 amazon technologies inc. + 74c330 shenzhen fast technologies co.,ltd 74c621 zhejiang hite renewable energy co.,ltd + 74c63b azurewave technology inc. + 74c929 zhejiang dahua technology co., ltd. 74c99a ericsson ab + 74c9a3 fiberhome telecommunication technologies co.,ltd 74ca25 calxeda, inc. + 74cbf3 lava international limited + 74cc39 fiberhome telecommunication technologies co.,ltd 74cd0c smith myers communications ltd. 74ce56 packet force technology limited company 74d02b asustek computer inc. 74d0dc ericsson ab + 74d21d huawei technologies co.,ltd + 74d285 texas instruments 74d435 giga-byte technology co.,ltd. + 74d637 amazon technologies inc. + 74d654 gint 74d675 wyma tecnologia + 74d6cb new h3c technologies co., ltd + 74d6ea texas instruments + 74d7ca panasonic corporation automotive + 74d83e intel corporate 74d850 evrisko systems + 74da38 edimax technology co. ltd. + 74da88 tp-link technologies co.,ltd. + 74dada d-link international + 74daea texas instruments + 74dbd1 ebay inc 74de2b liteon technology corporation + 74dfbf liteon technology corporation 74e06e ergophone gmbh - 74e1b6 apple - 74e2f5 apple + 74e14a ieee registration authority + 74e182 texas instruments + 74e19a fiberhome telecommunication technologies co.,ltd + 74e1b6 apple, inc. + 74e277 vizmonet pte ltd + 74e28c microsoft corporation + 74e2f5 apple, inc. 74e424 apiste corporation 74e50b intel corporate 74e537 radspin 74e543 liteon technology corporation + 74e5f9 intel corporate + 74e60f tecno mobile limited + 74e6e2 dell inc. 74e7c6 arris group, inc. + 74e9bf huawei technologies co.,ltd 74ea3a tp-link technologies co.,ltd. + 74eac8 new h3c technologies co., ltd + 74eacb new h3c technologies co., ltd + 74eae8 arris group, inc. + 74eb80 samsung electronics co.,ltd + 74ec42 fiberhome telecommunication technologies co.,ltd + 74ecb2 amazon technologies inc. 74ecf1 acumen - 74f06d azurewave technologies, inc. + 74ee2a shenzhen bilian electronic co.,ltd + 74f06d azurewave technology inc. 74f07d bncom co.,ltd 74f102 beijing hchcom technology co., ltd + 74f413 maxwell forest 74f612 arris group, inc. + 74f61c htc corporation + 74f661 schneider electric fire & security oy 74f726 neuron robotics + 74f737 kce + 74f7f6 shanghai sunmi technology co.,ltd. 74f85d berkeley nucleonics corp - 74fda0 compupal (group) corporation + 74f8db ieee registration authority + 74f91a onface + 74f9ca nintendo co.,ltd + 74fda0 compupal (group) corporation 74fe48 advantech co., ltd. + 74ff4c skyworth digital technology(shenzhen) co.,ltd 74ff7d wren sound systems, llc + 78009e samsung electronics co.,ltd 78028f adaptive spectrum and signal alignment (assia), inc. + 7802b1 cisco systems, inc + 7802b7 shenzhen ultra easy technology co.,ltd + 7802f8 xiaomi communications co ltd + 780473 texas instruments + 7804e3 huawei device co., ltd. + 780541 queclink wireless solutions co., ltd + 78055f shenzhen wyc technology co., ltd. + 78058c mmax communications, inc. 780738 z.u.k. elzab s.a. + 780ac7 baofeng tv co., ltd. + 780cb8 intel corporate + 780cf0 cisco systems, inc + 780ed1 trumpf werkzeugmaschinen gmbh+co.kg + 780f77 hangzhou gubei electronics technology co.,ltd + 781053 china mobile group device co.,ltd. + 781100 quantumsolution 781185 nbs payment solutions inc. + 7811dc xiaomi electronics,co.,ltd 7812b8 orantek limited - 781881 azurewave technologies, inc. + 781735 nokia shanghai bell co., ltd. + 7817be huawei technologies co.,ltd + 781881 azurewave technology inc. + 7818a8 huawei device co., ltd. 78192e nascent technology 7819f7 juniper networks 781c5a sharp corporation + 781d4a zte corporation 781dba huawei technologies co.,ltd 781dfd jabil inc + 781f11 rab lighting 781fdb samsung electronics co.,ltd + 782079 id tech 78223d affirmed networks + 782327 samsung electronics co.,ltd + 7823ae arris group, inc. + 7824af asustek computer inc. 782544 omnima limited - 7825ad samsung electronics co., ltd. - 782bcb dell inc + 78257a leo innovation lab + 7825ad samsung electronics co.,ltd + 7828ca sonos, inc. + 7829ed askey computer corp + 782a79 integrated device technology (malaysia) sdn. bhd. + 782b46 intel corporate + 782b64 bose corporation + 782bcb dell inc. + 782c29 new h3c technologies co., ltd + 782d7e trendnet, inc. + 782e56 china mobile group device co.,ltd. 782eef nokia corporation + 782f17 xlab co.,ltd 78303b stephen technologies co.,limited 7830e1 ultraclenz, llc - 7831c1 apple + 78312b zte corporation + 7831c1 apple, inc. + 78321b d-link international 78324f millennium group, inc. + 7835a0 zurn industries llc + 783607 cermate technologies inc. + 783690 yulong computer telecommunication scientific (shenzhen) co.,ltd + 7836cc guangdong oppo mobile telecommunications corp.,ltd + 783716 samsung electronics co.,ltd + 783a6c tecno mobile limited + 783a84 apple, inc. 783ce3 kai-ee 783d5b telnet redes inteligentes s.a. 783e53 bskyb ltd 783f15 easysync ltd. + 7840e4 samsung electronics co.,ltd 784405 fujitu(hong kong) electronic co.,ltd. - 784476 zioncom technology co.,ltd - 7845c4 dell inc + 784476 zioncom electronics (shenzhen) ltd. + 7844fd tp-link technologies co.,ltd. + 784501 biamp systems + 784558 ubiquiti networks inc. + 784561 cybertan technology inc. + 7845b3 huawei device co., ltd. + 7845c4 dell inc. 7846c4 daehap hyper-tech + 7846d4 samsung electronics co.,ltd 78471d samsung electronics co.,ltd + 7847e3 sichuan tianyi comheart telecom co.,ltd 784859 hewlett packard 78491d the will-burt company 784b08 f.robotics acquisitions ltd - 784b87 murata manufacturing co.,ltd. + 784b87 murata manufacturing co., ltd. + 784f43 apple, inc. + 784f9b juniper networks + 78507c juniper networks 78510c liveu ltd. 78521a samsung electronics co.,ltd + 78524a ensenso gmbh 785262 shenzhen hojy software co., ltd. + 78530d shenzhen skyworth digital technology co., ltd + 785364 shift gmbh + 7853f2 roxton systems ltd. 78542e d-link international 785517 sankyuelectronics 785712 mobile integration workgroup + 785773 huawei technologies co.,ltd + 785860 huawei technologies co.,ltd + 7858f3 vachen co.,ltd 78593e rafi gmbh & co.kg 78595e samsung electronics co.,ltd - 785968 hon hai precision ind.co.,ltd. + 785968 hon hai precision ind. co.,ltd. + 785c28 prime motion inc. 785c72 hioso technology co., ltd. - 78617c mitsumi electric co.,ltd + 785dc8 lg electronics + 785f4c argox information co., ltd. + 78617c mitsumi electric co.,ltd. + 786256 huawei technologies co.,ltd + 7864c0 apple, inc. + 7864e6 green motive technology limited + 78653b shaoxing ourten electronics co., ltd. + 786559 sagemcom broadband sas 7866ae ztec instruments, inc. - 786a89 huawei technologies co., ltd - 786c1c apple + 7867d7 apple, inc. + 7868f7 ysten technology co.,ltd + 7869d4 shenyang vibrotech instruments inc. + 786a1f arris group, inc. + 786a89 huawei technologies co.,ltd + 786c1c apple, inc. + 786d94 palo alto networks + 786deb ge lighting + 787052 welotec gmbh + 78719c arris group, inc. + 78725d cisco systems, inc + 787a6f juice technology ag + 787b8a apple, inc. + 787d48 itel mobile limited + 787d53 extreme networks, inc. + 787df3 sterlite technologies limited + 787e61 apple, inc. 787f62 gik mbh + 788038 funai electric co., ltd. + 788102 sercomm corporation. 78818f server racks australia pty ltd + 7881ce china mobile iot limited company 78843c sony corporation 7884ee indra espacio s.a. + 7885f4 huawei device co., ltd. + 78870d unifiedgateways india private limited + 78886d apple, inc. + 78888a cdr sp. z o.o. sp. k. 788973 cmc - 788c54 eltek technologies ltd + 788a20 ubiquiti networks inc. + 788b2a zhen shi information technology (shanghai) co., ltd. + 788b77 standar telecom + 788c4d indyme solutions, llc + 788c54 ping communication + 788c77 lexmark international, inc. 788df7 hitron technologies. inc + 788e33 jiangsu seuic technology co.,ltd + 7891e9 raisecom technology co.,ltd 78923e nokia corporation 78929c intel corporate + 7894b4 sercomm corporation. + 7894e8 radio bridge + 7895eb itel mobile limited + 789682 zte corporation + 789684 arris group, inc. + 7897c3 dingxin information technology co.,ltd + 7898e8 d-link international 7898fd q9 networks inc. 78995c nationz technologies inc 789966 musilab electronics (dongguan)co.,ltd. 78998f mediline italia srl - 789ed0 samsung electronics + 789c85 august home, inc. + 789ce7 shenzhen aikede technology co., ltd + 789ed0 samsung electronics co.,ltd 789f4c hoerbiger elektronik gmbh + 789f70 apple, inc. 789f87 siemens ag i ia pp prm - 78a051 iinet labs pty ltd + 78a051 iinet labs pty ltd 78a106 tp-link technologies co.,ltd. 78a183 advidia 78a2a0 nintendo co., ltd. - 78a3e4 apple + 78a351 shenzhen zhibotong electronics co.,ltd + 78a3e4 apple, inc. 78a504 texas instruments 78a5dd shenzhen smarteye digital electronics co., ltd 78a683 precidata + 78a6a0 hangzhou ezviz software co.,ltd. 78a6bd daeyeon control&instrument co,.ltd + 78a6e1 brocade communications systems llc 78a714 amphenol + 78a7eb 1more 78a873 samsung electronics co.,ltd + 78aa82 new h3c technologies co., ltd 78ab60 abb australia 78abbb samsung electronics co.,ltd - 78acc0 hewlett-packard company + 78ac44 dell inc. + 78acbf igneous systems + 78acc0 hewlett packard 78ae0c far south networks + 78af58 gimasi sa + 78afe4 comau s.p.a + 78b213 dwnet technologies(suzhou) corporation + 78b28d beijing tengling technology co.ltd + 78b3b9 shanghai sunup lighting co.,ltd 78b3ce elo touch solutions + 78b46a huawei technologies co.,ltd + 78b554 huawei device co., ltd. 78b5d2 ever treasure industrial limited 78b6c1 aobo telecom co.,ltd + 78b6ec scuf gaming international llc 78b81a inter sales a/s + 78b84b sichuan tianyi comheart telecomco.,ltd + 78b8d6 zebra technologies inc. 78bad0 shinybow technology co. ltd. + 78baf9 cisco systems, inc + 78bc1a cisco systems, inc + 78bdbc samsung electronics co.,ltd 78beb6 enhanced vision 78bebd stulz gmbh + 78c1a7 zte corporation + 78c2c0 ieee registration authority + 78c313 china mobile group device co.,ltd. + 78c3e9 samsung electronics co.,ltd 78c40e h&d wireless 78c4ab shenzhen runsil technology co.,ltd 78c5e5 texas instruments + 78c5f8 huawei device co., ltd. 78c6bb innovasic, inc. + 78c881 sony interactive entertainment inc. + 78c95e midmark rtls 78ca04 nokia corporation - 78ca39 apple + 78ca39 apple, inc. 78ca5e elno + 78ca83 ieee registration authority + 78cb2c join digital, inc. 78cb33 dhc software co.,ltd + 78cb68 daehap hyper-tech + 78cc2b sinewy technology co., ltd 78cd8e smc networks inc + 78cf2f huawei technologies co.,ltd + 78cff9 huawei device co., ltd. 78d004 neousys technology inc. 78d129 vicos + 78d162 apple, inc. + 78d294 netgear + 78d347 ericsson ab 78d34f pace-o-matic, inc. 78d38d hongkong yunlink technology limited + 78d4f1 ieee registration authority 78d5b5 navielektro ky 78d66f aristocrat technologies australia pty. ltd. - 78d6f0 samsung electro mechanics + 78d6b2 toshiba + 78d6f0 samsung electro mechanics co., ltd. + 78d71a ciena corporation 78d752 huawei technologies co.,ltd + 78d75f apple, inc. + 78d800 ieee registration authority 78d99f nucom hk ltd. - 78da6e cisco + 78d9e9 momentum iot + 78da07 zhejiang tmall technology co., ltd. + 78da6e cisco systems, inc + 78daa2 cynosure technologies co.,ltd 78dab3 gbo technology + 78db2f texas instruments 78dd08 hon hai precision ind. co.,ltd. + 78dd12 arcadyan corporation 78ddd6 c-scape + 78ddd9 guangzhou shiyuan electronics co., ltd. 78dee4 texas instruments - 78e3b5 hewlett-packard company + 78e103 amazon technologies inc. + 78e22c huawei device co., ltd. + 78e2bd vodafone automotive s.p.a. + 78e36d espressif inc. + 78e3b5 hewlett packard + 78e3de apple, inc. 78e400 hon hai precision ind. co.,ltd. - 78e7d1 hewlett-packard company + 78e7d1 hewlett packard 78e8b6 zte corporation + 78e980 rainus co.,ltd + 78eb14 shenzhen fast technologies co.,ltd + 78eb39 instituto nacional de tecnología industrial 78ec22 shanghai qihui telecom technology co., ltd 78ec74 kyland-usa 78ef4c unetconvergence co., ltd. + 78f09b huawei device co., ltd. + 78f235 sichuan ai-link technology co., ltd. + 78f29e pegatron corporation + 78f557 huawei technologies co.,ltd 78f5e5 bega gantenbrink-leuchten kg - 78f5fd huawei technologies co., ltd + 78f5fd huawei technologies co.,ltd 78f7be samsung electronics co.,ltd 78f7d0 silverbrook research + 78f882 lg electronics (mobile communications) + 78f8b8 rako controls ltd + 78f944 private + 78f9b4 nokia solutions and networks gmbh & co. kg + 78fc14 family zone cyber safety ltd + 78fd94 apple, inc. 78fe3d juniper networks 78fe41 socus networks 78fee2 shanghai diveo technology co., ltd 78ff57 intel corporate + 78ffca tecno mobile limited + 7c004d huawei technologies co.,ltd + 7c010a texas instruments 7c0187 curtis instruments, inc. + 7c0191 apple, inc. 7c02bc hansung electronics co. ltd - 7c034c sagemcom - 7c03d8 sagemcom sas + 7c034c sagemcom broadband sas + 7c035e xiaomi communications co ltd + 7c03ab xiaomi communications co ltd + 7c03c9 shenzhen youhua technology co., ltd + 7c03d8 sagemcom broadband sas + 7c04d0 apple, inc. 7c0507 pegatron corporation 7c051e rafael ltd. - 7c0623 ultra electronics, cis + 7c0623 ultra electronics sonar system division 7c08d9 shanghai b-star technology co 7c092b bekey a/s + 7c0a3f samsung electronics co.,ltd 7c0a50 j-mex inc. - 7c11be apple + 7c0bc6 samsung electronics co.,ltd + 7c0cf6 guangdong huiwei high-tech co., ltd. + 7c0ece cisco systems, inc + 7c1015 brilliant home technology, inc. + 7c11be apple, inc. + 7c11cb huawei technologies co.,ltd + 7c11cd qiantang technology 7c1476 damall technologies sas 7c160d saia-burgess controls ag + 7c18cd e-tron co.,ltd. 7c1a03 8locations co., ltd. 7c1afc dalian co-edifice video technology co., ltd + 7c1b93 huawei device co., ltd. + 7c1c4e lg innotek + 7c1c68 samsung electronics co.,ltd + 7c1cf1 huawei technologies co.,ltd + 7c1dd9 xiaomi communications co ltd + 7c1e06 new h3c technologies co., ltd 7c1e52 microsoft 7c1eb3 2n telekomunikace a.s. 7c2048 koamtac - 7c2064 alcatel lucent ipd + 7c2064 alcatel-lucent ipd + 7c210d cisco systems, inc + 7c210e cisco systems, inc + 7c21d8 shenzhen think will communication technology co., ltd. + 7c2302 samsung electronics co.,ltd + 7c240c telechips, inc. + 7c2586 juniper networks + 7c2587 chaowifi.com + 7c25da fn-link technology limited + 7c2634 arris group, inc. + 7c2664 sagemcom broadband sas + 7c2a31 intel corporate + 7c2adb xiaomi communications co ltd + 7c2be1 shenzhen ferex electrical co.,ltd 7c2cf3 secure electrans ltd 7c2e0d blackmagic design + 7c2ebd google, inc. + 7c2edd samsung electronics co.,ltd 7c2f80 gigaset communications gmbh + 7c310e cisco systems, inc 7c336e meg electronics inc. + 7c3548 transcend information + 7c3866 texas instruments 7c386c real time logic + 7c38ad samsung electronics co.,ltd 7c3920 ssoma security + 7c3953 zte corporation 7c3bd5 imago group + 7c3cb6 shenzhen homecare technology co.,ltd. + 7c3d2b huawei device co., ltd. 7c3e9d patech + 7c41a2 nokia 7c438f e-band communications corp. 7c444c entertainment solutions, s.l. + 7c4685 motorola (wuhan) mobility technologies communication co., ltd. + 7c477c ieee registration authority + 7c48b2 vida resources lte ltd 7c49b9 plexus manufacturing sdn bhd + 7c49eb xiaomi electronics,co.,ltd 7c4a82 portsmith llc 7c4aa8 mindtree wireless pvt ltd 7c4b78 red sun synthesis pte ltd 7c4c58 scale computing, inc. 7c4ca5 bskyb ltd + 7c4e09 shenzhen skyworth wireless technology co.,ltd + 7c4f7d sawwave 7c4fb5 arcadyan technology corporation + 7c5049 apple, inc. + 7c5079 intel corporate + 7c50da private + 7c5189 sg wireless limited + 7c5259 sichuan jiuzhou electronic technology co., ltd. + 7c534a metamako + 7c55a7 kastle systems 7c55e7 ysi, inc. + 7c573c aruba, a hewlett packard enterprise company + 7c574e cobi gmbh + 7c5a1c sophos ltd + 7c5a67 jnc systems, inc. + 7c5cf8 intel corporate + 7c604a avelon 7c6097 huawei technologies co.,ltd + 7c6166 amazon technologies inc. 7c6193 htc corporation + 7c6456 samsung electronics co.,ltd 7c669d texas instruments - 7c69f6 cisco + 7c67a2 intel corporate + 7c696b atmosic technologies + 7c69f6 cisco systems, inc 7c6ab3 ibc technologies inc. + 7c6ac3 gatesair, inc 7c6adb safetone technology co.,ltd + 7c6af3 integrated device technology (malaysia) sdn. bhd. 7c6b33 tenyu tech co. ltd. 7c6b52 tigaro wireless + 7c6b9c guangdong oppo mobile telecommunications corp.,ltd + 7c6bf7 nti co., ltd. 7c6c39 pixsys srl 7c6c8f ams neve ltd - 7c6d62 apple + 7c6d62 apple, inc. + 7c6da6 superwave group llc + 7c6df8 apple, inc. 7c6f06 caterpillar trimble control technologies 7c6ff8 shenzhen acto digital video technology co.,ltd. + 7c70bc ieee registration authority + 7c7176 wuxi idata technology company ltd. 7c72e4 unikey technologies + 7c738b cocoon alarm ltd + 7c73eb huawei device co., ltd. + 7c7630 shenzhen youhua technology co., ltd + 7c7635 intel corporate + 7c7668 huawei technologies co.,ltd 7c7673 enmas gmbh + 7c787e samsung electronics co.,ltd + 7c78b2 wyze labs inc + 7c79e8 payrange inc. + 7c7a53 phytrex technology corp. 7c7a91 intel corporate + 7c7b8b control concepts, inc. 7c7be4 z'sedai kenkyusho corporation + 7c7d3d huawei technologies co.,ltd 7c7d41 jinmuyu electronics co., ltd. 7c822d nortec + 7c8274 shenzhen hikeen technology co.,ltd 7c8306 glen dimplex nordic as + 7c8956 samsung electronics co.,ltd + 7c89c1 palo alto networks + 7c8ae1 compal information (kunshan) co., ltd. + 7c8bb5 samsung electronics co.,ltd + 7c8bca tp-link technologies co.,ltd. 7c8d91 shanghai hongzhuo information technology co.,ltd 7c8ee4 texas instruments + 7c8fde dwnet technologies(suzhou) corporation + 7c9122 samsung electronics co.,ltd + 7c942a huawei technologies co.,ltd 7c94b2 philips healthcare pcci - 7c95f3 cisco + 7c95b1 extreme networks, inc. + 7c95f3 cisco systems, inc + 7c96d2 fihonest communication co.,ltd 7c9763 openmatics s.r.o. + 7c9a1d apple, inc. + 7c9a54 technicolor ch usa inc. 7c9a9b vse valencia smart energy + 7c9ebd espressif inc. + 7c9f07 cig shanghai co ltd 7ca15d gn resound a/s + 7ca177 huawei technologies co.,ltd + 7ca1ae apple, inc. + 7ca237 king slide technology co., ltd. + 7ca23e huawei technologies co.,ltd 7ca29b d.signt gmbh & co. kg 7ca61d mhl, llc + 7ca7b0 shenzhen bilian electronic co.,ltd + 7ca96b syrotech networks. ltd. + 7ca97d objenious + 7cab25 mesmo technology inc. + 7cab60 apple, inc. 7cacb2 bosch software innovations gmbh - 7cad74 cisco + 7cad4f cisco systems, inc + 7cad74 cisco systems, inc 7cb03e osram gmbh + 7cb0c2 intel corporate + 7cb15d huawei technologies co.,ltd + 7cb177 satelco ag 7cb21b cisco spvtg - 7cb232 tcl king high frequency ei,co.,ltd + 7cb232 hui zhou gaoshengda technology co.,ltd + 7cb25c acacia communications + 7cb27d intel corporate + 7cb37b qingdao intelligent&precise electronics co.,ltd. 7cb542 aces technology + 7cb59b tp-link technologies co.,ltd. 7cb733 askey computer corp 7cb77b paradigm electronics inc + 7cb94c bouffalo lab (nanjing) co., ltd. + 7cb960 shanghai x-cheng telecom ltd + 7cbacc ieee registration authority 7cbb6f cosco electronics co., ltd. + 7cbb8a nintendo co., ltd. + 7cbc84 ieee registration authority 7cbd06 ae refusol 7cbf88 mobilicom ltd 7cbfb1 arris group, inc. - 7cc3a1 apple - 7cc537 apple + 7cc294 beijing xiaomi mobile software co., ltd + 7cc2c6 tp-link corporation limited + 7cc385 huawei technologies co.,ltd + 7cc3a1 apple, inc. + 7cc4ef devialet + 7cc537 apple, inc. + 7cc6c4 kolff computer supplies b.v. + 7cc709 shenzhen rf-link technology co.,ltd. + 7cc77e fiberhome telecommunication technologies co.,ltd 7cc8ab acro associates, inc. 7cc8d0 tianjin yaan technology co., ltd. 7cc8d7 damalisk + 7cc926 wuhan greenet information service co.,ltd. + 7cc95a dell emc 7ccb0d antaira technologies, llc + 7ccbe2 ieee registration authority + 7ccc1f sichuan tianyi comheart telecomco.,ltd + 7cccb8 intel corporate 7ccd11 ms-magnet 7ccd3c guangzhou juzing technology co., ltd 7ccfcf shanghai seari intelligent system co., ltd - 7cd1c3 apple + 7cd1c3 apple, inc. 7cd30a inventec corporation + 7cd566 amazon technologies inc. + 7cd661 xiaomi communications co ltd 7cd762 freestyle technology pty ltd 7cd844 enmotus inc + 7cd95c google, inc. + 7cd9a0 huawei technologies co.,ltd + 7cd9f4 uab teltonika telematics 7cd9fe new cosmos electric co., ltd. 7cda84 dongnian networks inc. + 7cdb98 askey computer corp 7cdd11 chongqing mas sci&tech.co.,ltd 7cdd20 ioxos technologies s.a. + 7cdd76 suzhou hanming technologies co., ltd. 7cdd90 shenzhen ogemray technology co., ltd. + 7cdde9 atom tech inc. + 7cdfa1 espressif inc. 7ce044 neon inc 7ce1ff computer performance, inc. dba digital loggers, inc. - 7ce4aa + 7ce2ca juniper networks + 7ce4aa private + 7ce524 quirky, inc. 7ce56b esen optoelectronics technology co.,ltd. + 7ce97c itel mobile limited 7ce9d3 hon hai precision ind. co.,ltd. + 7ceb7f dmet products corp. + 7cebae ridgeline instruments 7cebea asct + 7cec79 texas instruments + 7cec9b fuzhou teraway information technology co.,ltd 7ced8d microsoft 7cef18 creative product design pty. ltd. + 7cef61 str elektronik josef schlechtinger gmbh 7cef8a inhon international ltd. - 7cf05f apple + 7cf05f apple, inc. 7cf098 bee beans technologies, inc. 7cf0ba linkwell telesystems pvt ltd - 7cf429 nuuo inc. - 7cfadf apple + 7cf2dd vence corp + 7cf31b lg electronics (mobile communications) + 7cf429 nuuo inc. + 7cf666 tuya smart inc. + 7cf854 samsung electronics co.,ltd + 7cf880 cisco systems, inc + 7cf90e samsung electronics co.,ltd + 7cf95c u.i. lapp gmbh + 7cf9a0 fiberhome telecommunication technologies co.,ltd + 7cfadf apple, inc. + 7cfc3c visteon corporation + 7cfd6b xiaomi communications co ltd + 7cfd82 guangdong genius technology co., ltd. 7cfe28 salutron inc. + 7cfe4e shenzhen safe vision technology co.,ltd + 7cfe90 mellanox technologies, inc. + 7cff4d avm audiovisuelles marketing und computersysteme gmbh 7cff62 huizhou super electron technology co.,ltd. 80000b intel corporate - 800010 att bell laboratories - 80006e apple + 800010 at&t + 80006e apple, inc. + 800184 htc corporation + 80029c gemtek technology co., ltd. + 8002df ora inc. + 800384 ruckus wireless + 800588 ruijie networks co.,ltd 8005df montage technology group limited + 80071b vsolution telecommunication technology co.,ltd. 8007a2 esson technology inc. + 800902 keysight technologies, inc. 800a06 comtec co.,ltd + 800a80 ieee registration authority + 800b51 chengdu xgimi technology co.,ltd + 800c67 apple, inc. + 800dd7 latticework, inc 800e24 forgetbox + 8012df shenzhen superelectron technology co.,ltd. + 801382 huawei technologies co.,ltd 801440 sunlit system technology corp + 8014a8 guangzhou v-solution electronic technology co., ltd. + 801605 vodafone italia s.p.a. + 801609 sleep number 8016b7 brunel university 80177d nortel networks - 8018a7 samsung eletronics co., ltd + 801844 dell inc. + 8018a7 samsung electronics co.,ltd + 801934 intel corporate + 801967 shanghai reallytek information technology co.,ltd + 8019fe jianling technology co., ltd 801daa avaya inc 801f02 edimax technology co. ltd. + 801f12 microchip technology inc. 8020af trade fides, a.s. + 8020da sagemcom broadband sas + 8020e1 bvba dptechnics + 8020fd samsung electronics co.,ltd 802275 beijing beny wave technology co ltd + 802278 china mobile iot company limited + 8022a7 nec platforms, ltd. + 802511 itel mobile limited + 802689 d-link international + 802994 technicolor ch usa inc. + 802aa8 ubiquiti networks inc. 802afa germaneers gmbh + 802bf9 hon hai precision ind. co.,ltd. + 802dbf cisco systems, inc 802de1 solarbridge technologies 802e14 azeti networks ag 802fde zurich instruments ag + 803049 liteon technology corporation + 8030dc texas instruments + 8030e0 hewlett packard enterprise + 8031f0 samsung electronics co.,ltd + 803253 intel corporate + 803428 microchip technology inc. 803457 ot systems limited + 8035c1 xiaomi communications co ltd + 803773 netgear + 803896 sharp corporation + 8038bc huawei technologies co.,ltd + 8038fb intel corporate 8038fd leapfrog enterprises, inc. 8039e5 patlite corporation + 803a0a integrated device technology (malaysia) sdn. bhd. + 803a59 at&t + 803af4 fiberhome telecommunication technologies co.,ltd + 803b2a abb xiamen low voltage equipment co.,ltd. 803b9a ghe-ces electronic ag + 803bf6 look easy international limited + 803e48 shenzhen gongjin electronics co.,lt 803f5d winstars technology ltd 803fd6 bytes at work ag - 80414e bbk electronics corp., ltd., + 804126 huawei technologies co.,ltd + 80414e bbk educational electronics corp.,ltd. 80427c adolf tedsen gmbh & co. kg + 8044fd china mobile (hangzhou) information technology co., ltd. + 8045dd intel corporate 804731 packet design, inc. - 8048a5 sichuan tianyi comheart telecom co.,ltd - 804971 apple + 804786 samsung electronics co.,ltd + 8048a5 sichuan tianyi comheart telecomco.,ltd + 804971 apple, inc. + 804a14 apple, inc. 804b20 ventilation control + 804b50 silicon laboratories + 804e70 samsung electronics co.,ltd + 804e81 samsung electronics co.,ltd 804f58 thinkeco, inc. 80501b nokia corporation + 805067 w & d technology corporation + 8050f6 itel mobile limited + 80546a shenzhen gongjin electronics co.,lt 8056f2 hon hai precision ind. co.,ltd. 805719 samsung electronics co.,ltd 8058c5 novatec kommunikationstechnik gmbh + 8058f8 motorola mobility llc, a lenovo company 8059fd noviga + 805a04 lg electronics (mobile communications) + 805e0c yealink(xiamen) network technology co.,ltd. + 805e4f fn-link technology limited + 805ec0 yealink(xiamen) network technology co.,ltd. + 805fc5 apple, inc. 806007 rim + 8060b7 cloud network technology singapore pte. ltd. + 80615f beijing sinead technology co., ltd. 80618f shenzhen sangfei consumer communications co.,ltd 806459 nimbus inc. + 80647a ola sense inc + 806559 em microelectronic + 80656d samsung electronics co.,ltd 8065e9 benq corporation 806629 prescope technologies co.,ltd. + 806933 huawei technologies co.,ltd + 806940 lexar co.,limited + 806ab0 shenzhen tinno mobile technology corp. + 806c1b motorola mobility llc, a lenovo company 806c8b kaeser kompressoren ag 806cbc net new electronic technology gmbh + 806d97 private + 806fb0 texas instruments 80711f juniper networks + 80717a huawei technologies co.,ltd + 807215 bskyb ltd + 807264 huawei device co., ltd. + 80739f kyocera corporation + 807459 k's co.,ltd. + 807484 all winner (hong kong) limited + 80751f bskyb ltd 807693 newag sa + 807871 askey computer corp + 80795d infinix mobility limited 8079ae shandong tecsunrise co.,ltd 807a7f abb genway xiamen electrical equipment co., ltd - 807b1e corsair components + 807abf htc corporation + 807b1e corsair memory, inc. + 807b3e samsung electronics co.,ltd + 807b85 ieee registration authority + 807d14 huawei technologies co.,ltd 807d1b neosystem co. ltd. + 807d3a espressif inc. 807de3 chongqing sichuan instrument microcircuit co.ltd. + 807ff8 juniper networks 8081a5 tongqing communication equipment (shenzhen) co.,ltd + 808223 apple, inc. 808287 atcom technology co.ltd. + 8084a9 oshkosh corporation 808698 netronics technologies inc. + 8086d9 samsung electronics co.,ltd 8086f2 intel corporate + 808917 tp-link technologies co.,ltd. + 808a8b vivo mobile communication co., ltd. + 808af7 nanoleaf 808b5c shenzhen runhuicheng technology co., ltd + 808c97 kaonmedia co., ltd. + 808db7 hewlett packard enterprise + 808f1d tp-link technologies co.,ltd. + 808fe8 intelbras 80912a lih rong electronic enterprise co., ltd. + 809133 azurewave technology inc. 8091c0 agilemesh, inc. - 80929f apple + 80929f apple, inc. 809393 xapt gmbh 80946c tokyo radar corporation + 809621 lenovo 8096b1 arris group, inc. + 8096ca hon hai precision ind. co.,ltd. 80971b altenergy power system,inc. 809b20 intel corporate + 809f9b sichuan ai-link technology co., ltd. + 809fab fiberhome telecommunication technologies co.,ltd + 809ff5 samsung electronics co.,ltd + 80a036 shanghai mxchip information technology co., ltd. + 80a1ab intellisis 80a1d7 shanghai dareglobal technologies co.,ltd + 80a235 edgecore networks corporation + 80a589 azurewave technology inc. + 80a796 neurotek llc + 80a85d osterhout design group 80aaa4 usag + 80ac7c sichuan ai-link technology co., ltd. + 80acac juniper networks + 80ad16 xiaomi communications co ltd + 80ad67 kasda networks inc + 80b03d apple, inc. + 80b07b zte corporation 80b219 elektron technology uk limited + 80b234 technicolor ch usa inc. 80b289 forworld electronics ltd. - 80b32a alstom grid - 80b686 huawei technologies co., ltd + 80b32a uk grid solutions ltd + 80b575 huawei technologies co.,ltd + 80b624 ivs + 80b655 intel corporate + 80b686 huawei technologies co.,ltd + 80b708 blue danube systems, inc + 80b709 viptela, inc 80b95c elftech co., ltd. + 80b97a eero inc. 80baac teleadapt ltd 80bae6 neets 80bbeb satmap systems ltd + 80be05 apple, inc. 80c16e hewlett packard + 80c501 octogate it security systems gmbh + 80c548 shenzhen zowee technology co.,ltd + 80c5e6 microsoft corporation + 80c5f2 azurewave technology inc. 80c63f remec broadband wireless , llc - 80c6ab technicolor usa inc. + 80c6ab technicolor ch usa inc. 80c6ca endian s.r.l. + 80c755 panasonic appliances company + 80c7c5 fiberhome telecommunication technologies co.,ltd 80c862 openpeak, inc + 80c955 redpine signals, inc. + 80ca4b shenzhen gongjin electronics co.,ltd + 80cc12 huawei device co., ltd. + 80ce62 hewlett packard 80ceb1 theissen training systems gmbh + 80ceb9 samsung electronics co.,ltd 80cf41 lenovo mobile communication technology ltd. + 80cfa2 huawei device co., ltd. 80d019 embed, inc + 80d04a technicolor ch usa inc. + 80d065 cks corporation + 80d09b huawei technologies co.,ltd + 80d160 integrated device technology (malaysia) sdn. bhd. 80d18b hangzhou i'converge technology co.,ltd + 80d21d azurewave technology inc. + 80d336 cern 80d433 lzlabs gmbh + 80d4a5 huawei technologies co.,ltd + 80d605 apple, inc. 80d733 qsr automations, inc. + 80da13 eero inc. + 80dabc megafone limited 80db31 power quotient international co., ltd. - 80ea96 apple + 80e01d cisco systems, inc + 80e1bf huawei technologies co.,ltd + 80e455 new h3c technologies co., ltd + 80e4da ieee registration authority + 80e540 arris group, inc. + 80e650 apple, inc. + 80e82c hewlett packard + 80e86f cisco systems, inc + 80ea07 tp-link technologies co.,ltd. + 80ea23 wistron neweb corporation + 80ea96 apple, inc. + 80eaca dialog semiconductor hellas sa + 80eb77 wistron corporation + 80ed2c apple, inc. + 80ee25 shenzhen skyworth digital technology co., ltd 80ee73 shuttle inc. + 80f1f1 tech4home, lda 80f25e kyynel + 80f3ef facebook technologies, llc + 80f503 arris group, inc. 80f593 irco sistemas de telecomunicación s.a. + 80f5b5 texas instruments 80f62e hangzhou h3c technologies co., limited + 80f8eb raytight 80fa5b clevo co. 80fb06 huawei technologies co.,ltd + 80fbf0 quectel wireless solutions co., ltd. + 80fd7a blu products inc 80ffa8 unidis - 8400d2 sony ericsson mobile communications ab - 840b2d samsung electro-mechanics co., ltd + 84002d pegatron corporation + 8400d2 sony mobile communications inc + 8401a7 greyware automation products, inc + 840283 humax co., ltd. + 840328 juniper networks + 8404d2 kirale technologies sl + 8406fa fiberhome telecommunication technologies co.,ltd + 840b2d samsung electro mechanics co., ltd. + 840b7c hitron technologies. inc + 840d8e espressif inc. 840f45 shanghai gmt digital technologies co., ltd + 84100d motorola mobility llc, a lenovo company + 84119e samsung electronics co.,ltd + 8411c2 ieee registration authority + 84139f zte corporation + 8416f9 tp-link technologies co.,ltd. 841715 gp electronics (hk) ltd. - 841766 weifang goertek electronics co., ltd + 841766 weifang goertek electronics co.,ltd + 8417ef technicolor ch usa inc. + 841826 osram gmbh + 84183a ruckus wireless 841888 juniper networks 841b38 shenzhen excelsecu data technology co.,ltd 841b5e netgear + 841b77 intel corporate + 841c70 zte corporation 841e26 kernel-i co.,ltd + 841ea3 sagemcom broadband sas + 842096 shenzhen rf-link technology co.,ltd. 842141 shenzhen ginwave technologies ltd. - 84248d motorola solutions inc - 84253f silex technology, inc + 8421f1 huawei technologies co.,ltd + 84225e shenzhen technewchip technology co.,ltd. + 842388 ruckus wireless + 84248d zebra technologies inc + 842519 samsung electronics + 84253f silex technology, inc. 8425a4 tariox limited 8425db samsung electronics co.,ltd 842615 adb broadband italia - 84262b alcatel-lucent + 84262b nokia + 84267a guangdong taide zhilian technology co.,ltd + 842690 beijing thought science co.,ltd. 8427ce corporation of the presiding bishop of the church of jesus christ of latter-day saints + 84285a saffron solutions inc 842914 emporia telecom produktions- und vertriebsgesmbh & co kg - 842999 apple + 842999 apple, inc. + 842afd hp inc. 842b2b dell inc. 842b50 huria co.,ltd. 842bbc modelleisenbahn gmbh + 842c80 sichuan changhong electric ltd. + 842e14 silicon laboratories + 842e27 samsung electronics co.,ltd 842f75 innokas group + 843095 hon hai precision ind.co.,ltd 8430e5 skyhawke technologies, llc + 84326f guangzhou ava electronics technology co.,ltd + 8432ea anhui wanzten p&t co., ltd 843497 hewlett packard 843611 hyungseul publishing networks - 843835 apple + 8437d5 samsung electronics co.,ltd + 843835 apple, inc. + 843838 samsung electro-mechanics(thailand) 843a4b intel corporate + 843a5b inventec(chongqing) corporation + 843b10 lv switch inc. + 843dc6 cisco systems, inc + 843e79 shenzhen belon technology co.,ltd + 843e92 huawei technologies co.,ltd 843f4e tri-tech manufacturing, inc. + 844076 drivenets + 844167 apple, inc. + 844464 serveru inc + 8444af zhejiang tmall technology co., ltd. + 8446fe huawei technologies co.,ltd + 844765 huawei technologies co.,ltd 844823 woxter technology co. ltd 844915 varmour networks, inc. + 844bb7 beijing sankuai online technology co.,ltd 844bf5 hon hai precision ind. co.,ltd. 844f03 ablelink electronics ltd + 84509a easy soft tv co., ltd 845181 samsung electronics co.,ltd + 8454df huawei device co., ltd. + 8455a5 samsung electronics co.,ltd 84569c coho data, inc., + 845733 microsoft corporation 845787 dvr c&c co., ltd. + 845a81 ffly4u + 845b12 huawei technologies co.,ltd 845c93 chabrier services + 845cf3 intel corporate 845dd7 shenzhen netcom electronics co.,ltd + 846082 private + 8461a0 arris group, inc. 846223 shenzhen coship electronics co., ltd. 8462a6 eurocb (phils), inc. + 8463d6 microsoft corporation + 846569 new h3c technologies co., ltd + 84683e intel corporate + 846878 apple, inc. + 8468c8 totolink technology int‘l limited + 846991 nokia + 846a66 sumitomo kizai co.,ltd. 846aed wireless tsukamoto.,co.ltd + 846b48 shenzhen eepulink co., ltd. 846eb1 park assist llc + 846fce guangdong oppo mobile telecommunications corp.,ltd + 847127 silicon laboratories + 84716a huawei device co., ltd. 847207 i&c technology + 847303 letv mobile and intelligent information technology (beijing) corporation ltd. 84742a zte corporation + 847460 zte corporation 847616 addat s.r.o. - 8478ac cisco + 847637 huawei technologies co.,ltd + 847778 cochlear limited + 84788b apple, inc. + 8478ac cisco systems, inc + 847933 profichip gmbh + 847973 shanghai baud data communication co.,ltd. 847a88 htc corporation + 847ab6 altobeam (china) inc. + 847beb dell inc. + 847c9b gd midea air-conditioning equipment co.,ltd. + 847d50 holley metering limited 847e40 texas instruments + 847f3d integrated device technology (malaysia) sdn. bhd. + 84802d cisco systems, inc + 848094 meter, inc. 8482f4 beijing huasun unicreate technology co., ltd + 848319 hangzhou zero zero technology co., ltd. 848336 newrun - 848371 avaya, inc + 848371 avaya inc 848433 paradox engineering sa - 848506 apple + 848506 apple, inc. + 84850a hella sonnen- und wetterschutztechnik gmbh + 8485e6 guangdong asano technology co.,ltd. + 8486f3 greenvity communications + 8489ad apple, inc. + 8489ec ieee registration authority + 848a8d cisco systems, inc + 848bcd ieee registration authority + 848c8d apple, inc. 848d84 rajant corporation 848dc7 cisco spvtg - 848e0c apple + 848e0c apple, inc. 848e96 embertec pty ltd + 848edf sony mobile communications inc 848f69 dell inc. - 849000 arnold & richter cine technik + 849000 arnold&richter cine technik gmbh & co. betriebs kg + 84930c incoax networks europe ab + 8493a0 huawei device co., ltd. + 84948c hitron technologies. inc + 849681 cathay communication co.,ltd + 8496d8 arris group, inc. 8497b8 memjet inc. + 849866 samsung electronics co.,ltd + 849a40 hangzhou hikvision digital technology co.,ltd. 849ca6 arcadyan technology corporation + 849d64 smc corporation + 849dc2 shanghai mxchip information technology co., ltd. 849dc5 centera photonics inc. + 849fb5 huawei technologies co.,ltd + 84a06e sagemcom broadband sas + 84a134 apple, inc. + 84a1d1 sagemcom broadband sas + 84a24d birds eye systems private limited + 84a3b5 propulsion systems + 84a423 sagemcom broadband sas + 84a466 samsung electronics co.,ltd 84a6c8 intel corporate 84a783 alcatel lucent - 84a8e4 shenzhen huawei communication technologies co., ltd + 84a788 perples + 84a8e4 huawei technologies co.,ltd + 84a93e hewlett packard 84a991 cyber trans japan co.,ltd. + 84a9c4 huawei technologies co.,ltd + 84a9ea career technologies usa + 84aa9c mitrastar technology corp. + 84ab1a apple, inc. + 84ab26 tiinlab corporation 84aca4 beijing novel super digital tv technology co., ltd + 84acfb crouzet automatismes + 84ad58 huawei technologies co.,ltd + 84ad8d apple, inc. 84af1f beat system service co,. ltd. - 84b153 apple + 84afec buffalo.inc + 84b153 apple, inc. + 84b261 cisco systems, inc + 84b31b kinexon gmbh + 84b517 cisco systems, inc + 84b541 samsung electronics co.,ltd 84b59c juniper networks + 84b802 cisco systems, inc + 84b866 beijing xiaolu technology co. ltd + 84b8b8 motorola (wuhan) mobility technologies communication co., ltd. + 84ba3b canon inc. + 84bb69 arris group, inc. + 84be52 huawei technologies co.,ltd + 84c0ef samsung electronics co.,ltd + 84c1c1 juniper networks 84c2e4 jiangsu qinheng co., ltd. + 84c3e8 vaillant gmbh + 84c5a6 intel corporate 84c727 gnodal ltd + 84c78f aps networks gmbh 84c7a9 c3po s.a. - 84c8b1 incognito software inc. + 84c7ea sony mobile communications inc + 84c807 adva optical networking ltd. + 84c8b1 incognito software systems inc. 84c9b2 d-link international + 84c9c6 shenzhen gongjin electronics co.,lt + 84cc63 huawei device co., ltd. + 84cca8 espressif inc. + 84cd62 shenzhen idwell technology co.,ltd + 84cfbf fairphone + 84d15a tct mobile ltd 84d32a ieee 1905.1 + 84d343 calix inc. + 84d412 palo alto networks + 84d47e aruba, a hewlett packard enterprise company + 84d4c8 widex a/s + 84d608 wingtech mobile communications co., ltd. + 84d6c5 solaredge technologies + 84d6d0 amazon technologies inc. + 84d81b tp-link technologies co.,ltd. + 84d931 hangzhou h3c technologies co., limited 84d9c8 unipattern co., - 84db2f sierra wireless inc + 84db2f sierra wireless + 84db9e pink nectarine health ab + 84dbac huawei technologies co.,ltd + 84dbfc nokia 84dd20 texas instruments + 84ddb7 cilag gmbh international 84de3d crystal vision ltd 84df0c net2grid bv + 84df19 chuango security technology corporation + 84e058 arris group, inc. + 84e0f4 ieee registration authority + 84e323 green wave telecommunication sdn bhd + 84e327 tailyn technologies inc + 84e342 tuya (hk) limietd 84e4d9 shenzhen need technology ltd. + 84e5d8 guangdong unipoe iot technology co.,ltd. 84e629 bluwan sa 84e714 liang herng enterprise,co.ltd. + 84e892 actiontec electronics, inc + 84e986 huawei device co., ltd. + 84ea97 shenzhen icomm semiconductor co.,ltd 84ea99 vieworks + 84eaed roku, inc + 84eb18 texas instruments + 84eb3e vivint smart home 84ed33 bbmc co.,ltd + 84ef18 intel corporate + 84f129 metrascale inc. + 84f147 cisco systems, inc + 84f3eb espressif inc. 84f493 oms spol. s.r.o. 84f64c cross point bv - 84fcfe apple + 84f6fa miovision technologies incorporated + 84f883 luminar technologies + 84fcac apple, inc. + 84fcfe apple, inc. + 84fd27 silicon laboratories + 84fdd1 intel corporate 84fe9e rtc industries, inc. - 880355 arcadyan technology corp. + 84fedc borqs beijing ltd. + 880118 blt co + 8801f2 vitec system engineering inc. + 880355 arcadyan technology corporation + 8803e9 guangdong oppo mobile telecommunications corp.,ltd + 88074b lg electronics (mobile communications) 880905 mtmcommunications + 880907 mkt systemtechnik gmbh & co. kg + 8809af masimo corporation 880f10 huami information technology co.,ltd. 880fb6 jabil circuits india pvt ltd,-ehtp unit 881036 panodic(shenzhen) electronics limted - 88124e qualcomm atheros + 88108f huawei technologies co.,ltd + 881196 huawei technologies co.,ltd + 88123d suzhou aquila solutions inc. + 88124e qualcomm inc. 88142b protonic holland - 881544 meraki, inc. + 881544 cisco meraki + 8815c5 huawei device co., ltd. + 8817a3 integrated device technology (malaysia) sdn. bhd. 8818ae tamron co., ltd - 881fa1 apple + 881908 apple, inc. + 881b99 shenzhen xin fei jia electronic co. ltd. + 881c95 itel mobile limited + 881dfc cisco systems, inc + 881fa1 apple, inc. 882012 lmi technologies 8821e3 nebusens, s.l. 882364 watchnet dvr inc + 88238c fiberhome telecommunication technologies co.,ltd 8823fe tttech computertechnik ag 88252c arcadyan technology corporation + 882593 tp-link technologies co.,ltd. + 8828b3 huawei technologies co.,ltd + 882949 renesas electronics (penang) sdn. bhd. + 882950 netmoon technology co., ltd + 88299c samsung electronics co.,ltd + 882a5e new h3c technologies co., ltd + 882b94 madoka system co.,ltd. + 882bd7 addÉnergie technologies + 882d53 baidu online network technology (beijing) co., ltd. 882e5a storone - 88308a murata manufactuaring co.,ltd. - 88329b samsung electro mechanics co.,ltd. + 88308a murata manufacturing co., ltd. + 88329b samsung electro-mechanics(thailand) 883314 texas instruments + 8833be ivenix, inc. + 8834fe bosch automotive products (suzhou) co. ltd 88354c transics + 8835c1 oi electric co.,ltd 883612 src computers, llc + 88365f lg electronics (mobile communications) + 88366c efm networks + 8836cf huawei device co., ltd. + 883a30 aruba, a hewlett packard enterprise company + 883b8b cheering connection co. ltd. + 883c1c mercury corporation + 883d24 google, inc. + 883f4a texas instruments + 883f99 siemens ag + 883fd3 huawei technologies co.,ltd + 884033 huawei technologies co.,ltd + 88403b huawei technologies co.,ltd + 884067 infomark + 884157 shenzhen atsmart technology co.,ltd. 8841c1 orbisat da amazonia ind e aerol sa - 8841fc airties wireless netowrks - 8843e1 cisco systems, inc. + 8841fc airties wireless networks + 8843e1 cisco systems, inc + 884477 huawei technologies co.,ltd 8844f6 nokia corporation + 884604 xiaomi communications co ltd 88462a telechips inc. + 884a18 opulinks + 884a70 wacom co.,ltd. + 884aea texas instruments 884b39 siemens ag, healthcare sector + 884ccf pulzze systems, inc + 8850dd infiniband trade association + 8850f6 shenzhen jingxun software telecommunication technology co.,ltd + 88517a hmd global oy 8851fb hewlett packard 88532e intel corporate - 885395 apple - 8853d4 huawei technologies co., ltd + 885395 apple, inc. + 8853d4 huawei technologies co.,ltd + 88541f google, inc. + 88571d seongji industry company 88576d xta electronics ltd - 885a92 cisco - 885bdd aerohive networks inc. - 885c4f alcatel lucent + 8857ee buffalo.inc + 885a06 guangdong oppo mobile telecommunications corp.,ltd + 885a85 wistron neweb corporation + 885a92 cisco systems, inc + 885bdd extreme networks, inc. + 885c47 alcatel lucent + 885d90 ieee registration authority + 885dfb zte corporation + 885fe8 ieee registration authority 88615a siano mobile silicon ltd. + 8863df apple, inc. + 886440 apple, inc. + 886639 huawei technologies co.,ltd + 88665a apple, inc. + 8866a5 apple, inc. 88685c shenzhen chuangdao & perpetual eternal technology co.,ltd + 886ab1 vivo mobile communication co., ltd. + 886ae3 alpha networks inc. + 886b0f bluegiga technologies oy + 886b44 sunnovo international limited + 886b6e apple, inc. 886b76 china hopeful group hopeful electric co.,ltd + 886fd4 dell inc. + 887033 hangzhou silan microelectronic inc + 88708c lenovo mobile communication technology ltd. + 8870ef sc professional trading co., ltd. + 8871b1 arris group, inc. + 8871e5 amazon technologies inc. + 887384 toshiba 887398 k2e tekpoint - 887556 cisco + 887556 cisco systems, inc + 887598 samsung electronics co.,ltd + 887873 intel corporate 88789c game technologies sa + 88795b konka group co., ltd. + 88797e motorola mobility llc, a lenovo company + 887a31 velankani electronics pvt. ltd. + 887e25 extreme networks, inc. + 887f03 comper technology investment limited + 888279 shenzhen rb-link intelligent technology co.ltd + 888322 samsung electronics co.,ltd + 88835d fn-link technology limited 888603 huawei technologies co.,ltd 8886a0 simton technologies, ltd. + 8886c2 stabilo international gmbh 888717 canon inc. 8887dd darbeevision inc. 888914 all components incorporated + 88892f huawei technologies co.,ltd 888964 gsi electronics inc. - 888b5d storage appliance corporation + 888b5d storage appliance corporation 888c19 brady corp asia pacific ltd + 888e68 huawei device co., ltd. + 889009 juniper networks + 88908d cisco systems, inc 889166 viewcooper corp. 8891dd racktivity - 889471 brocade communications systems, inc. + 889471 brocade communications systems llc + 88947e fiberhome telecommunication technologies co.,ltd + 88948f xi'an zhisensor technologies co.,ltd 8894f9 gemicom technology, inc. 8895b9 unified packet systems crop + 88964e arris group, inc. + 889655 zitte corporation 889676 ttc marconi s.r.o. + 8896b6 global fire equipment s.a. + 8896f2 valeo schalter und sensoren gmbh + 889746 sichuan ai-link technology co., ltd. + 889765 exands 8897df entrypass corporation sdn. bhd. 889821 teraon 889b39 samsung electronics co.,ltd 889ca6 btb korea inc + 889d98 allied-telesisk.k. + 889e33 tct mobile ltd + 889e68 technicolor ch usa inc. + 889f6f samsung electronics co.,ltd + 889faa hella gutmann solutions gmbh 889ffa hon hai precision ind. co.,ltd. + 88a084 formation data systems + 88a25e juniper networks + 88a2d7 huawei technologies co.,ltd + 88a303 samsung electronics co.,ltd 88a3cc amatis controls + 88a479 apple, inc. 88a5bd qpcom inc. + 88a6c6 sagemcom broadband sas 88a73c ragentek technology group - 88acc1 generiton co., ltd. - 88ae1d compal information(kunshan)co.,ltd + 88a9a7 ieee registration authority + 88a9b7 apple, inc. + 88acc0 zyxel communications corporation + 88acc1 generiton co., ltd. + 88ad43 pegatron corporation + 88add2 samsung electronics co.,ltd + 88ae07 apple, inc. + 88ae1d compal information (kunshan) co., ltd. + 88b111 intel corporate 88b168 delta control gmbh - 88b1e1 airtight networks, inc. + 88b1e1 mojo networks, inc. + 88b291 apple, inc. + 88b362 nokia shanghai bell co., ltd. + 88b436 private + 88b4a6 motorola mobility llc, a lenovo company 88b627 gembird europe bv + 88b66b easynetworks + 88b6ee dish technologies corp + 88b8d0 dongguan koppo electronic co.,ltd 88ba7f qfiednet co., ltd. + 88bcc1 huawei technologies co.,ltd + 88bd45 samsung electronics co.,ltd + 88bd78 flaircomm microelectronics,inc. 88bfd5 simple audio ltd + 88bfe4 huawei technologies co.,ltd + 88c08b apple, inc. + 88c242 poynt co. + 88c255 texas instruments 88c36e beijing ereneben lnformation technology limited - 88c626 logitech - ultimate ears - 88c663 apple - 88cb87 apple + 88c397 beijing xiaomi mobile software co., ltd + 88c3b3 sovico + 88c3e5 betop techonologies + 88c626 logitech, inc + 88c663 apple, inc. + 88c9d0 lg electronics (mobile communications) + 88cb87 apple, inc. + 88cba5 suzhou torchstar intelligent technology co.,ltd + 88cc45 skyworth digital technology(shenzhen) co.,ltd + 88cefa huawei technologies co.,ltd + 88cf98 huawei technologies co.,ltd + 88d039 tcl technoly electronics(huizhou).,ltd + 88d171 beghelli s.p.a + 88d211 eko devices, inc. + 88d274 zte corporation + 88d2bf german autolabs + 88d37b firmtek, llc + 88d50c guangdong oppo mobile telecommunications corp.,ltd + 88d5a8 itel mobile limited + 88d652 amergint technologies 88d7bc dep company + 88d7f6 asustek computer inc. 88d962 canopus systems us llc + 88d98f juniper networks + 88da1a redpine signals, inc. + 88da33 beijing xiaoyuer network technology co., ltd 88dc96 senao networks, inc. 88dd79 voltaire + 88de7c askey computer corp. + 88dea9 roku, inc. + 88df9e new h3c technologies co., ltd + 88e034 shinwa industries(china) ltd. + 88e056 huawei technologies co.,ltd 88e0a0 shenzhen visionstor technologies co., ltd 88e0f3 juniper networks - 88e3ab huawei technologies co., ltd + 88e161 art beijing science and technology development co., ltd. + 88e3ab huawei technologies co.,ltd + 88e603 avotek corporation + 88e628 shenzhen kezhonglong optoelectronic technology co.,ltd + 88e64b juniper networks 88e712 whirlpool corporation 88e7a6 iknowledge integration corp. + 88e87f apple, inc. 88e8f8 yong tai electronic (dongguan) ltd. + 88e90f innomdlelab 88e917 tamaggo + 88e9a4 hewlett packard enterprise + 88e9fe apple, inc. 88ed1c cudo communication co., ltd. - 88f077 cisco systems, inc. + 88ef16 arris group, inc. + 88f031 cisco systems, inc + 88f077 cisco systems, inc 88f488 cellon communications technology(shenzhen)co.,ltd. 88f490 jetmobile pte ltd - 88f7c7 technicolor usa inc. + 88f56e huawei technologies co.,ltd + 88f7bf vivo mobile communication co., ltd. + 88f7c7 technicolor ch usa inc. + 88f872 huawei technologies co.,ltd 88fd15 lineeye co., ltd 88fed6 shanghai wangyong software co., ltd. - 8c006d apple - 8c04ff technicolor usa inc. + 8c006d apple, inc. + 8c02fa commando networks limited + 8c04ba dell inc. + 8c04ff technicolor ch usa inc. + 8c0551 koubachi ag 8c078c flow data inc 8c088b remote solution 8c09f4 arris group, inc. + 8c0c87 nokia 8c0c90 ruckus wireless 8c0ca3 amper - 8c0ee3 guangdong oppo mobile telecommunications corp.,ltd. + 8c0d76 huawei technologies co.,ltd + 8c0e60 nanjing juplink intelligent technologies co., ltd. + 8c0ee3 guangdong oppo mobile telecommunications corp.,ltd + 8c0f6f pegatron corporation + 8c0f83 angie hospitality llc + 8c0fa0 di-soric gmbh & co. kg + 8c0fc9 huawei device co., ltd. + 8c0ffa hutec co.,ltd + 8c10d4 sagemcom broadband sas 8c11cb abus security-center gmbh & co. kg - 8c1f94 rf surgical system inc. - 8c210a tp-link technologies co., ltd. + 8c147d ieee registration authority + 8c14b4 zte corporation + 8c15c7 huawei technologies co.,ltd + 8c1645 lcfc(hefei) electronics technology co., ltd + 8c1850 china mobile (hangzhou) information technology co., ltd. + 8c18d9 shenzhen rf technology co., ltd + 8c192d ieee registration authority + 8c19b5 arcadyan corporation + 8c1abf samsung electronics co.,ltd + 8c1cda ieee registration authority + 8c1f94 rf surgical system inc. + 8c210a tp-link technologies co.,ltd. + 8c2505 huawei technologies co.,ltd 8c271d quanthouse 8c278a vocollect inc - 8c2937 apple - 8c2daa apple + 8c2937 apple, inc. + 8c2a8e dongguan ramaxel memory technology + 8c2daa apple, inc. 8c2f39 iba dosimetry gmbh + 8c2fa6 solid optics b.v. + 8c31e2 dayouplus 8c3330 emfirst co., ltd. - 8c3ae3 lg electronics + 8c3357 hitevision digital media technology co.,ltd. + 8c3401 guangdong oppo mobile telecommunications corp.,ltd + 8c3446 huawei device co., ltd. + 8c34fd huawei technologies co.,ltd + 8c3579 qdiqo sp. z o.o. + 8c367a palo alto networks + 8c395c bit4id srl + 8c3a7e universal electronics, inc. + 8c3ae3 lg electronics (mobile communications) + 8c3b32 microfan b.v. + 8c3bad netgear 8c3c07 skiva technologies, inc. - 8c3c4a nakayo telecommunications,inc. + 8c3c4a nakayo inc 8c41f2 rda technologies ltd. + 8c41f4 ipmotion gmbh + 8c426d huawei technologies co.,ltd + 8c4361 hailo digital hub gmbh & co. kg 8c4435 shanghai broadmobi communication technology co., ltd. + 8c444f humax co., ltd. + 8c4500 murata manufacturing co., ltd. + 8c476e ieee registration authority + 8c47be dell inc. + 8c4962 roku, inc 8c4aee giga tms inc 8c4b59 3d imaging & simulations corp + 8c4cad evoluzn inc. 8c4cdc planex communications inc. 8c4db9 unmonday ltd 8c4dea cerio corporation 8c5105 shenzhen ireadygo information technology co.,ltd. + 8c53c3 beijing xiaomi mobile software co., ltd + 8c53d2 china mobile group device co.,ltd. 8c53f7 a&d engineering co., ltd. - 8c541d lge + 8c541d lge + 8c554a intel corporate + 8c55bb songwoo information & technology co., ltd 8c569d imaging solutions group 8c56c5 nintendo co., ltd. + 8c579b wistron neweb corporation 8c57fd lvx western - 8c5877 apple + 8c5877 apple, inc. + 8c593c ieee registration authority + 8c5973 zyxel communications corporation 8c598b c technologies ab + 8c59c3 adb italia + 8c59dc asr microelectronics (shanghai) co., ltd. + 8c5a25 arris group, inc. + 8c5ac1 huawei device co., ltd. 8c5af0 exeltech solar products + 8c5af8 beijing xiaomi electronics co., ltd. + 8c5bf0 arris group, inc. 8c5ca1 d-broad,inc + 8c5d60 uci corporation co.,ltd. + 8c5ebd huawei device co., ltd. + 8c5f48 continental intelligent transportation systems llc + 8c5fad fiberhome telecommunication technologies co.,ltd 8c5fdf beijing railway signal factory - 8c604f cisco systems, inc. + 8c604f cisco systems, inc + 8c6078 swissbit ag + 8c60e7 mpgio co.,ltd + 8c6102 beijing baofengmojing technologies co., ltd + 8c61a3 arris group, inc. 8c640b beyond devices d.o.o. - 8c6422 sony ericsson mobile communications ab + 8c6422 sony mobile communications inc + 8c64d4 hyeco smart tech co.,ltd + 8c683a huawei technologies co.,ltd 8c6878 nortek-as + 8c68c8 zte corporation 8c6ae4 viogem limited + 8c6d50 shenzhen mtc co ltd + 8c6d77 huawei technologies co.,ltd + 8c6dc4 megapixel vr 8c705a intel corporate + 8c7086 gesellschaft für sonder-edv-anlagen mbh 8c71f8 samsung electronics co.,ltd 8c736e fujitsu limited + 8c73a0 fiberhome telecommunication technologies co.,ltd 8c76c1 goden tech limited 8c7712 samsung electronics co.,ltd 8c7716 longcheer telecommunication limited - 8c7b9d apple - 8c7c92 apple + 8c78d7 shenzhen fast technologies co.,ltd + 8c7967 zte corporation + 8c79f5 samsung electronics co.,ltd + 8c7a15 ruckus wireless + 8c7b9d apple, inc. + 8c7bf0 xufeng development limited + 8c7c92 apple, inc. 8c7cb5 hon hai precision ind. co.,ltd. - 8c7cff brocade communications systems, inc. + 8c7cff brocade communications systems llc 8c7eb3 lytro, inc. + 8c7f3b arris group, inc. + 8c8126 arcom 8c82a8 insigma technology co.,ltd - 8c8401 + 8c839d shenzhen xinyupeng electronic technology co., ltd + 8c83df nokia + 8c83e1 samsung electronics co.,ltd + 8c83fc axioma metering uab + 8c8401 private + 8c8580 smart innovation llc + 8c8590 apple, inc. + 8c85c1 aruba, a hewlett packard enterprise company + 8c85e6 cleondris gmbh + 8c861e apple, inc. + 8c873b leica camera ag + 8c897a augtek 8c89a5 micro-star int'l co., ltd + 8c89fa zhejiang hechuan technology co., ltd. 8c8a6e estun automation technoloy co., ltd + 8c8abb beijing orient view technology co., ltd. + 8c8b83 texas instruments + 8c8caa lcfc(hefei) electronics technology co., ltd + 8c8d28 intel corporate 8c8e76 taskit gmbh - 8c90d3 alcatel lucent + 8c8ef2 apple, inc. + 8c8f8b china mobile chongqing branch + 8c8fe9 apple, inc. + 8c90d3 nokia + 8c9109 toyoshima electric technoeogy(suzhou) co.,ltd. 8c9236 aus.linx technology co., ltd. + 8c9246 oerlikon textile gmbh&co.kg + 8c9351 jigowatts inc. + 8c941f cisco systems, inc 8c94cf encell technology, inc. + 8c965f shandong zhongan technology co., ltd. + 8c97ea freebox sas + 8c99e6 tct mobile ltd + 8c9f3b qingdao hisense communications co.,ltd. 8ca048 beijing netopchip technology co.,ltd + 8ca2fd starry, inc. + 8ca5a1 oregano systems - design & consulting gmbh + 8ca6df tp-link technologies co.,ltd. + 8ca96f d&m holdings inc. 8ca982 intel corporate + 8caab5 espressif inc. + 8caace xiaomi communications co ltd + 8cab8e shanghai feixun communication co.,ltd. + 8cae49 ieee registration authority 8cae4c plugable technologies 8cae89 y-cam solutions ltd - 8cb64f cisco systems, inc. + 8caedb nag llc + 8cb094 airtech i&c co., ltd + 8cb0e9 samsung electronics.,ltd + 8cb64f cisco systems, inc 8cb7f7 shenzhen unistrong science & technology co., ltd 8cb82c ipitomy communications + 8cb84a samsung electro-mechanics(thailand) 8cb864 acsip technology corp. - 8cbebe xiaomi technology co.,ltd + 8cba25 unionman technology co.,ltd + 8cbe24 tashang semiconductor(shanghai) co., ltd. + 8cbebe xiaomi communications co ltd + 8cbf9d shanghai xinyou information technology ltd. co. + 8cbfa6 samsung electronics co.,ltd 8cc121 panasonic corporation avc networks company + 8cc5b4 sagemcom broadband sas 8cc5e1 shenzhen konka telecommunication technology co.,ltd + 8cc661 current, powered by ge + 8cc681 intel corporate 8cc7aa radinet communications inc. 8cc7d0 zhejiang ebang communication co.,ltd - 8cc8cd samsung electronics co., ltd + 8cc84b chongqing fugui electronics co.,ltd. + 8cc8cd samsung electronics co.,ltd + 8cc8f4 ieee registration authority 8ccda2 actp, inc. 8ccde8 nintendo co., ltd. + 8cce4e espressif inc. + 8ccefd shenzhen zhouhai technology co.,ltd + 8ccf09 dell emc 8ccf5c befega gmbh + 8ccf8f itc systems 8cd17b cg mobile + 8cd2e9 yokote seiko co., ltd. 8cd3a2 vissim as + 8cd48e itel mobile limited 8cd628 ikor metering + 8cd67f em microelectronic + 8cd9d6 xiaomi communications co ltd 8cdb25 esg solutions + 8cdc02 zte corporation + 8cdcd4 hewlett packard 8cdd8d wifly-city system inc. 8cde52 issc technologies corp. 8cde99 comlab inc. + 8cdee6 samsung electronics co.,ltd + 8cdef9 beijing xiaomi mobile software co., ltd + 8cdf9d nec corporation 8ce081 zte corporation - 8ce748 + 8ce117 zte corporation + 8ce2da circle media inc + 8ce38e kioxia corporation + 8ce468 guangzhou sageran technology co., ltd. + 8ce5c0 samsung electronics co.,ltd + 8ce5ef huawei technologies co.,ltd + 8ce748 hangzhou hikvision digital technology co.,ltd. + 8ce78c dk networks 8ce7b3 sonardyne international ltd + 8cea1b edgecore networks corporation + 8cea48 samsung electronics co.,ltd + 8cebc6 huawei technologies co.,ltd + 8cec4b dell inc. + 8cec7b apple, inc. 8ceec6 precepscion pty. ltd. + 8cf112 motorola mobility llc, a lenovo company + 8cf228 mercury communication technologies co.,ltd. + 8cf319 siemens industrial automation products ltd., chengdu + 8cf5a3 samsung electro-mechanics(thailand) + 8cf710 ampak technology, inc. + 8cf773 nokia + 8cf813 orange polska 8cf945 power automation pte ltd + 8cf957 ruixinghengfang network (shenzhen) co.,ltd 8cf9c9 mesada technology co.,ltd. - 8cfaba apple - 8cfdf0 qualcomm incorporated + 8cfaba apple, inc. + 8cfca0 shenzhen smart device technology co., ltd. + 8cfd18 huawei technologies co.,ltd + 8cfdde sagemcom broadband sas + 8cfdf0 qualcomm inc. + 8cfe57 apple, inc. + 8cfe74 ruckus wireless + 8cfeb4 vsoontech electronics co., limited 90004e hon hai precision ind. co.,ltd. - 90013b sagemcom + 9000db samsung electronics co.,ltd + 90013b sagemcom broadband sas + 900218 bskyb ltd + 90027a shenzhen sworix techonlogy co., ltd 90028a shenzhen shidean legrand electronic products co.,ltd - 9002a9 zhejiang dahua technology co.,ltd - 9003b7 parrot + 9002a9 zhejiang dahua technology co., ltd. + 900325 huawei technologies co.,ltd + 900372 longnan junya digital technology co. ltd. + 9003b7 parrot sa + 900628 samsung electronics co.,ltd 900917 far-sighted mobile + 900a1a taicang t&w electronics + 900a39 wiio, inc. 900a3a psg plastic service gmbh + 900a84 mellanox technologies, inc. + 900bc1 sprocomm technologies co.,ltd + 900cb4 alinket electronic technology co., ltd + 900cc8 google, inc. 900d66 digimore electronics co., ltd 900dcb arris group, inc. + 900e83 monico monitoring, inc. + 900eb3 shenzhen amediatech technology co., ltd. + 900f0c cloud network technology singapore pte. ltd. + 901234 shenzhen youhua technology co., ltd + 9012a1 we corporation inc. + 9013da athom b.v. + 9016ba huawei technologies co.,ltd + 901711 hagenuk marinekommunikation gmbh + 90173f huawei technologies co.,ltd + 90179b nanomegas + 9017ac huawei technologies co.,ltd + 9017c8 huawei technologies co.,ltd 90185e apex tool group gmbh & co ohg 90187c samsung electro mechanics co., ltd. 9018ae shanghai meridian technologies, co. ltd. 901900 scs sa + 901a4f em microelectronic 901aca arris group, inc. 901b0e fujitsu technology solutions gmbh 901d27 zte corporation 901edd great computer corporation + 90203a byd precision manufacture co.,ltd 902083 general engine management systems ltd. + 9020c2 aruba, a hewlett packard enterprise company + 902106 bskyb ltd 902155 htc corporation - 9027e4 apple + 902181 shanghai huaqin telecom technology co.,ltd + 9023b4 new h3c technologies co., ltd + 9023ec availink, inc. + 90272b algorab s.r.l. + 9027e4 apple, inc. 902b34 giga-byte technology co.,ltd. + 902bd2 huawei technologies co.,ltd + 902cc7 c-max asia limited + 902e1c intel corporate 902e87 labjack 9031cd onyx healthcare inc. + 90324b hon hai precision ind. co.,ltd. 90342b gatekeeper systems, inc. 9034fc hon hai precision ind. co.,ltd. 90356e vodafone omnitel n.v. + 903809 ericsson ab 9038df changzhou tiannengbo system co. ltd. - 903aa0 alcatel-lucent + 903a72 ruckus wireless + 903aa0 nokia + 903ae6 parrot sa + 903c92 apple, inc. 903cae yunnan ksec digital technology co.,ltd. + 903cb3 edgecore networks corporation 903d5a shenzhen wision technology holding limited + 903d68 g-printec, inc. 903d6b zicon technology corp. + 903dbd secure meters limited 903eab arris group, inc. + 903fea huawei technologies co.,ltd + 9043e2 cornami, inc + 904506 tokyo boeki medisys inc. + 9046a2 tedipay uk ltd 9046b7 vadaro pte ltd 904716 rorze corporation - 9049fa intel corporation + 90473c china mobile group device co.,ltd. + 90489a hon hai precision ind. co.,ltd. + 9049fa intel corporate + 904c81 hewlett packard enterprise 904ce5 hon hai precision ind. co.,ltd. - 904e2b huawei technologies co., ltd + 904d4a sagemcom broadband sas + 904dc3 flonidan a/s + 904e2b huawei technologies co.,ltd + 904e91 ieee registration authority + 90505a unglue, inc 90507b advanced panmobil systems gmbh & co. kg - 90513f elettronica santerno + 9050ca hitron technologies. inc + 90513f elettronica santerno spa 905446 tes electronic solutions 9055ae ericsson, eab/rwi/k + 9055de fiberhome telecommunication technologies co.,ltd 905682 lenbrook industries limited 905692 autotalks ltd. + 9056fc tecno mobile limited + 905851 technicolor ch usa inc. 9059af texas instruments - 905f2e tct mobile limited + 905c34 sirius electronic systems srl + 905c44 compal broadband networks, inc. + 905d7c new h3c technologies co., ltd + 905f2e tct mobile ltd 905f8d modas gmbh + 9060f1 apple, inc. 90610c fida international (s) pte ltd + 9061ae intel corporate + 90633b samsung electronics co.,ltd 906717 alphion india private limited + 90671c huawei technologies co.,ltd 9067b5 alcatel-lucent 9067f3 alcatel lucent + 9068c3 motorola mobility llc, a lenovo company + 906cac fortinet, inc. + 906d05 bxb electronics co., ltd 906dc8 dlg automação industrial ltda 906ebb hon hai precision ind. co.,ltd. + 906f18 private + 906fa9 nanjing putian telecommunications technology co.,ltd. 907025 garea microsys co.,ltd. - 907240 apple + 907065 texas instruments + 907240 apple, inc. + 907282 sagemcom broadband sas + 90735a motorola mobility llc, a lenovo company + 90749d iray technology co., ltd. + 90769f shenzhen mercury communication technologies co.,ltd. + 9077ee cisco systems, inc + 907841 intel corporate + 9078b2 xiaomi communications co ltd + 907910 integrated device technology (malaysia) sdn. bhd. 907990 benchmark electronics romania srl 907a0a gebr. bode gmbh & co kg 907a28 beijing morncloud information and technology co. ltd. - 907af1 snupi technologies + 907a58 zegna-daidong limited + 907af1 wally + 907e30 lars + 907eba utek technology (shenzhen) co.,ltd 907f61 chicony electronics co., ltd. + 90808f huawei device co., ltd. + 90812a apple, inc. + 908158 apple, inc. 908260 ieee 1904.1 working group + 90834b beijing yunyi times technology co,.ltd 90837a general electric water & process technologies - 90840d apple + 90840d apple, inc. + 90842b lego system a/s + 90848b hdr10+ technologies, llc + 908674 sichuan tianyi comheart telecomco., ltd + 90869b zte corporation 9088a2 ionics technology me ltda + 90895f weifang goertek electronics co.,ltd + 908c09 total phase + 908c43 apple, inc. 908c44 h.k zongmu technology co., ltd. + 908c63 gz weedong networks technology co. , ltd 908d1d gh technologies + 908d6c apple, inc. + 908d78 d-link international 908fcf uno system co., ltd 90903c trison technology corporation 909060 rsi video technologies + 909164 chongqing lavid technology co., ltd. 9092b4 diehl bgt defence gmbh & co. kg + 90940a analog devices, inc + 909497 huawei technologies co.,ltd 9094e4 d-link international + 9096f3 buffalo.inc + 9097d5 espressif inc. + 9097f3 samsung electronics co.,ltd + 909838 huawei device co., ltd. 909864 impex-sat gmbh&co kg 909916 elvees neotek ojsc + 909a4a tp-link technologies co.,ltd. + 909a77 texas instruments + 909c4a apple, inc. + 909d7d arris group, inc. 909de0 newland design + assoc. inc. + 909f33 efm networks 909f43 accutron instruments inc. + 90a137 beijing splendidtel communication technology co,. ltd + 90a210 united telecoms ltd + 90a25b apple, inc. 90a2da gheo sa - 90a4de wistron neweb corp. - 90a783 jsw pacific corporation + 90a365 hmd global oy + 90a46a sisnet co., ltd + 90a4de wistron neweb corporation + 90a5af huawei technologies co.,ltd + 90a62f naver + 90a783 jsw pacific corporation 90a7c1 pakedge device and software inc. + 90a822 amazon technologies inc. + 90a935 jwentertainment + 90aac3 hitron technologies. inc 90ac3f brightsign llc + 90adf7 vivo mobile communication co., ltd. + 90adfc telechips, inc. 90ae1b tp-link technologies co.,ltd. + 90afd1 netkti co., ltd + 90b0ed apple, inc. 90b11c dell inc. 90b134 arris group, inc. - 90b21f apple + 90b144 samsung electronics co.,ltd + 90b1e0 beijing nebula link technology co., ltd + 90b21f apple, inc. + 90b4dd private + 90b67a shenzhen skyworth digital technology co., ltd + 90b686 murata manufacturing co., ltd. + 90b832 extreme networks, inc. 90b8d0 joyent, inc. - 90b931 apple, inc + 90b8e0 shenzhen yanray technology co.,ltd + 90b931 apple, inc. 90b97d johnson outdoors marine electronics d/b/a minnkota - 90c115 sony ericsson mobile communications ab + 90bde6 quectel wireless solutions co., ltd. + 90c115 sony mobile communications inc + 90c119 nokia + 90c1c6 apple, inc. + 90c35f nanjing jiahao technology co., ltd. + 90c54a vivo mobile communication co., ltd. + 90c682 ieee registration authority + 90c792 arris group, inc. + 90c7d8 zte corporation + 90c99b tesorion nederland b.v. 90cc24 synaptics, inc + 90ccdf intel corporate + 90cdb6 hon hai precision ind. co.,ltd. 90cf15 nokia corporation 90cf6f dlogixs co ltd - 90cf7d qingdao hisense electric co.,ltd. + 90cf7d qingdao hisense communications co.,ltd. 90d11b palomar medical technologies 90d74f bookeen + 90d7be wavelab global inc. 90d7eb texas instruments 90d852 comtec co., ltd. + 90d8f3 zte corporation 90d92c hug-witschi ag 90da4e avanu + 90da6a focus h&s co., ltd. 90db46 e-lead electronic co., ltd + 90dd5d apple, inc. + 90de80 shenzhen century xinyang technology co., ltd 90dfb7 s.m.s smart microwave sensors gmbh + 90dffb homerider systems 90e0f0 ieee 1722a working group + 90e17b apple, inc. + 90e202 texas instruments 90e2ba intel corporate + 90e2fc ieee registration authority 90e6ba asustek computer inc. - 90ea60 spi lasers ltd + 90e710 new h3c technologies co., ltd + 90e7c4 htc corporation + 90ea60 spi lasers ltd + 90ec50 c.o.b.o. spa + 90ec77 silicom + 90eec7 samsung electronics co.,ltd + 90eed9 universal de desarrollos electrÓnicos, sa + 90ef68 zyxel communications corporation + 90f052 meizu technology co., ltd. 90f1aa samsung electronics co.,ltd 90f1b0 hangzhou anheng info&tech co.,ltd 90f278 radius gateway + 90f305 humax co., ltd. 90f3b7 kirisun communications co., ltd. 90f4c1 rand mcnally - 90f652 tp-link technologies co., ltd. - 90f72f phillips machine & welding co., inc. - 90fb5b avaya, inc - 90fba6 hon hai precision ind.co.ltd + 90f644 huawei device co., ltd. + 90f652 tp-link technologies co.,ltd. + 90f72f phillips machine & welding co., inc. + 90f891 kaonmedia co., ltd. + 90f9b7 huawei technologies co.,ltd + 90fb5b avaya inc + 90fba6 hon hai precision ind. co.,ltd. + 90fd61 apple, inc. + 90fd73 zte corporation + 90fd9f silicon laboratories 90ff79 metro ethernet forum + 90ffd6 honor device co., ltd. + 940006 jinyoung 940070 nokia corporation + 9400b0 huawei technologies co.,ltd 940149 autohotbox 9401c2 samsung electronics co.,ltd + 94026b optictimes co.,ltd + 94049c huawei technologies co.,ltd + 9405b6 liling fullriver electronics & technology ltd + 9405bb ieee registration authority + 940853 liteon technology corporation + 9408c7 huawei device co., ltd. + 940937 humax co., ltd. + 9409d3 shenzhen maxtopic technology co.,ltd + 940b19 huawei technologies co.,ltd 940b2d netview technologies(shenzhen) co., ltd 940bd5 himax technologies, inc 940c6d tp-link technologies co.,ltd. + 940c98 apple, inc. + 940e6b huawei technologies co.,ltd 94103e belkin international inc. 9411da itf fröschl gmbh + 94147a vivo mobile communication co., ltd. + 941625 apple, inc. 941673 point core sarl + 941700 xiaomi communications co ltd + 941882 hewlett packard enterprise + 94193a elvaco ab + 941c56 actiontec electronics, inc 941d1c tlab west systems ab 942053 nokia corporation 942197 stalmart technology limited 94236e shenzhen junlan electronic ltd + 9424b8 gree electric appliances, inc. of zhuhai + 9424e1 alcatel-lucent enterprise + 942533 huawei technologies co.,ltd + 942790 tct mobile ltd + 94282e new h3c technologies co., ltd + 94290c shenyang wisdom foundation technology development co., ltd. + 94292f new h3c technologies co., ltd + 94298d shanghai adaptcomm technology co., ltd. + 942a3f diversey inc + 942cb3 humax co., ltd. + 942ddc samsung electronics co.,ltd 942e17 schneider electric canada inc 942e63 finsécur 94319b alphatronics bv - 9433dd taco electronic solutions, inc. + 9433dd taco inc 94350a samsung electronics co.,ltd 9436e0 sichuan bihong broadcast & television new technologies co.,ltd + 9437f7 huawei device co., ltd. 9439e5 hon hai precision ind. co.,ltd. + 943a91 amazon technologies inc. 943af0 nokia corporation - 943bb1 kaonmedia + 943bb0 new h3c technologies co., ltd + 943bb1 kaonmedia co., ltd. + 943cc6 espressif inc. + 943dc9 asahi net, inc. + 943fc2 hewlett packard enterprise 9440a2 anywave communication technologies, inc. + 9440c9 hewlett packard enterprise + 9441c1 mini-cam limited + 94434d ciena corporation 944444 lg innotek 944452 belkin international inc. 944696 baudtec corporation + 9447b0 beijing eswin computing technology co., ltd + 944996 wisilica inc 944a09 bitwise controls + 944a0c sercomm corporation. + 944f4c sound united llc 945047 rechnerbetriebsgruppe - 945103 samsung electronics + 945089 simonsvoss technologies gmbh + 945103 samsung electronics co.,ltd + 94513d ismart alarm, inc. 9451bf hyundai esg + 945330 hon hai precision ind. co.,ltd. + 945493 rigado, llc + 9454ce guangdong oppo mobile telecommunications corp.,ltd + 9454df yst corp. + 945641 palo alto networks + 9457a5 hewlett packard + 9458cb nintendo co.,ltd + 945907 shanghai hite-belden network technology co., ltd. 94592d eke building technology systems ltd 945b7e trilobit ltda. + 945f34 renesas electronics (penang) sdn. bhd. + 946010 huawei device co., ltd. + 94611e wata electronics co.,ltd. 946124 pason systems + 946269 arris group, inc. + 946372 vivo mobile communication co., ltd. 9463d1 samsung electronics co.,ltd - 9471ac tct mobile limited + 94652d oneplus technology (shenzhen) co., ltd + 94659c intel corporate + 9466e7 wom engineering + 94677e belden india private limited + 946a77 technicolor ch usa inc. + 946ab0 arcadyan corporation + 9470d2 winfirm technology + 9471ac tct mobile ltd 94756e qinetiq north america + 9476b7 samsung electronics co.,ltd + 94772b huawei technologies co.,ltd + 947bbe ubicquia llc + 947be7 samsung electronics co.,ltd 947c3e polewall norge as + 947eb9 national narrowband network communications pty ltd 9481a4 azuray technologies + 9483c4 gl technologies (hong kong) limited 94857a evantage industries corp + 9486cd seoul electronics&telecom 9486d4 surveillance pro corporation 94877c arris group, inc. + 9487e0 xiaomi communications co ltd + 948815 infinique worldwide inc 948854 texas instruments + 94885e surfilter network technology co., ltd. + 948ac6 realme chongqing mobile telecommunications corp.,ltd. 948b03 eaget innovation and technology co., ltd. + 948bc1 samsung electronics co.,ltd 948d50 beamex oy ab - 948fee hughes telematics, inc. - 949426 apple + 948def oetiker schweiz ag + 948e89 industrias unidas sa de cv + 948ed3 arista networks + 948fcf arris group, inc. + 948fee verizon telematics + 949034 shenzhen chuangwei-rgb electronics co.,ltd + 94917f askey computer corp + 9492bc syntech(hk) technology limited + 9492d2 kcf technologies, inc. + 949426 apple, inc. + 9495a0 google, inc. 9498a2 shanghai listen tech.ltd + 949901 shenzhen yitoa digital appliance co.,ltd + 949990 vtc telecommunications + 949aa9 microsoft corporation + 949b2c extreme networks, inc. 949bfd trans new technology, inc. 949c55 alta data technologies + 949d57 panasonic do brasil limitada + 949f3e sonos, inc. 949f3f optek digital technology company limited 949fb4 chengdu jiafaantai technology co.,ltd + 94a04e bostex technology co., ltd + 94a1a2 ampak technology, inc. + 94a3ca konnectone, llc + 94a40c diehl metering gmbh + 94a4f9 huawei technologies co.,ltd + 94a67e netgear + 94a7b7 zte corporation 94a7bc bodymedia, inc. 94aab8 joview(beijing) technology co. ltd. + 94abde omx technology - fze 94acca trivum technologies gmbh 94ae61 alcatel lucent + 94aee3 belden hirschmann industries (suzhou) ltd. + 94aef0 cisco systems, inc + 94b01f apple, inc. + 94b10a samsung electronics co.,ltd + 94b271 huawei technologies co.,ltd + 94b2cc pioneer corporation + 94b40f aruba, a hewlett packard enterprise company + 94b819 nokia + 94b86d intel corporate 94b8c5 ruggedcom inc. + 94b97e espressif inc. 94b9b4 aptos technology 94ba31 visiontec da amazônia ltda. 94ba56 shenzhen coship electronics co., ltd. + 94bbae husqvarna ab + 94be46 motorola (wuhan) mobility technologies communication co., ltd. 94bf1e eflow inc. / smart device planning and development division + 94bf2d apple, inc. + 94bf80 zte corporation + 94bf94 juniper networks + 94bf95 shenzhen coship electronics co., ltd + 94bfc4 ruckus wireless 94c014 sorter sp. j. konrad grzeszczyk michaa, ziomek + 94c038 tallac networks 94c150 2wire inc - 94c3e4 sca schucker gmbh & co kg + 94c2bd tecnobit + 94c3e4 atlas copco ias gmbh 94c4e9 powerlayer microsystems hongkong limited + 94c691 elitegroup computer systems co., ltd 94c6eb nova electronics, inc. 94c7af raylios technology + 94c960 zhongshan b&t technology.co.,ltd 94c962 teseq ag 94ca0f honeywell analytics + 94cc04 ieee registration authority 94ccb9 arris group, inc. 94cdac creowave oy - 94ce2c sony mobile communications ab + 94ce2c sony mobile communications inc + 94ce31 cts limited + 94d00d huawei technologies co.,ltd 94d019 cydle corp. - 94d723 shanghai dareglobal technologies co., ltd + 94d029 guangdong oppo mobile telecommunications corp.,ltd + 94d075 cis crypto + 94d299 techmation co.,ltd. + 94d417 gpi korea inc. + 94d469 cisco systems, inc + 94d505 fiberhome telecommunication technologies co.,ltd + 94d60e shenzhen yunmao information technologies co., ltd + 94d6db nexfi + 94d723 shanghai dareglobal technologies co.,ltd 94d771 samsung electronics co.,ltd + 94d859 tct mobile ltd 94d93c enelps + 94d9b3 tp-link technologies co.,ltd. 94db49 sitcorp - 94dbc9 azurewave + 94db56 sony home entertainment&sound products inc + 94dbc9 azurewave technology inc. + 94dbda huawei technologies co.,ltd + 94dc4e aev, spol. s r. o. 94dd3f a+v link technologies, corp. 94de0e smartoptics as 94de80 giga-byte technology co.,ltd. 94df4e wistron infocomm(kunshan)co.,ltd. 94df58 ij electron co.,ltd. 94e0d0 healthstream taiwan inc. + 94e0d6 china dragon technology limited + 94e1ac hangzhou hikvision digital technology co.,ltd. 94e226 d. ortiz consulting, llc + 94e23c intel corporate + 94e2fd boge kompressoren otto boge gmbh & co. kg + 94e36d texas instruments + 94e3ee zte corporation + 94e4ba huawei device co., ltd. + 94e6f7 intel corporate + 94e70b intel corporate 94e711 xirka dama persada pt + 94e7ea huawei technologies co.,ltd 94e848 fylde micro ltd - 94e98c alcatel-lucent - 94eb2c google inc. - 94ebcd research in motion limited + 94e8c5 arris group, inc. + 94e96a apple, inc. + 94e979 liteon technology corporation + 94e98c nokia + 94e9ee huawei device co., ltd. + 94ea32 apple, inc. + 94eaea tellescom industria e comercio em telecomunicacao + 94eb2c google, inc. + 94ebcd blackberry rts + 94ee9f hmd global oy + 94f128 hewlett packard enterprise + 94f19e huizhou maorong intelligent technology co.,ltd + 94f278 elma electronic + 94f2bb valeo vision systems + 94f551 cadi scientific pte ltd + 94f665 ruckus wireless 94f692 geminico co.,ltd. + 94f6a3 apple, inc. + 94f6d6 apple, inc. 94f720 tianjin deviser electronics instrument co., ltd - 94fae8 shenzhen eycom technology co., ltd - 94fbb2 shenzhen gongjin electronics co.,ltd + 94f7ad juniper networks + 94fae8 shenzhen eycom technology co., ltd + 94fb29 zebra technologies inc. + 94fba7 ieee registration authority + 94fbb2 shenzhen gongjin electronics co.,lt 94fd1d wherewhen corp 94fd2e shanghai uniscope technologies co.,ltd - 94fef4 sagemcom + 94fe22 huawei technologies co.,ltd + 94fe9d shenzhen gongjin electronics co.,lt + 94fef4 sagemcom broadband sas + 94ff61 china mobile group device co.,ltd. + 98006a zte corporation + 980074 raisecom technology co., ltd + 9800c1 guangzhou creator technology co.,ltd.(china) + 9800c6 apple, inc. + 9801a7 apple, inc. 980284 theobroma systems gmbh + 9802d8 ieee registration authority + 98039b mellanox technologies, inc. 9803a0 abb n.v. power quality products - 9803d8 apple - 980c82 samsung electro mechanics + 9803d8 apple, inc. + 980637 ieee registration authority + 98063a home control singapore pte ltd + 98063c samsung electronics co.,ltd + 98072d texas instruments + 9809cf oneplus technology (shenzhen) co., ltd + 980c82 samsung electro mechanics co., ltd. + 980ca5 motorola (wuhan) mobility technologies communication co., ltd. 980d2e htc corporation - 980ee4 + 980d51 huawei device co., ltd. + 980d67 zyxel communications corporation + 980e24 phytium technology co.,ltd. + 980ee4 private 981094 shenzhen vsun communication technology co.,ltd + 9810e8 apple, inc. + 981333 zte corporation + 9814d2 avonic + 9816ec ic intracom + 981888 cisco meraki + 981a35 huawei technologies co.,ltd + 981bb5 assa abloy korea co., ltd irevo + 981dfa samsung electronics co.,ltd + 981e0f jeelan (shanghai jeelan technology information inc + 981e19 sagemcom broadband sas + 981fb1 shenzhen lemon network technology co.,ltd 98208e definium technologies + 9822ef liteon technology corporation + 98234e micromedia ag 98262a applied research associates, inc + 982782 ieee registration authority + 9828a6 compal information (kunshan) co., ltd. 98291d jaguar de mexico, sa de cv 98293f fujian start computer equipment co.,ltd - 982cbe 2wire + 9829a6 compal information (kunshan) co., ltd. + 982cbc intel corporate + 982cbe 2wire inc 982d56 resolution audio + 982d68 samsung electronics co., ltd + 982dba fibergate inc. + 982f3c sichuan changhong electric ltd. + 982ff8 huawei device co., ltd. 983000 beijing kemacom technologies co., ltd. 983071 daikyung vascom 98349d krauss maffei technologies gmbh 983571 sub10 systems ltd 9835b8 assembled products corporation + 9835ed huawei technologies co.,ltd 983713 pt.navicom indonesia - 983b16 ampak technology inc + 98387d itronic technology co . , ltd . + 98398e samsung electronics co.,ltd + 983b16 ampak technology, inc. + 983b8f intel corporate + 983f60 huawei technologies co.,ltd + 983f66 wuhan funshion online technologies co.,ltd 983f9f china ssj (suzhou) network technology inc. + 9840bb dell inc. + 98415c nintendo co.,ltd 984246 sol industry pte., ltd + 984265 sagemcom broadband sas 9843da intertech + 9844b6 infranor sas + 9844ce huawei technologies co.,ltd + 984562 shanghai baud data communication co.,ltd. + 98460a apple, inc. 98473c shanghai sunmon communication technogy co.,ltd + 984827 tp-link technologies co.,ltd. + 984874 huawei technologies co.,ltd + 984914 wistron neweb corporation + 9849e1 boeing defence australia 984a47 chg hospital beds 984b4a arris group, inc. - 984be1 hewlett-packard company + 984be1 hewlett packard 984c04 zhangzhou keneng electrical equipment co ltd 984cd3 mantis deposition 984e97 starlight marketing (h. k.) ltd. 984fee intel corporate - 9852b1 samsung electronics + 98523d sunitec enterprise co.,ltd + 98524a technicolor ch usa inc. + 9852b1 samsung electronics co.,ltd + 98541b intel corporate 9857d3 hon hai-ccpbg precision ind.co.,ltd. 98588a sysgration ltd. 985945 texas instruments + 985949 luxottica group s.p.a. + 985aeb apple, inc. + 985bb0 kmdata inc. 985c93 sbg systems sas 985d46 peoplenet communication + 985d82 arista networks + 985dad texas instruments 985e1b conversdigital co., ltd. + 985fd3 microsoft corporation 986022 emw co., ltd. + 9860ca apple, inc. 9866ea industrial control communications, inc. 986b3d arris group, inc. + 986c5c jiangxi gosun guard security co.,ltd 986cf5 zte corporation + 986d35 ieee registration authority 986dc8 toshiba mitsubishi-electric industrial systems corporation + 986f60 guangdong oppo mobile telecommunications corp.,ltd + 9870e8 innatech sdn bhd 9873c4 sage electronic engineering llc + 98743d shenzhen jun kai hengye technology co. ltd + 9874da infinix mobility limited + 98751a huawei device co., ltd. 9876b6 adafruit 987770 pep digital technology (guangzhou) co., ltd + 9877e7 kaonmedia co., ltd. + 987a10 ericsson ab + 987a14 microsoft corporation + 987bf3 texas instruments + 987e46 emizon networks limited + 987eca inventus power eletronica do brasil ltda + 9880ee samsung electronics co.,ltd 988217 disruptive ltd + 988389 samsung electronics co.,ltd + 9884e3 texas instruments + 98865d nokia shanghai bell co., ltd. 9886b1 flyaudio corporation (china) + 988744 wuxi hongda science and technology co.,ltd 9889ed anadem information inc. - 988b5d sagem communication + 988b0a hangzhou hikvision digital technology co.,ltd. + 988b5d sagemcom broadband sas + 988b69 shenzhen hylitech co.,ltd 988bad corintech ltd. + 988d46 intel corporate 988e34 zhejiang boxsam electronic co.,ltd 988e4a noxus(beijing) technology co.,ltd + 988e79 qudelix, inc. + 988ed4 itel mobile limited 988edd te connectivity limerick 989080 linkpower network system inc ltd. - 9893cc lg electronics inc. + 989096 dell inc. + 9893cc lg electronics inc 989449 skyworth wireless technology ltd. + 9897d1 mitrastar technology corp. + 989ab9 zte corporation + 989bcb avm audiovisuelles marketing und computersysteme gmbh + 989c57 huawei technologies co.,ltd + 989d5d technicolor ch usa inc. + 989e63 apple, inc. + 98a404 ericsson ab + 98a40e snap, inc. 98a7b0 mcst zao + 98a942 guangzhou tozed kangwei intelligent technology co., ltd + 98aa3c will i-tech co., ltd. 98aad7 blue wave networking co ltd - 98b039 alcatel-lucent - 98b8e3 apple + 98aafc ieee registration authority + 98ad1d huawei device co., ltd. + 98ae71 vvdn technologies pvt ltd + 98af65 intel corporate + 98b039 nokia + 98b3ef huawei device co., ltd. + 98b6e9 nintendo co.,ltd + 98b8ba lg electronics (mobile communications) + 98b8bc samsung electronics co.,ltd + 98b8e3 apple, inc. + 98ba39 doro ab + 98bb1e byd precision manufacture company ltd. + 98bb99 phicomm (sichuan) co.,ltd. 98bc57 sva technologies co.ltd 98bc99 edeltech co.,ltd. 98be94 ibm + 98bedc honor device co., ltd. 98c0eb global regency ltd + 98c3d2 ningbo sanxing medical electric co.,ltd + 98c5db ericsson ab + 98c7a4 shenzhen hs fiber communication equipment co., ltd 98c845 packetaccess + 98c8b8 vivo mobile communication co., ltd. + 98c97c shenzhen icomm semiconductor co.,ltd + 98ca33 apple, inc. + 98cb27 galore networks pvt. ltd. + 98cba4 benchmark electronics + 98cc4d shenzhen mantunsci co., ltd + 98cdac espressif inc. 98cdb4 virident systems, inc. + 98cf53 bbk educational electronics corp.,ltd. + 98d293 google, inc. 98d331 shenzhen bolutek technology co.,ltd. + 98d3d2 mekra lang gmbh & co. kg + 98d3e7 netafim l 98d686 chyi lee industry co., ltd. - 98d6bb apple - 98d6f7 lg electronics + 98d6bb apple, inc. + 98d6f7 lg electronics (mobile communications) + 98d863 shanghai high-flying electronics technology co., ltd 98d88c nortel networks 98da92 vuzix corporation + 98dac4 tp-link technologies co.,ltd. 98dcd9 unitec co., ltd. + 98dd5b takumi japan ltd + 98ddea infinix mobility limited + 98ded0 tp-link technologies co.,ltd. + 98df82 hangzhou hikvision digital technology co.,ltd. + 98e0d9 apple, inc. 98e165 accutome + 98e476 zentan + 98e743 dell inc. 98e79a foxconn(nanjing) communication co.,ltd. + 98e7f4 hewlett packard + 98e7f5 huawei technologies co.,ltd + 98e848 axiim + 98e8fa nintendo co.,ltd 98ec65 cosesy aps - 98f0ab apple + 98ed5c tesla,inc. + 98ed7e eero inc. + 98eecb wistron infocomm (zhongshan) corporation + 98ef9b ohsung + 98f058 lynxspring, incl. + 98f0ab apple, inc. + 98f170 murata manufacturing co., ltd. + 98f181 new h3c technologies co., ltd + 98f199 nec platforms, ltd. + 98f2b3 hewlett packard enterprise + 98f428 zte corporation + 98f4ab espressif inc. 98f537 zte corporation + 98f5a9 ohsung + 98f621 xiaomi communications co ltd + 98f781 arris group, inc. + 98f7d7 arris group, inc. 98f8c1 idt technology limited 98f8db marini impianti industriali s.r.l. + 98f9c7 ieee registration authority + 98fa9b lcfc(hefei) electronics technology co., ltd + 98faa7 innonet + 98fae3 xiaomi communications co ltd 98fb12 grand electronics (hk) ltd 98fc11 cisco-linksys, llc + 98fc84 ieee registration authority + 98fd74 act.co.ltd + 98fdb4 primax electronics ltd. 98fe03 ericsson - north america - 98fe94 apple + 98fe94 apple, inc. 98ff6a otec(shanghai)technology co.,ltd. 98ffd0 lenovo mobile communication technology ltd. 9c0111 shenzhen newabel electronic co., ltd. 9c0298 samsung electronics co.,ltd 9c039e beijing winchannel software technology co., ltd - 9c0473 tecmobile (international) ltd. - 9c04eb apple + 9c0473 tecmobile (international) ltd. + 9c04eb apple, inc. + 9c0567 honor device co., ltd. + 9c061b hangzhou h3c technologies co., limited 9c066e hytera communications corporation limited + 9c0cdf guangdong oppo mobile telecommunications corp.,ltd 9c0dac tymphany hk limited + 9c0e4a shenzhen vastking electronic co.,ltd. + 9c13ab chanson water co., ltd. + 9c1463 zhejiang dahua technology co., ltd. 9c1465 edata elektronik san. ve tic. a.Ş. 9c1874 nokia danmark a/s - 9c1c12 aruba networks + 9c19c2 dongguan liesheng electronic co., ltd. + 9c1c12 aruba, a hewlett packard enterprise company + 9c1c37 altobeam (china) inc. + 9c1d36 huawei technologies co.,ltd + 9c1d58 texas instruments + 9c1e95 actiontec electronics, inc + 9c1ea4 renesas electronics (penang) sdn. bhd. 9c1fdd accupix inc. - 9c207b apple + 9c207b apple, inc. 9c216a tp-link technologies co.,ltd. - 9c220e tascan service gmbh + 9c220e tascan systems gmbh + 9c25be wildlife acoustics, inc. 9c2840 discovery technology,ltd.. + 9c28b3 apple, inc. 9c28bf continental automotive czech republic s.r.o. 9c28ef huawei technologies co.,ltd + 9c28f7 xiaomi communications co ltd + 9c293f apple, inc. + 9c2976 intel corporate 9c2a70 hon hai precision ind. co.,ltd. + 9c2a83 samsung electronics co.,ltd + 9c2dcf shishi tongyun technology(chengdu)co.,ltd. + 9c2ea1 xiaomi communications co ltd + 9c2f4e zte corporation + 9c2f73 universal tiancheng technology (beijing) co., ltd. + 9c305b hon hai precision ind. co.,ltd. + 9c3066 rwe effizienz gmbh 9c3178 foshan huadian intelligent communications teachnologies co.,ltd 9c31b6 kulite semiconductor products inc + 9c31c3 bskyb ltd + 9c32a9 sichuan tianyi comheart telecomco., ltd + 9c32ce canon inc. + 9c3426 arris group, inc. + 9c3583 nipro diagnostics, inc + 9c35eb apple, inc. + 9c37f4 huawei technologies co.,ltd + 9c3a9a shenzhen sundray technologies company limited 9c3aaf samsung electronics co.,ltd + 9c3dcf netgear 9c3eaa envylogic co.,ltd. - 9c417c hame technology co., limited + 9c417c hame technology co., limited + 9c431e ieee registration authority 9c443d chengdu xuguang technology co, ltd 9c44a6 swifttest, inc. 9c4563 dimep sistemas + 9c497f integrated device technology (malaysia) sdn. bhd. 9c4a7b nokia corporation 9c4cae mesa labs - 9c4e20 cisco systems, inc. + 9c4e20 cisco systems, inc 9c4e36 intel corporate 9c4e8e alt systems ltd 9c4ebf boxcast + 9c4f5f tap sound system + 9c4fcf tct mobile ltd + 9c4fda apple, inc. + 9c50ee cambridge industries(group) co.,ltd. + 9c52f8 huawei technologies co.,ltd 9c53cd engicam s.r.l. 9c541c shenzhen my-power technology co.,ltd 9c54ca zhengzhou vcom science and technology co.,ltd + 9c54da skybell technologies inc. 9c55b4 i.s.e. s.r.l. 9c5711 feitian xunda(beijing) aeronautical information technology co., ltd. + 9c57ad cisco systems, inc + 9c5a44 compal information (kunshan) co., ltd. 9c5b96 nmr corporation 9c5c8d firemax indÚstria e comÉrcio de produtos eletrÔnicos ltda - 9c5d12 aerohive networks inc + 9c5c8e asustek computer inc. + 9c5cf9 sony mobile communications inc + 9c5d12 extreme networks, inc. 9c5d95 vtc electronics corp. 9c5e73 calibre uk ltd - 9c611d omni-id usa, inc. + 9c5f5a guangdong oppo mobile telecommunications corp.,ltd + 9c5fb0 samsung electronics co.,ltd + 9c611d panasonic corporation of north america + 9c6121 sichuan tianyi comheart telecomco.,ltd + 9c62ab sumavision technologies co.,ltd + 9c63ed zte corporation 9c645e harman consumer group + 9c648b apple, inc. 9c65b0 samsung electronics co.,ltd + 9c65ee dasan network solutions 9c65f9 acsip technology corp. 9c6650 glodio technolies co.,ltd tianjin branch + 9c685b octonion sa + 9c6865 fiberhome telecommunication technologies co.,ltd + 9c6937 qorvo international pte. ltd. + 9c69b4 ieee registration authority + 9c69d1 huawei technologies co.,ltd 9c6abe qees aps. + 9c6b37 renesas electronics (penang) sdn. bhd. + 9c6b72 realme chongqing mobiletelecommunications corp ltd + 9c6c15 microsoft corporation + 9c6f52 zte corporation + 9c713a huawei technologies co.,ltd + 9c7370 huawei technologies co.,ltd + 9c741a huawei technologies co.,ltd + 9c746f huawei technologies co.,ltd 9c7514 wildix srl + 9c760e apple, inc. + 9c7613 ring llc 9c77aa nadasnv 9c79ac suntec software(shanghai) co., ltd. + 9c7a03 ciena corporation 9c7bd2 neolab convergence + 9c7bef hewlett packard + 9c7da3 huawei technologies co.,ltd + 9c7f57 unic memory technology co ltd + 9c7f81 shenzhen fast technologies co.,ltd 9c807d syscable korea inc. 9c80df arcadyan technology corporation + 9c823f huawei device co., ltd. + 9c8275 yichip microelectronics (hangzhou) co.,ltd + 9c8281 vivo mobile communication co., ltd. + 9c83bf pro-vision, inc. + 9c84bf apple, inc. 9c86da phoenix geophysics ltd. 9c8888 simac techniek nv + 9c88ad fiberhome telecommunication technologies co.,ltd + 9c8acb juniper networks + 9c8ba0 apple, inc. 9c8bf1 the warehouse limited + 9c8c6e samsung electronics co.,ltd + 9c8cd8 hewlett packard enterprise 9c8d1a integ process group inc - 9c8e99 hewlett-packard company + 9c8d7c alpsalpine co,.ltd + 9c8dd3 leonton technologies + 9c8e99 hewlett packard + 9c8e9c huawei device co., ltd. + 9c8ecd amcrest technologies 9c8edc teracom limited 9c934e xerox corporation + 9c93b0 megatronix (beijing) technology co., ltd. + 9c93e4 private + 9c9567 huawei device co., ltd. 9c95f8 smartdoor systems, llc 9c9726 technicolor + 9c9789 1more 9c9811 guangzhou sunrise electronics development co., ltd + 9c99a0 xiaomi communications co ltd + 9c99cd voippartners + 9c9ac0 lego system a/s 9c9c1d starkey labs inc. + 9c9c1f espressif inc. + 9c9c40 sichuan tianyi comheart telecomco., ltd + 9c9d5d raden inc + 9c9d7e beijing xiaomi mobile software co., ltd 9ca10a scle sfe 9ca134 nike, inc. + 9ca3a9 guangzhou juan optical and electronical tech joint stock co., ltd 9ca3ba sakura internet inc. + 9ca513 samsung electronics co.,ltd + 9ca525 shandong usr iot technology limited + 9ca570 eero inc. 9ca577 osorno enterprises inc. + 9ca5c0 vivo mobile communication co., ltd. + 9ca615 tp-link technologies co.,ltd. + 9ca69d whaley technology co.ltd 9ca9e4 zte corporation + 9caa1b microsoft corporation + 9cac6d universal electronics, inc. + 9cad97 hon hai precision ind. co.,ltd. 9cadef obihai technology, inc. - 9cafca cisco systems, inc. + 9caed3 seiko epson corporation + 9caf6f itel mobile limited + 9cafca cisco systems, inc 9cb008 ubiquitous computing technology corporation 9cb206 procentec + 9cb2b2 huawei technologies co.,ltd + 9cb2e8 huawei technologies co.,ltd 9cb654 hewlett packard + 9cb6d0 rivet networks 9cb70d liteon technology corporation 9cb793 creatcomm technology inc. 9cbb98 shen zhen rnd electronic co.,ltd + 9cbcf0 xiaomi communications co ltd + 9cbd6e dera co., ltd 9cbd9d skydisk, inc. + 9cbee0 biosoundlab co., ltd. 9cc077 printcounts, llc - 9cc0d2 conductix-wampfler ag + 9cc0d2 conductix-wampfler gmbh + 9cc172 huawei technologies co.,ltd 9cc7a6 avm gmbh 9cc7d1 sharp corporation + 9cc8ae becton, dickinson and company + 9cc8fc arris group, inc. + 9cc950 baumer holding + 9cc9eb netgear 9ccad9 nokia corporation + 9ccc83 juniper networks 9ccd82 cheng uei precision industry co.,ltd 9cd21e hon hai precision ind. co.,ltd. 9cd24b zte corporation - 9cd36d netgear inc., + 9cd332 plc technology ltd + 9cd35b samsung electronics co.,ltd + 9cd36d netgear + 9cd48b innolux technology europe bv 9cd643 d-link international + 9cd917 motorola mobility llc, a lenovo company + 9cd9cb lesira manufacturing pty ltd + 9cda3e intel corporate + 9cdb07 thum+mahr gmbh + 9cdbcb wuhan funshion online technologies co.,ltd + 9cdc71 hewlett packard enterprise + 9cdd1f intelligent steward co.,ltd 9cdf03 harman/becker automotive systems gmbh + 9cdfb1 shenzhen crave communication co., ltd + 9ce063 samsung electronics co.,ltd 9ce10e nctech ltd + 9ce176 cisco systems, inc 9ce1d6 junger audio-studiotechnik gmbh + 9ce230 julong co,.ltd. + 9ce33f apple, inc. + 9ce374 huawei technologies co.,ltd 9ce635 nintendo co., ltd. + 9ce65e apple, inc. 9ce6e7 samsung electronics co.,ltd 9ce7bd winduskorea co., ltd + 9ce82b vivo mobile communication co., ltd. + 9ce895 new h3c technologies co., ltd + 9ce91c zte corporation + 9ce951 shenzhen sang fei consumer communications ltd., co. + 9cea97 honor device co., ltd. 9cebe8 bizlink (kunshan) co.,ltd - 9cf61a utc fire and security + 9cedfa evulution ag + 9cefd5 panda wireless, inc. + 9cf029 integrated device technology (malaysia) sdn. bhd. + 9cf387 apple, inc. + 9cf48e apple, inc. + 9cf531 guangdong oppo mobile telecommunications corp.,ltd + 9cf61a carrier fire & security 9cf67d ricardo prague, s.r.o. + 9cf6dd ieee registration authority 9cf8db shenzhen eyunmei technology co,.ltd 9cf938 areva np gmbh + 9cfbd5 vivo mobile communication co., ltd. 9cfbf1 mesomatic gmbh & co.kg + 9cfc01 apple, inc. + 9cfc28 apple, inc. + 9cfcd1 aetheris technology (shanghai) co., ltd. + 9cfce8 intel corporate + 9cfea1 fiberhome telecommunication technologies co.,ltd 9cffbe otsl inc. + 9cffc2 avi systems gmbh + a002dc amazon technologies inc. a00363 robert bosch healthcare gmbh - a00798 samsung electronics + a0043e parker hannifin manufacturing germany gmbh & co. kg + a00460 netgear + a00627 nexpa system + a00798 samsung electronics co.,ltd a007b6 advanced technical support, inc. + a0086f huawei technologies co.,ltd + a0094c centurylink + a009ed avaya inc a00abf wieson technologies co., ltd. - a00bba samsung electro-mechanics + a00bba samsung electro mechanics co., ltd. a00ca1 sktb skit - a01290 avaya, inc - a0133b copyright © hiti digital, inc. + a01081 samsung electronics co.,ltd + a01290 avaya inc + a012db tabuchi electric co.,ltd + a0133b hiti digital, inc. + a013cb fiberhome telecommunication technologies co.,ltd a0143d parrot sa a0165c triteka ltd + a01828 apple, inc. a01859 shenzhen yidashi electronics co ltd a01917 bertel s.p.a. + a019b2 ieee registration authority + a01b29 sagemcom broadband sas a01c05 nimax telecom co.,ltd. + a01c8d huawei technologies co.,ltd a01d48 hewlett packard - a02195 samsung electronics digital imaging + a01e0b minix technology limited + a020a6 espressif inc. + a02195 samsung electronics co.,ltd a021b7 netgear + a0224e ieee registration authority + a022de vivo mobile communication co., ltd. a0231b telecomp r&d corp. + a0239f cisco systems, inc + a027b6 samsung electronics co.,ltd + a02833 ieee registration authority + a028ed hmd global oy a02bb8 hewlett packard + a02c36 fn-link technology limited + a02d13 airties wireless networks a02ef3 united integrated services co., led. + a03299 lenovo (beijing) co., ltd. + a0341b adero inc + a03679 huawei technologies co.,ltd a0369f intel corporate a036f0 comprehensive power a036fa ettus research llc + a038f8 oura health oy + a039ee sagemcom broadband sas + a039f7 lg electronics (mobile communications) a03a75 pss belgium n.v. + a03b01 kyung in electronics a03b1b inspire tech + a03be3 apple, inc. + a03c31 shenzhen belon technology co.,ltd + a03d6e cisco systems, inc + a03d6f cisco systems, inc + a03e6b ieee registration authority a04025 actioncable, inc. a04041 samwonfa co.,ltd. + a040a0 netgear + a0412d lansen systems ab + a04147 huawei device co., ltd. + a0415e opsens solution inc. a041a7 nl ministry of defense a0423f tyan computer corp + a04246 it telecom co., ltd. + a043b0 hangzhou broadlink technology co.,ltd + a043db sitael s.p.a. + a047d7 best it world (india) pvt ltd a0481c hewlett packard + a04a5e microsoft corporation + a04c5b shenzhen tinno mobile technology corp. a04cc1 helixtech corp. + a04e01 central engineering co.,ltd. a04e04 nokia corporation - a051c6 avaya, inc - a055de pace plc + a04ea7 apple, inc. + a04f85 lg electronics (mobile communications) + a04fd4 adb broadband italia + a0510b intel corporate + a051c6 avaya inc + a0554f cisco systems, inc + a055de arris group, inc. + a056b2 harman/becker automotive systems gmbh + a056f3 apple, inc. + a057e3 huawei technologies co.,ltd a0593a v.d.s. video display systems srl a05aa4 grand products nevada, inc. a05b21 envinet gmbh a05dc1 tmct co., ltd. a05de7 directv, inc. a05e6b melper co., ltd. + a06090 samsung electronics co.,ltd + a06260 private + a062fb hisense visual technology co.,ltd + a06391 netgear + a0648f askey computer corp a06518 vnpt technology - a067be sicon s.r.l. + a06610 fujitsu limited + a067be sicon srl + a0681c gd midea air-conditioning equipment co.,ltd. + a0687e arris group, inc. + a06974 honor device co., ltd. a06986 wellav technologies ltd a06a00 verilink corporation + a06a44 vizio, inc a06cec rim a06d09 intelcan technosystems inc. a06e50 nanotek elektronik sistemler ltd. sti. + a06faa lg innotek + a07099 beijing huacan electronics co., ltd + a070b7 huawei technologies co.,ltd a071a9 nokia corporation + a0722c humax co., ltd. + a072e4 nj system co.,ltd a07332 cashmaster international limited a073fc rancore technologies private limited a07591 samsung electronics co.,ltd + a075ea boxlock, inc. + a0764e espressif inc. + a07751 asmedia technology inc. a07771 vialis bv + a07817 apple, inc. a078ba pantech co., ltd. a0821f samsung electronics co.,ltd + a082ac linear dms solutions sdn. bhd. a082c7 p.t.i co.,ltd + a084cb sonicsensory,inc. + a085fc microsoft corporation a0861d chengdu fuhuaxin technology co.,ltd + a086c6 xiaomi communications co ltd a086ec saehan hitec co., ltd a08869 intel corporate a088b4 intel corporate @@ -16735,1895 +23439,4979 @@ exit a08a87 huizhou kaiyue electronic co.,ltd a08c15 gerhard d. wempe kg a08c9b xtreme technologies corp + a08cf8 huawei technologies co.,ltd + a08cfd hewlett packard + a08d16 huawei technologies co.,ltd + a08e78 sagemcom broadband sas a090de veedims,llc + a09169 lg electronics (mobile communications) + a091a2 oneplus electronics (shenzhen) co., ltd. + a091c8 zte corporation + a09347 guangdong oppo mobile telecommunications corp.,ltd + a09351 cisco systems, inc + a0946a shenzhen xgtec technology co,.ltd. + a0950c china mobile iot company limited a09805 openvox communication co ltd a098ed shandong intelligent optical communication development co., ltd. + a0999b apple, inc. a09a5a time domain + a09b12 china mobile iot company limited + a09b17 taicang t&w electronics a09bbd total aviation solutions pty ltd + a09d86 alcatel-lucent shanghai bell co., ltd + a09d91 soundbridge + a09dc1 china dragon technology limited + a09e1a polar electro oy + a09f10 shenzhen bilian electronic co.,ltd a0a130 dli taiwan branch office a0a23c gpms + a0a33b huawei technologies co.,ltd + a0a3b8 wiscloud + a0a3e2 actiontec electronics, inc + a0a3f0 d-link international + a0a4c5 intel corporate + a0a65c supercomputing systems ag a0a763 polytron vertrieb gmbh a0a8cd intel corporate a0aafd erathink technologies corp. + a0ab1b d-link international + a0ab51 weifang goertek electronics co.,ltd + a0ac69 samsung electronics co.,ltd + a0ada1 jmr electronics, inc + a0afbd intel corporate + a0b045 halong mining a0b100 shenzhen cando electronics co.,ltd a0b3cc hewlett packard + a0b437 gd mission systems + a0b439 cisco systems, inc + a0b4a5 samsung electronics co.,ltd + a0b549 arcadyan corporation a0b5da hongkong thtf co., ltd a0b662 acutvista innovation co., ltd. + a0b8f8 amgen u.s.a. inc. a0b9ed skytap a0bab8 pixon imaging + a0bb3e ieee registration authority + a0bd1d zhejiang dahua technology co., ltd. + a0bdcd bskyb ltd a0bf50 s.c. add-production s.r.l. a0bfa5 coresys + a0c2de costar video systems a0c3de triton electronic systems ltd. + a0c4a5 sygn house co.,ltd + a0c562 arris group, inc. + a0c589 intel corporate + a0c5f2 ieee registration authority a0c6ec shenzhen anyk technology co.,ltd + a0c9a0 murata manufacturing co., ltd. + a0caa5 intelligence technology of cec co., ltd + a0cbfd samsung electronics co.,ltd + a0cc2b murata manufacturing co., ltd. a0cec8 ce link limited - a0cf5b cisco systems, inc. + a0cf5b cisco systems, inc + a0cff5 zte corporation + a0d0dc amazon technologies inc. a0d12a axpro technology inc. + a0d37a intel corporate + a0d385 auma riester gmbh & co. kg a0d3c1 hewlett packard + a0d635 wbs technology + a0d795 apple, inc. + a0d7a0 huawei device co., ltd. + a0d807 huawei device co., ltd. + a0d83d fiberhome telecommunication technologies co.,ltd + a0d86f argo ai, llc a0da92 nanjing glarun atten technology co. ltd. a0dc04 becker-antriebe gmbh a0dd97 polarlink technologies, ltd a0dde5 sharp corporation - a0de05 jsc "irbis-t" + a0de05 jsc irbis-t + a0de0f huawei device co., ltd. + a0df15 huawei technologies co.,ltd + a0e0af cisco systems, inc a0e201 avtrace ltd.(china) a0e25a amicus sk, s.r.o. a0e295 dat system co.,ltd - a0e453 sony mobile communications ab + a0e453 sony mobile communications inc + a0e4cb zyxel communications corporation a0e534 stratec biomedical ag a0e5e9 enimai inc + a0e617 matis + a0e6f8 texas instruments a0e9db ningbo freewings technologies co.,ltd a0eb76 aircuve inc. a0ec80 zte corporation - a0edcd apple + a0ecf9 cisco systems, inc + a0edcd apple, inc. a0ef84 seine image int'l co., ltd - a0f217 ge medical system(china) co., ltd. - a0f3c1 tp-link technologies co., ltd. - a0f3e4 alcatel lucent ipd + a0f217 ge medical system(china) co., ltd. + a0f3c1 tp-link technologies co.,ltd. + a0f3e4 alcatel-lucent ipd a0f419 nokia corporation a0f450 htc corporation a0f459 fn-link technology limited + a0f479 huawei technologies co.,ltd + a0f6fd texas instruments + a0f849 cisco systems, inc + a0f895 shenzhen tinno mobile technology corp. + a0f9b7 ademco smart homes technology(tianjin)co.,ltd. + a0f9e0 vivatel company limited + a0fbc5 apple, inc. + a0fc6e telegrafia a.s. + a0fe61 vivint wireless inc. a0fe91 avat automation gmbh + a0ff70 technicolor ch usa inc. + a400e2 huawei technologies co.,ltd a40130 abisystems co., ltd + a402b9 intel corporate + a40450 nfore technology inc. + a4056e tiinlab corporation a4059e sta infinity llp + a406e9 texas instruments + a407b6 samsung electronics co.,ltd + a40801 amazon technologies inc. + a408ea murata manufacturing co., ltd. + a408f5 sagemcom broadband sas a409cb alfred kaercher gmbh & co kg a40bed carry technology co.,ltd - a40cc3 cisco systems, inc. - a4134e luxul - a41566 wei fang goertek electronics co.,ltd + a40c66 shenzhen colorful yugong technology and development co., ltd. + a40cc3 cisco systems, inc + a40dbc xiamen intretech inc. + a40e2b facebook inc + a41115 robert bosch engineering and business solutions pvt. ltd. + a41162 arlo technology + a41163 ieee registration authority + a41194 lenovo + a41232 guangdong oppo mobile telecommunications corp.,ltd + a41242 nec platforms, ltd. + a4134e luxul + a41437 hangzhou hikvision digital technology co.,ltd. + a41566 weifang goertek electronics co.,ltd + a41588 arris group, inc. + a416e7 huawei technologies co.,ltd a41731 hon hai precision ind. co.,ltd. - a41875 cisco systems, inc. + a4178b huawei technologies co.,ltd + a41791 shenzhen decnta technology co.,ltd. + a41875 cisco systems, inc + a41908 fiberhome telecommunication technologies co.,ltd + a41b34 china mobile group device co.,ltd. a41bc0 fastec imaging corporation a41f72 dell inc. a4218a nortel networks a42305 open networking laboratory a424b3 flatfrog laboratories ab + a424dd cambrionix ltd + a4251b avaya inc + a42618 integrated device technology (malaysia) sdn. bhd. + a42655 lti motion (shanghai) co., ltd. + a428b7 yangtze memory technologies co., ltd. a42940 shenzhen youhua technology co., ltd + a42983 boeing defence australia + a42985 sichuan ai-link technology co., ltd. a429b7 bluesky + a42b8c netgear + a42bb0 tp-link technologies co.,ltd. a42c08 masterwork automodules + a4307a samsung electronics co.,ltd + a43111 ziv + a43135 apple, inc. a433d1 fibrlink communications co.,ltd. + a433d7 mitrastar technology corp. + a43412 thales alenia space + a434d9 intel corporate + a434f1 texas instruments + a43523 guangdong donyan network technologies co.,ltd. + a4352d triz networks corp. + a43831 rf elements s.r.o. + a438cc nintendo co.,ltd a438fc plastic logic + a439b6 shenzhen peizhe microelectronics co .ltd a43a69 vers inc + a43b0e huawei device co., ltd. + a43bfa ieee registration authority + a43d78 guangdong oppo mobile telecommunications corp.,ltd + a43e51 anov france + a43ea0 icomm hk limited + a44027 zte corporation + a4423b intel corporate + a444d1 wingtech group (hongkong)limited + a44519 xiaomi communications co ltd + a445cd iot diagnostics a4466b eoc technology + a446b4 huawei device co., ltd. a446fa amtran video corporation + a44ad3 st electronics(shanghai) co.,ltd a44b15 sun cupid technology (hk) ltd - a44c11 cisco systems, inc. + a44bd5 xiaomi communications co ltd + a44c11 cisco systems, inc + a44c62 hangzhou microimage software co., ltd + a44cc8 dell inc. a44e2d adaptive wireless solutions, llc a44e31 intel corporate + a44f29 ieee registration authority + a45006 shenzhen huachuang shidai technologyco.,ltd + a45046 xiaomi communications co ltd a45055 busware.de + a45129 xag + a4516f microsoft mobile oy a4526f adb broadband italia + a4530e cisco systems, inc + a45385 weifang goertek electronics co.,ltd + a453ee ieee registration authority + a45602 fenglian technology co.,ltd. a4561b mcot corporation - a45630 cisco systems, inc. + a45630 cisco systems, inc + a456cc technicolor ch usa inc. + a45802 shin-il tech + a4580f ieee registration authority a45a1c smart-electronic gmbh a45c27 nintendo co., ltd. a45d36 hewlett packard + a45da1 adb broadband italia + a45e5a activio inc. + a45e60 apple, inc. + a45f9b nexell + a46011 verifone a46032 mrv communications (networks) ltd - a46706 apple + a46191 namjunsa + a462df ds global. co., ltd + a463a1 inventus power eletronica do brasil ltda + a46706 apple, inc. + a468bc oakley inc. + a46bb6 intel corporate + a46c2a cisco systems, inc a46cc1 lti reenergy gmbh + a46cf1 samsung electronics co.,ltd + a46da4 huawei technologies co.,ltd a46e79 dft system co.ltd - a47733 google + a470d6 motorola mobility llc, a lenovo company + a47174 huawei technologies co.,ltd + a47733 google, inc. + a47758 ningbo freewings technologies co.,ltd a47760 nokia corporation + a47886 avaya inc a479e4 klinfo corp a47aa4 arris group, inc. a47acf vibicom communications inc. + a47b1a huawei device co., ltd. + a47b2c nokia + a47b85 ultimedia co ltd, + a47b9d espressif inc. a47c14 chargestorm ab a47c1f cobham plc + a47cc9 huawei technologies co.,ltd + a47d9f shenzhen icomm semiconductor co.,ltd + a47e36 em microelectronic a47e39 zte corporation + a4817a cig shanghai co ltd a481ee nokia corporation + a48269 datrium, inc. + a483e7 apple, inc. + a48431 samsung electronics co.,ltd a4856b q electronics ltd + a486ae quectel wireless solutions co., ltd. + a48873 cisco systems, inc a4895b ark infosolutions pvt ltd + a48cc0 jlg industries, inc. + a48cdb lenovo + a48d3b vizio, inc + a48e0a delaval international ab a49005 china greatwall computer shenzhen co.,ltd - a4934c cisco systems, inc. + a491b1 technicolor + a492cb nokia + a4933f huawei technologies co.,ltd + a49340 beijing supvan information technology co.,ltd. + a4934c cisco systems, inc + a49426 elgama-elektronika ltd. + a49733 askey computer corp + a4975c vtech telecommunications ltd. + a497b1 chongqing fugui electronics co.,ltd. a497bb hitachi industrial equipment systems co.,ltd - a49947 huawei technologies co., ltd + a49813 arris group, inc. + a49947 huawei technologies co.,ltd a49981 fujian elite power tech co.,ltd. a49a58 samsung electronics co.,ltd - a49b13 burroughs payment systems, inc. + a49b13 digital check + a49b4f huawei technologies co.,ltd + a49bcd cisco systems, inc + a49bf5 hybridserver tec gmbh + a49d49 ketra, inc. a49edb autocrib, inc. a49f85 lyve minds, inc a49f89 shanghai rui rui communication technology co.ltd. + a4a179 nanjing dianyan electric power automation co. ltd + a4a1c2 ericsson ab + a4a1e4 innotube, inc. a4a24a cisco spvtg + a4a46b huawei technologies co.,ltd + a4a4d3 bluebank communication technology co.ltd + a4a6a9 private a4a80f shenzhen coship electronics co., ltd. + a4aafe huawei device co., ltd. + a4ac0f huawei device co., ltd. a4ad00 ragsdale technology a4adb8 vitec group, camera dynamics ltd + a4ae11 hon hai precision ind. co., ltd. + a4ae12 hon hai precision ind. co., ltd. a4ae9a maestro wireless solutions ltd. a4b121 arantia 2010 s.l. - a4b197 apple + a4b197 apple, inc. + a4b1c1 intel corporate a4b1e9 technicolor a4b1ee h. zander gmbh & co. kg + a4b239 cisco systems, inc a4b2a7 adaxys solutions ag a4b36a jsc sdo chromatec + a4b439 cisco systems, inc + a4b52e integrated device technology (malaysia) sdn. bhd. + a4b61e huawei device co., ltd. + a4b805 apple, inc. a4b818 penta gesellschaft für elektronische industriedatenverarbeitung mbh a4b980 parking boxx inc. + a4ba76 huawei technologies co.,ltd a4badb dell inc. + a4bb6d dell inc. a4bbaf lime instruments + a4bdc4 huawei technologies co.,ltd + a4be2b huawei technologies co.,ltd a4be61 eutrovision system, inc. + a4bf01 intel corporate a4c0c7 shenzhen hitom communication technology co..ltd a4c0e1 nintendo co., ltd. + a4c138 telink semiconductor (taipei) co. ltd. a4c2ab hangzhou lead-it information & technology co.,ltd - a4c361 apple + a4c361 apple, inc. + a4c3f0 intel corporate + a4c494 intel corporate + a4c54e huawei device co., ltd. + a4c64f huawei technologies co.,ltd + a4c74b huawei device co., ltd. a4c7de cambridge industries(group) co.,ltd. + a4c939 guangdong oppo mobile telecommunications corp.,ltd + a4caa0 huawei technologies co.,ltd + a4cc32 inficomm co., ltd + a4ccb9 realme chongqing mobile telecommunications corp.,ltd. + a4cd23 shenzhenshi xinzhongxin co., ltd + a4ceda arcadyan corporation + a4cf12 espressif inc. + a4cfd2 ubee interactive co., limited a4d094 erwin peters systemtechnik gmbh - a4d18f shenzhen skyee optical fiber communication technology ltd. + a4d18c apple, inc. + a4d18f shenzhen skyee optical fiber communication technology ltd. a4d1d1 ecotality north america - a4d1d2 apple + a4d1d2 apple, inc. a4d3b5 glitel stropkov, s.r.o. - a4d856 qualcomm labs inc. + a4d4b2 shenzhen meig smart technology co.,ltd + a4d578 texas instruments + a4d795 wingtech mobile communications co.,ltd + a4d856 gimbal, inc + a4d8ca hong kong water world technology co. limited + a4d931 apple, inc. + a4d990 samsung electronics co.,ltd + a4d9a4 nexus id solutions ab + a4da22 ieee registration authority + a4da32 texas instruments a4da3f bionics corp. + a4dad4 yamato denki co.,ltd. a4db2e kingspan environmental ltd a4db30 liteon technology corporation + a4dcbe huawei technologies co.,ltd a4de50 total walther gmbh + a4dec9 qlove mobile intelligence information technology (w.h.) co. ltd. a4e0e6 filizola s.a. pesagem e automacao + a4e31b nokia a4e32e silicon & software systems ltd. a4e391 deny fontaine - a4e4b8 blackberry limited + a4e4b8 blackberry rts + a4e57c espressif inc. + a4e597 gessler gmbh + a4e615 shenzhen chuangwei-rgb electronics co.,ltd + a4e6b1 shanghai joindata technology co.,ltd. a4e731 nokia corporation a4e7e4 connex gmbh + a4e975 apple, inc. a4e991 sistemas audiovisuales itelsis s.l. a4e9a3 honest technology co., ltd + a4ea8e extreme networks, inc. a4ebd3 samsung electronics co.,ltd + a4ed43 ieee registration authority a4ed4e arris group, inc. a4ee57 seiko epson corporation a4ef52 telewave co., ltd. + a4f05e guangdong oppo mobile telecommunications corp.,ltd + a4f1e8 apple, inc. a4f3c1 open source robotics foundation, inc. + a4f3e7 integrated device technology (malaysia) sdn. bhd. + a4f465 itel mobile limited + a4f4c2 vnpt technology a4f522 chofu seisakusho co.,ltd a4f7d0 lan accessories co., ltd. + a4f9e4 airvine scientific, inc. + a4fa76 new h3c technologies co., ltd a4fb8d hangzhou dunchong technology co.ltd + a4fc77 mega well limited a4fcce security expert ltd. + a8016d aiwa corporation a80180 imago technologies gmbh + a802db zte corporation + a8032a espressif inc. + a80577 netlist, inc. a80600 samsung electronics co.,ltd - a80c0d cisco + a80c0d cisco systems, inc + a80c63 huawei technologies co.,ltd + a80cca shenzhen sundray technologies company limited + a81087 texas instruments + a811fc arris group, inc. + a81374 panasonic corporation avc networks company a8154d tp-link technologies co.,ltd. - a816b2 lg electronics + a81559 breathometer, inc. + a815d6 shenzhen meione technology co., ltd + a816b2 lg electronics (mobile communications) + a816d0 samsung electronics co.,ltd a81758 elektronik system i umeå ab a81b18 xts corp + a81b5a guangdong oppo mobile telecommunications corp.,ltd + a81b5d foxtel management pty ltd + a81b6a texas instruments + a81d16 azurewave technology inc. + a81e84 quanta computer inc. a81faf krypton polska - a82066 apple + a82066 apple, inc. + a823fe lg electronics + a824b8 nokia a824eb zao npo introtest + a825eb cambridge industries(group) co.,ltd. a826d9 htc corporation a8294c precision optical transceivers, inc. + a82bb5 edgecore networks corporation + a82bb9 samsung electronics co.,ltd + a82bcd huawei technologies co.,ltd a82bd6 shina system co., ltd - a830ad wei fang goertek electronics co.,ltd + a8301c qingdao intelligent&precise electronics co.,ltd. + a830ad weifang goertek electronics co.,ltd + a830bc samsung electronics co.,ltd + a8329a digicom futuristic technologies ltd. + a8346a samsung electronics co.,ltd + a83512 huawei device co., ltd. + a8367a frogblue technology gmbh + a83759 huawei device co., ltd. a83944 actiontec electronics, inc + a83b5c huawei technologies co.,ltd + a83ccb rossma + a83e0e hmd global oy + a83fa1 ieee registration authority + a84025 oxide computer company a84041 dragino technology co., limited + a8407d gd midea air-conditioning equipment co.,ltd. + a84122 china mobile (hangzhou) information technology co.,ltd. + a842a7 jiangsu huitong group co.,ltd. + a84397 innogrit corporation a84481 nokia corporation + a845cd siselectron technology ltd. a845e9 firich enterprises co., ltd. + a8469d cisco meraki + a8474a hon hai precision ind. co.,ltd. + a8494d huawei technologies co.,ltd a849a5 lisantech co., ltd. - a854b2 wistron neweb corp. + a84d4a audiowise technology inc. + a84e3f hitron technologies. inc + a85081 huawei technologies co.,ltd + a8515b samsung electronics co.,ltd + a854b2 wistron neweb corporation a8556a pocketnet technology inc. a8574e tp-link technologies co.,ltd. + a85840 cambridge industries(group) co.,ltd. + a85ae0 huawei device co., ltd. + a85af3 shanghai siflower communication technology co., ltd + a85b6c robert bosch gmbh, cm-ci2 + a85b78 apple, inc. a85bb0 shenzhen dehoo technology co.,ltd a85bf3 audivo gmbh + a85c2c apple, inc. + a85e45 asustek computer inc. + a85ee4 12sided technology, llc + a860b6 apple, inc. + a8610a arduino ag a861aa cloudview limited a862a2 jiwumedia co., ltd. + a8637d d-link international a863df displaire corporation a863f2 texas instruments + a86405 nimbus 9, inc a865b2 dongguan yishang electronic technology co., limited + a8667f apple, inc. + a8698c oracle corporation a86a6f rim + a86abb sagemcom broadband sas + a86ac1 hanbiteds co., ltd. + a86b7c shenzhen fenglian technology co., ltd. + a86bad hon hai precision ind. co.,ltd. + a86d5f raisecom technology co., ltd + a86daa intel corporate + a86e4e huawei device co., ltd. + a8705d arris group, inc. a870a5 unicomm inc. + a87285 idt, inc. + a8741d phoenix contact electronics gmbh + a87484 zte corporation a875d6 freetek international co., ltd. a875e2 aventura technologies, inc. a8776f zonoff + a877e5 shenzhen chuangwei-rgb electronics co.,ltd a87b39 nokia corporation + a87c01 samsung electronics co.,ltd + a87d12 huawei technologies co.,ltd a87e33 nokia danmark a/s + a87eea intel corporate + a88038 shenzhen movingcomm technology co., limited + a8817e apple, inc. + a88195 samsung electronics co.,ltd a881f1 bmeye b.v. + a88200 hisense electric co.,ltd + a8827f cibn oriental network(beijing) co.,ltd + a885d7 sangfor technologies inc. a886dd apple, inc. a88792 broadband antenna tracking systems + a887b3 samsung electronics co.,ltd a887ed arc wireless llc - a88808 apple + a88808 apple, inc. a88cee micromade galka i drozdz sp.j. a88d7b sundroid global limited. - a8922c lg electronics + a88e24 apple, inc. + a89008 beijing yuecheng technology co. ltd. + a89042 beijing wanwei intelligent technology co., ltd. + a8913d apple, inc. + a8922c lg electronics (mobile communications) + a8934a chongqing fugui electronics co.,ltd. + a89352 shanghai zhongmi communication technology co.,ltd a893e6 jiangxi jinggangshan cking communication technology co.,ltd a895b0 aker subsea ltd - a8968a apple + a89675 motorola mobility llc, a lenovo company + a8968a apple, inc. + a897cd arris group, inc. a897dc ibm a898c6 shinbo co., ltd. a8995c aizo ag + a89969 dell inc. + a899dc i-top desing technology co.,ltd + a89a93 sagemcom broadband sas + a89ad7 nokia a89b10 inmotion ltd. + a89ca4 furrion limited + a89ced xiaomi communications co ltd + a89d21 cisco systems, inc + a89dd2 shanghai dareglobal technologies co.,ltd + a89fba samsung electronics co.,ltd + a89fec arris group, inc. + a8a089 tactical communications + a8a097 scioteq bvba + a8a159 asrock incorporation + a8a198 tct mobile ltd + a8a5e2 msf-vathauer antriebstechnik gmbh & co kg + a8a648 qingdao hisense communications co.,ltd. a8a668 zte corporation + a8a795 hon hai precision ind. co.,ltd. a8ad3d alcatel-lucent shanghai bell co., ltd - a8b0ae leoni - a8b1d4 cisco systems, inc. + a8b088 eero inc. + a8b0ae leoni + a8b1d4 cisco systems, inc + a8b2da fujitsu limited + a8b456 cisco systems, inc + a8b86e lg electronics (mobile communications) a8b9b3 essys - a8bbcf apple + a8bb50 wiz iot company limited + a8bbcf apple, inc. + a8bc9c cloud light technology limited a8bd1a honey bee (hong kong) limited + a8bd27 hewlett packard enterprise a8bd3a unionman technology co.,ltd + a8be27 apple, inc. + a8bf3c hdv phoelectron technology limited + a8c092 huawei device co., ltd. + a8c0ea pepwave limited a8c222 tm-research inc. + a8c252 huawei device co., ltd. + a8c83a huawei technologies co.,ltd + a8c87f roqos, inc. + a8ca7b huawei technologies co.,ltd + a8cab9 samsung electro mechanics co., ltd. a8cb95 east best co., ltd. + a8cc6f hmd global oy a8ccc5 saab ab (publ) a8ce90 cvc + a8d0e3 systech electronics ltd a8d0e5 juniper networks a8d236 lightware visual engineering - a8d3c8 wachendorff elektronik gmbh & co. kg + a8d3c8 topcon electronics gmbh & co. kg + a8d3f7 arcadyan technology corporation + a8d409 usa 111 inc + a8d498 avira operations gmbh & co. kg + a8d579 beijing chushang science and technology co.,ltd + a8d828 ascensia diabetes care + a8d88a wyconn + a8da01 shenzhen nuolijia digital technology co.,ltd + a8da0c servercom (india) private limited + a8db03 samsung electro-mechanics(thailand) a8e018 nokia corporation - a8e3ee sony computer entertainment inc. + a8e2c1 texas instruments + a8e2c3 shenzhen youhua technology co., ltd + a8e3ee sony interactive entertainment inc. + a8e539 moimstone co.,ltd + a8e544 huawei technologies co.,ltd + a8e552 juwel aquarium ag & co. kg + a8e705 fiberhome telecommunication technologies co.,ltd + a8e77d texas instruments + a8e81e atw technology, inc. + a8e824 inim electronics s.r.l. + a8e978 huawei device co., ltd. + a8eec6 muuselabs nv/sa a8ef26 tritonwave - a8f274 samsung electronics + a8f038 shen zhen shi jin hua tai electronics co.,ltd + a8f266 huawei device co., ltd. + a8f274 samsung electronics co.,ltd a8f470 fujian newland communication science technologies co.,ltd. + a8f5ac huawei technologies co.,ltd + a8f5dd arris group, inc. + a8f766 ite tech inc + a8f7e0 planet technology corporation a8f94b eltex enterprise ltd. - a8fad8 apple + a8fad8 apple, inc. a8fb70 wisesec l.t.d a8fcb7 consolidated resource imaging + a8ffba huawei technologies co.,ltd aa0000 digital equipment corporation aa0001 digital equipment corporation aa0002 digital equipment corporation aa0003 digital equipment corporation aa0004 digital equipment corporation + ac00d0 zte corporation ac0142 uriel technologies sia ac02ca hi solutions, inc. ac02cf rw tecnologia industria e comercio ltda ac02ef comsis + ac040b peloton interactive, inc + ac0481 jiangsu huaxing electronics co., ltd. ac0613 senselogix ltd + ac06c7 servernet s.r.l. + ac075f huawei technologies co.,ltd ac0a61 labor s.r.l. + ac0d1b lg electronics (mobile communications) ac0dfe ekon gmbh - mygekko + ac11d3 suzhou hotek video technology co. ltd + ac1203 intel corporate + ac122f fantasia trading llc + ac139c adtran inc ac1461 ataw co., ltd. ac14d2 wi-daq, inc. + ac1585 silergy corp + ac15f4 apple, inc. ac162d hewlett packard ac1702 fibar group sp. z o.o. + ac17c8 cisco meraki ac1826 seiko epson corporation ac199f sungrow power supply co.,ltd. + ac1d06 apple, inc. + ac1ddf ieee registration authority + ac1e92 samsung electronics co.,ltd + ac1ed0 temic automotive philippines inc. + ac1f09 shenzhen rakwireless technology co.,ltd + ac1f0f texas instruments + ac1f6b super micro computer, inc. + ac1f74 apple, inc. + ac1fd7 real vision technology co.,ltd. + ac202e hitron technologies. inc + ac203e wuhan tianyu information industry co., ltd. ac20aa dmatek co., ltd. + ac2205 compal broadband networks, inc. ac220b asustek computer inc. + ac2316 mist systems, inc. + ac2334 infinix mobility limited + ac233f shenzhen minew technologies co., ltd. + ac293a apple, inc. + ac2a0c csr zhuzhou institute co.,ltd. + ac2b6e intel corporate ac2da3 txtr gmbh + ac2da9 tecno mobile limited ac2fa8 humannix co.,ltd. ac319d shenzhen tg-net botone technology co.,ltd. + ac3328 huawei device co., ltd. ac34cb shanhai gbcom communication technology co. ltd + ac35ee fn-link technology limited ac3613 samsung electronics co.,ltd - ac3c0b apple + ac3651 jiangsu hengtong terahertz technology co., ltd. + ac3728 taicang t&w electronics + ac3743 htc corporation + ac37c9 raid incorporated + ac3870 lenovo mobile communication technology ltd. + ac3a67 cisco systems, inc + ac3a7a roku, inc. + ac3b77 sagemcom broadband sas + ac3c0b apple, inc. + ac3c8e flextronics computing(suzhou)co.,ltd. ac3cb4 nilan a/s ac3d05 instorescreen aisa ac3d75 hangzhou zhiway technologies co.,ltd. ac3fa4 taiyo yuden co.,ltd - ac40ea c&t solution inc. + ac40ea c&t solution inc. ac4122 eclipse electronic systems inc. - ac44f2 revolabs inc + ac4228 parta networks + ac4330 versa networks + ac44f2 yamaha corporation + ac471b huawei device co., ltd. ac4723 genelec + ac482d ralinwi nanjing electronic technology co., ltd. + ac4a56 cisco systems, inc + ac4a67 cisco systems, inc ac4afe hisense broadband multimedia technology co.,ltd. + ac4b1e integri-sys.com llc ac4bc8 juniper networks + ac4e2e shenzhen jinghanda electronics co.ltd ac4e91 huawei technologies co.,ltd ac4ffc svs-vistek gmbh ac5036 pi-coral inc + ac5093 magna electronics europe gmbh & co. ohg + ac512c infinix mobility limited ac5135 mpi tech ac51ee cambridge communication systems ltd + ac5474 china mobile iot company limited ac54ec ieee p1823 standards working group + ac562c lava international(h.k) limited + ac5775 hmd global oy ac583b human assembler, inc. + ac587b jct healthcare + ac5a14 samsung electronics co.,ltd + ac5aee china mobile group device co.,ltd. + ac5afc intel corporate ac5d10 pace americas + ac5d5c fn-link technology limited ac5e8c utillink + ac5f3e samsung electro-mechanics(thailand) + ac5fea oneplus technology (shenzhen) co., ltd + ac6089 huawei technologies co.,ltd + ac60b6 ericsson ab ac6123 drivven, inc. + ac6175 huawei technologies co.,ltd + ac61b9 wama technology limited + ac61ea apple, inc. + ac620d jabil circuit(wuxi) co.,ltd + ac63be amazon technologies inc. + ac6417 siemens ag + ac6462 zte corporation + ac64cf fn-link technology limited + ac64dd ieee registration authority ac6706 ruckus wireless + ac675d intel corporate + ac676f electrocompaniet a.s. + ac6784 google, inc. + ac67b2 espressif inc. + ac6aa3 shenzhen kertong technology co.,ltd + ac6b0f cadence design systems inc ac6bac jenny science ag - ac6e1a shenzhen gongjin electronics co.,ltd + ac6e1a shenzhen gongjin electronics co.,lt ac6f4f enspert inc ac6fbb tatung technology inc. ac6fd9 valueplus inc. + ac710c china mobile group device co.,ltd. ac7236 lexking technology co., ltd. ac7289 intel corporate + ac7409 hangzhou h3c technologies co., limited + ac74c4 maytronics ltd. + ac751d huawei technologies co.,ltd + ac7713 honeywell safety products (shanghai) co.,ltd + ac78d1 juniper networks ac7a42 iconnectivity + ac7a4d alpsalpine co,.ltd + ac7a56 cisco systems, inc ac7ba1 intel corporate - ac7f3e apple + ac7e8a cisco systems, inc + ac7f3e apple, inc. ac80d6 hexatronic ab ac8112 gemtek technology co., ltd. ac81f3 nokia corporation + ac8247 intel corporate ac8317 shenzhen furtunetel communication co., ltd + ac83e9 beijing zile technology co., ltd ac83f0 immediatv corporation + ac83f3 ampak technology, inc. + ac84c6 tp-link technologies co.,ltd. + ac84c9 sagemcom broadband sas ac853d huawei technologies co.,ltd ac8674 open mesh, inc. ac867e create new technology (hk) limited company + ac87a3 apple, inc. + ac88fd apple, inc. + ac8995 azurewave technology inc. ac8acd roger d.wensker, g.wensker sp.j. + ac8b9c primera technology, inc. ac8d14 smartrove inc + ac8d34 huawei technologies co.,ltd + ac8ff8 nokia + ac9085 apple, inc. + ac9232 huawei technologies co.,ltd ac932f nokia corporation ac9403 envision peripherals inc - ac9a96 lantiq deutschland gmbh + ac9572 jovision technology co., ltd. + ac9929 huawei technologies co.,ltd + ac9a22 nxp semiconductors + ac9a96 maxlinear, inc + ac9b0a sony corporation ac9b84 smak tecnologia e automacao ac9ce4 alcatel-lucent shanghai bell co., ltd - aca016 cisco systems, inc. + ac9e17 asustek computer inc. + aca016 cisco systems, inc + aca213 shenzhen bilian electronic co.,ltd aca22c baycity technologies ltd + aca31e aruba, a hewlett packard enterprise company aca430 peerless av + aca46e shenzhen gongjin electronics co.,lt + aca667 electronic systems protection, inc. + aca88e sharp corporation aca919 trekstor gmbh aca9a0 audioengine, ltd. + acab2e beijing lasnubes technology co., ltd. acab8d lyngso marine a/s + acabbf athentek inc. + acae19 roku, inc + acafb9 samsung electronics co.,ltd + acb1ee shenzhen fenda technology co., ltd acb313 arris group, inc. + acb3b5 huawei technologies co.,ltd + acb57d liteon technology corporation + acb74f metel s.r.o. acb859 uniband electronic corp, - acbd0b imac co.,ltd + acbb61 ysten technology co.,ltd + acbc32 apple, inc. + acbd0b leimac ltd. + acbd70 huawei device co., ltd. acbe75 ufine technologies co.,ltd. acbeb6 visualedge technology co., ltd. + acc1ee xiaomi communications co ltd + acc25d fiberhome telecommunication technologies co.,ltd acc2ec clt int'l ind. corp. + acc33a samsung electronics co.,ltd + acc358 continental automotive czech republic s.r.o. + acc51b zhuhai pantum electronics co., ltd. acc595 graphite systems + acc662 mitrastar technology corp. acc698 kohzu precision co., ltd. + acc73f vitsmo co., ltd. acc935 ness corporation acca54 telldus technologies ab acca8e oda technologies - accaba midokura co., ltd. + accaab virtual electric inc + accaba midokura co., ltd. accb09 hefcom metering (pty) ltd + accb51 hangzhou hikvision digital technology co.,ltd. accc8e axis communications ab acce8f hwa yao technologies co., ltd accf23 hi-flying electronics technology co.,ltd - accf5c apple + accf5c apple, inc. + accf85 huawei technologies co.,ltd + acd074 espressif inc. acd180 crexendo business solutions, inc. + acd1b8 hon hai precision ind. co.,ltd. acd364 abb spa, abb sace div. - acd657 shaanxi guolian digital tv technology co., ltd. + acd564 chongqing fugui electronics co.,ltd. + acd618 oneplus technology (shenzhen) co., ltd + acd657 shaanxi guolian digital tv technology co.,ltd. acd9d6 tci gmbh + acdb48 arris group, inc. acdbda shenzhen geniatech inc, ltd - acde48 + acdcca huawei technologies co.,ltd + acdce5 procter & gamble company + acde48 private + ace010 liteon technology corporation ace069 isaac instruments - ace215 huawei technologies co., ltd + ace215 huawei technologies co.,ltd + ace2d3 hewlett packard + ace342 huawei technologies co.,ltd ace348 madgetech, inc ace42e sk hynix + ace4b5 apple, inc. + ace5f0 doppler labs ace64b shenzhen baojia battery technology co., ltd. - ace87b huawei technologies co., ltd + ace77b sichuan tianyi comheart telecomco.,ltd + ace87b huawei technologies co.,ltd ace87e bytemark computer consulting ltd ace97f iot tech limited ace9aa hay systems ltd acea6a genix infocomm co., ltd. + aceb51 universal electronics, inc. + acec80 arris group, inc. + aced5c intel corporate acee3b 6harmonics inc + acee70 fontem ventures bv + acee9e samsung electronics co.,ltd acf0b2 becker electronics taiwan ltd. + acf108 lg innotek acf1df d-link international - acf2c5 cisco - acf7f3 xiaomi corporation + acf2c5 cisco systems, inc + acf5e6 cisco systems, inc + acf6f7 lg electronics (mobile communications) + acf7f3 xiaomi communications co ltd + acf85c chengdu higon integrated circuit design co,. ltd. + acf8cc arris group, inc. + acf970 huawei technologies co.,ltd acf97e elesys inc. - acfdec apple, inc - b000b4 cisco + acfaa5 digitron + acfd93 weifang goertek electronics co.,ltd + acfdce intel corporate + acfdec apple, inc. + acfe05 itel mobile limited + b00073 wistron neweb corporation + b000b4 cisco systems, inc + b00247 ampak technology, inc. + b0027e muller services b00594 liteon technology corporation + b00875 huawei technologies co.,ltd + b008bf vital connect, inc. + b009d3 avizia + b009da ring solutions + b00ad5 zte corporation + b00cd1 hewlett packard + b01041 hon hai precision ind. co.,ltd. b01203 dynamics hong kong limited b01266 futaba-kikaku b01408 lightspeed international co. + b01656 huawei technologies co.,ltd b01743 edison global circuits llc + b01886 smardtv + b019c6 apple, inc. b01b7c ontrol a.s. + b01bd2 le shi zhi xin electronic technology (tianjin) limited b01c91 elim co + b01f29 helvetia inc. + b01f81 ieee registration authority + b0227a hp inc. + b02491 huawei device co., ltd. b024f3 progeny systems - b025aa - b03495 apple + b025aa private + b02628 broadcom limited + b02680 cisco systems, inc + b02a1f wingtech group (hongkong)limited + b02a43 google, inc. + b03055 china mobile iot company limited + b030c8 teal drones, inc. + b033a6 juniper networks + b03495 apple, inc. + b0350b mobiwire mobiles (ningbo) co.,ltd b0358d nokia corporation + b0359f intel corporate + b035b5 apple, inc. b03829 siliconware precision industries co., ltd. b03850 nanjing cas-zdc iot system co.,ltd + b03956 netgear + b03ace huawei device co., ltd. + b03d96 vision valley fz llc + b03dc2 wasp artificial intelligence(shenzhen) co.,ltd + b03e51 bskyb ltd + b03eb0 microdia ltd. + b04089 senient systems ltd + b0411d ittim technologies + b0416f shenzhen maxtang computer co.,ltd b0435d nuleds, inc. + b04414 new h3c technologies co., ltd + b04502 huawei device co., ltd. + b04515 mira fitness,llc. + b04519 tct mobile ltd + b04530 bskyb ltd b04545 yacoub automation gmbh b046fc mitrastar technology corp. - b0487a tp-link technologies co., ltd. + b047bf samsung electronics co.,ltd + b0481a apple, inc. + b0487a tp-link technologies co.,ltd. + b0495f omron healthcare co., ltd. + b04a39 beijing roborock technology co., ltd. + b04bbf pt han sung electoronics indonesia b04c05 fresenius medical care deutschland gmbh + b04e26 tp-link technologies co.,ltd. + b04f13 dell inc. + b04fc3 shenzhen nvc cloud technology co., ltd. b050bc shenzhen basicom electronic co.,ltd. b0518e holl technology co.ltd. + b05216 hon hai precision ind. co.,ltd. + b05365 china mobile iot company limited + b05508 huawei technologies co.,ltd b05706 vallox oy b058c4 broadcast microwave services, inc + b05947 shenzhen qihu intelligent technology company limited + b05ada hewlett packard b05b1f thermo fisher scientific s.p.a. + b05b67 huawei technologies co.,ltd + b05cda hp inc. b05ce5 nokia corporation + b05dd4 arris group, inc. + b06088 intel corporate b061c7 ericsson-lg enterprise b06563 shanghai railway communication factory - b065bd apple + b065bd apple, inc. + b065f1 wio manufacturing hk limited + b0672f bowers & wilkins b068b6 hangzhou oye technology co. ltd + b068e6 chongqing fugui electronics co.,ltd. b06971 dei sales, inc. b06cbf 3ality digital systems gmbh + b06ebf asustek computer inc. + b06fe0 samsung electronics co.,ltd + b0700d nokia + b0702d apple, inc. + b072bf murata manufacturing co., ltd. + b0735d huawei device co., ltd. b0750c qa cafe + b0754d nokia b075d5 zte corporation + b0761b huawei technologies co.,ltd b077ac arris group, inc. + b07870 wi-next, inc. + b078f0 beijing huaqinworld technology co.,ltd. b07908 cummings engineering b0793c revolv inc - b07994 motorola mobility llc + b07994 motorola mobility llc, a lenovo company + b07b25 dell inc. + b07d47 cisco systems, inc b07d62 dipl.-ing. h. horstmann gmbh + b07d64 intel corporate + b07e11 texas instruments + b07e70 zadara storage ltd. + b07fb9 netgear b0808c laser light engines b081d8 i-sys corp + b083d6 arris group, inc. + b083fe dell inc. b0869e chloride s.r.l b08807 strata worldwide - b08991 lge + b08900 huawei technologies co.,ltd + b08991 lge + b089c2 zyptonite + b08bcf cisco systems, inc + b08bd0 cisco systems, inc + b08c75 apple, inc. b08e1a uradio systems co., ltd b09074 fulan electronics limited + b0907e cisco systems, inc + b090d4 shenzhen hoin internet technology co., ltd + b09122 texas instruments b09134 taleo + b09137 isis imagestream internet solutions, inc + b0935b arris group, inc. + b09575 tp-link technologies co.,ltd. + b0958e tp-link technologies co.,ltd. + b0966c lanbowan technology ltd. b0973a e-fuel corporation + b0982b sagemcom broadband sas b0989f lg cns + b098bc huawei device co., ltd. b09928 fujitsu limited b09ae2 stemmer imaging gmbh b09bd4 gnh software india private limited - b09fba apple + b09fba apple, inc. b0a10a pivotal systems corporation + b0a2e7 shenzhen tinno mobile technology corp. + b0a37e qing dao haier telecom co.,ltd. + b0a454 tripwire inc. + b0a460 intel corporate + b0a651 cisco systems, inc + b0a6f5 xaptum, inc. b0a72a ensemble designs, inc. + b0a737 roku, inc. b0a86e juniper networks - b0aa36 guangdong oppo mobile telecommunications corp.,ltd. + b0aa36 guangdong oppo mobile telecommunications corp.,ltd + b0aa77 cisco systems, inc + b0aad2 sichuan tianyi kanghe communications co., ltd + b0acd2 zte corporation b0acfa fujitsu limited - b0adaa avaya, inc + b0adaa avaya inc + b0ae25 varikorea + b0b113 texas instruments + b0b194 zte corporation + b0b28f sagemcom broadband sas b0b2dc zyxel communications corporation b0b32b slican sp. z o.o. + b0b353 ieee registration authority + b0b3ad humax co., ltd. b0b448 texas instruments + b0b5c3 guangdong oppo mobile telecommunications corp.,ltd + b0b5e8 ruroc ltd + b0b867 hewlett packard enterprise b0b8d5 nanjing nengrui auto equipment co.,ltd + b0b98a netgear + b0bb8b wavetel technology limited + b0bbe5 sagemcom broadband sas + b0bd1b dongguan liesheng electronic co., ltd. b0bd6d echostreams innovative solutions b0bda1 zaklad elektroniczny sims + b0be76 tp-link technologies co.,ltd. b0bf99 wizitdongdo - b0c4e7 samsung electronics + b0c090 chicony electronics co., ltd. + b0c128 adler elreha gmbh + b0c19e zte corporation + b0c205 bionime + b0c287 technicolor ch usa inc. + b0c387 goefer, inc. + b0c46c senseit + b0c4e7 samsung electronics co.,ltd + b0c53c cisco systems, inc b0c554 d-link international + b0c559 samsung electronics co.,ltd + b0c5ca ieee registration authority b0c69a juniper networks - b0c745 buffalo inc. + b0c745 buffalo.inc b0c83f jiangsu cynray iot co., ltd. b0c8ad people power company + b0c952 guangdong oppo mobile telecommunications corp.,ltd b0c95b beijing symtech co.,ltd + b0ca68 apple, inc. + b0ccfe huawei device co., ltd. b0ce18 zhejiang shenghui lighting co.,ltd b0cf4d mi-zone technology ireland b0d09c samsung electronics co.,ltd b0d2f5 vello systems, inc. + b0d568 shenzhen cultraview digital technology co., ltd b0d59d shenzhen zowee technology co., ltd - b0d7c5 stp kft + b0d5cc texas instruments + b0d7c5 logipix ltd + b0d7cc tridonic gmbh & co kg b0da00 cera electronique + b0daf9 arris group, inc. b0df3a samsung electronics co.,ltd + b0dfc1 tenda technology co.,ltd.dongguan branch + b0e03c tct mobile ltd + b0e17e huawei technologies co.,ltd + b0e235 xiaomi communications co ltd + b0e2e5 fiberhome telecommunication technologies co.,ltd b0e39d cat system co.,ltd. + b0e4d5 google, inc. b0e50e nrg systems inc - b0e754 2wire + b0e5ed huawei technologies co.,ltd + b0e5f9 apple, inc. + b0e71d shanghai maigantech co.,ltd + b0e754 2wire inc + b0e7de homa technologies jsc b0e892 seiko epson corporation b0e97e advanced micro peripherals + b0eabc askey computer corp + b0eb57 huawei technologies co.,ltd b0ec71 samsung electronics co.,ltd b0ec8f gmx sas - b0ee45 azurewave technologies, inc. + b0ecdd huawei technologies co.,ltd + b0ece1 private + b0ee45 azurewave technology inc. + b0ee7b roku, inc + b0f1a3 fengfan (beijing) technology co., ltd. b0f1bc dhemax ingenieros ltda - b0faeb cisco - b0febd + b0f1ec ampak technology, inc. + b0f530 hitron technologies. inc + b0f893 shanghai mxchip information technology co., ltd. + b0f963 hangzhou h3c technologies co., limited + b0faeb cisco systems, inc + b0fc0d amazon technologies inc. + b0fc36 cybertan technology inc. + b0fd0b ieee registration authority + b0febd private + b0fee5 huawei device co., ltd. + b40016 ingenico terminals sas b4009c cableworld ltd. b40142 gci science & technology co.,ltd + b40216 cisco systems, inc b40418 smartchip integrated inc. - b407f9 samsung electro-mechanics + b4055d inspur electronic information industry co.,ltd. + b40566 sp best corporation co., ltd. + b407f9 samsung electro mechanics co., ltd. b40832 tc communications + b40931 huawei technologies co.,ltd + b40ac6 dexon systems ltd. + b40b44 smartisan technology co., ltd. + b40b78 brusa elektronik ag b40b7a brusa elektronik ag b40c25 palo alto networks - b40e96 heran + b40e96 heran b40edc lg-ericsson co.,ltd. - b41489 cisco systems, inc. + b40ede intel corporate + b40f3b tenda technology co.,ltd.dongguan branch + b40fb3 vivo mobile communication co., ltd. + b4107b texas instruments + b41489 cisco systems, inc + b414e6 huawei technologies co.,ltd b41513 huawei technologies co.,ltd - b418d1 apple + b4157e celona inc. + b41780 dti group ltd + b418d1 apple, inc. + b41a1d samsung electronics co.,ltd + b41bb0 apple, inc. + b41c30 zte corporation + b41d2b shenzhen youhua technology co., ltd b41def internet laboratories, inc. b4211d beijing guangxin technology co., ltd b4218a dog hunter llc + b42200 brother industries, ltd. + b42330 itron inc b424e7 codetek technology co.,ltd + b4265d taicang t&w electronics b428f1 e-prime co., ltd. + b4293d shenzhen urovo technology co.,ltd. + b42a0e technicolor ch usa inc. b42a39 orbit merret, spol. s r. o. b42c92 zhejiang weirong electronic co., ltd b42cbe direct payment solutions limited + b42d56 extreme networks, inc. + b42e99 giga-byte technology co.,ltd. + b42ef8 eline technology co.ltd + b43052 huawei technologies co.,ltd + b430c0 york instruments ltd b431b8 aviwest b4346c matsunichi digital technology (hong kong) limited b43564 fujian tian cheng electron science & technical development co.,ltd. b435f7 zhejiang pearmain electronics co.ltd. + b436a9 fibocom wireless inc. + b436d1 renesas electronics (penang) sdn. bhd. + b436e3 kbvision group b43741 consert, inc. + b437d1 ieee registration authority + b43934 pen generations, inc. + b43939 shenzhen tinno mobile technology corp. b439d6 procurve networking by hp b43a28 samsung electronics co.,ltd b43db2 degreane horizon b43e3b viableware, inc - b4417a shenzhen gongjin electronics co.,ltd + b440a4 apple, inc. + b4417a shenzhen gongjin electronics co.,lt b4430d broadlink pty ltd + b44326 huawei technologies co.,ltd + b4475e avaya inc + b447f5 earda technologies co ltd + b44bd2 apple, inc. + b44bd6 ieee registration authority + b44c3b zhejiang dahua technology co., ltd. b44cc2 nr electric co., ltd + b44f96 zhejiang xinzailing technology co., ltd + b45062 embestor technology inc. b451f9 nb software b45253 seagate technology - b4527d sony mobile communications ab - b4527e sony mobile communications ab + b4527d sony mobile communications inc + b4527e sony mobile communications inc + b452a9 texas instruments + b45459 china mobile (hangzhou) information technology co., ltd. b45570 borea + b456b9 teraspek technologies co.,ltd + b456e3 apple, inc. b45861 cremote, llc b45ca4 thing-talk wireless communication technologies corporation limited + b45d50 aruba, a hewlett packard enterprise company + b46077 sichuan changhong electric ltd. + b4608c fiberhome telecommunication technologies co.,ltd + b460ed beijing xiaomi mobile software co., ltd b461ff lumigon a/s b46238 exablox b46293 samsung electronics co.,ltd - b462ad raytest gmbh + b462ad elysia germany gmbh b46698 zealabs srl b467e9 qingdao goertek technology co., ltd. + b46921 intel corporate + b46bfc intel corporate + b46c47 panasonic appliances company + b46d35 dalian seasky automation co;ltd + b46d83 intel corporate + b46e08 huawei technologies co.,ltd + b46f2d wahoo fitness + b47356 hangzhou treebear networking co., ltd. + b47443 samsung electronics co.,ltd + b47447 coreos b4749f askey computer corp b4750e belkin international inc. + b47748 shenzhen neoway technology co.,ltd. + b47947 nutanix + b479a7 samsung electro-mechanics(thailand) + b479c8 ruckus wireless + b47af1 hewlett packard enterprise + b47c29 shenzhen guzidi technology co.,ltd + b47c59 jiangsu hengxin technology co.,ltd. + b47c9c amazon technologies inc. b47f5e foresight manufacture (s) pte ltd + b48107 shenzhen chuangwei-rgb electronics co.,ltd + b481bf meta-networks, llc b48255 research products corporation b4827b akg acoustics gmbh b482c5 relay2, inc. b482fe askey computer corp b48547 amptown system company gmbh + b485e1 apple, inc. + b48655 huawei technologies co.,ltd + b48901 huawei technologies co.,ltd b48910 coster t.e. s.p.a. + b48a5f juniper networks + b48b19 apple, inc. b4944e wetelecom co., ltd. + b49691 intel corporate b49842 zte corporation b4994c texas instruments - b499ba hewlett-packard company + b499ba hewlett packard + b49a95 shenzhen boomtech industrial corporation + b49cdf apple, inc. + b49d02 samsung electronics co.,ltd + b49d0b bq b49db4 axion technologies inc. + b49e80 sichuan changhong electric ltd. + b49eac imagik int'l corp b49ee6 shenzhen technology co ltd + b4a25c cambium networks limited + b4a2eb ieee registration authority + b4a305 xiamen yaxon network co., ltd. + b4a382 hangzhou hikvision digital technology co.,ltd. b4a4b5 zen eye co.,ltd - b4a4e3 cisco systems, inc. + b4a4e3 cisco systems, inc b4a5a9 modi gmbh + b4a5ac guangdong oppo mobile telecommunications corp.,ltd + b4a5ef sercomm corporation. + b4a828 shenzhen concox information technology co., ltd b4a82b histar digital electronics co., ltd. - b4a95a avaya, inc + b4a898 huawei device co., ltd. + b4a8b9 cisco systems, inc + b4a94f mercury corporation + b4a95a avaya inc + b4a984 symantec corporation + b4a9fc quanta computer inc. + b4a9fe ghia technology (shenzhen) ltd b4aa4d ensequence, inc. b4ab2c mtm technology corporation - b4b017 avaya, inc + b4ada3 guangzhou shiyuan electronic technology company limited + b4ae2b microsoft + b4ae6f circle reliance, inc dba cranberry networks + b4b017 avaya inc + b4b055 huawei technologies co.,ltd + b4b15a siemens ag energy management division + b4b265 daeho i&t + b4b291 lg electronics b4b362 zte corporation + b4b384 shenzhen figigantic electronic co.,ltd b4b52f hewlett packard b4b542 hubbell power systems, inc. b4b5af minsung electronics + b4b5b6 chongqing fugui electronics co.,ltd. b4b676 intel corporate + b4b686 hewlett packard + b4b859 texa spa b4b88d thuh company + b4ba12 china mobile (hangzhou) information technology co.,ltd. + b4bc7c texas instruments + b4bff6 samsung electronics co.,ltd + b4c0f5 shenzhen tinno mobile technology corp. + b4c170 yi chip microelectronics (hangzhou) co., ltd + b4c26a garmin international b4c44e vxl etech pvt ltd - b4c799 motorola solutions inc. + b4c476 wuhan maritime communication research institute + b4c4fc xiaomi communications co ltd + b4c62e molex cms + b4c6f8 axilspot communication + b4c799 extreme networks, inc. b4c810 umpi elettronica + b4c9b9 sichuan ai-link technology co., ltd. + b4cb57 guangdong oppo mobile telecommunications corp.,ltd + b4cc04 piranti b4cce9 prosyst + b4cd27 huawei technologies co.,ltd + b4ce40 samsung electronics co.,ltd + b4cef6 htc corporation + b4cefe james czekaj b4cfdb shenzhen jiuzhou electric co.,ltd + b4cfe0 sichuan tianyi kanghe communications co., ltd + b4d0a9 china mobile group device co.,ltd. + b4d135 cloudistics + b4d5bd intel corporate + b4d64e caldero limited b4d8a9 betterbots b4d8de iota computing, inc. + b4dc09 guangzhou dawei communication co.,ltd b4dd15 controlthings oy ab + b4ddd0 continental automotive hungary kft + b4de31 cisco systems, inc + b4dedf zte corporation b4df3b chromlech b4dffa litemax electronics inc. + b4e01d conception electronique b4e0cd fusion-io, inc - b4e1eb - b4e9b0 cisco + b4e10f dell inc. + b4e1c4 microsoft mobile oy + b4e1eb private + b4e3f9 silicon laboratories + b4e62a lg innotek + b4e62d espressif inc. + b4e782 vivalnk + b4e842 hong kong bouffalo lab limited + b4e8c9 xada technologies + b4e9a3 port industrial automation gmbh + b4e9b0 cisco systems, inc + b4ec02 alpsalpine co,.ltd + b4ecf2 shanghai listent medical tech co., ltd. b4ed19 pie digital, inc. b4ed54 wohler technologies + b4ee25 shenzhen belon technology co.,ltd + b4eeb4 askey computer corp b4eed4 texas instruments - b4f0ab apple - b4f2e8 pace plc + b4ef04 daihan scientific co., ltd. + b4ef1c 360 ai technology co.ltd + b4ef39 samsung electronics co.,ltd + b4effa lemobile information technology (beijing) co., ltd. + b4f0ab apple, inc. + b4f18c huawei device co., ltd. + b4f1da lg electronics (mobile communications) + b4f2e8 arris group, inc. b4f323 petatel inc. + b4f58e huawei technologies co.,ltd + b4f61c apple, inc. + b4f7a1 lg electronics (mobile communications) + b4f81e kinova + b4f949 optilink networks pvt ltd + b4fa48 apple, inc. + b4fbe3 altobeam (china) inc. + b4fbe4 ubiquiti networks inc. + b4fbf9 huawei technologies co.,ltd b4fc75 sema electronics(hk) co.,ltd b4fe8c centro sicurezza italia spa + b4ff98 huawei technologies co.,ltd + b80018 htel + b802a4 aeonsemi, inc. b80305 intel corporate b80415 bayan audio + b805ab zte corporation + b80716 vivo mobile communication co., ltd. + b80756 cisco meraki + b808cf intel corporate + b808d7 huawei technologies co.,ltd + b8098a apple, inc. b80b9d ropex industrie-elektronik gmbh + b810d4 masimo corporation + b8114b cisco systems, inc + b813e9 trace live network b81413 keen high holding(hk) ltd. + b814db ohsung b81619 arris group, inc. - b817c2 apple + b816db chant sincere co.,ltd + b817c2 apple, inc. + b8186f oriental motor co., ltd. + b81904 nokia shanghai bell co., ltd. b81999 nesys + b81daa lg electronics (mobile communications) + b81f5e apption labs limited b820e7 guangzhou horizontal information & network integration co. ltd + b8224f sichuan tianyi comheart telecomco., ltd b82410 magneti marelli slovakia s.r.o. b8241a sweda informatica ltda + b824f0 soyo technology development co., ltd. + b8259a thalmic labs b8266c anov france b826d4 furukawa industrial s.a. produtos elétricos + b827c5 huawei device co., ltd. b827eb raspberry pi foundation - b8288b parker hannifin + b8288b parker hannifin manufacturing (uk) ltd b829f7 blaster tech - b82a72 dell inc + b82a72 dell inc. + b82aa9 apple, inc. b82adc efr europäische funk-rundsteuerung gmbh - b82ca0 honeywell hommed + b82ca0 resideo + b82d28 ampak technology,inc. + b82fcb cms electracom b830a8 road-track telematics development + b831b5 microsoft corporation + b83241 wuhan tianyu information industry co., ltd. b836d8 videoswitch - b83861 cisco + b83765 guangdong oppo mobile telecommunications corp.,ltd + b83861 cisco systems, inc b838ca kyokko tsushin system co.,ltd + b83a08 tenda technology co.,ltd.dongguan branch + b83a5a aruba, a hewlett packard enterprise company b83a7b worldplay (canada) inc. + b83a9d alarm.com b83d4e shenzhen cultraview digital technology co.,ltd shanghai branch - b83e59 roku, inc + b83e59 roku, inc. b8415f asp ag + b841a4 apple, inc. b843e4 vlatacom + b844ae tct mobile ltd + b844d9 apple, inc. + b8477a dasan electron co., ltd. b847c6 sanjet technology corp. + b848aa em microelectronic + b84dee hisense broadband multimedia technology co.,ltd + b84fd5 microsoft corporation + b85001 extreme networks, inc. + b853ac apple, inc. b85510 zioncom electronics (shenzhen) ltd. + b856bd itt llc + b85776 lignex1 + b857d8 samsung electronics co.,ltd b85810 numera, inc. + b8599f mellanox technologies, inc. + b85a73 samsung electronics co.,ltd b85af7 ouya, inc b85afe handaer communication technology (beijing) co., ltd + b85d0a apple, inc. b85e7b samsung electronics co.,ltd + b85f98 amazon technologies inc. + b85fb0 huawei technologies co.,ltd b86091 onnet technologies and innovations llc - b8616f accton wireless broadband(awb), corp. - b8621f cisco systems, inc. + b86142 beijing tricolor technology co., ltd + b8616f accton technology corp + b8621f cisco systems, inc + b8634d apple, inc. + b86392 guangdong genius technology co., ltd. b863bc robotis, co, ltd b86491 ck telecom ltd b8653b bolymin, inc. + b86685 sagemcom broadband sas + b869c2 sunitec enterprise co., ltd. + b869f4 routerboard.com + b86a97 edgecore networks corporation b86b23 toshiba b86ce8 samsung electronics co.,ltd - b870f4 compal information (kunshan) co., ltd. + b870f4 compal information (kunshan) co., ltd. b87424 viessmann elektronik gmbh b87447 convergence technologies b875c0 paypal, inc. b8763f hon hai precision ind. co.,ltd. - b877c3 decagon devices, inc. - b8782e apple + b877c3 meter group + b87826 nintendo co.,ltd + b8782e apple, inc. + b87879 roche diagnostics gmbh b8797e secure meters (uk) limited b87ac9 siemens ltd. - b87cf2 aerohive networks inc. + b87bc5 apple, inc. + b87c6f nxp (china) management ltd. + b87cf2 extreme networks, inc. + b88035 shenzhen qihu intelligent technology company limited + b8804f texas instruments + b88198 intel corporate + b881fa apple, inc. + b88303 hewlett packard enterprise + b88584 dell inc. + b88687 liteon technology corporation b8871e good mind industries co., ltd. + b8876e yandex services ag b887a8 step ahead innovations inc. - b888e3 compal information (kunshan) co., ltd + b887c6 prudential technology co.,ltd + b888e3 compal information (kunshan) co., ltd. + b88981 chengdu innothings technology co., ltd. b889ca iljin electric co., ltd. b88a60 intel corporate - b88d12 apple + b88aec nintendo co.,ltd + b88d12 apple, inc. + b88df1 nanjing bigfish semiconductor co., ltd. b88e3a infinite technologies jlt + b88e82 huawei device co., ltd. + b88ec6 stateless networks + b88edf zencheer communication technology co., ltd. b88f14 analytica gmbh + b88fb4 jabil circuit italia s.r.l + b89047 apple, inc. + b891c9 handreamnet b8921d bg t&a + b89436 huawei technologies co.,ltd b894d2 retail innovation htt ab b89674 alldsp gmbh & co. kg b8975a biostar microtech int'l corp. b898b0 atlona inc. b898f7 gionee communication equipment co,ltd.shenzhen + b89919 7signal solutions, inc + b899ae shenzhen miaoming intelligent technology co.,ltd + b899b0 cohere technologies + b89a2a intel corporate + b89a9a xin shi jia technology (beijing) co.,ltd + b89acd elite optoelectronic(asia)co.,ltd b89aed oceanserver technology, inc b89bc9 smc networks inc + b89be4 abb power systems power generation + b89f09 wistron neweb corporation + b8a175 roku, inc. + b8a377 cisco systems, inc b8a386 d-link international b8a3e0 benrui technology co.,ltd + b8a44f axis communications ab + b8a58d axe group holdings limited b8a8af logic s.p.a. - b8ac6f dell inc + b8ac6f dell inc. + b8ad3e bluecom + b8ae1c smart cube., ltd b8ae6e nintendo co., ltd. - b8af67 hewlett-packard company + b8aeed elitegroup computer systems co.,ltd. + b8af67 hewlett packard b8b1c7 bt&com co.,ltd + b8b2eb googol technology (hk) limited + b8b2f8 apple, inc. + b8b3dc derek (shaoguan) limited b8b42e gionee communication equipment co,ltd.shenzhen b8b7d7 2gig technologies + b8b7f1 wistron neweb corporation + b8b81e intel corporate b8b94e shenzhen ibaby labs, inc. b8ba68 xi'an jizhong digital communication co.,ltd b8ba72 cynove + b8bb23 guangdong nufront csc co., ltd b8bb6d eneres co.,ltd. - b8bebf cisco systems, inc. + b8bbaf samsung electronics co.,ltd + b8bc1b huawei technologies co.,ltd + b8bc5b samsung electronics co.,ltd + b8bd79 trendpoint systems + b8bebf cisco systems, inc + b8bef4 devolo ag + b8bf83 intel corporate + b8c111 apple, inc. b8c1a2 dragon path technologies co., limited + b8c227 pstec + b8c253 juniper networks + b8c385 huawei technologies co.,ltd + b8c3bf henan chengshi network technology co.,ltd b8c46f primmcon industries inc b8c68e samsung electronics co.,ltd + b8c6aa earda technologies co ltd b8c716 fiberhome telecommunication technologies co.,ltd - b8c75d apple + b8c74a guangdong oppo mobile telecommunications corp.,ltd + b8c75d apple, inc. b8c855 shanghai gbcom communication technology co.,ltd. - b8ca3a dell inc + b8c8eb itel mobile limited + b8c9b5 guangdong oppo mobile telecommunications corp.,ltd + b8ca04 holtek semiconductor inc. + b8ca3a dell inc. + b8cb29 dell inc. b8cd93 penetek, inc b8cda7 maxeler technologies ltd. + b8cef6 mellanox technologies, inc. b8d06f guangzhou hkust fok ying tung research institute + b8d309 cox communications, inc + b8d43e vivo mobile communication co., ltd. b8d49d m seven system ltd. - b8d9ce samsung electronics + b8d4e7 aruba, a hewlett packard enterprise company + b8d50b sunitec enterprise co.,ltd + b8d526 zyxel communications corporation + b8d6f6 huawei technologies co.,ltd + b8d7af murata manufacturing co., ltd. + b8d812 ieee registration authority + b8d94d sagemcom broadband sas + b8d9ce samsung electronics co.,ltd b8daf1 strahlenschutz- entwicklungs- und ausruestungsgesellschaft mbh b8daf7 advanced photonics, inc. + b8db1c integrated device technology (malaysia) sdn. bhd. b8dc87 iai corporation + b8dd71 zte corporation + b8de5e longcheer telecommunication limited b8df6b spotcam co., ltd. + b8e3b1 huawei technologies co.,ltd + b8e3ee universal electronics, inc. b8e589 payter bv - b8e625 2wire + b8e625 2wire inc b8e779 9solutions oy - b8e856 apple + b8e856 apple, inc. b8e937 sonos, inc. + b8eaaa icg networks co.,ltd + b8eca3 zyxel communications corporation + b8ee0e sagemcom broadband sas + b8ee65 liteon technology corporation b8ee79 ywire technologies, inc. + b8ef8b shenzhen cannice technology co.,ltd + b8f009 espressif inc. + b8f080 sps, inc. + b8f12a apple, inc. + b8f317 isun smasher communications private limited b8f4d0 herrmann ultraschalltechnik gmbh & co. kg b8f5e7 waytools, llc - b8f6b1 apple + b8f653 shenzhen jingxun software telecommunication technology co.,ltd + b8f6b1 apple, inc. b8f732 aryaka networks inc + b8f74a rcntec b8f828 changshu gaoshida optoelectronic technology co. ltd. - b8f934 sony ericsson mobile communications ab + b8f853 arcadyan corporation + b8f883 tp-link technologies co.,ltd. + b8f8be bluecom + b8f934 sony mobile communications inc + b8fc9a le shi zhi xin electronic technology (tianjin) limited b8fd32 zhejiang roicx microelectronics - b8ff61 apple + b8ff61 apple, inc. b8ff6f shanghai typrotech technology co.ltd + b8ffb3 mitrastar technology corp. b8fffe texas instruments bc0200 stewart audio + bc024a hmd global oy + bc03a7 mfp michelin bc0543 avm gmbh + bc0963 apple, inc. bc0da5 texas instruments bc0f2b fortune techgroup co.,ltd + bc0f64 intel corporate + bc0f9a d-link international + bc0fa7 ouster bc125e beijing wisvideo inc. + bc13a8 shenzhen youhua technology co., ltd bc1401 hitron technologies. inc + bc1485 samsung electronics co.,ltd bc14ef iton technology limited bc15a6 taiwan jantek electronics,ltd. - bc1665 cisco + bc15ac vodafone italia s.p.a. + bc1665 cisco systems, inc + bc1695 zte corporation + bc16f5 cisco systems, inc + bc17b8 intel corporate bc1a67 yf technology co., ltd - bc20a4 samsung electronics + bc1ae4 huawei device co., ltd. + bc1c81 sichuan ilink technology co., ltd. + bc20a4 samsung electronics co.,ltd bc20ba inspur (shandong) electronic information co., ltd + bc22fb rf industries + bc2392 byd precision manufacture company ltd. + bc25e0 huawei technologies co.,ltd + bc25f0 3d display technologies co., ltd. bc261d hong kong tecon technology + bc2643 elprotronic inc. + bc26a1 factory five corporation + bc26c7 cisco systems, inc + bc282c e-smart systems pvt. ltd bc2846 nextbit computing pvt. ltd. bc28d6 rowley associates limited bc2b6b beijing haier ic design co.,ltd bc2bd7 revogi innovation co., ltd. bc2c55 bear flag design, inc. bc2d98 thinglobal llc + bc2def realme chongqing mobile telecommunications corp.,ltd. + bc2e48 arris group, inc. + bc2ef6 huawei device co., ltd. + bc2f3d vivo mobile communication co., ltd. bc305b dell inc. - bc307d wistron neweb corp. + bc307d wistron neweb corporation + bc307e wistron neweb corporation + bc30d9 arcadyan corporation + bc325f zhejiang dahua technology co., ltd. + bc33ac silicon laboratories + bc3400 ieee registration authority bc35e5 hydro systems company + bc3865 jwcnetworks bc38d2 pandachip limited bc39a6 csun system technology co.,ltd - bc3baf apple + bc39d9 z-tec + bc3aea guangdong oppo mobile telecommunications corp.,ltd + bc3baf apple, inc. + bc3d85 huawei technologies co.,ltd + bc3e07 hitron technologies. inc bc3e13 accordance systems inc. + bc3ecb vivo mobile communication co., ltd. + bc3f4e teleepoch ltd + bc3f8f huawei technologies co.,ltd bc4100 codaco electronic s.r.o. + bc4101 shenzhen tinno mobile technology corp. + bc428c alpsalpine co,.ltd bc4377 hang zhou huite technology co.,ltd. + bc4434 shenzhen tinno mobile technology corp. bc4486 samsung electronics co.,ltd + bc44b0 elastifile + bc452e knowledge development for pof s.l. + bc4699 tp-link technologies co.,ltd. bc4760 samsung electronics co.,ltd + bc4a56 cisco systems, inc bc4b79 sensingtek + bc4cc4 apple, inc. + bc4dfb hitron technologies. inc bc4e3c core staff co., ltd. + bc4e5d zhongmiao technology co., ltd. bc51fe swann communications pty ltd - bc52b7 apple + bc52b4 nokia + bc52b7 apple, inc. + bc542f intel corporate + bc5436 apple, inc. + bc5451 samsung electronics co.,ltd + bc54f9 drogoo technology co., ltd. + bc54fc shenzhen mercury communication technologies co.,ltd. + bc5a56 cisco systems, inc + bc5bd5 arris group, inc. + bc5c4c elecom co.,ltd. + bc5ea1 psikick, inc. bc5ff4 asrock incorporation + bc5ff6 mercury communication technologies co.,ltd. + bc6010 qingdao hisense communications co.,ltd. + bc60a7 sony interactive entertainment inc. + bc620e huawei technologies co.,ltd bc629f telenet systems p. ltd. - bc6778 apple + bc62ce shenzhen netis technology co.,ltd + bc62d2 genexis international b.v. + bc644b arris group, inc. + bc6641 ieee registration authority + bc66de shadow creator information technology co.,ltd. + bc671c cisco systems, inc + bc6778 apple, inc. bc6784 environics oy + bc69cb panasonic life solutions networks co., ltd. bc6a16 tdvine bc6a29 texas instruments + bc6a2f henge docks llc + bc6a44 commend international gmbh + bc6b4d nokia + bc6c21 apple, inc. + bc6d05 dusun electron co.,ltd. + bc6e64 sony mobile communications inc bc6e76 green energy options ltd bc71c1 xtrillion, inc. bc72b1 samsung electronics co.,ltd + bc74d7 hangzhou juru technology co.,ltd + bc7536 alpsalpine co,.ltd + bc7574 huawei technologies co.,ltd + bc7596 beijing broadwit technology co., ltd. bc764e rackspace us, inc. - bc7670 shenzhen huawei communication technologies co., ltd + bc765e samsung electronics co.,ltd + bc7670 huawei technologies co.,ltd + bc76c5 huawei technologies co.,ltd bc7737 intel corporate bc779f sbm co., ltd. bc79ad samsung electronics co.,ltd + bc7abf samsung electronics co.,ltd bc7dd1 radio data comms + bc7e8b samsung electronics co.,ltd + bc7f7b huawei device co., ltd. + bc7fa4 xiaomi communications co ltd bc811f ingate systems bc8199 basic co.,ltd. - bc83a7 shenzhen chuangwei-rgb electronics co.,lt - bc851f samsung electronics + bc825d mitsumi electric co.,ltd. + bc8385 microsoft corporation + bc83a7 shenzhen chuangwei-rgb electronics co.,ltd + bc851f samsung electronics co.,ltd bc8556 hon hai precision ind. co.,ltd. bc8893 villbau ltd. + bc88c3 ningbo dooya mechanic & electronic technology co., ltd + bc8aa3 nhn entertainment + bc8ae8 qing dao haier telecom co.,ltd. bc8b55 npp eliks america inc. dba t&m atlantic - bc8ccd samsung electro mechanics co.,ltd. - bc8d0e alcatel-lucent - bc926b apple - bc9680 shenzhen gongjin electronics co.,ltd - bc9889 fiberhome telecommunication tech.co.,ltd. + bc8ccd samsung electro-mechanics(thailand) + bc8d0e nokia + bc903a robert bosch gmbh + bc91b5 infinix mobility limited + bc926b apple, inc. + bc9325 ningbo joyson preh car connect co.,ltd. + bc9680 shenzhen gongjin electronics co.,lt + bc9740 ieee registration authority + bc9789 huawei device co., ltd. + bc97e1 broadcom limited + bc9889 fiberhome telecommunication technologies co.,ltd + bc98df motorola mobility llc, a lenovo company + bc9911 zyxel communications corporation + bc9930 huawei technologies co.,ltd bc99bc fonsee technology inc. + bc9a53 huawei device co., ltd. + bc9b68 technicolor ch usa inc. + bc9c31 huawei technologies co.,ltd + bc9cc5 beijing huafei technology co., ltd. + bc9d42 shenzhen rf-link technology co.,ltd. bc9da5 dascom europe gmbh + bc9fe4 aruba, a hewlett packard enterprise company + bc9fef apple, inc. + bca042 shanghai flyco electrical appliance co.,ltd + bca13a ses-imagotag bca4e1 nabto + bca511 netgear + bca58b samsung electronics co.,ltd + bca5a9 apple, inc. + bca8a6 intel corporate + bca920 apple, inc. + bca993 cambium networks limited bca9d6 cyber-rain, inc. + bcab7c trnp korea co ltd + bcad28 hangzhou hikvision digital technology co.,ltd. + bcadab avaya inc bcaec5 asustek computer inc. + bcaf91 te connectivity sensor solutions + bcb0e7 huawei technologies co.,ltd bcb181 sharp corporation - bcb1f3 samsung electronics + bcb1f3 samsung electronics co.,ltd + bcb22b em-tech + bcb308 hongkong ragentek communication technology co.,limited bcb852 cybera, inc. + bcb863 apple, inc. + bcbac2 hangzhou hikvision digital technology co.,ltd. bcbae1 arec inc. bcbbc9 kellendonk elektronik gmbh + bcbc46 sks welding systems gmbh + bcbd9e itel mobile limited + bcc00f fiberhome telecommunication technologies co.,ltd bcc168 dinbox sverige ab bcc23a thomson video networks + bcc31b kygo life a + bcc342 panasonic communications co., ltd. + bcc493 cisco systems, inc bcc61a spectra embedded systems bcc6db nokia corporation bcc810 cisco spvtg + bccab5 arris group, inc. bccd45 voismart + bccf4f zyxel communications corporation bccfcc htc corporation + bcd11f samsung electronics co.,ltd + bcd165 cisco spvtg bcd177 tp-link technologies co.,ltd. + bcd1d3 shenzhen tinno mobile technology corp. + bcd295 cisco systems, inc bcd5b6 d2d technologies + bcd713 owl labs + bcd767 private + bcd7ce china mobile (hangzhou) information technology co., ltd. bcd940 asr co,.ltd. + bcddc2 espressif inc. bce09d eoslink + bce143 apple, inc. + bce265 huawei technologies co.,ltd bce59f waterworld technology co.,ltd + bce63f samsung electronics co.,ltd + bce67c cambium networks limited + bce712 cisco systems, inc + bce767 quanzhou tdx electronics co., ltd + bce796 wireless cctv ltd + bce92f hp inc. bcea2b citycom gmbh + bceafa hewlett packard + bceb5f fujian beifeng telecom technology co., ltd. + bcec23 shenzhen chuangwei-rgb electronics co.,ltd + bcec5d apple, inc. bcee7b asustek computer inc. + bcf171 intel corporate + bcf1f2 cisco systems, inc + bcf292 plantronics, inc. bcf2af devolo ag - bcf5ac lg electronics + bcf310 extreme networks, inc. + bcf45f zte corporation + bcf5ac lg electronics (mobile communications) bcf61c geomodeling wuxi technology co. ltd. bcf685 d-link international + bcf811 xiamen dnake technology co.,ltd + bcf9f2 teko + bcfab8 guangzhou shiyuan electronic technology company limited bcfe8c altronic, llc + bcfed9 apple, inc. + bcff21 smart code(shenzhen)technology co.,ltd + bcff4d espressif inc. bcffac topcon corporation + bcffeb motorola mobility llc, a lenovo company + c0028d winstar display co.,ltd + c00380 juniper networks + c005c2 arris group, inc. + c006c3 tp-link corporation limited + c0074a brita gmbh c00d7e additech, inc. + c010b1 hmd global oy + c01173 samsung electronics co.,ltd c011a6 fort-telecom ltd. c01242 alpha security products + c0132b sichuan changhong electric ltd. c0143d hon hai precision ind. co.,ltd. + c014b8 nokia + c014fe cisco systems, inc + c01692 china mobile group device co.,ltd. + c0174d samsung electronics co.,ltd + c01850 quanta computer inc. c01885 hon hai precision ind. co.,ltd. + c01ada apple, inc. + c01b23 sichuan tianyi comheart telecom co.,ltd + c01c30 shenzhen wifi-3l technology co.,ltd c01e9b pixavi as - c02250 + c0210d shenzhen rf-link technology co.,ltd. + c02250 koss corporation c02506 avm gmbh - c0255c cisco + c0252f shenzhen mercury communication technologies co.,ltd. + c0255c cisco systems, inc + c02567 nexxt solutions + c025a2 nec platforms, ltd. + c025e9 tp-link technologies co.,ltd. c027b9 beijing national railway research & design institute of signal & communication co., ltd. + c0280b honor device co., ltd. + c0288d logitech, inc c02973 audyssey laboratories inc. c029f3 xysystem c02bfc ines. applied informatics gmbh - c02c7a shen zhen horn audio co., ltd. + c02c7a shenzhen horn audio co.,ltd. + c02dee cuff + c02e25 guangdong oppo mobile telecommunications corp.,ltd + c02e26 private + c02ff1 volta networks + c0335e microsoft + c033da shenzhen jrun technologies co., ltd c034b4 gigastone corporation c03580 a&r tech c035bd velocytech aps + c035c5 prosoft systems ltd + c03656 fiberhome telecommunication technologies co.,ltd + c03896 hon hai precision ind. co.,ltd. c038f9 nokia danmark a/s + c03937 gree electric appliances, inc. of zhuhai + c0395a zhejiang dahua technology co., ltd. c03b8f minicom digital signage + c03c59 intel corporate + c03d03 samsung electronics co.,ltd + c03d46 shanghai sango network technology co.,ltd + c03dd9 mitrastar technology corp. c03e0f bskyb ltd + c03eba dell inc. c03f0e netgear c03f2a biscotti, inc. - c03fd5 elitegroup computer systems co., ltd + c03fd5 elitegroup computer systems co.,ltd. + c03fdd huawei technologies co.,ltd + c04004 medicaroid corporation + c04121 nokia solutions and networks gmbh & co. kg c041f6 lg electronics inc + c042d0 juniper networks c04301 epec oy c044e3 shenzhen sinkna electronics co., ltd + c04754 vivo mobile communication co., ltd. + c048e6 samsung electronics co.,ltd + c048fb shenzhen jinghanda electronics co.ltd c0493d maitrise technologique c04a00 tp-link technologies co.,ltd. + c04a09 zhejiang everbright communication equip. co,. ltd + c04b13 wondersound technology co., ltd c04df7 serelec - c057bc avaya, inc + c0517e hangzhou hikvision digital technology co.,ltd. + c05336 beijing national railway research & design institute of signal & communication group co..ltd. + c05627 belkin international inc. + c056e3 hangzhou hikvision digital technology co.,ltd. + c057bc avaya inc c058a7 pico systems co., ltd. - c05e6f v. stonkaus firma "kodinis raktas" + c05e6f v. stonkaus firma kodinis raktas c05e79 shenzhen huaxun ark technologies co.,ltd c06118 tp-link technologies co.,ltd. - c0626b cisco systems, inc. - c06394 apple + c0619a ieee registration authority + c0626b cisco systems, inc + c06369 binxin technology(zhejiang) ltd. + c06394 apple, inc. c064c6 nokia corporation + c064e4 cisco systems, inc c06599 samsung electronics co.,ltd - c067af cisco + c067af cisco systems, inc c06c0f dobbs stanford c06c6d magnemotion, inc. - c07bbc cisco + c06d1a tianjin henxinhuifeng technology co.,ltd. + c07009 huawei technologies co.,ltd + c0742b shenzhen xunlong software co.,limited + c074ad grandstream networks, inc. + c07831 huawei device co., ltd. + c07878 flextronics manufacturing(zhuhai)co.,ltd. + c07bbc cisco systems, inc + c07cd1 pegatron corporation c07e40 shenzhen xdk communication equipment co.,ltd + c08135 ningbo forfan technology co., ltd c08170 effigis geosolutions - c0830a 2wire - c0847a apple + c0830a 2wire inc + c08359 ieee registration authority + c083c9 huawei device co., ltd. + c0847a apple, inc. + c0847d ampak technology, inc. + c08488 finis inc + c0854c ragentek technology group + c086b3 shenzhen voxtech co., ltd. + c087eb samsung electronics co.,ltd c0885b snd tech co., ltd. + c08997 samsung electronics co.,ltd + c089ab arris group, inc. + c08acd guangzhou shiyuan electronic technology company limited c08ade ruckus wireless c08b6f s i sistemas inteligentes eletrônicos ltda - c08c60 cisco + c08c60 cisco systems, inc + c08c71 motorola mobility llc, a lenovo company + c08f20 shenzhen skyworth digital technology co., ltd c09132 patriot memory c09134 procurve networking by hp + c09296 zte corporation + c09435 arris group, inc. + c094ad zte corporation + c095da nxp india private limited + c09727 samsung electro-mechanics(thailand) + c09879 acer inc. + c098da china mobile iot company limited c098e5 university of michigan + c09a71 xiamen meitu mobile technology co.ltd + c09ad0 apple, inc. + c09bf4 ieee registration authority + c09c04 shaanxi guolian digital tv technology co.,ltd. c09c92 coby c09d26 topicon hk lmd. - c09f42 apple + c09f05 guangdong oppo mobile telecommunications corp.,ltd + c09f42 apple, inc. + c09fe1 zte corporation + c0a00d arris group, inc. c0a0bb d-link international c0a0c7 fairfield industries c0a0de multi touch oy c0a0e2 eden innovations + c0a1a2 marqmetrix c0a26d abbott point of care c0a364 3d systems massachusetts + c0a36e bskyb ltd c0a39e earthcam, inc. + c0a53e apple, inc. + c0a5dd shenzhen mercury communication technologies co.,ltd. + c0a600 apple, inc. + c0a66d inspur group co., ltd. + c0a8f0 adamson systems engineering c0aa68 osasi technos inc. - c0ac54 sagemcom + c0ac54 sagemcom broadband sas + c0aefd shenzhen hc-wlan technology co.,ltd + c0b101 zte corporation c0b339 comigo ltd. c0b357 yoshiki electronics industry ltd. + c0b47d huawei device co., ltd. + c0b5cd huawei device co., ltd. + c0b5d7 chongqing fugui electronics co.,ltd. + c0b658 apple, inc. + c0b6f9 intel corporate + c0b713 beijing xiaoyuer technology co. ltd. + c0b883 intel corporate c0b8b1 bitbox ltd + c0b8e6 ruijie networks co.,ltd c0bae6 application solutions (electronics and vision) ltd + c0bc9a huawei technologies co.,ltd c0bd42 zpa smart energy a.s. + c0bdc8 samsung electronics co.,ltd + c0bdd1 samsung electro-mechanics(thailand) + c0bfa7 juniper networks + c0bfc0 huawei technologies co.,ltd c0c1c0 cisco-linksys, llc c0c3b6 automatic systems c0c520 ruckus wireless + c0c522 arris group, inc. c0c569 shanghai lynuc cnc technology co.,ltd c0c687 cisco spvtg c0c946 mitsuya laboratories inc. + c0c976 shenzhen tinno mobile technology corp. + c0c9e3 tp-link technologies co.,ltd. c0cb38 hon hai precision ind. co.,ltd. + c0cbf1 mobiwire mobiles (ningbo) co., ltd + c0cc42 sichuan tianyi comheart telecom co., ltd. + c0ccf8 apple, inc. + c0cecd apple, inc. c0cfa3 creative electronics & software, inc. - c0d044 sagemcom - c0d962 askey computer corp. + c0d012 apple, inc. + c0d026 huawei device co., ltd. + c0d044 sagemcom broadband sas + c0d0ff china mobile iot company limited + c0d193 huawei device co., ltd. + c0d2dd samsung electronics co.,ltd + c0d2f3 hui zhou gaoshengda technology co.,ltd + c0d391 ieee registration authority + c0d3c0 samsung electronics co.,ltd + c0d46b huawei device co., ltd. + c0d682 arista networks + c0d834 xvtec ltd + c0d962 askey computer corp + c0d9f7 shandong domor intelligent s&t co.,ltd c0da74 hangzhou sunyard technology co., ltd. + c0dc6a qingdao eastsoft communication technology co.,ltd + c0dcd7 huawei device co., ltd. + c0dcda samsung electronics co.,ltd c0df77 conrad electronic se + c0e018 huawei technologies co.,ltd + c0e1be huawei technologies co.,ltd + c0e3a0 renesas electronics (penang) sdn. bhd. + c0e3fb huawei technologies co.,ltd c0e422 texas instruments - c0e54e denx computer systems gmbh + c0e42d tp-link technologies co.,ltd. + c0e434 azurewave technology inc. + c0e54e aries embedded gmbh + c0e7bf sichuan ai-link technology co., ltd. + c0e862 apple, inc. c0eae4 sonicwall + c0ee40 laird technologies + c0eeb5 enice network. + c0eefb oneplus tech (shenzhen) ltd c0f1c4 pacidal corporation ltd. + c0f2fb apple, inc. + c0f4e6 huawei technologies co.,ltd + c0f636 hangzhou kuaiyue technologies, ltd. + c0f6c2 huawei technologies co.,ltd + c0f6ec huawei technologies co.,ltd c0f79d powercode c0f8da hon hai precision ind. co.,ltd. + c0f945 toshiba toko meter systems co., ltd. c0f991 gme standard communications p/l + c0fd84 zte corporation + c0ffa8 huawei technologies co.,ltd + c0ffd4 netgear + c40006 lipi data systems ltd. + c40049 kamama + c400ad advantech technology (china) co., ltd. c40142 maxmedia technology limited c4017c ruckus wireless c401b1 seektech inc - c40415 netgear inc., - c40528 huawei technologies co., ltd - c40938 fujian star-net communication co., ltd - c40acb cisco systems, inc. + c401ce presition (2000) co., ltd. + c402e1 khwahish technologies private limited + c40415 netgear + c4047b shenzhen youhua technology co., ltd + c40528 huawei technologies co.,ltd + c40683 huawei technologies co.,ltd + c4072f huawei technologies co.,ltd + c4084a nokia + c40880 shenzhen utepo tech co., ltd. + c40938 fujian star-net communication co.,ltd + c40acb cisco systems, inc + c40b31 apple, inc. + c40bcb xiaomi communications co ltd + c40d96 huawei technologies co.,ltd c40e45 ack networks,inc. c40f09 hermes electronic gmbh c4108a ruckus wireless - c4143c cisco + c411e0 bull group co., ltd + c412f5 d-link international + c413e2 extreme networks, inc. + c41411 apple, inc. + c4143c cisco systems, inc + c41688 huawei device co., ltd. c416fa prysm inc c417fe hon hai precision ind. co.,ltd. + c418e9 samsung electronics co.,ltd c4198b dominion voting systems corporation + c419d1 telink semiconductor (shanghai) co., ltd. c419ec qualisys ab + c41c9c jiqidao + c41cff vizio, inc c41ece hmi sources ltd. - c421c8 kyocera corporation + c421c8 kyocera corporation + c42360 intel corporate c4237a whiznets inc. + c423a2 pt. emsonic indonesia c4242e galvanic applied sciences inc + c42456 palo alto networks c42628 airo wireless - c42795 technicolor usa inc. + c4278c huawei device co., ltd. + c42795 technicolor ch usa inc. + c4282d embedded intellect pty ltd c4291d klemsan elektrik elektronik san.ve tic.as. - c42c03 apple + c42996 signify b.v. + c42ad0 apple, inc. + c42b44 huawei device co., ltd. + c42c03 apple, inc. + c42c4f qingdao hisense mobile communication technology co,ltd + c42f90 hangzhou hikvision digital technology co.,ltd. + c43018 mcs logic inc. + c430ca sd biosensor + c432d1 farlink technology limited + c43306 china mobile group device co.,ltd. c4346b hewlett packard + c43655 shenzhen fenglian technology co., ltd. + c4366c lg innotek c436da rusteletech ltd. + c43772 virtuozzo international gmbh c438d3 tagatec co.,ltd c4393a smc networks inc + c43960 gd midea air-conditioning equipment co.,ltd. + c43a35 fn-link technology limited c43a9f siconix inc. + c43abe sony mobile communications inc c43c3c cybelec sa + c43cea buffalo.inc c43dc7 netgear - c4438f lg electronics + c44044 racktop systems inc. + c440f6 guangdong oppo mobile telecommunications corp.,ltd + c4411e belkin international inc. + c44137 quectel wireless solutions co., ltd. + c44202 samsung electronics co.,ltd + c44268 crestron electronics, inc. + c4438f lg electronics (mobile communications) + c4447d huawei technologies co.,ltd + c444a0 cisco systems, inc c44567 sambon precison and electronics c445ec shanghai yali electron co.,ltd c44619 hon hai precision ind. co.,ltd. + c4473f huawei technologies co.,ltd c44838 satcom direct, inc. + c449bb mitsumi electric co.,ltd. c44ad0 fireflies systems c44b44 omniprint inc. + c44bd1 wallys communications teachnologies co.,ltd. c44e1f bluen c44eac shenzhen shiningworth technology co., ltd. + c44f33 espressif inc. c45006 samsung electronics co.,ltd + c4518d shenzhen youhua technology co., ltd c45444 quanta computer inc. c455a6 cadac holdings ltd c455c2 bach-simpson c45600 galleon embedded computing + c456fe lava international ltd. + c4571f june life inc + c4576e samsung electronics co.,ltd c458c2 shenzhen tatfook technology co., ltd. c45976 fugoo coorporation + c45a86 huawei device co., ltd. + c45bbe espressif inc. + c45bf7 ants + c45d83 samsung electronics co.,ltd c45dd8 hdmi forum c46044 everex electronics limited + c4618b apple, inc. c4626b zpt vigantice c462ea samsung electronics co.,ltd c46354 u-raku, inc. - c46413 cisco systems, inc. + c463fb neatframe as + c46413 cisco systems, inc + c464b7 fiberhome telecommunication technologies co.,ltd + c464e3 texas instruments + c46516 hewlett packard + c46699 vivo mobile communication co., ltd. c467b5 libratone a/s - c46ab7 xiaomi technology,inc. + c467d1 huawei technologies co.,ltd + c468d0 vtech telecommunications ltd. + c4693e turbulence design inc. + c469f0 huawei technologies co.,ltd + c46ab7 xiaomi communications co ltd c46bb4 myidkey c46df1 datagravity - c46e1f tp-link technologies co.,ltd + c46e1f tp-link technologies co.,ltd. + c46e7b shenzhen rf-link technology co.,ltd. + c4700b guangzhou chip technologies co.,ltd + c470ab ruijie networks co.,ltd c47130 fon technology s.l. - c471fe cisco systems, inc. - c4731e samsung eletronics co., ltd + c47154 tp-link technologies co.,ltd. + c471fe cisco systems, inc + c47295 cisco systems, inc + c4731e samsung electronics co.,ltd + c4741e zte corporation + c47469 bt9 + c474f8 hot pepper, inc. + c477ab beijing asu tech co.,ltd + c477af advanced digital broadcast sa c47b2f beijing joinhope image technology ltd. c47ba3 navis inc. - c47d4f cisco systems, inc. - c47dcc motorola solutions inc. + c47c8d ieee registration authority + c47d46 fujitsu limited + c47d4f cisco systems, inc + c47dcc zebra technologies inc c47dfe a.n. solutions gmbh c47f51 inventek systems c4823f fujian newland auto-id tech. co,.ltd. c4824e changzhou uchip electronics co., ltd. + c4836f ciena corporation + c48466 apple, inc. c48508 intel corporate + c486e9 huawei technologies co.,ltd c488e5 samsung electronics co.,ltd + c489ed solid optics eu n.v. + c48a5a jfcontrol + c48e8f hon hai precision ind. co.,ltd. + c48f07 shenzhen yihao hulian science and technology co., ltd. + c48fc1 deeptrack s.l.u. + c4910c apple, inc. c4913a shenzhen sanland electronic co., ltd. + c491cf luxul + c4924c keisokuki center co.,ltd. c49300 8devices c49313 100fio networks technology llc c49380 speedytel technology + c493d9 samsung electronics co.,ltd + c49500 amazon technologies inc. + c4954d ieee registration authority c495a2 shenzhen weijiu industry and trade development co., ltd c49805 minieum networks, inc + c4985c hui zhou gaoshengda technology co.,ltd + c49878 shanghai moaan intelligent technology co.,ltd + c49880 apple, inc. + c49886 qorvo international pte. ltd. + c49a02 lg electronics (mobile communications) + c49ded microsoft corporation + c49e41 g24 power limited + c49f4c huawei technologies co.,ltd + c49ff3 mciao technologies, inc. + c4a151 sichuan tianyi comheart telecom co., ltd. + c4a366 zte corporation + c4a402 huawei technologies co.,ltd + c4a72b shenzhen chuangwei-rgb electronics co.,ltd c4a81d d-link international c4aaa1 summit development, spol.s r.o. + c4abb2 vivo mobile communication co., ltd. + c4ac59 murata manufacturing co., ltd. c4ad21 mediaedge corporation + c4ad34 routerboard.com + c4adf1 gopeace inc. + c4ae12 samsung electronics co.,ltd + c4b239 cisco systems, inc + c4b301 apple, inc. + c4b36a cisco systems, inc c4b512 general electric digital energy + c4b8b4 huawei technologies co.,ltd + c4b9cd cisco systems, inc c4ba99 i+me actia informatik und mikro-elektronik gmbh + c4baa3 beijing winicssec technologies co., ltd. + c4bb4c zebra information tech co. ltd + c4bbea pakedge device and software inc + c4bcd7 new ryatek + c4bd6a skf gmbh + c4be84 texas instruments + c4bed4 avaya inc + c4bf60 tecno mobile limited c4c0ae midori electronic co., ltd. + c4c138 owlink technology inc c4c19f national oilwell varco instrumentation, monitoring, and optimization (nov imo) + c4c563 tecno mobile limited + c4c603 cisco systems, inc c4c755 beijing huaqinworld technology co.,ltd c4c919 energy imports ltd + c4c9ec gugaoo hk limited c4cad9 hangzhou h3c technologies co., limited + c4cb54 fibocom auto inc. + c4cb6b airista flow, inc. c4cd45 beijing boomsense technology co.,ltd. + c4cd82 hangzhou lowan information technology co., ltd. + c4d0e3 intel corporate + c4d197 ventia utility services + c4d438 huawei technologies co.,ltd c4d489 jiangsu joyque information industry co.,ltd c4d655 tercel technology co.,ltd + c4d738 huawei device co., ltd. + c4d8f3 izotope c4d987 intel corporate c4da26 noblex sa + c4da7d ivium technologies b.v. + c4dd57 espressif inc. + c4de7b huawei device co., ltd. c4e032 ieee 1904.1 working group + c4e0de zhengzhou xindajiean information technology co.,ltd. c4e17c u2s co. + c4e1a1 guangdong oppo mobile telecommunications corp.,ltd + c4e287 huawei technologies co.,ltd + c4e39f guangdong oppo mobile telecommunications corp.,ltd + c4e506 piper networks, inc. + c4e510 mechatro, inc. c4e7be scspro co.,ltd + c4e90a d-link international c4e92f ab sciex c4e984 tp-link technologies co.,ltd. + c4ea1d technicolor c4ebe3 rrcn sas c4edba texas instruments c4eeae vss monitoring - c4eef5 oclaro, inc. + c4eef5 ii-vi incorporated + c4ef70 home skinovations + c4f081 huawei technologies co.,ltd + c4f0ec fiberhome telecommunication technologies co.,ltd + c4f174 eero inc. + c4f1d1 beijing sogou technology development co., ltd. + c4f312 texas instruments c4f464 spica international - c4f57c brocade communications systems, inc. + c4f57c brocade communications systems llc + c4f5a5 kumalift co., ltd. + c4f7d5 cisco systems, inc + c4f839 actia automotive + c4fbaa huawei technologies co.,ltd c4fce4 dishtv nz ltd + c4fde6 drtech + c4fe5b guangdong oppo mobile telecommunications corp.,ltd + c4fee2 amiccom electronics corporation + c4ff1f huawei technologies co.,ltd + c4ffbc ieee registration authority + c80084 cisco systems, inc + c80210 lg innotek c80258 itw gse aps + c8028f nova electronics (shanghai) co., ltd. c802a6 beijing newmine technology + c803f5 ruckus wireless c80718 tdsi + c80739 nakayo inc + c80873 ruckus wireless + c808e9 lg electronics + c809a8 intel corporate c80aa9 quanta computer inc. - c80e77 le shi zhi xin electronic technology (tianjin) co.,ltd + c80cc8 huawei technologies co.,ltd + c80d32 holoplot gmbh + c80e14 avm audiovisuelles marketing und computersysteme gmbh + c80e77 le shi zhi xin electronic technology (tianjin) limited c80e95 omnilync inc. + c81073 century opticomm co.,ltd + c8138b shenzhen skyworth digital technology co., ltd + c81451 huawei technologies co.,ltd c81479 samsung electronics co.,ltd - c816bd hisense electric co.,ltd. + c816a5 masimo corporation + c816bd qingdao hisense communications co.,ltd. + c816da realme chongqing mobile telecommunications corp.,ltd. + c81739 itel mobile limited c819f7 samsung electronics co.,ltd c81afe dlogic gmbh + c81b5c bctech + c81b6b innova security c81e8e adv security (s) pte ltd - c81f66 dell inc + c81ee7 apple, inc. + c81f66 dell inc. + c81fbe huawei technologies co.,ltd + c81fea avaya inc c8208e storagedata + c82158 intel corporate + c821da shenzhen youhua technology co., ltd + c825e1 lemobile information technology (beijing) co., ltd + c82832 beijing xiaomi electronics co., ltd. c8292a barun electronics - c82a14 apple + c82a14 apple, inc. + c82b96 espressif inc. + c82c2b ieee registration authority + c82e47 suzhou smartchip semiconductor co., ltd c82e94 halfa enterprise co., ltd. + c83168 ezex corporation c83232 hunting innova - c8334b apple + c8334b apple, inc. + c833e5 huawei technologies co.,ltd + c8348e intel corporate c835b8 ericsson, eab/rwi/k + c83870 samsung electronics co.,ltd c83a35 tenda technology co., ltd. - c83b45 jri-maxant + c83a6b roku, inc + c83b45 jri + c83c85 apple, inc. c83d97 nokia corporation + c83dd4 cybertan technology inc. + c83ddc xiaomi communications co ltd + c83dfc alphatheta corporation c83e99 texas instruments c83ea7 kunbus gmbh + c83f26 microsoft corporation + c83fb4 arris group, inc. + c84029 fiberhome telecommunication technologies co.,ltd c84529 imk networks co.,ltd - c84544 shanghai enlogic electric technology co., ltd. + c84544 asia pacific cis (wuxi) co, ltd + c8458f wyler ag + c84782 areson technology corp. + c8478c beken corporation c848f5 medison xray co., ltd - c84c75 cisco systems, inc. + c84c75 cisco systems, inc + c84d34 lions taiwan technology inc. + c84f0e integrated device technology (malaysia) sdn. bhd. + c84f86 sophos ltd + c850ce huawei technologies co.,ltd + c850e9 raisecom technology co., ltd + c85195 huawei technologies co.,ltd + c85261 arris group, inc. + c853e1 beijing bytedance network technology co., ltd + c8544b zyxel communications corporation c85645 intermas france c85663 sunflex europe gmbh + c858c0 intel corporate + c85a9f zte corporation + c85b76 lcfc(hefei) electronics technology co., ltd + c85ba0 shenzhen qihu intelligent technology company limited + c85d38 humax co., ltd. c86000 asustek computer inc. + c86314 ieee registration authority + c863f1 sony interactive entertainment inc. + c863fc arris group, inc. c864c7 zte corporation + c8662c beijing haitai fangyuan high technology co,.ltd. + c8665d extreme networks, inc. + c8675e extreme networks, inc. + c868de huawei device co., ltd. + c869cd apple, inc. c86c1e display systems ltd - c86c87 zyxel communications corp + c86c3d amazon technologies inc. + c86c87 zyxel communications corporation c86cb6 optcom co., ltd. - c86f1d apple + c86f1d apple, inc. + c87125 johnson outdoors marine electronics d/b/a minnkota c87248 aplicom oy + c87324 sow cheng technology co. ltd. + c8755b quantify technology pty. ltd. + c87765 tiesse spa + c8778b mercury systems – trusted mission solutions, inc. + c87b23 bose corporation c87b5b zte corporation - c87cbc valink co., ltd. + c87cbc valink co., ltd. c87d77 shenzhen kingtech communication equipment co.,ltd c87e75 samsung electronics co.,ltd + c87ea1 tcl moka international limited + c88314 tempo communications c88439 sunrise technologies c88447 beautiful enterprise co., ltd + c884a1 cisco systems, inc + c88550 apple, inc. + c88629 shenzhen duubee intelligent technologies co.,ltd. + c88722 lumenpulse c8873b net optics c88a83 dongguan huahong electronics co.,ltd c88b47 nolangroup s.p.a con socio unico + c88be8 masimo corporation + c88d83 huawei technologies co.,ltd + c88ed1 ieee registration authority + c88f26 skyworth digital technology(shenzhen) co.,ltd c8903e pakton technologies + c891f9 sagemcom broadband sas c89346 mxchip company limited c89383 embedded automation, inc. + c89402 chongqing fugui electronics co.,ltd. + c894bb huawei technologies co.,ltd c894d2 jiangsu datang electronic products co., ltd c8979f nokia corporation - c89c1d cisco systems, inc. - c89cdc elitegroup computer system co., ltd. + c89bad honor device co., ltd. + c89c13 inspiremobile + c89c1d cisco systems, inc + c89cdc elitegroup computer systems co.,ltd. c89f1d shenzhen communication technologies co.,ltd c89f42 vdii innovation ab c8a030 texas instruments c8a1b6 shenzhen longway technologies co., ltd c8a1ba neul ltd + c8a2ce oasis media systems llc + c8a40d cooler master technology inc c8a620 nebula, inc c8a70a verizon business c8a729 systronics co., ltd. + c8a776 huawei technologies co.,ltd + c8a823 samsung electronics co.,ltd + c8a9fc goyoo networks inc. c8aa21 arris group, inc. - c8aacc + c8aa55 hunan comtom electronic incorporated co.,ltd + c8aacc private c8ae9c shanghai tyd elecronic technology co. ltd c8af40 marco systemanalyse und entwicklung gmbh + c8afe3 hefei radio communication technology co., ltd + c8b1cd apple, inc. + c8b1ee qorvo + c8b21e chipsea technologies (shenzhen) corp. + c8b29b intel corporate c8b373 cisco-linksys, llc - c8b5b7 apple + c8b422 askey computer corp + c8b5ad hewlett packard enterprise + c8b5b7 apple, inc. + c8b6d3 huawei technologies co.,ltd + c8ba94 samsung electro-mechanics(thailand) + c8bae9 qdis + c8bb81 huawei device co., ltd. c8bbd3 embrane - c8bcc8 apple + c8bc9c huawei device co., ltd. + c8bcc8 apple, inc. + c8bce5 sense things japan inc. c8be19 d-link international + c8bffe huawei device co., ltd. c8c126 zpm industria e comercio ltda c8c13c ruggedtek hangzhou co., ltd + c8c2c6 shanghai airm2m communication technology co., ltd + c8c2f5 flextronics manufacturing(zhuhai)co.,ltd. + c8c2fa huawei technologies co.,ltd + c8c465 huawei technologies co.,ltd + c8c50e shenzhen primestone network technologies.co., ltd. + c8c64a flextronics tech.(ind) pvt ltd + c8c750 motorola mobility llc, a lenovo company c8c791 zero1.tv gmbh + c8ca63 huawei device co., ltd. c8cbb8 hewlett packard - c8cd72 sagemcom + c8cd72 sagemcom broadband sas + c8d019 shanghai tigercel communication technology co.,ltd + c8d083 apple, inc. c8d10b nokia corporation - c8d15e huawei technologies co., ltd + c8d12a comtrend corporation + c8d15e huawei technologies co.,ltd c8d1d1 agait technology corporation c8d2c1 jetlun (shenzhen) corporation c8d3a3 d-link international + c8d3ff hewlett packard c8d429 muehlbauer ag c8d590 flight data systems c8d5fe shenzhen zowee technology co., ltd - c8d719 cisco consumer products, llc + c8d69d arab international optronics + c8d719 cisco-linksys, llc + c8d778 bsh hausgeraete gmbh + c8d779 qing dao haier telecom co.,ltd. + c8d7b0 samsung electronics co.,ltd + c8d884 universal electronics, inc. + c8d9d2 hewlett packard + c8db26 logitech c8ddc9 lenovo mobile communication technology ltd. - c8de51 integra networks, inc. + c8de51 integraoptics + c8dec9 coriant c8df7c nokia corporation - c8e0eb apple + c8df84 texas instruments + c8e0eb apple, inc. + c8e130 milkyway group ltd c8e1a7 vertu corporation limited + c8e265 intel corporate + c8e42f technical research design and development + c8e600 huawei technologies co.,ltd + c8e776 ptcom technology + c8e7d8 mercury communication technologies co.,ltd. + c8e7f0 juniper networks + c8eaf8 zte corporation c8ee08 tangtop technology co.,ltd c8ee75 pishion international co. ltd c8eea6 shenzhen shx technology co., ltd - c8ef2e beijing gefei tech. co., ltd + c8ef2e beijing gefei tech. co., ltd + c8f230 guangdong oppo mobile telecommunications corp.,ltd + c8f319 lg electronics (mobile communications) c8f36b yamato scale co.,ltd. c8f386 shenzhen xiaoniao technology co.,ltd - c8f406 avaya, inc - c8f650 apple + c8f406 avaya inc + c8f650 apple, inc. c8f68d s.e.technologies limited + c8f6c8 fiberhome telecommunication technologies co.,ltd c8f704 building block video c8f733 intel corporate + c8f742 hangzhou gubei electronics technology co.,ltd + c8f750 dell inc. + c8f86d alcatel-lucent shanghai bell co., ltd + c8f946 locosys technology inc. c8f981 seneca s.r.l. - c8f9f9 cisco systems, inc. + c8f9c8 newsharp technology(suzhou)co,ltd + c8f9f9 cisco systems, inc + c8fa84 trusonus corp. + c8fae1 arq digital llc c8fb26 cisco spvtg + c8fd19 texas instruments c8fe30 bejing dayo mobile communication technology ltd. + c8fe6a juniper networks + c8ff28 liteon technology corporation + c8ff77 dyson limited cc0080 bettini srl + cc03d9 cisco meraki + cc03fa technicolor ch usa inc. cc047c g-way microwave cc04b4 select comfort cc051b samsung electronics co.,ltd + cc0577 huawei technologies co.,ltd + cc0677 fiberhome telecommunication technologies co.,ltd cc07ab samsung electronics co.,ltd cc07e4 lenovo mobile communication technology ltd. - cc08e0 apple + cc088d apple, inc. + cc08e0 apple, inc. + cc08fb tp-link technologies co.,ltd. cc09c8 imaqliq ltd cc0cda miljovakt as cc0dec cisco spvtg + cc0df2 motorola mobility llc, a lenovo company + cc10a3 beijing nan bao technology co., ltd. cc14a6 yichun myenergy domain, inc + cc167e cisco systems, inc cc187b manzanita systems, inc. + cc19a8 pt inovação e sistemas sa cc1afa zte corporation + cc1be0 ieee registration authority cc1eff metrological group bv + cc1fc4 invue + cc208c huawei technologies co.,ltd + cc20e8 apple, inc. + cc2119 samsung electronics co.,ltd cc2218 innodigital co., ltd. + cc2237 ieee registration authority + cc242e shenzhen superelectron technology co.,ltd. + cc25ef apple, inc. cc262d verifi, llc + cc29f5 apple, inc. cc2a80 micro-biz intelligence solutions co.,ltd + cc2c83 darkmatter l.l.c + cc2d1b sfr + cc2d21 tenda technology co.,ltd.dongguan branch + cc2d83 guangdong oppo mobile telecommunications corp.,ltd cc2d8c lg electronics inc - cc33bb sagemcom sas + cc2db7 apple, inc. + cc2de0 routerboard.com + cc2f71 intel corporate + cc3080 vaio corporation + cc3296 huawei device co., ltd. + cc32e5 tp-link technologies co.,ltd. + cc3331 texas instruments + cc33bb sagemcom broadband sas cc3429 tp-link technologies co.,ltd. cc34d7 gewiss s.p.a. - cc3540 technicolor usa inc. + cc3540 technicolor ch usa inc. + cc355a secugen corporation + cc37ab edgecore networks corporation cc398c shiningtek cc3a61 samsung electro mechanics co., ltd. + cc3adf private + cc3b27 tecno mobile limited + cc3b3e lester electrical + cc3b58 curiouser products inc cc3c3f sa.s.s. datentechnik ag + cc3d82 intel corporate cc3e5f hewlett packard + cc3f1d intesis software sl + cc3fea bae systems, inc + cc40d0 netgear + cc418e msa innovation cc43e3 trump s.a. + cc4463 apple, inc. + cc4639 waav, inc. + cc464e samsung electronics co.,ltd + cc46d6 cisco systems, inc cc4703 intercon systems co., ltd. + cc47bd rhombus systems + cc483a dell inc. cc4ae1 fourtec -fourier technologies + cc4b73 ampak technology, inc. cc4bfb hellberg safety ab - cc4e24 brocade communications systems, inc. + cc4d38 carnegie technologies + cc4e24 brocade communications systems llc + cc4eec humax co., ltd. + cc4f5c ieee registration authority + cc500a fiberhome telecommunication technologies co.,ltd cc501c kvh industries, inc. cc5076 ocom communications, inc. + cc50e3 espressif inc. + cc51b4 integrated device technology (malaysia) sdn. bhd. + cc5289 shenzhen optfocus technology.,ltd cc52af universal global scientific industrial co., ltd. cc53b5 huawei technologies co.,ltd cc5459 ontime networks as cc55ad rim - cc593e toumaz ltd + cc593e sensium healthcare limited + cc5a53 cisco systems, inc cc5c75 weightech com. imp. exp. equip. pesagem ltda + cc5cde china mobile group device co.,ltd. cc5d4e zyxel communications corporation cc5d57 information system research institute,inc. + cc5d78 jtd consulting + cc5fbf topwise 3g communication co., ltd. cc60bb empower rf systems + cc61e5 motorola mobility llc, a lenovo company + cc64a6 huawei technologies co.,ltd cc65ad arris group, inc. + cc660a apple, inc. + cc66b2 nokia + cc68b6 tp-link corporation limited cc69b0 global traffic technologies, llc + cc69fa apple, inc. + cc6a10 the chamberlain group, inc + cc6b1e cloud network technology singapore pte. ltd. cc6b98 minetec wireless technologies cc6bf1 sound masking inc. cc6da0 roku, inc. cc6def tjk tietolaite oy + cc6ea4 samsung electronics co.,ltd + cc70ed cisco systems, inc cc720f viscount systems inc. + cc7286 xi'an fengyu information technology co., ltd. + cc7314 hong kong wheatek technology limited cc7498 filmetrics inc. + cc75e2 arris group, inc. cc7669 seetech - cc785f apple + cc785f apple, inc. + cc78ab texas instruments + cc794a blu products inc. + cc79cf shenzhen rf-link technology co.,ltd. cc7a30 cmax wireless co., ltd. cc7b35 zte corporation + cc7b61 nikkiso co., ltd. cc7d37 arris group, inc. - cc7ee7 panasonic avc networks company + cc7ee7 panasonic corporation avc networks company + cc7f75 cisco systems, inc + cc7f76 cisco systems, inc + cc812a vivo mobile communication co., ltd. + cc81da phicomm (shanghai) co., ltd. + cc82eb kyocera corporation cc856c shenzhen mdk digital technology co.,ltd + cc86ec silicon laboratories + cc874a nokia + cc8826 lg innotek + cc88c7 aruba, a hewlett packard enterprise company + cc895e huawei technologies co.,ltd cc89fd nokia corporation + cc8cda shenzhen wei da intelligent technology go.,ltd cc8ce3 texas instruments + cc8e71 cisco systems, inc + cc9070 cisco systems, inc cc9093 hansong tehnologies + cc90e8 shenzhen youhua technology co., ltd cc912b te connectivity touch solutions + cc934a sierra wireless cc944a pfeiffer vacuum gmbh + cc9470 kinestral technologies, inc. cc95d7 vizio, inc - cc96a0 shenzhen huawei communication technologies co., ltd + cc9635 lvs co.,ltd. + cc96a0 huawei technologies co.,ltd + cc988b sony visual products inc. + cc9891 cisco systems, inc + cc9916 integrated device technology (malaysia) sdn. bhd. + cc9c3e cisco meraki cc9e00 nintendo co., ltd. + cc9ea2 amazon technologies inc. + cc9eca hmd global oy cc9f35 transbit sp. z o.o. + cc9f7a chiun mai communication systems, inc cca0e5 dzg metering gmbh + cca12b tcl king electrical appliances (huizhou) co., ltd + cca219 shenzhen along investment co.,ltd + cca223 huawei technologies co.,ltd + cca260 sichuan tianyi comheart telecomco.,ltd cca374 guangdong guanglian electronic technology co.ltd cca462 arris group, inc. + cca4af shenzhen sowell technology co., ltd cca614 aifa technology corp. + cca7c1 google, inc. + ccab2c humax co., ltd. ccaf78 hon hai precision ind. co.,ltd. + ccb0a8 huawei device co., ltd. + ccb0da liteon technology corporation + ccb11a samsung electronics co.,ltd + ccb182 huawei technologies co.,ltd ccb255 d-link international + ccb3ab shenzhen biocare bio-medical equipment co.,ltd. ccb3f8 fujitsu isotec limited ccb55a fraunhofer itwm ccb691 necmagnuscommunications ccb888 anb securite s.a. + ccb8a8 ampak technology, inc. ccb8f1 eagle kingdom technologies limited + ccbbfe huawei technologies co.,ltd ccbd35 steinel gmbh + ccbdd3 ultimaker b.v. + ccbe59 calix inc. ccbe71 optilogix bv + ccc079 murata manufacturing co., ltd. ccc104 applied technical systems - ccc3ea motorola mobility llc + ccc261 ieee registration authority + ccc2e0 raisecom technology co., ltd + ccc3ea motorola mobility llc, a lenovo company ccc50a shenzhen dajiahao technology co.,ltd + ccc5e5 dell inc. + ccc5ef co-comm servicios telecomunicaciones s.l. ccc62b tri-systems corporation + ccc760 apple, inc. ccc8d7 cias elettronica srl - cccc4e sun fountainhead usa. corp + ccc92c schindler - port technology + ccc95d apple, inc. + cccc4e sun fountainhead usa. corp cccc81 huawei technologies co.,ltd + cccccc silicon laboratories cccd64 sm-electronic gmbh + ccce1e avm audiovisuelles marketing und computersysteme gmbh ccce40 janteq corp + ccd083 aruba, a hewlett packard enterprise company + ccd281 apple, inc. ccd29b shenzhen bopengfa elec&technology co.,ltd - ccd539 cisco + ccd31e ieee registration authority + ccd39d ieee registration authority + ccd3c1 vestel elektronik san ve tic. a.Ş. + ccd3e2 jiangsu yinhe electronics co.,ltd. + ccd42e arcadyan corporation + ccd4a1 mitrastar technology corp. + ccd539 cisco systems, inc + ccd73c huawei technologies co.,ltd ccd811 aiconn technology corporation + ccd81f maipu communication technology co.,ltd. + ccd8c1 cisco systems, inc + ccd9ac intel corporate ccd9e9 scr engineers ltd. - cce1d5 buffalo inc. + ccdb04 dataremote inc. + ccdb93 cisco systems, inc + ccdc55 dragonchip limited + cce0c3 exten technologies, inc. + cce0da baidu online network technology (beijing) co., ltd + cce17f juniper networks + cce194 juniper networks + cce1d5 buffalo.inc cce798 my social stuff cce7df american magnetics, inc. cce8ac soyea technology co.,ltd. ccea1c dconworks co., ltd - cceed9 deto mechatronic gmbh - ccef48 cisco systems, inc. + cced21 nokia shanghai bell co., ltd. + cceddc mitrastar technology corp. + cceed9 vahle automation gmbh + ccef03 hunan keyshare communication technology co., ltd. + ccef48 cisco systems, inc + ccf0fd china mobile (hangzhou) information technology co., ltd. ccf3a5 chi mei communication systems, inc ccf407 eukrea electromatique sarl + ccf411 google, inc. + ccf538 3isysnetworks + ccf55f e focus instruments india private limited ccf67a ayecka communication systems ltd + ccf735 amazon technologies inc. ccf841 lumewave ccf8f0 xi'an hisu multimedia technology co.,ltd. - ccf954 avaya, inc + ccf954 avaya inc + ccf957 u-blox ag + ccf9e4 intel corporate ccf9e8 samsung electronics co.,ltd - ccfa00 lg electronics + ccfa00 lg electronics (mobile communications) ccfb65 nintendo co., ltd. ccfc6d riz transmitters ccfcb1 wireless technology, inc. - ccfe3c samsung electronics + ccfd17 tct mobile ltd + ccfe3c samsung electronics co.,ltd + ccff90 huawei device co., ltd. + d0034b apple, inc. + d003df samsung electronics co.,ltd + d003eb texas instruments + d00401 motorola mobility llc, a lenovo company + d00492 fiberhome telecommunication technologies co.,ltd + d0052a arcadyan corporation + d005e4 huawei device co., ltd. d00790 texas instruments + d007ca juniper networks + d00aab yokogawa digital computer corporation + d00df7 huawei device co., ltd. d00ea4 porsche cars north america + d00ed9 taicang t&w electronics + d00f6d t&w electronics company + d01242 bios corporation + d012cb avm audiovisuelles marketing und computersysteme gmbh d0131e sunrex technology corp + d013fd lg electronics (mobile communications) + d01411 ieee registration authority d0154a zte corporation + d015a6 aruba, a hewlett packard enterprise company + d016b4 huawei technologies co.,ltd d0176a samsung electronics co.,ltd + d017c2 asustek computer inc. + d0196a ciena corporation d01aa7 uniprint + d01c3c tecno mobile limited d01cbb beijing ctimes digital technology co., ltd. - d022be samsung electro mechanics co.,ltd. - d023db apple - d02788 hon hai precision ind.co.ltd + d021ac yo labs llc + d021f9 ubiquiti networks inc. + d02212 ieee registration authority + d022be samsung electro-mechanics(thailand) + d023db apple, inc. + d02516 mercury communication technologies co.,ltd. + d02544 samsung electro-mechanics(thailand) + d02598 apple, inc. + d02788 hon hai precision ind. co.,ltd. + d028ba realme chongqing mobiletelecommunications corp ltd + d02b20 apple, inc. d02c45 littlebits electronics, inc. - d02db3 huawei technologies co., ltd + d02db3 huawei technologies co.,ltd + d02eab texas instruments d03110 ingenic semiconductor co.,ltd + d03169 samsung electronics co.,ltd + d03311 apple, inc. + d035e5 em microelectronic + d03742 yulong computer telecommunication scientific (shenzhen) co.,ltd + d03745 tp-link technologies co.,ltd. d03761 texas instruments d03972 texas instruments + d039b3 arris group, inc. + d039ea netapp + d03c1f intel corporate + d03d52 ava security limited + d03dc3 aq corporation + d03e5c huawei technologies co.,ltd + d03faa apple, inc. + d040ef murata manufacturing co., ltd. + d041c9 fiberhome telecommunication technologies co.,ltd + d0431e dell inc. d046dc southwest research institute + d047c1 elma electronic ag + d048f3 dattus inc + d0498b zoom server d04cc1 sintrones technology corp. + d04d2c roku, inc. + d04e50 mobiwire mobiles (ningbo) co., ltd + d04f7e apple, inc. d05099 asrock incorporation - d05162 sony mobile communications ab + d05157 leax arkivator telecom + d05162 sony mobile communications inc d052a8 physical graph corporation + d05349 liteon technology corporation d0542d cambridge industries(group) co.,ltd. - d0574c cisco systems, inc. + d05509 nintendo co.,ltd + d055b2 integrated device technology (malaysia) sdn. bhd. + d056bf amosense + d0574c cisco systems, inc + d0577b intel corporate d05785 pantech co., ltd. + d05794 sagemcom broadband sas d057a1 werma signaltechnik gmbh & co. kg d05875 active control technology inc. + d058a8 zte corporation + d058c0 qingdao haier multimedia limited. + d058fc bskyb ltd + d05919 zte corporation + d05995 fiberhome telecommunication technologies co.,ltd d059c3 ceramicro technology corporation + d059e4 samsung electronics co.,ltd + d05a00 technicolor ch usa inc. d05a0f i-bt digital co.,ltd + d05af1 shenzhen pulier tech co.,ltd + d05afd realme chongqing mobile telecommunications corp.,ltd. + d05ba8 zte corporation + d05c7a sartura d.o.o. + d05f64 ieee registration authority d05fb8 texas instruments d05fce hitachi data systems + d0608c zte corporation + d062a0 china essence technology (zhumadian) co., ltd. d0634d meiko maschinenbau gmbh & co. kg d063b4 solidrun ltd. - d0667b samsung electronics co., ltd - d067e5 dell inc + d06544 apple, inc. + d065ca huawei technologies co.,ltd + d0666d shenzhen bus-lan technology co., ltd. + d0667b samsung electronics co.,ltd + d06726 hewlett packard enterprise + d067e5 dell inc. d0699e luminex lighting control equipment d069d0 verto medical solutions, llc - d072dc cisco + d06a1f bse co.,ltd. + d06ede sagemcom broadband sas + d06f4a topwell international holdings limited + d06f82 huawei technologies co.,ltd + d071c4 zte corporation + d072dc cisco systems, inc d0737f mini-circuits - d0738e dong oh precision co., ltd. + d0738e dong oh precision co., ltd. d073d5 lifi labs management pty ltd d075be reno a&e - d07650 ieee registration authority - please see mam public listing for more information. - d07ab5 huawei technologies co., ltd + d07650 ieee registration authority + d0768f calix inc. + d076e7 tp-link technologies co.,ltd. + d07714 motorola mobility llc, a lenovo company + d07ab5 huawei technologies co.,ltd + d07c2d leie iot technology co., ltd + d07d33 huawei device co., ltd. d07de5 forward pay systems, inc. d07e28 hewlett packard d07e35 intel corporate + d07fa0 samsung electronics co.,ltd + d07fc4 ou wei technology co.,ltd. of shenzhen city + d0817a apple, inc. + d083d4 xtel wireless aps + d084b0 sagemcom broadband sas + d087e2 samsung electronics co.,ltd d08999 apcon, inc. d08a55 skullcandy + d08a91 technicolor ch usa inc. d08b7e passif semiconductor d08cb5 texas instruments d08cff upwis ab + d0929e microsoft corporation + d092fa fiberhome telecommunication technologies co.,ltd + d09380 ducere technologies pvt. ltd. d093f8 stonestreet one llc + d09466 dell inc. d095c7 pantech co., ltd. + d096fb dasan network solutions + d097fe realme chongqing mobile telecommunications corp.,ltd. + d099d5 alcatel-lucent d09b05 emtronix d09c30 foster electric company, limited + d09c7a xiaomi communications co ltd d09d0a linkcom + d09dab tct mobile ltd + d0a0d6 chengdu td tech ltd. d0a311 neuberger gebäudeautomation gmbh + d0a4b1 sonifex ltd. + d0a5a6 cisco systems, inc + d0a637 apple, inc. + d0abd5 intel corporate d0aeec alpha networks inc. d0afb6 linktop technology co., ltd - d0b33f shenzhen tinno mobile technology co.,ltd. + d0b0cd moen + d0b128 samsung electronics co.,ltd + d0b214 poewit inc + d0b2c4 technicolor ch usa inc. + d0b33f shenzhen tinno mobile technology corp. + d0b45d huawei device co., ltd. d0b498 robert bosch llc automotive electronics d0b523 bestcare cloucal corp. d0b53d sepro robotique + d0b5c2 texas instruments + d0b60a xingluo technology company limited + d0bae4 shanghai mxchip information technology co., ltd. d0bb80 shl telemedicine international ltd. + d0bcc1 weifang goertek electronics co.,ltd d0bd01 ds international d0be2c cnslink co., ltd. + d0bf9c hewlett packard + d0c0bf actions microelectronics co., ltd + d0c193 skybell, inc d0c1b1 samsung electronics co.,ltd - d0c282 cisco systems, inc. + d0c282 cisco systems, inc + d0c31e jungjin electronics co.,ltd d0c42f tamagawa seiki co.,ltd. - d0c789 cisco + d0c5d3 azurewave technology inc. + d0c5d8 latecoere + d0c5f3 apple, inc. + d0c637 intel corporate + d0c65b huawei technologies co.,ltd + d0c789 cisco systems, inc d0c7c0 tp-link technologies co.,ltd. + d0c857 ieee registration authority d0cde1 scientech electronics d0cf5e energy micro as - d0d0fd cisco systems, inc. + d0cfd8 huizhou boshijie technology co.,ltd + d0d003 samsung electronics co.,ltd + d0d04b huawei technologies co.,ltd + d0d0fd cisco systems, inc d0d212 k2net co.,ltd. + d0d23c apple, inc. d0d286 beckman coulter k.k. + d0d2b0 apple, inc. + d0d3e0 aruba, a hewlett packard enterprise company d0d3fc mios, ltd. d0d412 adb broadband italia d0d471 mvtech co., ltd d0d6cc wintop + d0d783 huawei technologies co.,ltd + d0d94f ieee registration authority d0db32 nokia corporation + d0dd49 juniper networks d0df9a liteon technology corporation d0dfb2 genie networks limited d0dfc7 samsung electronics co.,ltd - d0e140 apple, inc + d0e042 cisco systems, inc + d0e140 apple, inc. d0e347 yoga d0e40b wearable inc. - d0e54d pace plc - d0e782 azurewave technologies, inc. + d0e44a murata manufacturing co., ltd. + d0e54d arris group, inc. + d0e782 azurewave technology inc. d0eb03 zhehua technology limited d0eb9e seowoo inc. + d0ec35 cisco systems, inc + d0efc1 huawei technologies co.,ltd d0f0db ericsson d0f27f steadyserv technoligies, llc - d0f73b helmut mauell gmbh - d0ff50 texas instruments, inc + d0f3f5 huawei device co., ltd. + d0f73b helmut mauell gmbh werk weida + d0f88c motorola (wuhan) mobility technologies communication co., ltd. + d0fa1d qihoo 360 technology co.,ltd + d0fccc samsung electronics co.,ltd + d0ff50 texas instruments + d0ff98 huawei technologies co.,ltd d4000d phoenix broadband technologies, llc. d40057 mc technologies gmbh - d40129 broadcom corporation + d40129 broadcom d4016d tp-link technologies co.,ltd. d4024a delphian systems llc + d404cd arris group, inc. + d404ff juniper networks + d40598 arris group, inc. + d40aa9 arris group, inc. + d40b1a htc corporation d40bb9 solid semecs bv. d40fb2 applied micro electronics ame bv d41090 inform systems ag d410cf huanshun network science and technology co., ltd. + d411a3 samsung electronics co.,ltd d411d6 shotspotter, inc. + d41243 ampak technology, inc. d41296 anobit technologies ltd. d412bb quadrant components inc. ltd d4136f asia pacific brands + d41a3f guangdong oppo mobile telecommunications corp.,ltd + d41ac8 nippon printer engineering + d41b81 chongqing fugui electronics co.,ltd. d41c1c rcf s.p.a. + d41d71 palo alto networks d41e35 toho electronics inc. - d41f0c tvi vision oy + d41f0c jai manufacturing d4206d htc corporation - d42122 sercomm corporation + d420b0 mist systems, inc. + d42122 sercomm corporation. d4223f lenovo mobile communication technology ltd. d4224e alcatel lucent + d422cd xsens technologies b.v. + d42493 gw technologies co.,ltd + d4258b intel corporate + d425cc ieee registration authority d42751 infopia co., ltd d428b2 iobridge, inc. + d428d5 tct mobile ltd d429ea zimory gmbh + d42c0f arris group, inc. d42c3d sky light digital limited + d42c44 cisco systems, inc + d42dc5 panasonic i-pro sensing solutions co., ltd. d42f23 akenori pte ltd d4319d sinwatec + d43260 gopro + d43266 fike corporation + d4351d technicolor + d43639 texas instruments + d436db jiangsu toppower automotive electronics co., ltd + d437d7 zte corporation + d4389c sony mobile communications inc + d439b8 ciena corporation + d43a2e shenzhen mtc co ltd d43a65 igrs engineering lab ltd. d43ae9 dongguan ipt industrial co., ltd + d43b04 intel corporate + d43d39 dialog semiconductor d43d67 carma industries inc. d43d7e micro-star int'l co, ltd + d43fcb arris group, inc. + d440d0 ocosmos co., ltd + d440f0 huawei technologies co.,ltd + d44165 sichuan tianyi comheart telecomco.,ltd d443a8 changzhou haojie electric co., ltd. + d445e8 jiangxi hongpai technology co., ltd. + d44649 huawei technologies co.,ltd + d446e1 apple, inc. + d4475a screenbeam, inc. + d4482d shenzhen deejoy lighting technology co.,ltd. d44b5e taiyo yuden co., ltd. + d44bb6 zhejiang tmall technology co., ltd. d44c24 vuppalamritha magnetic components ltd d44c9c shenzhen yoobao technology co.ltd d44ca7 informtekhnika & communication, llc + d44da4 murata manufacturing co., ltd. + d44f67 huawei technologies co.,ltd + d44f68 eidetic communications inc d44f80 kemper digital gmbh + d4503f guangdong oppo mobile telecommunications corp.,ltd d4507a ceiva logic, inc + d4522a tangowifi.com d45251 ibt ingenieurbureau broennimann thun d45297 nstreams technologies, inc. + d452ee bskyb ltd + d45383 murata manufacturing co., ltd. d453af vigo system s.a. + d45556 fiber mountain inc. + d455be shenzhen fast technologies co.,ltd + d45800 fiberhome telecommunication technologies co.,ltd d45ab2 galleon systems - d45c70 wireless gigabit alliance + d45c70 wi-fi alliance d45d42 nokia corporation + d45d64 asustek computer inc. + d45ddf pegatron corporation + d45eec beijing xiaomi electronics co., ltd. + d45f25 shenzhen youhua technology co., ltd + d46075 baidu online network technology (beijing) co., ltd + d460e3 sercomm corporation. + d4612e huawei technologies co.,ltd + d46132 pro concept manufacturer co.,ltd. + d4619d apple, inc. + d461da apple, inc. + d461fe hangzhou h3c technologies co., limited + d462ea huawei technologies co.,ltd + d463c6 motorola mobility llc, a lenovo company + d463fe arcadyan corporation d464f7 chengdu usee digital technology co., ltd - d466a8 riedo networks gmbh - d46761 sahab technology - d467e7 fiberhome telecommunication tech.co.,ltd. + d466a8 riedo networks ltd + d46761 xontel technology co. + d467d3 guangdong oppo mobile telecommunications corp.,ltd + d467e7 fiberhome telecommunication technologies co.,ltd + d4684d ruckus wireless d46867 neoventus design group - d46a91 snap av + d468ba shenzhen sundray technologies company limited + d469a5 miura systems ltd. + d46a35 cisco systems, inc + d46a6a hon hai precision ind. co.,ltd. + d46a91 snapav d46aa8 huawei technologies co.,ltd + d46ba6 huawei technologies co.,ltd d46cbf goodrich isr d46cda csm gmbh - d46e5c huawei technologies co., ltd + d46d50 cisco systems, inc + d46d6d intel corporate + d46e0e tp-link technologies co.,ltd. + d46e5c huawei technologies co.,ltd d46f42 waxess usa inc + d47208 bragi gmbh + d47226 zte corporation + d4741b beijing huada zhibao electronic system co.,ltd. + d476a0 fortinet, inc. + d476ea zte corporation + d4772b nanjing ztlink network technology co.,ltd + d47798 cisco systems, inc + d477b2 netix global b.v. + d47856 avaya inc + d4789b cisco systems, inc d479c3 cameronet gmbh & co. kg + d47ae2 samsung electronics co.,ltd + d47b35 neo monitors as d47b75 harting electronics gmbh + d47bb0 askey computer corp + d47c44 ieee registration authority + d47dfc tecno mobile limited + d47ee4 china mobile iot company limited d481ca idevices, llc + d481d7 dell inc. d4823e argosy technologies, ltd. - d48564 hewlett-packard company - d487d8 samsung electronics + d48304 shenzhen fast technologies co.,ltd + d48564 hewlett packard + d487d8 samsung electronics co.,ltd + d4883f hdpro co., ltd. d48890 samsung electronics co.,ltd - d48cb5 cisco systems, inc. + d48a39 samsung electronics co.,ltd + d48cb5 cisco systems, inc + d48dd9 meld technology, inc + d48f33 microsoft corporation d48faa sogecam industrial, s.a. + d4909c apple, inc. + d490e0 topcon electronics gmbh & co. kg + d4910f amazon technologies inc. d491af electroacustica general iberica, s.a. + d49234 nec corporation + d49398 nokia corporation d493a0 fidelix oy d4945a cosmo co., ltd d494a1 texas instruments + d494e8 huawei technologies co.,ltd d49524 clover network, inc. d496df sungjin c&t co.,ltd - d49a20 apple - d49c28 jaybird gear llc + d4970b xiaomi communications co ltd + d49a20 apple, inc. + d49aa0 vnpt technology + d49b5c chongqing miedu technology co., ltd. + d49c28 jaybird llc d49c8e university of fukui + d49cdd ampak technology,inc. + d49cf4 palo alto networks + d49dc0 samsung electronics co.,ltd + d49e05 zte corporation + d49e3b guangzhou shiyuan electronic technology company limited d49e6d wuhan zhongyuan huadian science & technology co., - d4a02a cisco systems, inc. + d4a02a cisco systems, inc + d4a148 huawei technologies co.,ltd + d4a33d apple, inc. d4a425 smax technology co., ltd. d4a499 inview technology corporation + d4a651 tuya smart inc. d4a928 greenwave reality inc - d4aaff micro world + d4aaff micro world + d4ab82 arris group, inc. + d4abcd hui zhou gaoshengda technology co.,ltd d4ac4e bodi rs, llc - d4ad2d fiberhome telecommunication tech.co.,ltd. - d4ae52 dell inc + d4ad2d fiberhome telecommunication technologies co.,ltd + d4ad71 cisco systems, inc + d4adbd cisco systems, inc + d4ae05 samsung electronics co.,ltd + d4ae52 dell inc. + d4aff7 arista networks d4b110 huawei technologies co.,ltd + d4b169 le shi zhi xin electronic technology (tianjin) limited + d4b27a arris group, inc. d4b43e messcomp datentechnik gmbh - d4bed9 dell inc + d4b709 zte corporation + d4b761 sichuan ai-link technology co., ltd. + d4b8ff home control singapore pte ltd + d4b92f technicolor ch usa inc. + d4bbc8 vivo mobile communication co., ltd. + d4bbe6 huawei device co., ltd. + d4bd1e 5vt technologies,taiwan ltd. + d4bed9 dell inc. d4bf2d se controls asia pacific ltd d4bf7f upvel + d4c19e ruckus wireless + d4c1c8 zte corporation d4c1fc nokia corporation d4c766 acentic gmbh + d4c8b0 prime electronics & satellitics inc. + d4c93c cisco systems, inc + d4c94b motorola mobility llc, a lenovo company + d4c9b2 quanergy systems inc d4c9ef hewlett packard d4ca6d routerboard.com d4ca6e u-blox ag d4cbaf nokia corporation d4ceb8 enatel ltd - d4cff9 shenzhen sen5 technology co., ltd. + d4cf37 symbolic io + d4cff9 shenzhen sei robotics co.,ltd d4d184 adb broadband italia d4d249 power ethernet + d4d252 intel corporate + d4d2d6 fn-link technology limited + d4d2e5 bkav corporation d4d50d southwest microwave, inc - d4d748 cisco systems, inc. + d4d51b huawei technologies co.,ltd + d4d748 cisco systems, inc + d4d7a9 shanghai kaixiang info tech ltd d4d898 korea cno tech co., ltd d4d919 gopro + d4dacd bskyb ltd + d4dc09 mist systems, inc. + d4dccd apple, inc. d4df57 alpinion medical systems d4e08e valuehd corporation d4e32c s. siedle & sohne - d4e33f alcatel-lucent - d4e8b2 samsung electronics - d4ea0e avaya, inc + d4e33f nokia + d4e6b7 samsung electronics co.,ltd + d4e880 cisco systems, inc + d4e8b2 samsung electronics co.,ltd + d4e90b cvt co.,ltd + d4ea0e avaya inc d4ec0c harley-davidson motor company + d4ec86 linkedhope intelligent technologies co., ltd + d4ecab vivo mobile communication co., ltd. d4ee07 hiwifi co., ltd. - d4f027 navetas energy management + d4f027 trust power ltd. + d4f057 nintendo co.,ltd d4f0b4 napco security technologies d4f143 iproad.,inc + d4f207 diaodiao(beijing)technology co.,ltd + d4f337 xunison ltd. + d4f46f apple, inc. + d4f4be palo alto networks + d4f513 texas instruments + d4f527 siemens ag + d4f547 google, inc. + d4f5ef hewlett packard enterprise d4f63f iea s.r.l. - d8004d apple + d4f756 zte corporation + d4f786 fiberhome telecommunication technologies co.,ltd + d4f829 sagemcom broadband sas + d4f9a1 huawei technologies co.,ltd + d4fc13 fiberhome telecommunication technologies co.,ltd + d8004d apple, inc. + d80093 aurender inc. d8052e skyviia corporation d806d1 honeywell fire system (shanghai) co,. ltd. - d808f5 arcadia networks co. ltd. + d807b6 tp-link technologies co.,ltd. + d80831 samsung electronics co.,ltd + d808f5 arcadia networks co. ltd. d809c3 cercacor labs + d809d6 zexelon co., ltd. + d80b9a samsung electronics co.,ltd + d80bcb telink semiconductor (shanghai) co., ltd. + d80ccf c.g.v. s.a.s. + d80d17 tp-link technologies co.,ltd. d80de3 fxi technologies as + d80f99 hon hai precision ind. co.,ltd. + d8109f huawei technologies co.,ltd + d810cb andrea informatique + d81265 chongqing fugui electronics co.,ltd. + d81399 hui zhou gaoshengda technology co.,ltd + d814d6 sure system co ltd + d814df tcl king electrical appliances (huizhou) co., ltd d8150d tp-link technologies co.,ltd. d8160a nippon electro-sensory devices + d816c1 dewav (hk) electronics limited d8182b conti temic microelectronic gmbh + d818d3 juniper networks + d8197a nuheara ltd d819ce telesquare d81bfe twinlinx corporation d81c14 compacta international, ltd. + d81c79 apple, inc. + d81d72 apple, inc. + d81edd guangdong oppo mobile telecommunications corp.,ltd d81ede b&w group ltd - d824bd cisco systems, inc. - d826b9 guangdong coagent electronics s &t co., ltd. + d81fcc brocade communications systems llc + d8209f cubro acronet gesmbh + d822f4 avnet silica + d82477 universal electric corporation + d824bd cisco systems, inc + d82522 arris group, inc. + d825b0 rockeetech systems co.,ltd. + d826b9 guangdong coagent electronics s&t co.,ltd. d8270c maxtronic international co., ltd. d828c9 general electric consumer and industrial d82916 ascent communication technology + d82918 huawei technologies co.,ltd d82986 best wish technology ltd d82a15 leitner spa d82a7e nokia corporation d82d9b shenzhen g.credit communication technology co., ltd d82de1 tricascade inc. - d83062 apple + d82fe6 zhejiang tmall technology co., ltd. + d83062 apple, inc. + d83134 roku, inc d831cf samsung electronics co.,ltd + d83214 tenda technology co.,ltd.dongguan branch + d8325a shenzhen youhua technology co., ltd + d832e3 xiaomi communications co ltd d8337f office fa.com co.,ltd. + d834ee stem audio + d8373b shenzhen jingxun software telecommunication technology co.,ltd + d837be shenzhen gongjin electronics co.,lt + d8380d shenzhen ip-com network co.,ltd + d838fc ruckus wireless + d83af5 wideband labs llc + d83bbf intel corporate + d83c69 shenzhen tinno mobile technology corp. d842ac shanghai feixun communication co.,ltd. + d842e2 canary connect, inc. + d843ed suzuken + d8445c dev tecnologia ind com man eq ltda + d8452b integrated device technology (malaysia) sdn. bhd. d84606 silicon valley global marketing + d84710 sichuan changhong electric ltd. + d84732 tp-link technologies co.,ltd. + d847bb huawei device co., ltd. + d848ee hangzhou xueji technology co., ltd. d8490b huawei technologies co.,ltd d8492f canon inc. + d84a87 oi electric co.,ltd d84b2a cognitas technologies, inc. + d84c90 apple, inc. + d84db9 wu qi technologies,inc. + d84f37 proxis, spol. s r.o. + d84fb8 lg electronics d850e6 asustek computer inc. d8543a texas instruments - d857ef samsung electronics + d854a2 extreme networks, inc. + d85575 samsung electronics co.,ltd + d855a3 zte corporation + d857ef samsung electronics co.,ltd d858d7 cz.nic, z.s.p.o. + d85982 huawei technologies co.,ltd + d85b2a samsung electronics co.,ltd d85d4c tp-link technologies co.,ltd. d85d84 cax soft gmbh + d85de2 hon hai precision ind. co.,ltd. + d85def busch-jaeger elektro gmbh + d85dfb private + d85ed3 giga-byte technology co.,ltd. + d85f77 telink semiconductor (shanghai) co., ltd. + d860b0 biomérieux italia s.p.a. + d860b3 guangdong global electronic technology co.,ltd + d86162 wistron neweb corporation d86194 objetivos y sevicios de valor añadido d862db eno inc. + d86375 xiaomi communications co ltd d86595 toy's myth inc. d866c6 shenzhen daystar technology co.,ltd - d867d9 cisco systems, inc. + d866ee boxin communication co.,ltd. + d867d9 cisco systems, inc + d868c3 samsung electronics co.,ltd d86960 steinsvik d86bf7 nintendo co., ltd. - d86ce9 sagemcom sas + d86c02 huaqin telecom technology co.,ltd + d86c63 google, inc. + d86ce9 sagemcom broadband sas + d8714d texas instruments d87157 lenovo mobile communication technology ltd. + d87495 zte corporation d87533 nokia corporation d8760a escort, inc. + d8778b intelbras + d8787f ubee interactive co., limited d878e5 kuhn sa - d87988 hon hai precision ind. co., ltd. + d87988 hon hai precision ind. co.,ltd. d87cdd sanix incorporated + d87d7f sagemcom broadband sas + d87e76 itel mobile limited d87eb1 x.o.ware, inc. + d88039 microchip technology inc. + d8803c anhui huami information technology company limited d881ce ahn inc. + d88466 extreme networks, inc. + d8860b ieee registration authority + d887d5 leadcore technology co.,ltd + d888ce rf technology pty ltd d88a3b unit-em + d88adc huawei device co., ltd. + d88b4c kingting tech. + d88c79 google, inc. + d88d5c elentec + d88dc8 atil technology co., ltd + d88f76 apple, inc. d890e8 samsung electronics co.,ltd + d8912a zyxel communications corporation + d89136 dover fueling solutions + d89341 general electric global research + d89403 hewlett packard enterprise d8952f texas instruments d89685 gopro - d89695 apple - d8973b emerson network power embedded power + d89695 apple, inc. + d896e0 alibaba cloud computing ltd. + d8973b artesyn embedded technologies d89760 c2 development, inc. d8977c grey innovation + d89790 commonwealth scientific and industrial research organisation + d897ba pegatron corporation + d89a34 beijing shenqi technology co., ltd. + d89ac1 nokia + d89b3b huawei technologies co.,ltd + d89c67 hon hai precision ind. co.,ltd. d89d67 hewlett packard d89db9 emegatech international corp. - d89e3f apple - d8a25e apple + d89e3f apple, inc. + d89e61 huawei device co., ltd. + d89ed4 fiberhome telecommunication technologies co.,ltd + d89ef3 dell inc. + d8a01d espressif inc. + d8a105 syslane, co., ltd. + d8a25e apple, inc. + d8a315 vivo mobile communication co., ltd. + d8a35c samsung electronics co.,ltd + d8a491 huawei device co., ltd. + d8a534 spectronix corporation + d8a6fd ghost locomotion + d8a756 sagemcom broadband sas + d8a8c8 zte corporation + d8a98b texas instruments + d8addd sonavation, inc. d8ae90 itibia technologies + d8aed0 shanghai engineering science & technology co.,ltd cgnpc d8af3b hangzhou bigbright integrated communications system co.,ltd + d8af81 zao npk rotek d8aff1 panasonic appliances company - d8b02e guangzhou zonerich business machine co., ltd + d8b02e guangzhou zonerich business machine co., ltd. d8b04c jinan usr iot technology co., ltd. - d8b12a panasonic mobile communications co., ltd. + d8b122 juniper networks + d8b12a panasonic mobile communications co.,ltd. + d8b190 cisco systems, inc d8b377 htc corporation + d8b6b7 comtrend corporation d8b6c1 networkaccountant, inc. d8b6d6 blu tether limited d8b8f6 nantworks d8b90e triple domain vision co.,ltd. + d8bb2c apple, inc. + d8bbc1 micro-star intl co., ltd. + d8bc59 shenzhen dapu microelectronics co., ltd d8bf4c victory concept electronics limited + d8bfc0 espressif inc. d8c068 netgenetech.co.,ltd. + d8c06a hunantv.com interactive entertainment media co.,ltd. + d8c0a6 azurewave technology inc. d8c3fb detracom + d8c46a murata manufacturing co., ltd. + d8c497 quanta computer inc. + d8c4e9 samsung electronics co.,ltd + d8c561 commfront communications pte ltd + d8c678 mitrastar technology corp. d8c691 hichan technology corp. - d8c7c8 aruba networks + d8c771 huawei technologies co.,ltd + d8c7c8 aruba, a hewlett packard enterprise company + d8c8e9 phicomm (shanghai) co., ltd. d8c99d ea display limited - d8cf9c apple - d8d1cb apple + d8ca06 titan datacenters france + d8cb8a micro-star intl co., ltd. + d8cc98 huawei device co., ltd. + d8cd2c wuxi neihua network technology co., ltd + d8ce3a xiaomi communications co ltd + d8cf89 beijing dosee science and technology co., ltd. + d8cf9c apple, inc. + d8d090 dell inc. + d8d1cb apple, inc. d8d27c jema energy, sa - d8d385 hewlett-packard company + d8d385 hewlett packard d8d43c sony corporation + d8d4e6 hytec inter co., ltd. d8d5b9 rainforest automation, inc. d8d67e gsk cnc equipment co.,ltd + d8d6f3 integrated device technology (malaysia) sdn. bhd. + d8d723 ids, inc + d8d775 sagemcom broadband sas + d8d866 shenzhen tozed technologies co.,ltd. d8da52 apator s.a. + d8dc40 apple, inc. d8dce9 kunshan erlab ductless filtration system co.,ltd d8dd5f balmuda inc. d8ddfd texas instruments + d8dece isung co.,ltd d8df0d beronet gmbh + d8df7a quest software, inc. + d8e004 vodia networks inc + d8e0b8 bulat llc + d8e0e1 samsung electronics co.,ltd d8e3ae cirtec medical systems - d8e72b onpath technologies + d8e56d tct mobile ltd + d8e72b netscout systems inc d8e743 wush, inc d8e952 keopsys + d8eb46 google, inc. d8eb97 trendnet, inc. + d8ec5e belkin international inc. + d8ece5 zyxel communications corporation + d8ed1c magna technology sl d8ee78 moog protokraft + d8ef42 huawei device co., ltd. + d8efcd nokia solutions and networks gmbh & co. kg d8f0f2 zeebo inc + d8f15b espressif inc. + d8f1f0 pepxim international limited + d8f2ca intel corporate + d8f3bc liteon technology corporation + d8f3db post ch ag + d8f710 libre wireless technologies inc. + d8f883 intel corporate + d8f8af daontec + d8fb11 axacore + d8fb5e askey computer corp + d8fb68 cloud corner ltd. + d8fc38 giantec semiconductor inc d8fc93 intel corporate d8fe8f idfone co., ltd. d8fee3 d-link international + dc0077 tp-link technologies co.,ltd. + dc00b0 freebox sas dc0265 meditech kft dc028e zte corporation dc052f national products inc. dc0575 siemens energy automation dc05ed nabtesco corporation dc07c1 hangzhou qiyang technology co.,ltd. + dc080f apple, inc. + dc0856 alcatel-lucent enterprise + dc0914 talk-a-phone co. + dc094c huawei technologies co.,ltd dc0b1a adb broadband italia - dc0ea1 compal information (kunshan) co., ltd + dc0b34 lg electronics (mobile communications) + dc0c2d weifang goertek electronics co.,ltd + dc0c5c apple, inc. + dc0d30 shenzhen feasycom technology co., ltd. + dc0ea1 compal information (kunshan) co., ltd. + dc15c8 avm audiovisuelles marketing und computersysteme gmbh + dc15db ge ruili intelligent technology ( beijing ) co., ltd. dc16a2 medtronic diabetes + dc16b2 huawei technologies co.,ltd dc175a hitachi high-technologies corporation dc1792 captivate network + dc1a01 ecoliv technology ( shenzhen ) ltd. + dc1ac5 vivo mobile communication co., ltd. + dc1ba1 intel corporate dc1d9f u & b tech dc1dd4 microstep-mis spol. s r.o. dc1ea3 accensus llc - dc2008 asd electronics ltd + dc2008 asd electronics ltd + dc21b9 sentec co.ltd + dc21e2 huawei technologies co.,ltd + dc2727 huawei device co., ltd. + dc2834 hakko corporation + dc2919 altobeam (xiamen) technology ltd, co. + dc293a shenzhen nuoshi technology co., ltd. dc2a14 shanghai longjing technology co. - dc2b61 apple + dc2aa1 medhab llc + dc2b2a apple, inc. + dc2b61 apple, inc. dc2b66 infoblock s.a. de c.v. dc2bca zera gmbh dc2c26 iton technology limited + dc2d3c huawei device co., ltd. + dc2dcb beijing unis hengyue technology co., ltd. dc2e6a hct. co., ltd. + dc2f03 step forward group co., ltd. dc309c heyrex limited + dc31d1 vivo mobile communication co., ltd. + dc330d qing dao haier telecom co.,ltd. + dc333d huawei device co., ltd. dc3350 techsat gmbh + dc35f1 positivo tecnologia s.a. + dc3714 apple, inc. + dc3752 ge + dc3757 integrated device technology (malaysia) sdn. bhd. dc37d2 hunan hkt electronic technology co., ltd - dc3a5e roku, inc + dc38e1 juniper networks + dc396f avm audiovisuelles marketing und computersysteme gmbh + dc3979 cisco systems, inc + dc3a5e roku, inc. dc3c2e manufacturing system insights, inc. dc3c84 ticom geomatics, inc. + dc3cf6 atomic rules llc dc3e51 solberg & andersen as dc3ef8 nokia corporation + dc415f apple, inc. + dc41a9 intel corporate + dc41e5 shenzhen zhixin data service co., ltd. + dc4427 ieee registration authority + dc446d allwinner technology co., ltd + dc44b6 samsung electronics co.,ltd dc4517 arris group, inc. + dc48b2 baraja pty. ltd. dc49c9 casco signal ltd + dc4a3e hewlett packard + dc4a9e ieee registration authority + dc4bdd shenzhen superelectron technology co.,ltd. + dc4bfe shenzhen belon technology co.,ltd + dc4d23 mrv comunications dc4ede shinyei technology co., ltd. + dc4ef4 shenzhen mtn electronics co., ltd + dc4f22 espressif inc. + dc503a nanjing ticom tech co., ltd. + dc5285 apple, inc. + dc5360 intel corporate + dc537c compal broadband networks, inc. + dc543d itel mobile limited + dc54d7 amazon technologies inc. + dc5583 guangdong oppo mobile telecommunications corp.,ltd + dc56e6 shenzhen bococom technology co.,ltd + dc56e7 apple, inc. dc5726 power-one + dc58bc thomas-krenn.ag dc5e36 paterson technology + dc60a1 teledyne dalsa professional imaging + dc6373 obara korea dc647c c.r.s. iimotion gmbh + dc64b8 shenzhen jinghanda electronics co.ltd + dc663a apacer technology inc. + dc6672 samsung electronics co.,ltd + dc6723 barox kommunikation gmbh + dc680c hewlett packard enterprise + dc68eb nintendo co.,ltd + dc6aea infinix mobility limited + dc6b12 worldcns inc. + dc6dcd guangdong oppo mobile telecommunications corp.,ltd dc6f00 livescribe, inc. dc6f08 bay storage technology - dc7014 - dc7144 samsung electro mechanics - dc7b94 cisco systems, inc. + dc7014 private + dc7137 zte corporation + dc7144 samsung electro mechanics co., ltd. + dc7196 intel corporate + dc7223 hui zhou gaoshengda technology co.,ltd + dc729b huawei technologies co.,ltd + dc7385 huawei device co., ltd. + dc74a8 samsung electronics co.,ltd + dc774c cisco systems, inc + dc7834 logicom sa + dc7b94 cisco systems, inc + dc7fa4 2wire inc dc825b janus, spol. s r.o. - dc85de azurewave technologies., inc. - dc86d8 apple, inc + dc82f6 iport + dc85de azurewave technology inc. + dc86d8 apple, inc. + dc87cb beijing perfectek technologies co., ltd. + dc8983 samsung electronics co.,ltd + dc8b28 intel corporate + dc8c1b vivo mobile communication co., ltd. + dc8c37 cisco systems, inc + dc9020 ruru tek private limited + dc9088 huawei technologies co.,ltd + dc91bf amazon technologies inc. + dc962c nst audio ltd + dc9840 microsoft corporation + dc9914 huawei technologies co.,ltd + dc9a8e nanjing cocomm electronics co., ltd dc9b1e intercom, inc. - dc9b9c apple + dc9b9c apple, inc. + dc9bd6 tct mobile ltd dc9c52 sapphire technology limited. + dc9c9f shenzhen youhua technology co., ltd dc9fa4 nokia corporation - dc9fdb ubiquiti networks, inc. - dca5f4 cisco + dc9fdb ubiquiti networks inc. + dca120 nokia + dca266 hon hai precision ind. co.,ltd. + dca333 shenzhen youhua technology co., ltd + dca3a2 feng mi(beijing)technology co., ltd + dca3ac rbcloudtech + dca4ca apple, inc. + dca5f4 cisco systems, inc + dca632 raspberry pi trading ltd dca6bd beijing lanbo technology co., ltd. dca7d9 compressor controls corp dca8cf new spin golf, llc. + dca904 apple, inc. dca971 intel corporate dca989 macandc dcad9e greenpriz dcae04 celoxica ltd - dcb058 burkert werke gmbh + dcaeeb ruckus wireless + dcaf68 weifang goertek electronics co.,ltd + dcb058 bürkert werke gmbh + dcb082 nokia + dcb131 shenzhen huaruian technology co.,ltd + dcb3b4 honeywell environmental & combustion controls (tianjin) co., ltd. + dcb4ac flextronics manufacturing(zhuhai)co.,ltd. dcb4c4 microsoft xcg + dcb72e xiaomi communications co ltd + dcb7fc alps electric (ireland) ltd + dcb808 extreme networks, inc. + dcbd7a guangzhou shiyuan electronic technology company limited + dcbe7a zhejiang nurotron biotechnology co. dcbf90 huizhou qiaoxing telecommunication industry co.,ltd. + dcbfe9 motorola mobility llc, a lenovo company dcc0db shenzhen kaiboer technology co., ltd. + dcc0eb assa abloy cÔte picarde dcc101 solid technologies, inc. dcc422 systembase limited + dcc622 buheung system + dcc64b huawei technologies co.,ltd dcc793 nokia corporation + dcc8f5 shanghai umeinfo co.,ltd. dccba8 explora technologies inc + dccc8d integrated device technology (malaysia) sdn. bhd. + dccd2f seiko epson corporation + dccd74 japan e.m.solutions co., ltd. dcce41 fe global hong kong limited dccebc shenzhen jsr technology co.,ltd. + dccec1 cisco systems, inc dccf94 beijing rongcheng hutong technology co., ltd. + dccf96 samsung electronics co.,ltd dcd0f7 bentek systems ltd. + dcd255 kinpo electronics, inc. dcd2fc huawei technologies co.,ltd - dcd321 humax co.,tld + dcd321 humax co., ltd. + dcd3a2 apple, inc. + dcd444 huawei device co., ltd. dcd52a sunny heart limited + dcd7a0 huawei device co., ltd. + dcd87c beijing jingdong century trading co., ltd. dcd87f shenzhen joincyber telecom equipment ltd + dcd916 huawei technologies co.,ltd + dcd9ae nokia shanghai bell co., ltd. + dcda4f getck technology, inc + dcda80 new h3c technologies co., ltd + dcdb70 tonfunk systementwicklung und service gmbh + dcdc07 trp systems bv + dcdce2 samsung electronics co.,ltd + dcdd24 energica motor company spa + dcde4f gionee communication equipment co ltd dcdeca akyllor + dcdfd6 zte corporation + dce026 patrol tag, inc + dce0eb nanjing aozheng information technology co.ltd + dce1ad shenzhen wintop photoelectric technology co., ltd dce2ac lumens digital optics inc. + dce305 zao npk rotek + dce533 ieee registration authority dce578 experimental factory of scientific engineering and special design department dce71c aug elektronik gmbh + dce838 ck telecom (shenzhen) limited + dce994 cloud network technology singapore pte. ltd. + dceb53 wuhan qianxiao elecronic technology co.,ltd + dceb69 technicolor ch usa inc. + dceb94 cisco systems, inc + dcec06 heimi network technology co., ltd. + dced84 haverford systems inc + dcee06 huawei technologies co.,ltd + dcef09 netgear + dcef80 huawei technologies co.,ltd + dcefca murata manufacturing co., ltd. dcf05d letta teknoloji + dcf090 nubia technology co.,ltd. + dcf110 nokia corporation + dcf401 dell inc. + dcf505 azurewave technology inc. + dcf719 cisco systems, inc dcf755 sitronik + dcf756 samsung electronics co.,ltd dcf858 lorent networks, inc. + dcf8b9 zte corporation dcfad5 strong ges.m.b.h. - dcfb02 buffalo inc. + dcfb02 buffalo.inc + dcfb48 intel corporate + dcfe07 pegatron corporation + dcfe18 tp-link technologies co.,ltd. + e00084 huawei technologies co.,ltd + e002a5 abb robotics + e00370 shenzhen continental wireless technology co., ltd. e005c5 tp-link technologies co.,ltd. e006e6 hon hai precision ind. co.,ltd. + e0071b hewlett packard enterprise + e009bf shenzhen tong bo wei technology co.,ltd e00b28 inovonics e00c7f nintendo co., ltd. + e00ce5 huawei technologies co.,ltd + e00db9 cree, inc. + e00eda cisco systems, inc + e00ee1 we corporation inc. + e00ee4 dwnet technologies(suzhou) corporation + e0107f ruckus wireless + e01283 shenzhen fanzhuo communication technology co., lt + e013b5 vivo mobile communication co., ltd. e0143e modoosis inc. e01877 fujitsu limited - e01c41 aerohive networks inc. + e0189f em microelectronic + e0191d huawei technologies co.,ltd + e01954 zte corporation + e01995 nutanix + e019d8 bh technologies + e01aea allied telesis, inc. + e01c41 extreme networks, inc. e01cee bravo tech, inc. - e01d3b cambridge industries(group) co.,ltd + e01cfc d-link international + e01d38 beijing huaqinworld technology co.,ltd + e01d3b cambridge industries(group) co.,ltd. e01e07 anite telecoms us. inc e01f0a xslent energy technologies. llc + e01f88 xiaomi communications co ltd + e01fed nokia shanghai bell co., ltd. + e02202 arris group, inc. + e023ff fortinet, inc. e0247f huawei technologies co.,ltd + e02481 huawei technologies co.,ltd e02538 titan pet products e02630 intrigue technologies, inc. e02636 nortel networks e0271a ttc next-generation home network system wg + e02861 huawei technologies co.,ltd + e0286d avm audiovisuelles marketing und computersysteme gmbh + e02967 hmd global oy e02a82 universal global scientific industrial co., ltd. - e02f6d cisco + e02ae6 fiberhome telecommunication technologies co.,ltd + e02b96 apple, inc. + e02be9 intel corporate + e02cb2 lenovo mobile communication (wuhan) company limited + e02cf3 mrs electronic gmbh + e02e3f huawei device co., ltd. + e02f6d cisco systems, inc e03005 alcatel-lucent shanghai bell co., ltd + e0319e valve corporation e031d0 sz telstar co., ltd + e0338e apple, inc. + e034e4 feit electric company, inc. + e03560 challenger supply holdings, llc + e03676 huawei technologies co.,ltd e036e3 stage one international co., ltd. + e03717 technicolor ch usa inc. + e037bf wistron neweb corporation + e0383f zte corporation e039d7 plexxi, inc. e03c5b shenzhen jiaxinjie electron co.,ltd + e03e44 broadcom e03e4a cavanagh group international e03e7d data-complex gmbh e03f49 asustek computer inc. + e04007 huawei device co., ltd. + e04136 mitrastar technology corp. + e043db shenzhen viewat technology co.,ltd. + e0456d china mobile group device co.,ltd. e0469a netgear + e046e5 gosuncn technology group co., ltd. + e048af premietech limited + e048d3 mobiwire mobiles (ningbo) co.,ltd + e049ed audeze llc + e04b45 hi-p electronics pte ltd + e04ba6 huawei technologies co.,ltd + e04f43 universal global scientific industrial co., ltd. + e04fbd sichuan tianyi comheart telecomco.,ltd + e0508b zhejiang dahua technology co., ltd. + e05124 nxp semiconductors + e05163 arcadyan corporation + e0553d cisco meraki e05597 emergent vision technologies inc. e056f4 axesnetwork solutions inc. e0589e laerdal medical + e05a9f ieee registration authority e05b70 innovid, co., ltd. + e05d5c oy everon ab e05da6 detlef fink elektronik & softwareentwicklung - e05fb9 cisco systems, inc. + e05f45 apple, inc. + e05fb9 cisco systems, inc + e06066 sercomm corporation. + e06089 cloudleaf, inc. e061b2 hangzhou zenointel technology co., ltd + e06234 texas instruments + e06267 xiaomi communications co ltd e06290 jinan jovision science & technology co., ltd. - e063e5 sony mobile communications ab + e063da ubiquiti networks inc. + e063e5 sony mobile communications inc e064bb digiview s.r.l. - e067b3 c-data technology co., ltd + e06678 apple, inc. + e067b3 shenzhen c-data technology co., ltd + e0686d raybased ab + e0693a innophase inc. e06995 pegatron corporation - e0750a alps erectoric co.,ltd. - e0757d motorola mobility llc + e06c4e shenzhen tinno mobile technology corp. + e06ca6 creotech instruments s.a. + e06d17 apple, inc. + e0735f nucom + e0750a alpsalpine co,.ltd + e0757d motorola mobility llc, a lenovo company + e076d0 ampak technology, inc. + e07726 huawei device co., ltd. + e078a3 shanghai winner information technology co.,inc + e0795e wuxi xiaohu technology co.,ltd. + e079c4 iray technology company limited + e07c13 zte corporation e07c62 whistle labs, inc. + e07dea texas instruments e07f53 techboard srl e07f88 evidence network sia e08177 greenbytes, inc. + e084f3 high grade controls corporation + e0859a shenzhen rf-link technology co.,ltd. e087b1 nata-info ltd. + e0885d technicolor ch usa inc. + e0897e apple, inc. + e0899d cisco systems, inc e08a7e exponent + e08e3c aztech electronics pte ltd e08fec repotec co., ltd. + e0913c kyeungin cns co., ltd. e09153 xavi technologies corp. e091f5 netgear + e0925c apple, inc. + e092a7 feitian technologies co., ltd e09467 intel corporate e09579 orthosoft inc, d/b/a zimmer cas + e09796 huawei technologies co.,ltd e097f2 atomax inc. + e09806 espressif inc. + e09861 motorola mobility llc, a lenovo company + e09971 samsung electronics co.,ltd e09d31 intel corporate e09db8 planex communications inc. + e09dfa wanan hongsheng electronic co.ltd + e09f2a iton technology corp. e0a198 noja power switchgear pty ltd e0a1d7 sfr e0a30f pevco + e0a3ac huawei technologies co.,ltd + e0a509 bitmain technologies inc e0a670 nokia corporation - e0aab0 general vision electronics co. ltd. + e0a700 verkada inc + e0a8b8 le shi zhi xin electronic technology (tianjin) limited + e0aa96 samsung electronics co.,ltd + e0aab0 suntaili enterprise co. ltd, + e0aadb nanjing paneng technology development co.,ltd e0abfe orb networks, inc. - e0ae5e alps co,. ltd. + e0accb apple, inc. + e0acf1 cisco systems, inc + e0ae5e alpsalpine co,.ltd e0aeb2 bender gmbh & co.kg e0aeed loenk e0af4b pluribus networks, inc. + e0af4f deutsche telekom ag + e0b260 teno network technologies company limited e0b2f1 fn-link technology limited - e0b7b1 pace plc - e0b9a5 azurewave - e0b9ba apple + e0b52d apple, inc. + e0b55f apple, inc. + e0b655 beijing xiaomi electronics co., ltd. + e0b6f5 ieee registration authority + e0b70a arris group, inc. + e0b7b1 arris group, inc. + e0b94d shenzhen bilian electronic co.,ltd + e0b9a5 azurewave technology inc. + e0b9ba apple, inc. + e0b9e5 technicolor + e0bab4 arrcus, inc + e0bb9e seiko epson corporation e0bc43 c2 microsystems, inc. + e0be03 lite-on network communication (dongguan) limited + e0c0d1 ck telecom (shenzhen) limited e0c286 aisai communication technology co., ltd. e0c2b7 masimo corporation + e0c377 samsung electronics co.,ltd e0c3f3 zte corporation + e0c63c sichuan tianyi comheart telecomco., ltd e0c6b3 mildef ab + e0c767 apple, inc. e0c79d texas instruments e0c86a shenzhen tw-scie co., ltd e0c922 jireh energy tech., ltd. - e0c97a apple + e0c97a apple, inc. e0ca4d shenzhen unistar communication co.,ltd - e0ca94 askey computer - e0cb1d + e0ca94 askey computer corp + e0cb1d private e0cb4e asustek computer inc. + e0cbbc cisco meraki + e0cbee samsung electronics co.,ltd + e0cc7a huawei technologies co.,ltd + e0ccf8 xiaomi communications co ltd + e0cdfd beijing e3control technology co, ltd e0cec3 askey computer corp e0cf2d gemintek corporation + e0d083 samsung electronics co.,ltd e0d10a katoudenkikougyousyo co ltd + e0d173 cisco systems, inc e0d1e6 aliph dba jawbone e0d31a eques technology co., limited + e0d462 huawei device co., ltd. + e0d464 intel corporate + e0d4e8 intel corporate + e0d55e giga-byte technology co.,ltd. e0d7ba texas instruments + e0d848 dell inc. e0d9a2 hippih aps + e0d9e3 eltex enterprise ltd. + e0da90 huawei technologies co.,ltd e0dadc jvc kenwood corporation - e0db55 dell inc + e0db10 samsung electronics co.,ltd + e0db55 dell inc. e0db88 open standard digital-if interface for satcom systems - e0dca0 siemens electrical apparatus ltd., suzhou chengdu branch + e0dbd1 technicolor ch usa inc. + e0dca0 siemens industrial automation products ltd chengdu + e0dcff xiaomi communications co ltd + e0ddc0 vivo mobile communication co., ltd. + e0e0c2 china mobile group device co.,ltd. + e0e0fc huawei device co., ltd. + e0e1a9 shenzhen four seas global link network technology co., ltd. + e0e2e6 espressif inc. + e0e37c huawei device co., ltd. + e0e5cf texas instruments + e0e62e tct mobile ltd e0e631 snb technologies limited + e0e656 nethesis srl e0e751 nintendo co., ltd. + e0e7bb nureva, inc. + e0e8bb unicom vsens telecommunications co., ltd. + e0e8e6 shenzhen c-data technology co., ltd. e0e8e8 olive telecommunication pvt. ltd + e0eb40 apple, inc. + e0eb62 shanghai hulu devices co., ltd e0ed1a vastriver technology co., ltd e0edc7 shenzhen friendcom technology development co., ltd e0ee1b panasonic automotive systems company of america e0ef25 lintes technology co., ltd. e0f211 digitalwatt e0f379 vaddio - e0f5c6 apple + e0f442 huawei device co., ltd. + e0f5c6 apple, inc. e0f5ca cheng uei precision industry co.,ltd. - e0f847 apple + e0f6b5 nintendo co.,ltd + e0f847 apple, inc. e0f9be cloudena corp. e0faec platan sp. z o.o. sp. k. + e0fff7 softiron inc. + e4029b intel corporate e40439 tomtom software ltd + e405f8 bytedance + e40eee huawei technologies co.,ltd e4115b hewlett packard + e41218 shenzhen rapoo technology co., ltd. e4121d samsung electronics co.,ltd e41289 topsystem systemhaus gmbh + e415f6 texas instruments + e417d8 8bitdo technology hk limited + e4186b zyxel communications corporation + e419c1 huawei technologies co.,ltd + e41a2c zpe systems, inc. e41c4b v2 technology, inc. + e41d2d mellanox technologies, inc. + e41e0a ieee registration authority e41f13 ibm corp - e425e7 apple + e41f7b cisco systems, inc + e41fe9 dunkermotoren gmbh + e422a5 plantronics, inc. + e42354 shenzhen fuzhi software technology co.,ltd + e4246c zhejiang dahua technology co., ltd. + e425e7 apple, inc. e425e9 color-chip + e42686 dwnet technologies(suzhou) corporation + e4268b huawei device co., ltd. + e42761 honor device co., ltd. e42771 smartlabs + e428a4 prama india private limited e42ad3 magneti marelli s.p.a. powertrain + e42b34 apple, inc. e42c56 lilee systems, ltd. - e42d02 tct mobile limited - e42f26 fiberhome telecommunication tech.co.,ltd. + e42d02 tct mobile ltd + e42d7b china mobile iot company limited + e42f26 fiberhome telecommunication technologies co.,ltd + e42f56 optomet gmbh e42ff6 unicore communication inc. + e43022 hanwha techwin security vietnam e432cb samsung electronics co.,ltd + e433ae guangdong oppo mobile telecommunications corp.,ltd + e43493 huawei technologies co.,ltd e43593 hangzhou goto technology co.ltd + e435c8 huawei technologies co.,ltd e435fb sabre technology (hull) ltd e437d7 henri depaepe s.a.s. + e4388c digital products limited e438f2 advantage controls + e43a65 mofinetwork inc + e43a6e shenzhen zeroone technology co.,ltd + e43c80 university of oklahoma + e43d1a broadcom limited + e43ec6 huawei technologies co.,ltd + e43ed7 arcadyan corporation e43fa2 wuxi dsp technologies inc. e440e2 samsung electronics co.,ltd + e44122 oneplus technology (shenzhen) co., ltd + e44164 nokia e441e6 ottec technology gmbh + e442a6 intel corporate + e4434b dell inc. e446bd c&c technic taiwan co., ltd. + e446da xiaomi communications co ltd + e44790 guangdong oppo mobile telecommunications corp.,ltd + e44791 iris id systems, inc. + e447b3 zte corporation e448c7 cisco spvtg e44c6c shenzhen guo wei electronic co,. ltd. + e44cc7 ieee registration authority e44e18 gardasoft visionlimited + e44e2d cisco systems, inc + e44e76 championtech enterprise (shenzhen) inc e44f29 ma lighting technology gmbh e44f5f eds elektronik destek san.tic.ltd.sti + e4509a hw communications ltd + e450eb apple, inc. + e454e8 dell inc. + e455a8 cisco meraki e455ea dedicated computing e45614 suttle apparatus + e45740 arris group, inc. e457a8 stuart manufacturing, inc. + e458b8 samsung electronics co.,ltd + e458e7 samsung electronics co.,ltd + e45aa2 vivo mobile communication co., ltd. + e45ad4 eltex enterprise ltd. + e45d37 juniper networks + e45d51 sfr + e45d52 avaya inc + e45d75 samsung electronics co.,ltd + e45e1b google, inc. + e45e37 intel corporate + e45f01 raspberry pi trading ltd + e46059 pingtek co., ltd. + e46251 hao cheng group limited e46449 arris group, inc. + e4671e shen zhen nuo xin cheng technology co., ltd. e467ba danish interpretation systems a/s e468a3 huawei technologies co.,ltd + e4695a dictum health, inc. e46c21 messma gmbh + e46f13 d-link international + e470b8 intel corporate e47185 securifi ltd + e472e2 huawei technologies co.,ltd e4751e getinge sterilization ab + e475dc arcadyan corporation + e47684 apple, inc. e47723 zte corporation + e47727 huawei technologies co.,ltd e4776b aartesys ag - e477d4 minrray industry co.,ltd - e47cf9 samsung electronics co., ltd + e477d4 minrray industry co.,ltd + e47b3f beijing co-cloud technology ltd. + e47c65 sunstar communication technology co., ltd + e47cf9 samsung electronics co.,ltd e47d5a beijing hanbang technology corp. - e48184 alcatel-lucent + e47dbd samsung electronics co.,ltd + e47deb shanghai notion information technology co.,ltd. + e47e66 huawei technologies co.,ltd + e47e9a zte corporation + e47fb2 fujitsu limited + e48184 nokia e481b3 shenzhen act industrial co.,ltd. + e482cc jumptronic gmbh + e48326 huawei technologies co.,ltd e48399 arris group, inc. + e4842b hangzhou softel optic co., ltd + e48501 geberit international ag e48ad5 rf window co., ltd. - e48b7f apple + e48b7f apple, inc. + e48c0f discovery insure + e48d8c routerboard.com + e48f1d huawei device co., ltd. + e48f34 vodafone italia s.p.a. + e48f65 yelatma instrument making enterprise, jsc e49069 rockwell automation + e4907e motorola mobility llc, a lenovo company + e490fd apple, inc. + e4922a dbg holdings limited e492e7 gridlink tech. co.,ltd. e492fb samsung electronics co.,ltd + e4956e ieee registration authority e496ae altographics inc. e497f0 shanghai vlc technologies ltd. co. - e498d6 apple, inc + e498bb phyplus microelectronics limited + e498d1 microsoft mobile oy + e498d6 apple, inc. + e49a79 apple, inc. + e49adc apple, inc. + e49e12 freebox sas + e49f1e arris group, inc. + e4a1e6 alcatel-lucent shanghai bell co., ltd + e4a32f shanghai artimen technology co., ltd. + e4a387 control solutions llc + e4a471 intel corporate e4a5ef tron link electronics co., ltd. + e4a749 palo alto networks + e4a7a0 intel corporate + e4a7c5 huawei technologies co.,ltd e4a7fd cellco partnership + e4a8b6 huawei technologies co.,ltd + e4a8df compal information (kunshan) co., ltd. + e4aa5d cisco systems, inc + e4aaea liteon technology corporation + e4aaec tianjin hualai technology co., ltd e4ab46 uab selteka + e4ab89 mitrastar technology corp. e4ad7d scl elements e4afa1 hes-so + e4b005 beijing iqiyi science & technology co., ltd. e4b021 samsung electronics co.,ltd + e4b2fb apple, inc. + e4b318 intel corporate + e4b97a dell inc. + e4bad9 360 fly inc. + e4bd4b zte corporation + e4beed netcore technology inc. + e4bffa technicolor ch usa inc. + e4c0cc china mobile group device co.,ltd. e4c146 objetivos y servicios de valor a + e4c1f1 shenzhen spotmau information technoligy co., ltd + e4c2d1 huawei technologies co.,ltd + e4c32a tp-link technologies co.,ltd. + e4c483 guangdong oppo mobile telecommunications corp.,ltd + e4c62b airware e4c63d apple, inc. e4c6e6 mophie, llc - e4c722 cisco + e4c722 cisco systems, inc + e4c801 blu products inc e4c806 ceiec electric technology inc. - e4ce8f apple + e4c90b radwin + e4ca12 zte corporation + e4cb59 beijing loveair science and technology co. ltd. + e4cc9d integrated device technology (malaysia) sdn. bhd. + e4ce02 wyrestorm technologies ltd + e4ce70 health & life co., ltd. + e4ce8f apple, inc. + e4d124 mojo networks, inc. e4d332 tp-link technologies co.,ltd. - e4d3f1 cisco + e4d373 huawei technologies co.,ltd + e4d3aa fujitsu connected technologies limited + e4d3f1 cisco systems, inc e4d53d hon hai precision ind. co.,ltd. e4d71d oraya therapeutics + e4db6d beijing xiaomi electronics co., ltd. + e4dc43 huawei device co., ltd. e4dd79 en-vision america, inc. - e4e0c5 samsung electronics co., ltd + e4e0a6 apple, inc. + e4e0c5 samsung electronics co.,ltd + e4e112 texas instruments + e4e130 tct mobile ltd e4e409 leifheit ag + e4e4ab apple, inc. + e4e749 hewlett packard + e4ea83 shenzhen gongjin electronics co.,lt e4ec10 nokia corporation e4eefd mr&d manufacturing + e4f004 dell inc. + e4f042 google, inc. + e4f14c private + e4f1d4 vivo mobile communication co., ltd. + e4f327 atol llc e4f365 time-o-matic, inc. + e4f3c4 samsung electronics co.,ltd e4f3e3 shanghai icomhome co.,ltd. + e4f3e8 shenzhen superelectron technology co.,ltd. + e4f3f5 shenzhen mercury communication technologies co.,ltd. + e4f4c6 netgear + e4f75b arris group, inc. e4f7a1 datafox gmbh + e4f89c intel corporate + e4f8ef samsung electronics co.,ltd + e4f939 minxon hotel technology inc. e4fa1d pad peripheral advanced design inc. + e4faed samsung electronics co.,ltd + e4fafd intel corporate + e4fb5d huawei technologies co.,ltd + e4fb8f mobiwire mobiles (ningbo) co.,ltd + e4fc82 juniper networks + e4fd45 intel corporate + e4fda1 huawei technologies co.,ltd + e4fed9 edmi europe ltd e4ffdd electron india - e8039a samsung electronics co., ltd - e8040b apple - e80410 - e80462 cisco systems, inc. + e80036 befs co,. ltd + e8018d fiberhome telecommunication technologies co.,ltd + e8039a samsung electronics co.,ltd + e8040b apple, inc. + e80410 private + e80462 cisco systems, inc e804f3 throughtek co., ltd. e8056d nortel networks - e80688 apple - e8088b huawei technologies co., ltd + e80688 apple, inc. + e80734 champion optical network engineering, llc + e807bf shenzhen boomtech industry co.,ltd + e8088b huawei technologies co.,ltd + e80945 integrated device technology (malaysia) sdn. bhd. + e80959 guoguang electric co.,ltd + e80aec jiangsu hengtong optic-electric co., ltd e80b13 akib systems taiwan, inc e80c38 daeyoung information system co., ltd e80c75 syncbak, inc. + e80fc8 universal electronics, inc. e8102e really simple software, inc - e81132 samsung electronics co., ltd + e81132 samsung electronics co.,ltd + e811ca shandong kaer electric.co.,ltd e81324 guangzhou bonsoninfo system co.,ltd - e817fc nifty corporation + e81363 comstock rd, inc. + e81367 airsound inc. + e8136e huawei technologies co.,ltd + e8150e nokia corporation + e8162b ideo security co., ltd. + e817fc fujitsu cloud technologies limited + e81863 ieee registration authority + e81a58 technologic systems + e81aac orfeo soundworks inc. + e81b4b amnimo inc. + e81b69 sercomm corporation. + e81cba fortinet, inc. + e81cd8 apple, inc. + e81da8 ruckus wireless + e81e92 huawei device co., ltd. + e820e2 humax co., ltd. + e82689 aruba, a hewlett packard enterprise company + e826b6 inside biometrics international limited e82877 tmy co., ltd. + e828c1 eltex enterprise ltd. e828d5 cots technology + e82a44 liteon technology corporation e82aea intel corporate + e82c6d smartrg, inc. + e82e0c netint technologies inc. e82e24 out of the fog research llc + e8330d xaptec gmbh + e83381 arris group, inc. + e8343e beijing infosec technologies co., ltd. + e83617 apple, inc. + e8361d sense labs, inc. + e8377a zyxel communications corporation e83935 hewlett packard - e839df askey computer - e83a97 ocz technology group + e839df askey computer corp + e83a12 samsung electronics co.,ltd + e83a97 toshiba corporation e83eb6 rim e83efb geodesic ltd. e83efc arris group, inc. - e84040 cisco systems, inc. + e83f67 huawei device co., ltd. + e84040 cisco systems, inc e840f2 pegatron corporation e843b6 qnap systems, inc. + e8447e bitdefender srl e8481f advanced automotive antennas + e848b8 tp-link corporation limited + e84943 yuge information technology co. ltd + e84c56 intercept services limited + e84d74 huawei technologies co.,ltd + e84dd0 huawei technologies co.,ltd e84e06 edup international (hk) co., ltd e84e84 samsung electronics co.,ltd e84ece nintendo co., ltd. + e84f25 murata manufacturing co., ltd. + e84f4b shenzhen delos electronic co., ltd + e8508b samsung electro-mechanics(thailand) e8516e tsmart inc. e8519d yeonhab precision co.,ltd e85484 neo information systems co., ltd. + e855b4 sai technology inc. + e85659 advanced-connectek inc. e856d6 nctech ltd + e85a8b xiaomi communications co ltd e85aa7 llc emzior + e85ad1 fiberhome telecommunication technologies co.,ltd e85b5b lg electronics inc + e85bb7 ample systems inc. e85bf0 imaging diagnostics + e85d6b luminate wireless + e85d86 chang yow technologies international co.,ltd. e85e53 infratec datentechnik gmbh e8611f dawning information industry co.,ltd e8617e liteon technology corporation e86183 black diamond advanced technology, llc + e861be melec inc. + e86549 cisco systems, inc + e865d4 tenda technology co.,ltd.dongguan branch + e866c4 diamanti + e86819 huawei technologies co.,ltd + e868e7 espressif inc. + e86a64 lcfc(hefei) electronics technology co., ltd + e86cc7 ieee registration authority e86cda supercomputers and neurocomputers research center e86d52 arris group, inc. e86d54 digit mobile inc - e86d6e control & display systems ltd t/a cdsrail + e86d65 audio mobil elektronik gmbh + e86d6e voestalpine signaling fareham ltd. + e86dcb samsung electronics co.,ltd + e86de9 huawei technologies co.,ltd + e86f38 chongqing fugui electronics co.,ltd. + e86ff2 actiontec electronics, inc e8718d elsys equipamentos eletronicos ltda + e874c7 sentinhealth + e874e6 adb broadband italia e8757f firs technologies(shenzhen) co., ltd e878a1 beoview intercom doo e87af3 s5 tech s.r.l. + e87f6b samsung electronics co.,ltd + e87f95 apple, inc. + e8802e apple, inc. e880d8 gntek electronics co.,ltd. + e88152 apple, inc. + e8825b arris group, inc. + e884a5 intel corporate + e884c6 huawei technologies co.,ltd + e8854b apple, inc. + e887a3 loxley public company limited + e8886c shenzhen sc technologies co.,ltd e8892c arris group, inc. - e88d28 apple + e88d28 apple, inc. e88df5 znyx networks, inc. + e88e60 nsd corporation + e8910f fiberhome telecommunication technologies co.,ltd + e89120 motorola mobility llc, a lenovo company e89218 arcontia international ab - e892a4 lg electronics + e892a4 lg electronics (mobile communications) + e89309 samsung electronics co.,ltd + e89363 nokia e8944c cogent healthcare systems ltd e894f6 tp-link technologies co.,ltd. + e89606 testo instruments (shenzhen) co., ltd. + e8986d palo alto networks + e898c2 zetlab company e8995a piigab, processinformation i goteborg ab e899c4 htc corporation e89a8f quanta computer inc. e89aff fujian landi commercial equipment co.,ltd e89d87 toshiba + e89e0c max8usa distributors inc. + e89eb4 hon hai precision ind. co.,ltd. + e89f39 nokia + e89f80 belkin international inc. + e89fec chengdu kt electronic hi-tech co.,ltd + e8a0cd nintendo co.,ltd + e8a1f8 zte corporation + e8a245 juniper networks e8a364 signal path international / peachtree audio - e8a4c1 deep sea electronics plc + e8a4c1 deep sea electronics ltd + e8a660 huawei technologies co.,ltd + e8a788 xiamen leelen technology co., ltd + e8a7f2 straffic + e8abf3 huawei technologies co.,ltd e8abfa shenzhen reecam tech.ltd. + e8acad zte corporation + e8ada6 sagemcom broadband sas e8b1fc intel corporate + e8b2ac apple, inc. + e8b2fe humax co., ltd. + e8b470 ieee registration authority e8b4ae shenzhen c&d electronics co.,ltd - e8b748 cisco systems, inc. - e8ba70 cisco systems, inc. + e8b4c8 samsung electronics co.,ltd + e8b541 zte corporation + e8b6c2 juniper networks + e8b748 cisco systems, inc + e8ba70 cisco systems, inc e8bb3d sino prime-tech limited - e8bba8 guangdong oppo mobile telecommunications corp.,ltd. - e8be81 sagemcom + e8bba8 guangdong oppo mobile telecommunications corp.,ltd + e8bdd1 huawei technologies co.,ltd + e8be81 sagemcom broadband sas + e8c1b8 nanjing bangzhong electronic commerce limited + e8c1d7 philips e8c229 h-displays (msc) bhd - e8c320 austco communication systems pty ltd + e8c2dd infinix mobility limited + e8c320 austco marketing & service (usa) ltd. + e8c417 fiberhome telecommunication technologies co.,ltd + e8c57a ufispace co., ltd. + e8c74f liteon technology corporation e8cba1 nokia corporation + e8cc18 d-link international e8cc32 micronet ltd - e8cd2d huawei technologies co., ltd + e8cd2d huawei technologies co.,ltd e8ce06 skyhawke technologies, llc. + e8d03c shenzhen jingxun software telecommunication technology co.,ltd + e8d099 fiberhome telecommunication technologies co.,ltd + e8d0b9 taicang t&w electronics e8d0fa mks instruments deutschland gmbh + e8d0fc liteon technology corporation + e8d11b askey computer corp + e8d2ff sagemcom broadband sas e8d483 ultimate europe transportation equipment gmbh e8d4e0 beijing benywave technology co., ltd. + e8d765 huawei technologies co.,ltd + e8d819 azurewave technology inc. + e8d8d1 hp inc. + e8da20 nintendo co.,ltd e8da96 zhuhai tianrui electrical power tech. co., ltd. e8daaa videohome technology corp. + e8db84 espressif inc. + e8de00 chongqing guanfang technology co.,ltd e8de27 tp-link technologies co.,ltd. + e8de8e integrated device technology (malaysia) sdn. bhd. + e8ded6 intrising networks, inc. + e8defb mesotic sas + e8df70 avm audiovisuelles marketing und computersysteme gmbh e8dff2 prf co., ltd. e8e08f gravotech marking sas e8e0b7 toshiba + e8e1e1 gemtek technology co., ltd. e8e1e2 energotest e8e5d6 samsung electronics co.,ltd - e8e732 alcatel-lucent + e8e732 alcatel-lucent enterprise e8e770 warp9 tech design, inc. e8e776 shenzhen kootion technology co., ltd e8e875 is5 communications inc. + e8e8b7 murata manufacturing co., ltd. + e8e98e solar controls s.r.o. + e8ea4d huawei technologies co.,ltd e8ea6a startech.com - e8eada denkovi assembly electroncs ltd - e8edf3 cisco - e8f1b0 sagemcom sas + e8eada denkovi assembly electronics ltd + e8eb11 texas instruments + e8eb1b microchip technology inc. + e8eb34 cisco systems, inc + e8eca3 dongguan liesheng electronic co.ltd + e8ed05 arris group, inc. + e8edf3 cisco systems, inc + e8ef89 opmex tech. + e8f1b0 sagemcom broadband sas e8f226 millson custom solutions inc. + e8f2e2 lg innotek + e8f2e3 starcor beijing co.,limited + e8f408 intel corporate + e8f654 huawei technologies co.,ltd + e8f724 hewlett packard enterprise e8f928 rftech srl + e8faf7 guangdong uniteddata holding group co., ltd. + e8fbe9 apple, inc. e8fc60 elcom innovations private limited + e8fcaf netgear + e8fd35 huawei device co., ltd. + e8fd72 shanghai linguo technology co., ltd. + e8fd90 turbostor + e8fde8 cela link corporation + ec0133 trinus systems inc. + ec01e2 foxconn interconnect technology + ec01ee guangdong oppo mobile telecommunications corp.,ltd + ec0273 aruba, a hewlett packard enterprise company + ec0441 shenzhen tigo semiconductor co., ltd. + ec086b tp-link technologies co.,ltd. + ec0bae hangzhou broadlink technology co.,ltd + ec0d9a mellanox technologies, inc. + ec0de4 amazon technologies inc. + ec0ec4 hon hai precision ind. co.,ltd. ec0ed6 itech instruments sas + ec107b samsung electronics co.,ltd ec1120 flodesign wind turbine corporation + ec1127 texas instruments + ec13b2 netonix + ec13db juniper networks ec14f6 biocontrol as - ec172f tp-link technologies co., ltd. + ec153d beijing yaxunhongda technology co., ltd. + ec172f tp-link technologies co.,ltd. ec1766 research centre module ec1a59 belkin international inc. + ec1bbd silicon laboratories + ec1d7f zte corporation + ec1d8b cisco systems, inc + ec1f72 samsung electro-mechanics(thailand) ec219f vidabox llc + ec21e5 toshiba ec2257 jiangsu nanjing university electronic information technology co.,ltd - ec233d huawei technologies co., ltd + ec2280 d-link international + ec233d huawei technologies co.,ltd ec2368 intellivoice co.,ltd. + ec237b zte corporation + ec24b8 texas instruments + ec2651 apple, inc. + ec26ca tp-link technologies co.,ltd. + ec26fb tecc co.,ltd. ec2af0 ypsomed ag ec2c49 university of tokyo + ec2ce2 apple, inc. ec2e4e hitachi-lg data storage inc - ec3091 cisco systems, inc. - ec3586 apple + ec2e98 azurewave technology inc. + ec3091 cisco systems, inc + ec316d hansgrohe + ec3586 apple, inc. + ec363f markov corporation + ec3873 juniper networks + ec388f huawei technologies co.,ltd ec3bf0 novelsat + ec3c5a shen zhen heng sheng hui digital technology co.,ltd + ec3c88 mcnex co.,ltd. + ec3cbb huawei device co., ltd. + ec3dfd shenzhen bilian electronic co.,ltd ec3e09 performance designed products, llc + ec3eb3 zyxel communications corporation + ec3ef7 juniper networks ec3f05 institute 706, the second academy china aerospace science & industry corp + ec4118 xiaomi electronics,co.,ltd + ec42b4 adc corporation ec42f0 adl embedded solutions, inc. + ec438b yaptv ec43e6 awcer ltd. ec43f6 zyxel communications corporation - ec4476 cisco systems, inc. + ec4476 cisco systems, inc ec4644 ttk sas ec4670 meinberg funkuhren gmbh & co. kg ec473c redwire, llc - ec4993 qihan technology co., ltd + ec4993 qihan technology co., ltd ec4c4d zao npk rotek + ec4d3e beijing xiaomi mobile software co., ltd + ec4d47 huawei technologies co.,ltd + ec4f82 calix inc. + ec51bc guangdong oppo mobile telecommunications corp.,ltd + ec52dc world media and technology corp. ec542e shanghai ximei electronic technology co. ltd ec55f9 hon hai precision ind. co.,ltd. + ec5623 huawei technologies co.,ltd + ec570d afe inc. + ec58ea ruckus wireless + ec59e7 microsoft corporation + ec5a86 yulong computer telecommunication scientific (shenzhen) co.,ltd + ec5b73 advanced & wise technology corp. + ec5c68 chongqing fugui electronics co.,ltd. ec5c69 mitsubishi heavy industries mechatronics systems,ltd. + ec5f23 qinghai kimascend electronics technology co. ltd. + ec60e0 avi-on labs ec6264 global411 internet services, llc + ec63d7 intel corporate ec63e5 epboard design llc + ec63ed hyundai autoever corp. + ec6488 honor device co., ltd. + ec64e7 mocacare corporation + ec65cc panasonic automotive systems company of america ec66d1 b&w group ltd + ec6881 palo alto networks + ec6c9a arcadyan corporation ec6c9f chengdu volans technology co.,ltd + ec6cb5 zte corporation + ec6f0b fadu, inc. + ec7097 arris group, inc. ec71db shenzhen baichuan digital technology co., ltd. + ec74ba hirschmann automation and control gmbh + ec753e huawei technologies co.,ltd + ec75ed citrix systems, inc. + ec7949 fujitsu limited + ec79f2 startel ec7c74 justone technologies co., ltd. - ec7d9d mei + ec7cb6 samsung electronics co.,ltd + ec7d11 vivo mobile communication co., ltd. + ec7d9d cpi + ec7e91 itel mobile limited + ec7fc6 eccel corporation sas + ec8009 novasparks + ec8193 logitech, inc + ec8263 zte corporation + ec8350 microsoft corporation ec836c rm tech co., ltd. - ec852f apple - ec888f tp-link technologies co., ltd. + ec83d5 gird systems inc + ec84b4 cig shanghai co ltd + ec852f apple, inc. + ec888f tp-link technologies co.,ltd. + ec8892 motorola mobility llc, a lenovo company + ec8914 huawei technologies co.,ltd ec89f5 lenovo mobile communication technology ltd. + ec8a4c zte corporation + ec8ac7 fiberhome telecommunication technologies co.,ltd + ec8c9a huawei technologies co.,ltd + ec8ca2 ruckus wireless ec8ead dlx + ec8eae nagravision sa + ec8eb5 hewlett packard ec9233 eddyfi ndt inc ec9327 memmert gmbh + co. kg + ec9365 mapper.ai, inc. + ec93ed ddos-guard ltd ec9681 2276427 ontario inc + ec97b2 sumec machinery & electric co.,ltd. ec986c lufft mess- und regeltechnik gmbh ec98c1 beijing risbo network technology co.,ltd ec9a74 hewlett packard ec9b5b nokia corporation - ec9ecd emerson network power and embedded computing + ec9b8b hewlett packard enterprise + ec9bf3 samsung electro-mechanics(thailand) + ec9c32 sichuan ai-link technology co., ltd. + ec9ecd artesyn embedded technologies + ec9f0d ieee registration authority + eca1d1 huawei technologies co.,ltd eca29b kemppi oy - eca86b elitegroup computer systems co., ltd. + eca5de onyx wifi inc + eca86b elitegroup computer systems co.,ltd. + eca940 arris group, inc. + eca9fa guangdong genius technology co., ltd. + ecaa25 samsung electronics co.,ltd + ecaaa0 pegatron corporation + ecadb8 apple, inc. + ecade0 d-link international + ecaf97 git + ecb0e1 ciena corporation ecb106 acuro networks, inc + ecb1d7 hewlett packard + ecb313 shenzhen gongjin electronics co.,lt + ecb4e8 wistron mexico sa de cv ecb541 shinano e and e co.ltd. + ecb5fa philips lighting bv + ecb870 beijing heweinet technology co.,ltd. + ecb907 cloudgenix inc + ecb970 ruijie networks co.,ltd + ecbafe giroptic ecbbae digivoice tecnologia em eletronica ltda ecbd09 fusion electronics ltd + ecbd1d cisco systems, inc + ecbe5f vestel elektronik san ve tic. a.Ş. + ecbedd sagemcom broadband sas + ecc01b huawei technologies co.,ltd + ecc06a powerchord group limited + ecc302 humax co., ltd. ecc38a accuenergy (canada) inc - ecc882 cisco systems, inc. + ecc40d nintendo co.,ltd + ecc57f suzhou pairlink network technology + ecc5d2 huawei device co., ltd. + ecc882 cisco systems, inc + ecc89c hangzhou hikvision digital technology co.,ltd. + eccb30 huawei technologies co.,ltd eccd6d allied telesis, inc. + ecce13 cisco systems, inc + ecced7 apple, inc. ecd00e miraerecognition co., ltd. ecd040 gea farm technologies gmbh + ecd09f xiaomi communications co ltd ecd19a zhuhai liming industries co., ltd + ecd68a shenzhen jmicron intelligent technology developmen ecd925 rami ecd950 irt sa + ecd9d1 shenzhen tg-net botone technology co.,ltd. + ecdb86 api-k ecde3d lamprey networks, inc. - ece09b samsung electronics co., ltd - ece1a9 cisco + ecdf3a vivo mobile communication co., ltd. + ece09b samsung electronics co.,ltd + ece154 beijing unisound information technology co.,ltd. + ece1a9 cisco systems, inc + ece2fd skg electric group(thailand) co., ltd. ece512 tado gmbh ece555 hirschmann automation ece744 omntec mfg. inc @@ -18631,412 +28419,1109 @@ exit ece915 sti ltd ece9f8 guang zhou tri-sun electronics technology co., ltd ecea03 darfon lighting corp + ecebb8 hewlett packard enterprise + eceed8 ztlx network technology co.,ltd ecf00e abocom + ecf0fe zte corporation + ecf22b tecno mobile limited ecf236 neomontana electronics + ecf342 guangdong oppo mobile telecommunications corp.,ltd ecf35b nokia corporation - ecf4bb dell inc + ecf451 arcadyan corporation + ecf4bb dell inc. + ecf6bd sncf mobilitÉs ecf72b hd digital tech co., ltd. + ecf8eb sichuan tianyi comheart telecomco., ltd + ecfa03 fca + ecfa5c beijing xiaomi electronics co., ltd. ecfaaa the ims company + ecfabc espressif inc. + ecfaf4 senra tech pvt. ltd ecfc55 a. eberle gmbh & co. kg ecfe7e blueradios, inc. f0007f janz - contadores de energia, sa + f0016e tianyi telecom terminals company limited f0022b chrontel f00248 smartebuilding + f0038c azurewave technology inc. f00786 shandong bittel electronics co., ltd + f008d1 espressif inc. f008f1 samsung electronics co.,ltd + f00d5c jinqianmao technology co.,ltd. + f00df5 acoma medical industry co,. ltd. + f00e1d megafone limited + f00ebf zettahash inc. + f00fec huawei technologies co.,ltd + f01090 new h3c technologies co., ltd + f010ab china mobile (hangzhou) information technology co., ltd. + f013c1 hannto technology co., ltd f013c3 shenzhen fenda technology co., ltd f015a0 kyungdong one co., ltd. - f01c13 lg electronics - f01faf dell inc + f015b9 playfusion limited + f01628 technicolor (china) technology co., ltd. + f0182b lg chem + f01898 apple, inc. + f01b6c vivo mobile communication co., ltd. + f01c13 lg electronics (mobile communications) + f01c2d juniper networks + f01d2d cisco systems, inc + f01dbc microsoft corporation + f01e34 orico technologies co., ltd + f01faf dell inc. f0219d cal-comp electronics & communications company ltd. + f021e0 eero inc. + f0224e esan electronic co. f02329 showa denki co.,ltd. + f023ae ampak technology,inc. + f023b9 ieee registration authority f02405 opus high technology corporation f02408 talaris (sweden) ab - f02572 cisco systems, inc. - f025b7 samsung electro mechanics co., ltd. - f0264c dr. sigrist ag - f02765 murata manufactuaring co.,ltd. - f02929 cisco + f02475 apple, inc. + f02572 cisco systems, inc + f0258e huawei technologies co.,ltd + f025b7 samsung electro-mechanics(thailand) + f02624 wafa technologies co., ltd. + f0264c sigrist-photometer ag + f0272d amazon technologies inc. + f02745 f-secure corporation + f02765 murata manufacturing co., ltd. + f02929 cisco systems, inc + f02a23 creative next design f02a61 waldo networks, inc. + f02e51 casa systems + f02f4b apple, inc. + f02f74 asustek computer inc. + f02fa7 huawei technologies co.,ltd f02fd8 bi2-vision f0321a mita-teknik a/s + f033e5 huawei technologies co.,ltd + f03404 tct mobile ltd f037a1 huike electronics (shenzhen) co., ltd. + f03965 samsung electronics co.,ltd f03a4b bloombase, inc. f03a55 omega elektronik as + f03d03 tecno mobile limited + f03d29 actility + f03e90 ruckus wireless + f03ebf gogoro taiwan limited + f03f95 huawei technologies co.,ltd f03ff8 r l drake + f0407b fiberhome telecommunication technologies co.,ltd + f041c6 heat tech company, ltd. + f041c8 ieee registration authority + f0421c intel corporate + f042f5 huawei device co., ltd. f04335 dvn(shanghai)ltd. + f04347 huawei technologies co.,ltd + f045da texas instruments + f0463b comcast cable corporation + f04a02 cisco systems, inc f04a2b pyramid computer gmbh + f04b3a juniper networks f04b6a scientific production association siberian arsenal, ltd. f04bf2 jtech communications, inc. + f04cd5 maxlinear, inc f04da2 dell inc. - f04f7c + f04f7c amazon technologies inc. + f05136 tct mobile ltd + f051ea fitbit, inc. + f05494 honeywell connected building + f05501 huawei device co., ltd. f05849 careview communications f05a09 samsung electronics co.,ltd + f05b7b samsung electronics co.,ltd + f05c19 aruba, a hewlett packard enterprise company + f05c77 google, inc. + f05cd5 apple, inc. f05d89 dycon limited f05dc8 duracell powermat f05f5a getriebebau nord gmbh and co. kg f06130 advantage pharmacy services, llc f0620d shenzhen egreat tech corp.,ltd + f0625a realme chongqing mobile telecommunications corp.,ltd. f06281 procurve networking by hp + f063f9 huawei technologies co.,ltd + f06426 extreme networks, inc. + f065c2 yanfeng visteon electronics technology (shanghai) co.,ltd. f065dd primax electronics ltd. + f06728 guangdong oppo mobile telecommunications corp.,ltd f06853 integrated corporation + f06865 taicang t&w electronics f06bca samsung electronics co.,ltd + f06d78 guangdong oppo mobile telecommunications corp.,ltd + f06e0b microsoft corporation + f06e32 microtel innovation s.r.l. + f06f46 ubiik f0728c samsung electronics co.,ltd + f072ea google, inc. f073ae peak-system technik + f07485 ngd systems, inc. + f074e4 thundercomm technology co., ltd + f0761c compal information (kunshan) co., ltd. + f0766f apple, inc. f07765 sourcefire, inc + f077c3 intel corporate f077d0 xcellen + f07807 apple, inc. + f07816 cisco systems, inc + f07959 asustek computer inc. + f07960 apple, inc. + f079e8 guangdong oppo mobile telecommunications corp.,ltd f07bcb hon hai precision ind. co.,ltd. + f07cc7 juniper networks f07d68 d-link corporation + f07f06 cisco systems, inc f07f0c leopold kostal gmbh &co. kg + f08173 amazon technologies inc. + f08175 sagemcom broadband sas f081af irz automation technologies ltd - f08261 sagemcom + f08261 sagemcom broadband sas f0842f adb broadband italia f084c9 zte corporation + f085c1 shenzhen rf-link technology co.,ltd. + f08620 arcadyan corporation f08a28 jiangsu hengsion electronic s and t co.,ltd + f08a76 samsung electronics co.,ltd f08bfe costel.,co.ltd - f08cfb fiberhome telecommunication tech.co.,ltd. + f08cfb fiberhome telecommunication technologies co.,ltd f08edb velocloud networks f0921c hewlett packard + f092b4 sichuan tianyi comheart telecomco., ltd f0933a nxtconect f093c5 garland technology + f095f1 carl zeiss ag + f097e5 tamio, inc + f09838 huawei technologies co.,ltd + f0989d apple, inc. + f09919 garmin international + f099b6 apple, inc. + f099bf apple, inc. + f09a51 shanghai viroyal electronic technology company limited + f09bb8 huawei technologies co.,ltd f09cbb raonthink inc. - f09ce9 aerohive networks inc - f0a225 + f09cd7 guangzhou blue cheetah intelligent technology co., ltd. + f09ce9 extreme networks, inc. + f09e4a intel corporate + f09e63 cisco systems, inc + f09fc2 ubiquiti networks inc. + f09ffc sharp corporation + f0a225 amazon technologies inc. + f0a35a apple, inc. + f0a3b2 hui zhou gaoshengda technology co.,ltd f0a764 gst co., ltd. + f0a7b2 futaba corporation + f0a968 antailiye technology co.,ltd + f0aa0b arra networks/ spectramesh + f0ab54 mitsumi electric co.,ltd. f0aca4 hbc-radiomatic + f0acd7 ieee registration authority f0ad4e globalscale technologies, inc. f0ae51 xi3 corp - f0b479 apple + f0af50 phantom intelligence + f0af85 arris group, inc. + f0b014 avm audiovisuelles marketing und computersysteme gmbh + f0b022 toho electronics inc. + f0b052 ruckus wireless + f0b0e7 apple, inc. + f0b107 ericsson ab + f0b11d nokia + f0b2e5 cisco systems, inc + f0b31e universal electronics, inc. + f0b3ec apple, inc. + f0b429 xiaomi communications co ltd + f0b479 apple, inc. + f0b4d2 d-link international + f0b5b7 disruptive technologies research as + f0b5d1 texas instruments f0b6eb poslab technology co., ltd. + f0b968 itel mobile limited f0bcc8 maxid (pty) ltd + f0bcc9 pfu limited + f0bd2e h+s polatis ltd f0bdf1 sipod inc. f0bf97 sony corporation f0c1f1 apple, inc. f0c24c zhejiang feiyue digital technology co., ltd f0c27c mianyang netop telecom equipment co.,ltd. + f0c371 apple, inc. + f0c42f huawei device co., ltd. + f0c77f texas instruments + f0c850 huawei technologies co.,ltd f0c88c leddartech inc. - f0cba1 apple + f0c9d1 gd midea air-conditioning equipment co.,ltd. + f0cba1 apple, inc. + f0d08c tct mobile ltd f0d14f linear llc - f0d1a9 apple + f0d1a9 apple, inc. + f0d1b8 ledvance + f0d2f1 amazon technologies inc. f0d3a7 cobaltray co., ltd f0d3e7 sensometrix sa + f0d4e2 dell inc. + f0d4f6 lars thrane a/s + f0d4f7 varram system + f0d5bf intel corporate + f0d657 echosens f0d767 axema passagekontroll ab + f0d7aa motorola mobility llc, a lenovo company + f0d7af ieee registration authority + f0d7dc wesine (wuhan) technology co., ltd. + f0d9b2 exo s.a. f0da7c rlh industries,inc. f0db30 yottabyte - f0dbf8 apple - f0dce2 apple + f0dbe2 apple, inc. + f0dbf8 apple, inc. + f0dce2 apple, inc. f0de71 shanghai edo technologies co.,ltd. f0deb9 shanghai y&y electronics co., ltd - f0def1 wistron infocomm (kunshan)co + f0def1 wistron infocomm (zhongshan) corporation + f0e3dc tecon mt, llc + f0e4a2 huawei technologies co.,ltd f0e5c3 drägerwerk ag & co. kg aa f0e77e samsung electronics co.,ltd f0ebd0 shanghai feixun communication co.,ltd. f0ec39 essec f0ed1e bilkon bilgisayar kontrollu cih. im.ltd. + f0ee10 samsung electronics co.,ltd + f0ee58 pace telematics gmbh f0eebb vipar gmbh + f0ef86 google, inc. + f0efd2 tf payment service co., ltd f0f002 hon hai precision ind. co.,ltd. + f0f08f nextek solutions pte ltd + f0f0a4 amazon technologies inc. + f0f249 hitron technologies. inc f0f260 mobitec ab + f0f336 tp-link technologies co.,ltd. + f0f564 samsung electronics co.,ltd f0f5ae adaptrum inc. - f0f61c apple + f0f61c apple, inc. f0f644 whitesky science & technology co.,ltd. f0f669 motion analysis corporation - f0f755 cisco systems, inc. + f0f6c1 sonos, inc. + f0f755 cisco systems, inc f0f7b3 phorm + f0f7e7 huawei technologies co.,ltd f0f842 keebox, inc. + f0f8f2 texas instruments f0f9f7 ies gmbh & co. kg - f0fda0 acurix networks lp + f0fac7 huawei device co., ltd. + f0fcc8 arris group, inc. + f0fda0 acurix networks pty ltd + f0fe6b shanghai high-flying electronics technology co., ltd + f0fee7 huawei device co., ltd. + f40223 pax computer technology(shenzhen) ltd. + f40228 samsung electro-mechanics(thailand) + f40270 dell inc. + f40304 google, inc. f40321 benext b.v. + f4032a amazon technologies inc. + f4032f reduxio systems + f40343 hewlett packard enterprise f4044c valencetech limited + f40616 apple, inc. + f40669 intel corporate f4068d devolo ag - f40b93 research in motion + f406a5 hangzhou bianfeng networking technology co., ltd. + f409d8 samsung electro-mechanics(thailand) + f40a4a indusnet communication technology co.,ltd + f40b93 blackberry rts + f40b9f cig shanghai co ltd + f40e01 apple, inc. + f40e11 ieee registration authority + f40e22 samsung electronics co.,ltd + f40e83 arris group, inc. + f40f1b cisco systems, inc + f40f24 apple, inc. f40f9b wavelink + f41535 spon communication technology co.,ltd + f41563 f5 networks, inc. f415fd shanghai pateo electronic equipment manufacturing co., ltd. - f41ba1 apple + f417b8 airties wireless networks + f419e2 volterra + f41ba1 apple, inc. + f41c95 beijing yunyi times technology co,.ltd + f41d6b huawei technologies co.,ltd f41e26 simon-kaloi engineering + f41e5e rtbrick inc. f41f0b yamabishi corporation - f41fc2 cisco + f41f88 zte corporation + f41fc2 cisco systems, inc f42012 cuciniale gmbh + f42833 mmpc inc. + f42853 zioncom electronics (shenzhen) ltd. f42896 specto paineis eletronicos ltda + f42981 vivo mobile communication co., ltd. + f42a7d tp-link technologies co.,ltd. + f42b48 ubiqam + f42c56 senor tech co ltd + f42e7f aruba, a hewlett packard enterprise company + f4308b xiaomi communications co ltd + f430b9 hewlett packard + f431c3 apple, inc. + f4323d sichuan tianyi kanghe communications co., ltd + f43328 cimcon lighting inc. + f434f0 apple, inc. f436e1 abilis systems sarl - f437b7 apple + f437b7 apple, inc. f43814 shanghai howell electronic co.,ltd + f43909 hewlett packard f43d80 fag industrial services gmbh - f43e61 shenzhen gongjin electronics co., ltd + f43e61 shenzhen gongjin electronics co.,lt + f43e66 bee computing (hk) limited f43e9d benu networks, inc. + f44156 arrikto inc. + f4419e huawei device co., ltd. f44227 s & s research inc. + f4428f samsung electronics co.,ltd f44450 bnd co., ltd. + f44588 huawei technologies co.,ltd f445ed portable innovation technology ltd. + f44713 leading public performance co., ltd. f4472a nanjing rousing sci. and tech. industrial co., ltd f44848 amscreen group ltd + f44955 mimo tech co., ltd. + f449ef emstone + f44b2a cisco spvtg + f44c70 skyworth digital technology(shenzhen) co.,ltd + f44c7f huawei technologies co.,ltd + f44d17 goldcard high-tech co.,ltd. + f44d30 elitegroup computer systems co.,ltd. + f44e05 cisco systems, inc + f44ee3 intel corporate f44efd actions semiconductor co.,ltd.(cayman islands) + f44fd3 shenzhen hemuwei technology co.,ltd f450eb telechips inc f45214 mellanox technologies, inc. + f45420 tellescom industria e comercio em telecomunicacao f45433 rockwell automation f45595 hengbao corporation ltd. - f4559c huawei technologies co., ltd + f4559c huawei technologies co.,ltd f455e0 niceway cnc technology co.,ltd.hunan province + f4573e fiberhome telecommunication technologies co.,ltd f45842 boxx tv ltd + f45b73 wanjiaan interconnected technology co., ltd + f45c89 apple, inc. + f45eab texas instruments f45f69 matsufu electronics distribution company f45fd4 cisco spvtg f45ff7 dq technology inc. f4600d panoptic technology, inc + f460e2 xiaomi communications co ltd + f462d0 not for radio, llc + f4631f huawei technologies co.,ltd f46349 diffon corporation + f4645d toshiba + f465a6 apple, inc. + f4672d shenzhen topstar technology company + f46942 askey computer corp + f469d5 ieee registration authority + f46a92 shenzhen fast technologies co.,ltd f46abc adonit corp. ltd. + f46ad7 microsoft corporation + f46b8c hon hai precision ind. co., ltd. + f46bef sagemcom broadband sas f46d04 asustek computer inc. f46de2 zte corporation + f46e24 nec personal computers, ltd. + f46e95 extreme networks, inc. + f46f4e echowell + f46fa4 physik instrumente gmbh & co. kg + f46fed fiberhome telecommunication technologies co.,ltd + f470ab vivo mobile communication co., ltd. + f47190 samsung electronics co.,ltd + f47335 logitech far east f473ca conversion sound inc. - f47626 viltechmeda uab + f47488 new h3c technologies co., ltd + f47626 viltechmeda uab + f47960 huawei technologies co.,ltd f47a4e woojeon&handan f47acc solidfire, inc. - f47b5e samsung eletronics co., ltd - f47f35 cisco systems, inc. + f47b5e samsung electronics co.,ltd + f47def samsung electronics co.,ltd + f47f35 cisco systems, inc f48139 canon inc. + f483cd tp-link technologies co.,ltd. + f483e1 shanghai clouder semiconductor co.,ltd + f4844c texas instruments + f485c6 fdt technologies f48771 infoblox + f487c5 huawei device co., ltd. + f48b32 xiaomi communications co ltd + f48c50 intel corporate + f48ceb d-link international f48e09 nokia corporation + f48e38 dell inc. + f48e92 huawei technologies co.,ltd f490ca tensorcom + f490cb ieee registration authority f490ea deciso b.v. + f4911e zhuhai ewpe information technology inc + f492bf ubiquiti networks inc. + f4939f hon hai precision ind. co., ltd. f49461 nexgen storage f49466 countmax, ltd + f4951b hefei radio communication technology co., ltd + f49634 intel corporate + f49651 nakayo inc + f497c2 nebulon inc f499ac weber schraubautomaten gmbh - f49f54 samsung electronics + f49c12 structab ab + f49eef taicang t&w electronics + f49f54 samsung electronics co.,ltd + f49ff3 huawei technologies co.,ltd f4a294 eagle world development co., limited + f4a4d6 huawei technologies co.,ltd f4a52a hawa technologies inc - f4acc1 cisco systems, inc. + f4a59d huawei device co., ltd. + f4a739 juniper networks + f4a80d wistron infocomm(kunshan)co.,ltd. + f4a997 canon inc. + f4acc1 cisco systems, inc + f4afe7 apple, inc. f4b164 lightning telecommunications technology co. ltd + f4b1c2 zhejiang dahua technology co., ltd. + f4b301 intel corporate f4b381 windowmaster a/s + f4b520 biostar microtech international corp. f4b52f juniper networks - f4b549 yeastar technology co., ltd. + f4b549 xiamen yeastar information technology co., ltd. + f4b5aa zte corporation + f4b5bb ceragon networks + f4b688 plantronics, inc. f4b6e5 terrasem co.,ltd f4b72a time interconnect ltd + f4b78d huawei technologies co.,ltd + f4b7b3 vivo mobile communication co., ltd. f4b7e2 hon hai precision ind. co.,ltd. + f4b85e texas instruments + f4b8a7 zte corporation + f4bc97 shenzhen crave communication co., ltd + f4bcda shenzhen jingxun software telecommunication technology co.,ltd f4bd7c chengdu jinshi communication co., ltd + f4bd9e cisco systems, inc + f4beec apple, inc. + f4bf80 huawei technologies co.,ltd + f4bfa8 juniper networks + f4c114 technicolor ch usa inc. + f4c248 samsung electronics co.,ltd + f4c447 coagent international enterprise limited + f4c4d6 shenzhen xinfa electronic co.,ltd + f4c613 alcatel-lucent shanghai bell co., ltd f4c6d7 blackned gmbh - f4c714 shenzhen huawei communication technologies co., ltd - f4c795 wey elektronik ag - f4cae5 freebox sa + f4c714 huawei technologies co.,ltd + f4c795 wey technology ag + f4c7aa marvell semiconductors + f4c7c8 kelvin inc. + f4ca24 freebit co., ltd. + f4cae5 freebox sas + f4cb52 huawei technologies co.,ltd + f4cc55 juniper networks f4cd90 vispiron rotec gmbh - f4ce46 hewlett-packard company - f4cfe2 cisco - f4d9fb samsung electronics co., ltd + f4ce36 nordic semiconductor asa + f4ce46 hewlett packard + f4cfa2 espressif inc. + f4cfe2 cisco systems, inc + f4d032 yunnan ideal information&technology.,ltd + f4d108 intel corporate + f4d261 semocon co., ltd + f4d488 apple, inc. + f4d620 guangdong oppo mobile telecommunications corp.,ltd + f4d7b2 lgs innovations, llc + f4d9c6 unionman technology co.,ltd + f4d9fb samsung electronics co.,ltd + f4dbe3 apple, inc. + f4dbe6 cisco systems, inc + f4dc41 youngzone culture (shanghai) corp f4dc4d beijing ccd digital technology co., ltd + f4dca5 dawon dns f4dcda zhuhai jiahe communication technology co., limited - f4dcf9 huawei technologies co., ltd + f4dcf9 huawei technologies co.,ltd + f4dd9e gopro + f4de0c espod ltd. + f4deaf huawei technologies co.,ltd + f4e11e texas instruments f4e142 delta elektronika bv + f4e204 traqueur + f4e3fb huawei technologies co.,ltd + f4e4ad zte corporation + f4e578 llc proizvodstvennaya kompania transservice + f4e5f2 huawei technologies co.,ltd f4e6d7 solar power technologies, inc. - f4ea67 cisco systems, inc. - f4ec38 tp-link technologies co., ltd. - f4f15a apple + f4e926 tianjin zanpu technology inc. + f4e9d4 qlogic corporation + f4ea67 cisco systems, inc + f4eab5 extreme networks, inc. + f4eb38 sagemcom broadband sas + f4eb9f ellu company 2019 sl + f4ec38 tp-link technologies co.,ltd. + f4ed5f shenzhen ktc technology group + f4ee14 mercury communication technologies co.,ltd. + f4ef9e sgsg science & technology co. ltd + f4f15a apple, inc. + f4f197 emtake inc + f4f1e1 motorola mobility llc, a lenovo company + f4f26d tp-link technologies co.,ltd. + f4f3aa jbl gmbh & co. kg + f4f524 motorola mobility llc, a lenovo company f4f5a5 nokia corporation - f4f951 apple + f4f5d8 google, inc. + f4f5db xiaomi communications co ltd + f4f5e8 google, inc. + f4f646 dediprog technology co. ltd. + f4f951 apple, inc. + f4fbb8 huawei technologies co.,ltd f4fc32 texas instruments - f80113 huawei technologies co., ltd + f4fcb1 jj corp + f4fd2b zoyi company + f4fefb samsung electronics co.,ltd + f80113 huawei technologies co.,ltd + f80278 ieee registration authority f80332 khomp + f80377 apple, inc. + f8042e samsung electro-mechanics(thailand) f8051c drs imaging and targeting solutions + f8084f sagemcom broadband sas f80bbe arris group, inc. + f80bcb cisco systems, inc f80bd0 datang telecom communication terminal (tianjin) co., ltd. - f80cf3 lg electronics + f80cf3 lg electronics (mobile communications) + f80d43 hon hai precision ind. co.,ltd. + f80d60 canon inc. + f80dac hp inc. f80dea zycast technology inc. - f80f41 wistron infocomm(zhongshan) corporation + f80df0 zte corporation + f80df1 sontex sa + f80f41 wistron infocomm (zhongshan) corporation + f80f6f cisco systems, inc f80f84 natural security sas + f80ff9 google, inc. f81037 atopia systems, lp - f81547 avaya, inc + f81093 apple, inc. + f81308 nokia + f81547 avaya inc f81654 intel corporate - f81a67 tp-link technologies co., ltd. + f81897 2wire inc + f81a2b google, inc. + f81a67 tp-link technologies co.,ltd. + f81b04 zhong shan city richsound electronic industrial ltd f81ce5 telefonbau behnke gmbh + f81d0f hitron technologies. inc + f81d78 ieee registration authority + f81d90 solidwintech f81d93 longdhua(beijing) controls technology co.,ltd - f81edf apple + f81e6f ebg compleo gmbh + f81edf apple, inc. + f81f32 motorola mobility llc, a lenovo company + f82055 green information system f82285 cypress technology co., ltd. - f82793 apple, inc + f82387 shenzhen horn audio co.,ltd. + f823b2 huawei technologies co.,ltd + f82441 yeelink + f8272e mercku + f82793 apple, inc. + f82819 liteon technology corporation f82bc8 jiangsu switter co., ltd + f82c18 2wire inc + f82d7c apple, inc. + f82dc0 arris group, inc. + f82e3f huawei technologies co.,ltd + f82e8e nanjing kechen electric co., ltd. f82edb rtw gmbh & co. kg + f82f08 molex cms f82f5b egauge systems llc + f82f65 huawei device co., ltd. + f82f6a itel mobile limited f82fa8 hon hai precision ind. co.,ltd. + f83002 texas instruments f83094 alcatel-lucent telecom limited f8313e endeavour gmbh + f832e4 asustek computer inc. + f83331 texas instruments f83376 good mind innovation co., ltd. + f83441 intel corporate f83553 magenta research ltd. f835dd gemtek technology co., ltd. + f8369b texas instruments + f83880 apple, inc. + f83b1d technicolor ch usa inc. + f83b7e huawei device co., ltd. + f83cbf botato electronics sdn bhd f83d4e softlink automation system co., ltd - f83dff huawei technologies co., ltd + f83dff huawei technologies co.,ltd + f83e95 huawei technologies co.,ltd + f83f51 samsung electronics co.,ltd f842fb yasuda joho co.,ltd. + f844e3 taicang t&w electronics f845ad konka group co., ltd. + f845c4 shenzhen netforward micro-electronic co., ltd. + f8461c sony interactive entertainment inc. f8462d syntec incorporation f8472d x2gen digital corp. ltd f84897 hitachi, ltd. + f848fd china mobile group device co.,ltd. f84a73 eumtech co., ltd f84a7f innometriks inc f84abf huawei technologies co.,ltd - f84f57 cisco + f84cda huawei technologies co.,ltd + f84d33 fiberhome telecommunication technologies co.,ltd + f84dfc hangzhou hikvision digital technology co.,ltd. + f84e73 apple, inc. + f84f57 cisco systems, inc + f84fad hui zhou gaoshengda technology co.,ltd + f8501c tianjin geneuo technology co.,ltd f85063 verathon + f85128 simplisafe f8516d denwa technology corp. f852df vnl europe ab + f85329 huawei technologies co.,ltd f854af eci telecom ltd. + f854b8 amazon technologies inc. + f855cd visteon corporation f8572e core brands, llc + f85971 intel corporate + f85a00 sanford lp + f85b3b askey computer corp + f85b9c sb systems co.,ltd f85bc9 m-cube spa f85c45 ic nexus co. ltd. + f85c4d nokia + f85c7d shenzhen honesty electronics co.,ltd. + f85e3c shenzhen zhibotong electronics co.,ltd + f85e42 technicolor ch usa inc. + f85ea0 intel corporate f85f2a nokia corporation + f860f0 aruba, a hewlett packard enterprise company + f86214 apple, inc. f862aa xn systems + f8633f intel corporate + f86465 anova applied electronics, inc. + f864b8 zte corporation f86601 suzhou chi-tek information technology co., ltd - f866f2 cisco systems, inc. + f8665a apple, inc. + f866d1 hon hai precision ind. co.,ltd. + f866f2 cisco systems, inc f86971 seibu electric co., + f86bd9 cisco systems, inc + f86c03 shenzhen teleone technology co., ltd + f86ce1 taicang t&w electronics + f86d73 zengge co., limited f86ecf arcx inc + f86eee huawei technologies co.,ltd + f86fc1 apple, inc. + f86fde shenzhen goodix technology co.,ltd. f871fe the goldman sachs group, inc. - f872ea cisco + f872ea cisco systems, inc + f87394 netgear + f873a2 avaya inc + f87588 huawei technologies co.,ltd + f875a4 lcfc(hefei) electronics technology co., ltd f8769b neopis co., ltd. + f877b8 samsung electronics co.,ltd + f8790a arris group, inc. + f87a41 cisco systems, inc + f87aef rosonix technology, inc. + f87b20 cisco systems, inc f87b62 fastwel international co., ltd. taiwan branch f87b7a arris group, inc. f87b8c amped wireless + f88096 elsys equipamentos eletrônicos ltda f8811a overkiz + f88200 captioncall + f88479 yaojin technology(shenzhen)co.,ltd + f884f2 samsung electronics co.,ltd + f885f9 calix inc. + f887f1 apple, inc. + f8893c inventec appliances corp. + f889d2 cloud network technology singapore pte. ltd. + f88a3c ieee registration authority + f88a5e texas instruments + f88b37 arris group, inc. f88c1c kaishun electronic technology co., ltd. beijing + f88c21 tp-link technologies co.,ltd. f88def tenebraex f88e85 comtrend corporation - f88fca google fiber, inc + f88f07 samsung electronics co.,ltd + f88fca google, inc. + f89066 nain inc. f8912a glp german light products gmbh + f89173 aedle sas f893f3 volans + f894c2 intel corporate f89550 proton products chengdu ltd + f895c7 lg electronics (mobile communications) + f895ea apple, inc. + f89753 huawei device co., ltd. f897cf daeshin-information technology co., ltd. + f8983a leeman international (hongkong) limited + f898b9 huawei technologies co.,ltd + f898ef huawei technologies co.,ltd + f89910 integrated device technology (malaysia) sdn. bhd. f89955 fortress technology inc + f89a78 huawei technologies co.,ltd f89d0d control technology inc. + f89dbb tintri + f89e28 cisco meraki f89fb8 yazaki energy system corporation f8a03d dinstar technologies co., ltd. + f8a097 arris group, inc. + f8a188 led roadway lighting + f8a26d canon inc. f8a2b4 rhewa-waagenfabrik august freudewald gmbh &co. kg - f8a45f beijing xiaomi communications co.,ltd - f8a963 compal information (kunshan) co., ltd. - f8a9d0 lg electronics + f8a2d6 liteon technology corporation + f8a34f zte corporation + f8a45f xiaomi communications co ltd + f8a5c5 cisco systems, inc + f8a73a cisco systems, inc + f8a763 zhejiang tmall technology co., ltd. + f8a963 compal information (kunshan) co., ltd. + f8a9d0 lg electronics (mobile communications) f8a9de puissance plus + f8aa3f dwnet technologies(suzhou) corporation f8aa8a axview technology (shenzhen) co.,ltd + f8ab05 sagemcom broadband sas + f8abe5 shenzhen worldelite electronics co., ltd + f8ac65 intel corporate f8ac6d deltenna ltd - f8b156 dell inc + f8adcb hmd global oy + f8ae27 john deere electronic solutions + f8af05 huawei device co., ltd. + f8afdb fiberhome telecommunication technologies co.,ltd + f8b156 dell inc. + f8b1dd apple, inc. + f8b2f3 guangzhou bosma technology co.,ltd + f8b46a hewlett packard + f8b568 ieee registration authority f8b599 guangzhou chnavs digital technology co.,ltd - f8bc12 dell inc + f8b797 nec platforms, ltd. + f8b7e2 cisco systems, inc + f8b95a lg innotek + f8bbbf eero inc. + f8bc0e eero inc. + f8bc12 dell inc. + f8bc41 rosslare enterprises limited + f8be0d a2uict co.,ltd. + f8bf09 huawei technologies co.,ltd f8c001 juniper networks f8c091 highgates technology + f8c120 xi'an link-science technology co.,ltd + f8c249 private + f8c288 cisco systems, inc + f8c372 tsuzuki denki + f8c397 nzxt corp. ltd. + f8c39e huawei technologies co.,ltd + f8c4f3 shanghai infinity wireless technologies co.,ltd. f8c678 carefusion - f8d0ac sony computer entertainment inc. + f8c96c fiberhome telecommunication technologies co.,ltd + f8ca59 netcomm wireless + f8cab8 dell inc. + f8cc6e depo electronics ltd + f8cfc5 motorola mobility llc, a lenovo company + f8d027 seiko epson corporation + f8d0ac sony interactive entertainment inc. f8d0bd samsung electronics co.,ltd - f8d111 tp-link technologies co., ltd. + f8d111 tp-link technologies co.,ltd. f8d3a9 axan networks f8d462 pumatronix equipamentos eletronicos ltda. - f8d756 simm tronic limited + f8d478 flextronics tech.(ind) pvt ltd + f8d756 simm tronic limited f8d7bf rev ritter gmbh + f8d9b8 open mesh, inc. + f8da0c hon hai precision ind. co.,ltd. f8dadf ecotech, inc. - f8dae2 beta lasermike + f8dae2 ndc technologies f8daf4 taishan online technology co., ltd. f8db4c pny technologies, inc. f8db7f htc corporation - f8db88 dell inc + f8db88 dell inc. f8dc7a variscite ltd + f8df15 sunitec enterprise co.,ltd f8dfa8 zte corporation - f8e079 motorola mobility llc + f8dfe1 mylight systems + f8e079 motorola mobility llc, a lenovo company + f8e43b asix electronics corporation + f8e44e mcot inc. + f8e4e3 intel corporate f8e4fb actiontec electronics, inc + f8e5cf cgi it uk limited + f8e61a samsung electronics co.,ltd + f8e71e ruckus wireless + f8e7a0 vivo mobile communication co., ltd. f8e7b5 µtech tecnologia ltda + f8e811 huawei technologies co.,ltd + f8e877 harman/becker automotive systems gmbh + f8e903 d-link international + f8e94e apple, inc. f8e968 egker kft. f8ea0a dipl.-math. michael rauch f8eda5 arris group, inc. f8f005 newport media inc. f8f014 rackware inc. - f8f082 orion networks international, inc - f8f1b6 motorola mobility llc + f8f082 nag llc + f8f1b6 motorola mobility llc, a lenovo company + f8f1e6 samsung electronics co.,ltd + f8f21e intel corporate f8f25a g-lab gmbh + f8f464 rawe electonic gmbh + f8f532 arris group, inc. f8f7d3 international communications corporation f8f7ff syn-tech systems inc f8fb2f santur corporation f8fe5c reciprocal labs corp f8fea8 technico japan corporation + f8ff0b electronic technology inc. f8ff5f shenzhen communication technology co.,ltd - fc0012 toshiba samsung storage technolgoy korea corporation + f8ffc2 apple, inc. + fc0012 toshiba samsung storage technolgoy korea corporation + fc017c hon hai precision ind. co.,ltd. fc019e vievu fc01cd fundacion tekniker + fc039f samsung electronics co.,ltd + fc041c guangdong oppo mobile telecommunications corp.,ltd fc0647 cortland research, llc + fc06ed m2motive technology inc. fc07a0 lre medical gmbh + fc084a fujitsu limited fc0877 prentke romich company fc09d8 acteon group fc09f6 guangdong tonze electric co.,ltd - fc0a81 motorola solutions inc. - fc0fe6 sony computer entertainment inc. + fc0a81 extreme networks, inc. + fc0c45 shenzhen superelectron technology co.,ltd. + fc0f4b texas instruments + fc0fe6 sony interactive entertainment inc. fc10bd control sistematizado s.a. + fc10c6 taicang t&w electronics fc1186 logic3 plc fc1349 global apps corp. + fc13f0 bouffalo lab (nanjing) co., ltd. + fc1499 aimore acoustics incorporation fc15b4 hewlett packard fc1607 taian technology(wuxi) co.,ltd. fc1794 intercreative co., ltd + fc183c apple, inc. + fc1910 samsung electronics co.,ltd + fc1928 actions microelectronics co., ltd + fc1999 xiaomi communications co ltd fc19d0 cloud vision networks technology co.,ltd. + fc1a11 vivo mobile communication co., ltd. + fc1bd1 huawei technologies co.,ltd fc1bff v-zug ag + fc1ca1 nokia + fc1d43 apple, inc. fc1d59 i smart cities hk ltd + fc1d84 autobase fc1e16 ipevo corp - fc1f19 samsung electro-mechanics co., ltd. + fc1f19 samsung electro mechanics co., ltd. fc1fc0 eurecam fc229c han kyung i net co.,ltd. - fc253f apple + fc2325 eostek (shenzhen) co., ltd. + fc253f apple, inc. fc27a2 trans electric co., ltd. + fc29f3 mcpay co.,ltd. fc2a54 connected data, inc. + fc2a9c apple, inc. + fc2bb2 actiontec electronics, inc + fc2d5e zte corporation fc2e2d lorom industrial co.ltd. fc2f40 calxeda, inc. + fc2f6b everspin technologies, inc. + fc2faa nokia + fc2fef utt technologies co., ltd. + fc3288 celot wireless co., ltd + fc3342 juniper networks + fc335f polyera + fc3497 asustek computer inc. fc3598 favite inc. fc35e6 visteon corp + fc372b sichuan tianyi comheart telecomco.,ltd + fc3964 itel mobile limited + fc3ce9 tsingtong technologies co, ltd. + fc3d93 longcheer telecommunication limited + fc3da5 arcadyan corporation + fc3f7c huawei technologies co.,ltd fc3fab henan lanxin technology co., ltd - fc4463 universal audio + fc3fdb hewlett packard + fc4009 zte corporation + fc4203 samsung electronics co.,ltd + fc4463 universal audio, inc + fc4482 intel corporate fc4499 swarco lea d.o.o. + fc449f zte corporation fc455f jiangxi shanshui optoelectronic technology co.,ltd + fc4596 compal information (kunshan) co., ltd. + fc45c3 texas instruments fc48ef huawei technologies co.,ltd + fc492d amazon technologies inc. fc4ae9 castlenet technology inc. fc4b1c intersensor s.r.l. + fc4b57 peerless instrument division of curtiss-wright fc4bbc sunplus technology co., ltd. + fc4d8c shenzhen pante electronics technology co., ltd + fc4da6 huawei technologies co.,ltd fc4dd4 universal global scientific industrial co., ltd. + fc4ea4 apple, inc. fc5090 simex sp. z o.o. + fc51a4 arris group, inc. + fc528d technicolor ch usa inc. fc52ce control id + fc539e shanghai wind technologies co.,ltd + fc55dc baltic latvian universal electronics llc + fc584a xiamenshi c-chip technology co., ltd + fc589a cisco systems, inc fc58fa shen zhen shi xin zhong xin technology co.,ltd. + fc5a1d hitron technologies. inc fc5b24 weibel scientific a/s fc5b26 mikrobits + fc5b39 cisco systems, inc fc6018 zhejiang kangtai electric co., ltd. + fc609b new h3c technologies co., ltd fc6198 nec personal products, ltd + fc61e9 fiberhome telecommunication technologies co.,ltd fc626e beijing mdc telecom + fc62b9 alpsalpine co,.ltd + fc643a samsung electronics co.,ltd + fc64ba xiaomi communications co ltd + fc65b3 huawei device co., ltd. + fc65de amazon technologies inc. + fc66cf apple, inc. fc683e directed perception, inc + fc6947 texas instruments + fc698c andreas stihl ag & co. kg + fc6bf0 topwell international holdinds limited fc6c31 lxinstruments gmbh + fc6dc0 bme corporation + fc6dd1 apresia systems, ltd. + fc6fb7 arris group, inc. + fc71fa trane technologies + fc73fb huawei technologies co.,ltd fc7516 d-link international fc75e6 handreamnet + fc7774 intel corporate + fc790b hitachi high technologies america, inc. + fc7c02 phicomm (shanghai) co., ltd. fc7ce7 fci usa llc + fc7d6c hyesung techwin co., ltd + fc7f56 cosyst control systems gmbh + fc7ff1 aruba, a hewlett packard enterprise company fc8329 trei technics - fc8399 avaya, inc - fc8b97 shenzhen gongjin electronics co.,ltd - fc8e7e pace plc + fc8399 avaya inc + fc83c6 n-radio technologies co., ltd. + fc8596 axonne inc. + fc862a huawei device co., ltd. + fc8743 huawei technologies co.,ltd + fc8b97 shenzhen gongjin electronics co.,lt + fc8d3d leapfive tech. ltd. + fc8e5b china mobile iot limited company + fc8e6e streamcctv, llc + fc8e7e arris group, inc. + fc8f7d shenzhen gongjin electronics co.,lt + fc8f90 samsung electronics co.,ltd fc8fc4 intelligent technology inc. + fc90fa independent technologies + fc9114 technicolor ch usa inc. fc923b nokia corporation + fc9435 huawei technologies co.,ltd fc946c ubivelox - fc94e3 technicolor usa inc. - fc9947 cisco + fc94ce zte corporation + fc94e3 technicolor ch usa inc. + fc956a octagon systems corp. + fc9643 juniper networks + fc9947 cisco systems, inc + fc9afa motus global inc. + fc9bc6 sumavision technologies co.,ltd + fc9c98 arlo technology + fc9dd8 beijing tongtongyilian science and technology ltd. fc9fae fidus systems inc - fca13e samsung electronics - fca841 avaya, inc + fc9fe1 conwin.tech. ltd + fca13e samsung electronics co.,ltd + fca183 amazon technologies inc. + fca22a pt. callysta multi engineering + fca386 shenzhen chuangwei-rgb electronics co.,ltd + fca47a ieee registration authority + fca5d0 guangdong oppo mobile telecommunications corp.,ltd + fca621 samsung electronics co.,ltd + fca667 amazon technologies inc. + fca6cd fiberhome telecommunication technologies co.,ltd + fca841 avaya inc + fca89a sunitec enterprise co.,ltd fca9b0 miartech (shanghai),inc. + fca9dc renesas electronics (penang) sdn. bhd. + fcaa14 giga-byte technology co.,ltd. + fcaab6 samsung electronics co.,ltd + fcab90 huawei technologies co.,ltd fcad0f qts networks - fcaf6a conemtech ab - fcb0c4 shanghai dareglobal technologies co., ltd + fcae34 arris group, inc. + fcaf6a qulsar inc + fcafac socionext inc. + fcb0c4 shanghai dareglobal technologies co.,ltd + fcb10d shenzhen tian kun technology co.,ltd. + fcb3bc intel corporate + fcb4e6 askey computer corp + fcb58a wapice ltd. + fcb662 ic holdings llc + fcb698 cambridge industries(group) co.,ltd. + fcb69d zhejiang dahua technology co., ltd. + fcb6d8 apple, inc. + fcb7f0 idaho national laboratory fcbba1 shenzhen minicreate technology co.,ltd + fcbc0e zhejiang cainiao supply chain management co., ltd + fcbc9c vimar spa + fcbcd1 huawei technologies co.,ltd + fcbd67 arista networks + fcbe7b vivo mobile communication co., ltd. + fcc233 asustek computer inc. fcc23d atmel corporation fcc2de murata manufacturing co., ltd. fcc734 samsung electronics co.,ltd fcc897 zte corporation + fccac4 lifehealth, llc fccce4 ascon ltd. + fccd2f ieee registration authority + fccf43 huizhou city huiyang district meisiqi industry development co,.ltd fccf62 ibm corp + fcd2b6 ieee registration authority + fcd436 motorola mobility llc, a lenovo company fcd4f2 the coca cola company fcd4f6 messana air.ray conditioning s.r.l. + fcd5d9 shenzhen sdmc technology co., ltd. fcd6bd robert bosch gmbh + fcd733 tp-link technologies co.,ltd. fcd817 beijing hesun technologies co.ltd. + fcd848 apple, inc. + fcdb21 samsara networks inc fcdb96 enervalley co., ltd + fcdbb3 murata manufacturing co., ltd. + fcdc4a g-wearables corp. fcdd55 shenzhen wewins wireless co.,ltd + fcde90 samsung electronics co.,ltd + fce14f brk brands, inc. fce186 a3m co., ltd fce192 sichuan jinwangtong electronic science&technology co,.ltd fce1d9 stable imaging solutions llc + fce1fb array networks fce23f clay paky spa + fce33c huawei technologies co.,ltd fce557 nokia corporation + fce66a industrial software co + fce806 edifier international fce892 hangzhou lancable technology co.,ltd + fce998 apple, inc. + fcea50 integrated device technology (malaysia) sdn. bhd. + fcecda ubiquiti networks inc. fcedb9 arrayent + fceee6 formike electronic co., ltd + fcf136 samsung electronics co.,ltd + fcf152 sony corporation fcf1cd optex-fa co.,ltd. + fcf29f china mobile iot limited company fcf528 zyxel communications corporation - fcf647 fiberhome telecommunication tech.co.,ltd. + fcf5c4 espressif inc. + fcf647 fiberhome telecommunication technologies co.,ltd fcf8ae intel corporate fcf8b7 tronteq electronic fcfaf7 shanghai baud data communication co.,ltd. - fcfbfb cisco systems, inc. + fcfbfb cisco systems, inc + fcfc48 apple, inc. fcfe77 hitachi reftechno, inc. + fcfec2 invensys controls uk limited + fcffaa ieee registration authority From 67017e89830356fad212080fb67511a1334fcc50 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 13 Dec 2019 05:23:18 +0000 Subject: [PATCH 210/402] lib/ndb: add submission service to /lib/ndb/commom (thanks Steven Stallion) --- lib/ndb/common | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ndb/common b/lib/ndb/common index 2b49bbf36e..600a06a200 100644 --- a/lib/ndb/common +++ b/lib/ndb/common @@ -253,6 +253,7 @@ tcp=9fs port=564 tcp=whoami port=565 tcp=guard port=566 tcp=ticket port=567 +tcp=submission port=587 tcp=ldaps port=636 tcp=fmclient port=729 tcp=iscsi-system port=860 From 288c748e322fb611c4da3ff94972fd597b20a6a8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:37 +0000 Subject: [PATCH 211/402] sys/lib: fix bzip2, gz and tgz mime types for ip/httpd/httpd --- sys/lib/mimetype | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/lib/mimetype b/sys/lib/mimetype index 780cf65242..98a718f979 100644 --- a/sys/lib/mimetype +++ b/sys/lib/mimetype @@ -21,7 +21,7 @@ .bcpio application x-bcpio - m .bib text plain - y # BibTex input .bmp image bmp - y # bitmapped image -.bz2 application x-bzip2 bzip2 m # bzipped file +.bz2 application x-bzip2 - m # bzipped file .c text plain - y # C program .c++ text plain - y # C++ program .cacert application x-x509-ca-cert - y # DER X.509 CA certificate @@ -53,7 +53,7 @@ .gcd text x-pcs-gcd - y # helper file for .qcp .gif image gif - y .gtar application x-gtar - m -.gz application x-gzip gzip m # gzipped file +.gz application x-gzip - m # gzipped file .h text plain - y # C header file .hdf application x-hdf - y .hdml text x-hdml - y @@ -135,7 +135,7 @@ .texi application x-texinfo - y .texinfo application x-texinfo - y .text text plain - y -.tgz application x-tar gzip m +.tgz application x-tar - m .tif image tiff - y .tiff image tiff - y .toc text plain - y # table of contents From 504d6487adb88cbd8d7d0a008d5cc0c61f53c679 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 11 Apr 2021 11:30:58 +0000 Subject: [PATCH 212/402] sys/lib/tls: import certificate authorities from cURL --- sys/lib/tls/ca.pem | 3228 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3228 insertions(+) create mode 100644 sys/lib/tls/ca.pem diff --git a/sys/lib/tls/ca.pem b/sys/lib/tls/ca.pem new file mode 100644 index 0000000000..3c79c596ee --- /dev/null +++ b/sys/lib/tls/ca.pem @@ -0,0 +1,3228 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Jan 19 04:12:04 2021 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.28. +## SHA256: 3bdc63d1de27058fec943a999a2a8a01fcc6806a611b19221a7727d3d9bbbdfd +## + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz +0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j +Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn +RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O ++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq +/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE +Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM +lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 +yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ +eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW +FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ +7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ +Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM +8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi +FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi +yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c +J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw +sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl +OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV +MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF +JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G3 +================================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC +TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l +ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y +olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t +x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy +EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K +Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur +mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5 +1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp +07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo +FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE +41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu +yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq +KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1 +v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA +8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b +8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r +mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq +1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI +JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV +tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk= +-----END CERTIFICATE----- + +Staat der Nederlanden EV Root CA +================================ +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M +MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl +cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk +SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW +O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r +0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 +Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV +XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr +08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV +0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd +74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx +fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa +ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu +c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq +5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN +b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN +f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi +5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 +WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK +DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy +eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +====================== +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +TrustCor RootCert CA-1 +====================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx +MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu +YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe +VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy +dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq +jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 +pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 +JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h +gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw +/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j +BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 +mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C +qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P +3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +TrustCor RootCert CA-2 +====================== +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w +DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT +eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0 +eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy +MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h +bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0 +IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb +ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk +RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1 +oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb +XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1 +/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q +jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP +eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg +rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU +2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h +Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp +kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv +2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3 +S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw +PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv +DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU +RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE +xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX +RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ +-----END CERTIFICATE----- + +TrustCor ECA-1 +============== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP +MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig +U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw +N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 +MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y +IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR +MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 +xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc +p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ +fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj +YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL +f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF +AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u +/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs +J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC +jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +======================================== +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +============================================== +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +=========================================== +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +GlobalSign Root CA - R6 +======================= +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GC CA +=============================== +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx +9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r +aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW +r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM +LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly +4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr +06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om +3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu +JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM +BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv +fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm +ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b +gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq +4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr +tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo +pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0 +sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql +CFF1pkgl +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG +EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv +b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG +A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk +k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo +7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI +m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm +dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu +ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz +cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl +aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy +5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM +BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ ++YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw +c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da +WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r +n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu +Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ +7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs +gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld +o/DUhgkC +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU +Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP +0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0 +glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa +KaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa +6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj +QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV +2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI +N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x +zPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +UCA Global G2 Root +================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE----- + +UCA Extended Validation Root +============================ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE----- + +Certigna Root CA +================ +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +emSign Root CA - G1 +=================== +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +emSign ECC Root CA - G3 +======================= +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +emSign Root CA - C1 +=================== +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +emSign ECC Root CA - C3 +======================= +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 3 +======================= +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG +A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK +Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 +MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv +bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX +SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz +iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf +jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim +5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe +sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj +0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ +JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u +y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h ++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG +xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN +AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw +W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld +y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov ++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc +eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw +9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 +nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY +hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB +60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq +dBb9HxEGmpv0 +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G4 +========================================= +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +Microsoft ECC Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +Microsoft RSA Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +e-Szigno Root CA 2017 +===================== +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE----- + +certSIGN Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +Trustwave Global Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 +zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf +LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq +stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o +WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ +OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 +Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE +uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm ++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj +ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H +PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H +ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla +4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R +vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd +zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O +856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH +Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu +3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +Trustwave Global ECC P256 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +Trustwave Global ECC P384 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE----- + +NAVER Global Root Certification Authority +========================================= +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE----- From 41dff6fffd6d672b2b9d28fb1ced3cde9502f806 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 16 Feb 2019 12:01:04 +0000 Subject: [PATCH 213/402] sys/lib/wiki: fix links in wiki pages --- sys/lib/wiki/diff.html | 2 +- sys/lib/wiki/edit.html | 2 +- sys/lib/wiki/history.html | 2 +- sys/lib/wiki/oldpage.html | 2 +- sys/lib/wiki/page.html | 2 +- sys/lib/wiki/werror.html | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/lib/wiki/diff.html b/sys/lib/wiki/diff.html index 921f3f88c7..35841133a7 100644 --- a/sys/lib/wiki/diff.html +++ b/sys/lib/wiki/diff.html @@ -33,7 +33,7 @@ About the server | Powered by Plan 9 diff --git a/sys/lib/wiki/edit.html b/sys/lib/wiki/edit.html index 0f92b6cd4a..02ab8e0dfb 100644 --- a/sys/lib/wiki/edit.html +++ b/sys/lib/wiki/edit.html @@ -42,7 +42,7 @@ About the server | Powered by Plan 9 diff --git a/sys/lib/wiki/history.html b/sys/lib/wiki/history.html index bfe9a18cd6..787cf5e6a0 100644 --- a/sys/lib/wiki/history.html +++ b/sys/lib/wiki/history.html @@ -33,7 +33,7 @@ About the server | Powered by Plan 9 diff --git a/sys/lib/wiki/oldpage.html b/sys/lib/wiki/oldpage.html index eb17220547..ad8a3e4c4b 100644 --- a/sys/lib/wiki/oldpage.html +++ b/sys/lib/wiki/oldpage.html @@ -33,7 +33,7 @@ About the server | Powered by Plan 9 diff --git a/sys/lib/wiki/page.html b/sys/lib/wiki/page.html index c3a2253a59..42d649d5fe 100644 --- a/sys/lib/wiki/page.html +++ b/sys/lib/wiki/page.html @@ -37,7 +37,7 @@ About the server | Powered by Plan 9 diff --git a/sys/lib/wiki/werror.html b/sys/lib/wiki/werror.html index 26d786b609..7917824063 100644 --- a/sys/lib/wiki/werror.html +++ b/sys/lib/wiki/werror.html @@ -39,7 +39,7 @@ About the server | Powered by Plan 9 From 1b1c4ebeaedd3fe1fbd66ad5efb5646b3fcaa1f8 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 19 Jan 2020 08:29:53 +0000 Subject: [PATCH 214/402] sys/src/cmd/wikifs: fix html links to man pages --- sys/src/cmd/wikifs/tohtml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/wikifs/tohtml.c b/sys/src/cmd/wikifs/tohtml.c index 716848951e..545b93d117 100644 --- a/sys/src/cmd/wikifs/tohtml.c +++ b/sys/src/cmd/wikifs/tohtml.c @@ -285,7 +285,7 @@ pagehtml(String *s, Wpage *wtxt, int ty) case Wman: sprint(tmp, "%d", w->section); s = s_appendlist(s, - "text, "\">", w->text, "(", tmp, ")", nil); break; From 6e58539ac1d6e7aa516cfbd3893d515c0fc6d744 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 18 Feb 2016 14:10:07 +0000 Subject: [PATCH 215/402] sys/src/games/sokoban: fix non constant initializer --- sys/src/games/sokoban/sokoban.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sys/src/games/sokoban/sokoban.c b/sys/src/games/sokoban/sokoban.c index 5b35186836..4c7de4e60b 100644 --- a/sys/src/games/sokoban/sokoban.c +++ b/sys/src/games/sokoban/sokoban.c @@ -39,10 +39,7 @@ Menu menu = buttons, }; -Menu lmenu = -{ - levelnames, -}; +Menu lmenu; void buildmenu(void) From e429cb32c19192d332981bfe595110701c49bb19 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 3 Mar 2016 21:44:25 +0000 Subject: [PATCH 216/402] sys/man: import ainc(2) manual (thanks Francisco Ballesteros) --- sys/man/2/ainc | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 sys/man/2/ainc diff --git a/sys/man/2/ainc b/sys/man/2/ainc new file mode 100644 index 0000000000..bc8c7a6ed0 --- /dev/null +++ b/sys/man/2/ainc @@ -0,0 +1,71 @@ +.TH AINC 2 +.SH NAME +ainc, adec, cas32, cas, casp, casl, cas64, mfence \- atomic operations +.SH SYNOPSIS +.B #include +.br +.B #include +.PP +.nf +.B +int ainc(long *p) +.PP +.B +int adec(long *p) +.PP +.B +int cas(uint *p, int ov, int nv) +.PP +.B +int casp(void **p, void *ov, void *nv) +.PP +.B +int casl(ulong *p, ulong ov, ulong nv) +.PP +.B +int cas32(u32int *p, u32int ov, u32int nv) +.PP +.B +int cas64(u64int *p, u64int ov, u64int nv) +.PP +.B +void mfence(void) +.SH DESCRIPTION +These functions provide access to atomic operations, useful for +synchronization. +.PP +.I Ainc +and +.I adec +atomically +increment and decrement (respectively) the integer pointed to by +.IR p , +and return the resulting value after the operation. +.PP +.I Cas +performs a compare and swap on the word pointed to by +.IR p , +provided that the value is still +.I ov +(the old value), so that the new value is +.IR nv . +Functions +.IR cas32 , +.IR cas64 , +.IR casp , +and +.I casul +do the same for 32-bit values, 64-bit values, pointers, and unsigned long +integers. +.PP +.I Mfence +sets a memory fence so that all outstanding memory operations are performed +before returning from it. +.SH SOURCE +.B /sys/src/libc/386/atom.s +.br +.B /sys/src/libc/amd64/atom.s +.SH SEE ALSO +.IR incref (2). +.SH BUGS +Some of them may not be implemented for some architectures. From b2236abbe4a00c038170dfc4473d33390fb642f0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 3 Aug 2016 19:14:14 +0000 Subject: [PATCH 217/402] sys/man: update lock(2) manual (thanks Geoff Collyer) --- sys/man/2/lock | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/sys/man/2/lock b/sys/man/2/lock index 76d15b1fef..128ea313bb 100644 --- a/sys/man/2/lock +++ b/sys/man/2/lock @@ -282,26 +282,20 @@ this ensures that wakeups are not missed. .SH SEE ALSO .I rfork in -.IR fork (2) +.IR fork (2), +.IR semacquire (2) .SH BUGS .B Locks -are not strictly spin locks. -After each unsuccessful attempt, +are not actually spin locks. +After one unsuccessful attempt, .I lock calls -.B sleep(0) -to yield the CPU; this handles the common case -where some other process holds the lock. -After a thousand unsuccessful attempts, -.I lock -sleeps for 100ms between attempts. -After another thousand unsuccessful attempts, -.I lock -sleeps for a full second between attempts. +.I semacquire +repeatedly (thus yielding the CPU) +until it succeeds in acquiring a semaphore internal to the +.BR Lock . .B Locks are not intended to be held for long periods of time. -The 100ms and full second sleeps are only heuristics to -avoid tying up the CPU when a process deadlocks. As discussed above, if a lock is to be held for much more than a few instructions, the queueing lock types should be almost always be used. From 7c6f22a73569b68ab3e846cf84d18b52878f4cd4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 17 Aug 2016 19:32:12 +0000 Subject: [PATCH 218/402] sys/man: update exec(2) manual (thanks Geoff Collyer) --- sys/man/2/exec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/man/2/exec b/sys/man/2/exec index 5c5e79669d..926bde4bb3 100644 --- a/sys/man/2/exec +++ b/sys/man/2/exec @@ -198,3 +198,8 @@ typically around 409,600 bytes. The kernel constant .B TSTKSIZ controls this. +.PP +Both functions rely upon the system's demand paging, +which in turn expects to be able to read full pages in a single +.I read +operation, no matter what the underlying file server is. From 407f74d8110cccd5f990404b5bfc10e61fbea7dc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 17 Aug 2016 19:32:26 +0000 Subject: [PATCH 219/402] sys/man: update read(2) manual (thanks Geoff Collyer) --- sys/man/2/read | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/man/2/read b/sys/man/2/read index 1ae0928626..76ae571e7d 100644 --- a/sys/man/2/read +++ b/sys/man/2/read @@ -90,7 +90,8 @@ without interference. .IR dup (2), .IR open (2), .IR pipe (2), -.IR readv (2) +.IR readv (2), +.IR read (5) .SH DIAGNOSTICS These functions set .IR errstr . From e0dd55d54b7faf61f3bfedc3effbbf5291dd4c18 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 17 Aug 2016 19:32:41 +0000 Subject: [PATCH 220/402] sys/man: update read(5) manual (thanks Geoff Collyer) --- sys/man/5/read | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/man/5/read b/sys/man/5/read index 4438ee984e..e454d74f72 100644 --- a/sys/man/5/read +++ b/sys/man/5/read @@ -48,7 +48,14 @@ reply message. The .I count field in the reply indicates the number of bytes returned. -This may be less than the requested amount. +This may be less than the requested amount, +if the requested amount is not all currently available. +However, servers should try to avoid returning less data than +requested if possible. +In particular, merely crossing a storage block boundary is not +sufficient reason to return a short count; +.IR exec (2) +in particular relies upon this property. If the .I offset field is greater than or equal to the number of bytes in the file, From 748e5b4096968ea52c5da676f116b22534a6ea2c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:37 +0000 Subject: [PATCH 221/402] sys/man: import kernel function manuals (thanks Charles Forsyth) --- sys/man/9/0intro | 53 ++++ sys/man/9/NOTICE | 2 + sys/man/9/allocb | 312 +++++++++++++++++++ sys/man/9/conf | 340 +++++++++++++++++++++ sys/man/9/delay | 41 +++ sys/man/9/devattach | 699 +++++++++++++++++++++++++++++++++++++++++++ sys/man/9/dmainit | 86 ++++++ sys/man/9/error | 168 +++++++++++ sys/man/9/eve | 46 +++ sys/man/9/inb | 83 +++++ sys/man/9/intrenable | 106 +++++++ sys/man/9/kbdputc | 52 ++++ sys/man/9/kproc | 131 ++++++++ sys/man/9/lib | 161 ++++++++++ sys/man/9/lock | 106 +++++++ sys/man/9/malloc | 193 ++++++++++++ sys/man/9/newchan | 225 ++++++++++++++ sys/man/9/panic | 25 ++ sys/man/9/parsecmd | 107 +++++++ sys/man/9/qio | 480 +++++++++++++++++++++++++++++ sys/man/9/qlock | 105 +++++++ sys/man/9/readnum | 58 ++++ sys/man/9/ref | 59 ++++ sys/man/9/seconds | 93 ++++++ sys/man/9/sleep | 123 ++++++++ sys/man/9/splhi | 57 ++++ sys/man/9/uartp8250 | 77 +++++ sys/man/9/xalloc | 72 +++++ 28 files changed, 4060 insertions(+) create mode 100644 sys/man/9/0intro create mode 100644 sys/man/9/NOTICE create mode 100644 sys/man/9/allocb create mode 100644 sys/man/9/conf create mode 100644 sys/man/9/delay create mode 100644 sys/man/9/devattach create mode 100644 sys/man/9/dmainit create mode 100644 sys/man/9/error create mode 100644 sys/man/9/eve create mode 100644 sys/man/9/inb create mode 100644 sys/man/9/intrenable create mode 100644 sys/man/9/kbdputc create mode 100644 sys/man/9/kproc create mode 100644 sys/man/9/lib create mode 100644 sys/man/9/lock create mode 100644 sys/man/9/malloc create mode 100644 sys/man/9/newchan create mode 100644 sys/man/9/panic create mode 100644 sys/man/9/parsecmd create mode 100644 sys/man/9/qio create mode 100644 sys/man/9/qlock create mode 100644 sys/man/9/readnum create mode 100644 sys/man/9/ref create mode 100644 sys/man/9/seconds create mode 100644 sys/man/9/sleep create mode 100644 sys/man/9/splhi create mode 100644 sys/man/9/uartp8250 create mode 100644 sys/man/9/xalloc diff --git a/sys/man/9/0intro b/sys/man/9/0intro new file mode 100644 index 0000000000..66981102bf --- /dev/null +++ b/sys/man/9/0intro @@ -0,0 +1,53 @@ +.TH INTRO 9 +.SH NAME +intro \- introduction to kernel functions +.SH DESCRIPTION +This section of the manual +describes the functions publicly available to the authors of +kernel code, particularly device drivers (real and virtual). +This section will eventually be much expanded, but this makes a start. +.PP +The +.SM SYNOPSIS +subsections do not show the header files needed for +the standard kernel declarations. +The primary combinations summarised below: +.IP +.RS +.ta \w'\fL#include 'u +.nf +.B +#include "u.h" +.B +#include "../port/lib.h" +.B +#include "mem.h" +.B +#include "dat.h" +.B +#include "fns.h" +.B +#include "../port/error.h" +.PP +.I "furthermore, added in IP code:" +.br +.B +#include "../ip/ip.h" +.PP +.I "furthermore, in hardware device drivers:" +.br +.B +#include "io.h" +.br +.B +#include "ureg.h" +.PP +.I "furthermore, in network interfaces or ether drivers:" +.B +#include "../port/netif.h" +.fi +.RE +.PP +There might also be specific include files needed by +drivers on particular platforms or to use specialised kernel interfaces. +The easiest method is to check the source of likely-looking drivers nearby. diff --git a/sys/man/9/NOTICE b/sys/man/9/NOTICE new file mode 100644 index 0000000000..d76c8e307f --- /dev/null +++ b/sys/man/9/NOTICE @@ -0,0 +1,2 @@ +Copyright © 1996-2005 Lucent Technologies Inc. +Portions Copyright © 1999-2005 Vita Nuova Limited diff --git a/sys/man/9/allocb b/sys/man/9/allocb new file mode 100644 index 0000000000..ac1f148570 --- /dev/null +++ b/sys/man/9/allocb @@ -0,0 +1,312 @@ +.TH ALLOCB 9 +.SH NAME +allocb, iallocb, freeb, freeblist, BLEN, blocklen, concatblock, copyblock, trimblock, packblock, padblock, pullblock, pullupblock, adjustblock, checkb \- data block management +.SH SYNOPSIS +.ta \w'\fLBlock* 'u +.B +Block* allocb(int size) +.PP +.B +Block* iallocb(int size) +.PP +.B +void freeb(Block *b) +.PP +.B +void freeblist(Block *b) +.PP +.B +long BLEN(Block *b) +.PP +.B +int blocklen(Block *b) +.PP +.B +Block* concatblock(Block *b) +.PP +.B +Block* copyblock(Block *b, int n) +.PP +.B +Block* trimblock(Block *b, int offset, int n) +.PP +.B +Block* packblock(Block *b) +.PP +.B +Block* padblock(Block *b, int n) +.PP +.B +int pullblock(Block **bph, int n) +.PP +.B +Block* pullupblock(Block *b, int n) +.PP +.B +Block* adjustblock(Block *b, int n) +.PP +.B +void checkb(Block *b, char *msg) +.SH DESCRIPTION +A +.B Block +provides a receptacle for data: +.IP +.EX +.DT +typedef +struct Block +{ + Block* next; + Block* list; + uchar* rp; /* first unconsumed byte */ + uchar* wp; /* first empty byte */ + uchar* lim; /* 1 past the end of the buffer */ + uchar* base; /* start of the buffer */ + void (*free)(Block*); + ulong flag; +} Block; +.EE +.PP +Each +.B Block +has an associated buffer, located at +.BR base , +and accessed via +.B wp +when filling the buffer, or +.B rp +when fetching data from it. +Each pointer should be incremented to reflect the amount of data written or read. +A +.B Block +is empty when +.B rp +reaches +.BR wp . +The pointer +.B lim +bounds the allocated space. +Some operations described below accept lists of +.BR Block s, +which are +chained via their +.B next +pointers, with a null pointer ending the list. +.B Blocks +are usually intended for a +.B Queue +(see +.IR qio (9)), +but can be used independently. +.PP +A +.B Block +and its buffer are normally allocated by one call to +.IR malloc (9) +and aligned on an 8 byte (\fLBY2V\fP) boundary. +Some devices with particular allocation constraints +(eg, requiring certain addresses for DMA) might allocate their own +.B Block +and buffer; +.B free +must then point to a function that can deallocate the specially allocated +.BR Block . +.PP +Many +.B Block +operations cannot be used in interrupt handlers +because they either +.IR sleep (9) +or raise an +.IR error (9). +Of operations that allocate blocks, only +.IR iallocb +is usable. +.PP +.I Allocb +allocates a +.B Block +of at least +.IR size +bytes. +The block +is initially empty: +.B rp +and +.B wp +point to the start of the data. +If it cannot allocate memory, +.I allocb +raises an +.IR error (9); +it cannot be used by an interrupt handler. +.PP +.IR Iallocb +is similar to +.IR allocb +but is intended for use by interrupt handlers, +and returns a null pointer if no memory is available. +It also limits its allocation to a quota allocated at system initialisation to interrupt-time buffering. +.PP +.I Freeb +frees a single +.B Block +(and its buffer). +.PP +.I Freeblist +frees the whole +list of blocks headed by +.IR b . +.PP +.I BLEN +returns the number of unread bytes in a single block +.IR b ; +it is implemented as a macro. +.PP +.I Blocklen +returns the number of bytes of unread data in the whole list of blocks headed by +.IR b . +.PP +.I Concatblock +returns +.I b +if it is not a list, and otherwise +returns a single +.B Block +containing all the data in the list of blocks +.IR b , +which it frees. +.PP +.I Copyblock +by contrast returns a single +.B Block +containing a copy of the first +.I n +bytes of data in the block list +.IR b , +padding with zeroes if the list contained less than +.I n +bytes. +The list +.I b +is unchanged. +.PP +.I Padblock +can pad a single +.B Block +at either end, to reserve space for protocol headers or trailers. +If +.IR n ≥ 0 , +it inserts +.I n +bytes at the start of the block, +setting the read pointer +.B rp +to point to the new space. +If +.IR n < 0 , +it adds +.I n +bytes at the end of the block, +leaving the write pointer +.B wp +pointing at the new space. +In both cases, it allocates a new +.B Block +if necessary, freeing the old, and +it always returns a pointer to the resulting +.BR Block . +.PP +.I Trimblock +trims the list +.I b +to contain no more than +.I n +bytes starting at +.I offset +bytes into the data of the original list. +It returns a new list, freeing unneeded parts of the old. +If no data remains, it returns a null pointer. +.PP +.I Packblock +examines each +.B Block +in the list +.IR b , +reallocating any block in the list that has four times more available space than actual data. +It returns a pointer to the revised list. +.PP +.I Pullblock +discards up to +.I n +bytes from the start of the list headed by +.BI * bph \f1.\f0 +Unneeded blocks are freed. +.I Pullblock +sets +.BI * bph +to point to the new list head +and returns the number of bytes discarded (which might be less than +.IR n ). +It is used by transport protocols to discard ack'd data at +the head of a retransmission queue. +.PP +.I Pullupblock +rearranges the data in the list of blocks +.I b +to ensure that there are at least +.I n +bytes of contiguous data in the first block, +and returns a pointer to the new list head. +It frees any blocks that it empties. +It returns a null pointer if there is not enough data in the list. +.PP +.I Adjustblock +ensures that the block +.I b +has at least +.I n +bytes of data, reallocating or padding with zero if necessary. +It returns a pointer to the new +.BR Block . +(If +.I n +is negative, it frees the block and returns a null pointer.) +.PP +.I Checkb +does some consistency checking of +the state of +.IR b ; +a +.IR panic (9) +results if things look grim. +It is intended for internal use by the queue I/O routines (see +.IR qio (9)) +but could be used elsewhere. +.PP +The only functions that can be called at interrupt level are +.IR iallocb , +.IR freeb , +.IR freeblist , +.IR BLEN , +.IR blocklen , +.IR trimblock +and +.IR pullupblock . +The others allocate memory and can potentially block. +.SH SOURCE +.B /sys/src/9/port/allocb.c +.SH DIAGNOSTICS +Many functions directly or indirectly can raise an +.IR error (9), +and callers must therefore provide for proper error recovery +as described therein to prevent memory leaks and other bugs. +Except for +.IR iallocb , +any functions that allocate new blocks or lists +are unsuitable for use by interrupt handlers. +.IR Iallocb +returns a null pointer when it runs out of memory. +.SH SEE ALSO +.IR qio (9) diff --git a/sys/man/9/conf b/sys/man/9/conf new file mode 100644 index 0000000000..dbc13d88af --- /dev/null +++ b/sys/man/9/conf @@ -0,0 +1,340 @@ +.TH CONF 9 +.SH NAME +conf \- native and hosted kernel configuration file +.SH DESCRIPTION +Plan 9 kernels are built for a given target +.I platform +using platform-specific code in directory +.BI /sys/src/9/ platform +and portable code in +.BR /sys/src/9/port , +.B /sys/src/9/ip +and elsewhere. +Existing +.I platforms +include +.B alphapc +for the DEC Alpha, +.B iPAQ +for the Compaq iPAQ, +.B pc +for the Intel x86, +and +.B ppc +for the IBM/Motorola PowerPC. +Each +.I platform +can have several different kernels with different configurations. +A given configuration is built in the platform's directory using the +.IR mk (1) +command: +.IP +.EX +mk 'CONF=\fIconf\fP' +.EE +.PP +where +.I conf +is a text file that specifies drivers, protocols and other parameters for that +particular kernel: +a parts list. +The result of a successful +.I mk +is +an executable or bootable file with a name determined by the +.IR platform 's +.BR mkfile , +typically +.BI 9 conf. +.PP +A kernel configuration file has several sections of the form +.IP +.EX +.I "label" +.IR " item" " [ " "subitem ..." " ]" +\& ... +.EE +.PP +Each section begins with a +.I label +at the start of a line, which names a configuration +category, followed by +a list of each +.I item +to select from that category, +one line per item, with white space (ie, blank or tab) at the start of the line. +An +.I item +line can optionally list one or more +.I subitems +that must be included in the kernel to support it. +A line that starts with a +.L # +is a comment. +Empty lines are ignored. +.PP +.I Labels +are chosen from the following set, listed in the order +in which they conventionally appear in a configuration file: +.TF etherxx +.TP +.B dev +Device drivers +.TP +.B ip +IP protocols (native kernels only) taken from +.B ../ip +.TP +.B link +Hardware-specific parts of device drivers. +.TP +.B misc +Architecture-specific files; specific VGA and SCSI interfaces +.TP +.B lib +Libraries to link with the kernel +.TP +.B port +C code and declarations to include as-is in the generated configuration file +.TP +.B boot +Configuration for +.IR boot (8) +.TP +.B bootdir +List of files and directories to put in the +.B boot +directory of +.IR root (3). +.PD +.PP +When an +.I item +is listed +under a given +.I label +it causes a corresponding component to be included in the kernel. +The details depend on the +.IR label , +as discussed below. +Each +.I subitem +represents a kernel subcomponent required by the corresponding +.IR item . +Both items and subitems can be either portable (platform-independent) +or platform-specific. +The source file for a given item or subitem +is sought in the platform-directory +(for platform-specific code), and +in directories +.BR ../port +and +.BR ../ip , +under control of the platform's +.BR mkfile +and +.B ../port/portmkfile +(which is included by +.BR mkfile ). +Resulting object files are left in the +.I platform +directory. +.PP +Outside the +.B dev +section, +each item and subitem +.I x +causes the kernel image to include the code compiled from +.IB x .c , +(or +.IB x .s +for assembly-language support), +or +.IB portdir / x .c , +where +.I portdir +is one of the portable directories mentioned above. +In the +.B dev +section, an item +.I x +corresponds instead to the driver source file +.BI dev x .c +in the current (platform-specific) +directory or a portable driver +.IB portdir /dev x .c . +Subitems are handled as in any other section. +Typically they are auxiliary files that are needed by the associated driver. +.PP +For instance, in a native kernel +the portable driver for the +.B draw +device uses platform-specific code from +.BR screen.c . +That can be represented as follows: +.IP +.EX +dev + draw screen +.EE +.PP +Each item +.I x +in the +.B ip +section +corresponds to a protocol implementation compiled from +.BI ../ip/ x .c . +Any subitems +are dealt with in the same way as in the +.B dev +section. +.PP +The +.B link +section provides a way for hardware-specific +parts of drivers to link at runtime to the hardware-invariant part of a device +drivers. +For each item +.IR x , +the kernel will call the function +.IB x link +during its initialisation. +Typically that function makes itself known to the device driver by +calling a function provided by that driver, +passing the address of a interface-specific data structure or linkage table. +For example, +.B ethersmc +is an interface-specific component: +.IP +.EX +link + \fR...\fP + ethersmc +.EE +.PP +and its source file +.B ethersmc.c +provides a function +.B ethersmclink +that +calls +.B addethercard +in the interface-invariant part of the driver, +.BR devether.c : +.IP +.EX +void +ethersmclink(void) +{ + addethercard("smc91cXX", reset); +} +.EE +.PP +The +.B boot +section configures +.IR boot (8), +the first user program run by the kernel. +Each line in the section names a possible boot method (see +.IR boot (8) +for the current list). +The first will be the default. +Also by default, +.B /boot +will run +.B /bin/termrc +from +.IR cpurc (8), +with +.B bootdisk +set to +.BR #S/sdC0/ . +To change the defaults, the line (or lines) containing a +.B boot +label can be given some options: +.RS +.TP +.B "boot cpu" +.br +The kernel is a cpu server: run +.B /bin/cpurc +not +.B /bin/termrc +(see +.IR cpurc (8)). +.TP +.BI "boot cpu boot " disk +Use +.I disk +as the default +.BR bootdisk . +.RE +.PP +The +.B lib +section lists the libraries to include when linking the kernel, +in an order that satisfies any dependencies amongst them. +Each item +.I x +corresponds to +.BI /$objtype/lib x .a , +a target-specific library +produced by compiling the C source code in +.BI /sys/src/lib item, +where +.B objtype +is set in the platform's +.B mkfile +to the target system's object type +(eg, +.BR 386 , +.BR power , +etc). +.PP +An item in the +.B bootdir +section +has one of the forms: +.IP +.EX +.I name +.I "source name" +.EE +.PP +where +.I name +and +.I source +are path names (often absolute path names). +The kernel's initial root file system (see +.IR root (3)) +will contain a file or directory with the given +.IR name . +The contents will come from the file +.I name +(which must exist) unless an explicit +.I source +file is given. +.PP +The +.B port +section usually contains initialisations for kernel-specific values. +The most common one is +.IP +.EX + int cpuserver = \fIn\fP; +.EE +.PP +where +.I n +is non-zero for cpu servers and file servers, and zero otherwise. +.SH FILES +.B /sys/src/9/port/mkdevc +.br +.B /sys/src/9/port/mkdevlist +.br +.B /sys/src/9/port/mkroot +.SH SEE ALSO +.IR mk (1) diff --git a/sys/man/9/delay b/sys/man/9/delay new file mode 100644 index 0000000000..8bc6710d1e --- /dev/null +++ b/sys/man/9/delay @@ -0,0 +1,41 @@ +.TH DELAY 9 +.SH NAME +delay, microdelay, addclock0link \- small delays, clock interrupts +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void delay(int n) +.PP +.B +void microdelay(int n) +.PP +.B +void addclock0link(void(*clockf)(void)) +.SH DESCRIPTION +.I Delay +busy waits for +.I n +milliseconds, forced to be at least one millisecond. +.PP +.I Microdelay +is similar, but busy waits for +.I n +microseconds. +.PP +For delays on the order of clock ticks, +.I tsleep +(see +.IR sleep (9)) +provides a better alternative to the busy waiting of these routines. +.PP +.I Addclock0link +adds +.I clockf +to a list of functions to be executed at each clock interrupt on +the first processor. +.SH SOURCE +.B /sys/src/9/port/portclock.c +.br +.B /sys/src/9/*/clock.c +.SH SEE ALSO +.IR sleep (9) diff --git a/sys/man/9/devattach b/sys/man/9/devattach new file mode 100644 index 0000000000..671afe7bc9 --- /dev/null +++ b/sys/man/9/devattach @@ -0,0 +1,699 @@ +.TH DEVATTACH 9 +.SH NAME +devattach, devclone, devdir, devgen, devwalk, devdirread, devstat, devopen, devbread, devbwrite, devcreate, devremove, devwstat, devreset, devinit, devshutdown, openmode \- common device driver support +.SH SYNOPSIS +.nf +.ta \w'\fLBlock* 'u +10n +.B +typedef int +.B +Devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) +.PP +.B +Chan* devattach(int tc, char *spec) +.PP +.B +Chan* devclone(Chan *c) +.PP +.B +void devdir(Chan *c, Qid qid, char *n, long length, +.B + char *user, long perm, Dir *dp) +.PP +.B +int devgen(Chan *c, char *name, Dirtab *tab, int ntab, +.B + int i, Dir *dp) +.PP +.B +Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, +.B + Dirtab *tab, int ntab, Devgen *gen) +.PP +.B +void devstat(Chan *c, uchar *db, int n, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +long devdirread(Chan *c, char *d, long n, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +Chan* devopen(Chan *c, int omode, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +Block* devbread(Chan *c, long n, ulong offset) +.PP +.B +long devbwrite(Chan *c, Block *bp, ulong offset) +.PP +.B +void devcreate(Chan*, char*, int, ulong) +.PP +.B +void devremove(Chan*) +.PP +.B +void devwstat(Chan*, uchar*, int) +.PP +.B +void devreset(void) +.PP +.B +void devinit(void) +.PP +.B +void devshutdown(void) +.PP +.B +int openmode(ulong mode) +.SH DESCRIPTION +Device drivers call these functions to carry out essential tasks and default actions. +They do most of the name space management +for a driver that serves a simple name space +(eg, data and control files), +leaving the driver to concentrate on the device-specific details +of the I/O requests. +More complex drivers also make good use of them at the leaves +of their name space, and to help manage the +.B Chan +structures correctly. +.PP +A device has an associated +.IR type , +represented as a Unicode character (`rune') that identifies the device +inside and outside the kernel. +It appears as the value of the +.B type +field in the +.B Dir +resulting from a +.IR stat (2) +of any file provided by the device. +A device is named outside the kernel using +a path name starting with +.B # +followed by the device character +(eg, +.B c +in +.B #c +for the console). +Any subsequent characters before +the next '/' or end of string is the `device specifier', +interpreted solely by the device itself. +.PP +.I Devattach +returns a new channel representing +the root of the file tree +corresponding to device type +.IR tc , +with device specifier +.IR spec . +It is normally called by a driver's +.I attach +function (see +.IR dev (9)). +The +.B qid +for the new channel is +.BR "(Qid){0,0,QTDIR}" , +suitable for a root directory for many devices, but +a device driver is free to change it (provided the +.B QTDIR +bit remains in the +.BR Qid.type ). +.PP +.I Devclone +returns a new channel that is a copy of +.IR c . +An attempt to clone an open channel causes a +.IR panic (9). +.PP +The +.L Dir +structure is shown below: +.IP +.EX +typedef +struct Dir +{ + /* system-modified data */ + ushort type; /* server type */ + uint dev; /* server subtype */ + /* file data */ + Qid qid; /* unique id from server */ + ulong mode; /* permissions */ + ulong atime; /* last read time */ + ulong mtime; /* last write time */ + vlong length; /* file length */ + char *name; /* last element of path */ + char *uid; /* owner name */ + char *gid; /* group name */ + char *muid; /* last modifier name */ +} Dir; +.EE +.PP +This +.B Dir +structure corresponds directly to the Limbo +.B Dir +adt described in +.IR stat (2). +.PP +Given a channel and assorted other information, +.I devdir +initialises a Dir structure at +.IR dp . +.I Devdir +supplies the following data itself: +.RS +.TF length +.TP +.B atime +last access time (set to current time) +.TP +.B mtime +last modification time (set to kernel creation date) +.TP +.B gid +group name (set to +.IR eve (9)) +.TP +.B length +length in bytes (set to zero, which +is normal for most devices) +.RE +.PD +.PP +Note that +.I devdir +assigns the values of +.I name +and +.I user +directly to fields of +.BI * dp, +and consequently those values must remain valid until the last use of +.BI * dp. +(Sometimes that requires the use of an auxiliary buffer, such as +.BR up->genbuf .) +If channel +.I c +corresponds to a file descriptor on which Styx is served, +.I devdir +sets both the flag bit +.B QTMOUNT +in +.IB dp ->qid.type +and the flag bit +.B DMMOUNT +in +.IB dp ->mode +(see +.I export +in +.IR dial (2) +and +.I mount +in +.IR bind (2)). +.PP +A simple name space can be represented in a driver by an array of +.B Dirtab +structures. +The array is typically static when the names and permissions +are static, but can be dynamically allocated and initialised if required. +The structure of +.B Dirtab +is shown below: +.IP +.EX +typedef +struct Dirtab +{ + char name[KNAMELEN]; + Qid qid; + vlong length; + long perm; +} Dirtab; +.EE +.PP +The name +.RB ` . ' +.I must +appear as the first entry in a +.B Dirtab +if the default +.I devgen +function is used. +On the other hand, the name +.RB ` .. ' +must never appear in a +.B Dirtab +table. +Drivers that support a directory hierarchy must walk up the hierarchy towards +the root when their +.I walk +function receives +.RB ` .. ' +as a file name component. +The name +.RB ` . ' +is never seen by a driver. +.PP +The +.IR devdirread , +.IR devopen , +.IR devstat , +and +.IR devwalk +functions all take a +.I gen +function argument, +of type +.BR Devgen , +which they invoke to retrieve the items in +a +.B Chan +that represents a directory. +.I Gen +takes a channel +.I c +(a directory), +a file +.I name +(which is nil except during +.IR devwalk ), +an array of +.B Dirtab +structures +.I tab +of length +.IR ntab , +and a table index +.IR i . +The functions calling +.I gen +expect it to place the +.IR i 'th +entry in the directory into +.IR \f5*\fPdp . +It should return 1 +if the call was successful, +-1 if +.I i +is beyond the index of the last directory entry, +or 0 if there is no entry at +.IR i , +but there are entries beyond it. +When +.I i +has the special value +.B DEVDOTDOT +then +.I gen +should set +.IR \f5*\fPdp +to reflect the parent of +.IR c ; +if +.I c +is a one-level device directory, then `..' is equivalent to `.'. +Custom implementations of +.I gen +often ignore +.IR devtab , +and instead return their own dynamically generated +set of directory entries from some other source. +Exceptionally, during +.I devwalk +a non-nil +.I name +is provided: it is the name being looked up, and a device-specific +.I gen +can short-circuit the search by returning -1 if the name does not exist, +or filling in +.IR \f5*\fPdp +and returning 1 if it does exist. +.PP +The function +.I devgen +is compatible with +.BR Devgen ; +it returns the +.IR i 'th +entry in +.IR devtab , +and can be used to provide a simple, static +set of directory entries. +.PP +.I Devwalk +walks channel +.I c +to the file in the device named by the path encoded in +.IR name , +which is an array of strings of length +.IR nname . +It provides the interface to +.IR walk (5) +within the kernel, and that specification must be well understood to appreciate +all the nuances of its interface. +Fortunately, in nearly all device drivers, a device's +.I walk +function typically passes its parameters on to +.I devwalk +(adding the device's own +.B Dirtab +array as the the value of +.IR tab ), +and simply returning the result of +.IR devwalk . +.PP +.I Devwalk +walks +.I c +using the given set of names, and if the walk is successful, the +channel +.I nc +will refer to the result of the walk +(specifically, +.IB nc ->qid +is set to the Qid for the file). +If +.I nc +is nil, +.I devwalk +will allocate a new channel itself, that is initially a clone of +.IR c . +As in +.IR walk (5), +.I devwalk +can return a partial result, +represented by +a dynamically allocated value of the following structure: +.IP +.EX +struct Walkqid +{ + Chan *clone; + int nqid; + Qid qid[1]; /* actually nname in length */ +}; +.EE +.PP +The value must be freed after use. +For each element of +.I name , +.I devwalk +passes +the +.I tab +parameter to +.I gen +together with the currently-sought element of +.IR name . +If the first element is not found, +.I devwalk +returns nil; otherwise, it returns a +.B Walkqid +value in which +.B nqid +elements of the array +.B qid +are set to the qids (see +.IR intro (5)) +of each valid element of +.IR name . +If all +.I nname +elements were successfully traversed, then +.B nqid +will have the value +.IR nname , +and +.B clone +will refer to the result of the walk, +which is either +.I nc +if given, or +the new channel allocated by +.IR devwalk . +Otherwise, at least one element succeeded and +.B nqid +is less than +.I nname +and +.B clone +is nil. +On an error or incomplete walk, +the error string is set to the error that stopped the walk (eg, +.B Enonexist +or +.BR Enotdir ). +.PP +.I Devstat +fills the array of bytes +.I db +with data in the format produced by +.IR stat (5) +that describes the file +referenced by channel +.IR c , +which must have a corresponding entry +returned by +.IR gen +(ie, an entry with matching +.BR Qid.path ). +If +.I c +is a communications channel connecting a Styx server to a current mount point, +the +.B DMMOUNT +bit is set in the resulting +.BR Dir.mode , +and +.B QTMOUNT +is set in +.BR Dir.qid.type . +As in +.IR stat (5), +the length of the data written to +.I db +varies; if more than +.I n +bytes are needed, +.I devstat +raises the +.IR error (9) +.BR Ebadarg . +Otherwise, it returns the number of bytes in +.I db +actually used. +.PP +If an entry with the desired qid is not found in the table, but +.I c +corresponds to a directory +(ie, +.B QTDIR +is set in +.IR c\f5->qid.type\fP ), +it is taken to be a +.I stat +of a notional directory containing the files listed in +.IR tab . +.I Dirstat +then builds the corresponding Dir structure: +its +.B Dir.name +is taken from +.IR c\f5->path->elem\fP ; +the length is +.BI DIRLEN*nelem(tab) ; +and +.B Dir.perm +is 0555 (read-execute for all). +.PP +.I Devdirread +calls +.I gen +to obtain successive +.B Dir +structures representing entries in the open directory +.IR c . +These are converted to standard format (see +.I convD2M +in +.IR fcall (2)) +and placed in the buffer +.IR b . +It returns the number of bytes in the result. +At most +.I n +bytes will be returned, in multiples of +.BR DIRLEN . +Because the kernel maintains the current offset in +.IR c , +successive calls to +.I devdirread +return successive directory components. +.PP +.I Devopen +is called to check and complete a request to open channel +.I c +for I/O according to +.IR omode +(the open mode of +.IR open (2)). +It calls +.I gen +to obtain successive directory entries +which it searches +for a Qid matching that of +.IR c , +and ensures that the current user has permission to open +.I c +with the given mode, +.IR omode , +and that the mode itself is valid +(see +.I openmode +below). +Permission is checked against the permission in the +matching entry. +If no matching Qid is found, it is assumed +that the notional parent directory of the files represented in +.I tab +is to be opened. +Such a directory is deemed to have mode +0555, allowing access by any user. +A directory can only be opened for reading +.RB ( OREAD ). +.I Devopen +returns the channel +.I c +on success. +Last, it sets the bit +.B COPEN +in +.B Chan.flag +to mark +.I c +as open. +This convention can always be relied upon by the driver's +.I close +function to tell if an open succeeded. +On the otherhand, +if the open request was unsuccessful, +.I devopen +raises an appropriate +.IR error (9) +and does not return. +.PP +.I Devbread +returns a +.B Block +(see +.IR allocb (9)) +containing up to +.I n +bytes read, +using +.BI "devtab[" c "->type]->read" , +from +.I c +starting at the given +.IR offset . +The read pointer in the returned +.B Block +points to the start of the data; +the write pointer points to the next available byte. +.PP +.I Devbwrite +writes the data in +.B Block +.I bp +to the file +.I c +at the given +.IR offset , +using the write function +.BI "devtab[" c "->type]->write" . +It then frees the block list +.I bp +before +returning the number of bytes written. +.PP +Most built-in devices do not allow +.IR create , +.IR remove +or +.I wstat +on their files. +.IR Devcreate , +.I devremove +and +.I devwstat +are stubs that raise an +.IR error (9), +.BR Eperm . +They can be named directly in a device driver's device +switch (the +.B Dev +structure in +.BR /sys/src/9/port/portdat.h : +see +.IR dev (9)). +.PP +.IR Devreset , +.I devinit +and +.I devshutdown +are also stubs; +they do nothing. +A device driver puts them in its +.B Dev +structure when it need take no action on device reset, initialisation, or shut down. +.PP +.I Openmode +is used by a driver that does not use +.IR devopen , +to check the open mode it receives in its open +routine. +.I Openmode +returns mode +.IR o , +the mode parameter to +.IR open (2) +or +.IR sys-create , +shorn of +.BR OTRUNC +and similar options, +and reduced to one of +.BR OREAD , +.BR OWRITE +or +.BR ORDWR . +In particular, +.B OEXEC +becomes +.B OREAD +within the kernel. +.I Openmode +raises an +.IR error (9) +.B Ebadarg +instead of returning, if +.I o +is an invalid mode (eg, reserved bits set). +.SH SOURCE +.B /sys/src/9/port/dev.c +.SH SEE ALSO +.IR allocb (9), +.IR eve (9), +.IR qio (9) diff --git a/sys/man/9/dmainit b/sys/man/9/dmainit new file mode 100644 index 0000000000..59af145212 --- /dev/null +++ b/sys/man/9/dmainit @@ -0,0 +1,86 @@ +.TH DMAINIT 9 +.SH NAME +dmainit, dmasetup, dmadone, dmaend, dmacount \- platform-specific DMA support +.SH SYNOPSIS +.ta \w'\fLushort 'u +.B +void dmainit(int chan) +.PP +.B +long dmasetup(int chan, void *va, long len, int isread) +.PP +.B +int dmadone(int chan) +.PP +.B +void dmaend(int chan) +.PP +.B +int dmacount(int chan) +.PP +.SH DESCRIPTION +These functions manage DMA on a bus that uses ISA-style DMA controllers. +They were originally devised for the x86 platform, but the same interface, and similar code, +is used by other platforms that use similar controllers. +They compensate as best they can for the limitations of older DMA implementations +(eg, alignment, boundary and length restrictions). +There are 8 DMA channels: +0 to 3 are byte-oriented; 4 to 7 are word-oriented (16-bit words). +.PP +.I Dmainit +must be called early in a driver's initialisation to prepare +.I chan +for use. +Amongst other things, it allocates a page-sized buffer to help circumvent hardware +restrictions on DMA addressing. +.PP +.I Dmasetup +prepares DMA channel +.IR chan +for a transfer between a device configured to use it +and the virtual address +.IR va . +(The transfer is started by issuing a command to the device.) +If +.I va +lies outside the kernel address space, +the transfer crosses a 64k boundary, +or exceeds the 16 Mbyte limit imposed by some DMA controllers, +the transfer will be split into page-sized transfers using the buffer previously allocated by +.IR dmainit . +If +.I isread +is true (non-zero), data is to be transferred from +.I chan +to +.IR va ; +if false, data is transferred from +.I va +to +.IR chan . +In all cases, +.I dmasetup +returns the number of bytes to be transferred. +That value (rather than +.IR len ) +must be given to the device in the read or write request that starts the transfer. +.PP +.I Dmadone +returns true (non-zero) if +.I chan +is idle. +.PP +.I Dmaend +must be called at the end of every DMA operation. +It disables +.IR chan , +preventing further access to the previously associated memory and, +if a low-memory buffer was required for input, transfers its contents +to the appropriate part of the target buffer. +.PP +.I Dmacount +returns the number of bytes that were last transferred by channel +.IR chan . +The count is always even for word-oriented DMA channels. +.SH SOURCE +.B /sys/src/9/pc/dma.c diff --git a/sys/man/9/error b/sys/man/9/error new file mode 100644 index 0000000000..2f9fa54c6d --- /dev/null +++ b/sys/man/9/error @@ -0,0 +1,168 @@ +.TH ERROR 9 +.SH NAME +error, nexterror, poperror, waserror \- error handling functions +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void error(char*) +.PP +.B +void nexterror(void) +.PP +.B +void poperror(void) +.PP +.B +int waserror(void) +.SH DESCRIPTION +The kernel handles error conditions using non-local gotos, +similar to +.IR setjmp (2), +but using a stack of error labels to implement nested exception handling. +This simplifies many of the internal interfaces by eliminating the need +for returning and checking error codes at every level of the call stack, +at the cost of requiring kernel routines to adhere to a strict discipline. +.PP +Each process has in its defining kernel +.B Proc +structure a stack of labels, +.B NERR +(currently 64) elements deep. +A kernel function that must perform a clean up or recovery action on an error +makes a stylised call to +.IR waserror , +.IR nexterror +and +.IR poperror : +.IP +.EX +.DT +if(waserror()){ + /* recovery action */ + nexterror(); +} +/* normal action */ +poperror(); +.EE +.PP +When called in the normal course of events, +.I waserror +registers an error handling block by pushing its label onto the stack, +and returns zero. +The return value of +.I waserror +should be tested as shown above. +If non-zero (true), the calling function should perform the needed +error recovery, ended by a call to +.I nexterror +to transfer control to the next location on the error stack. +Typical recovery actions include deallocating memory, unlocking resources, and +resetting state variables. +.PP +Within the recovery block, +after handling an error condition, there must normally +be a call to +.I nexterror +to transfer control to any error recovery lower down in the stack. +The main exception is in the outermost function in a process, +which must not call +.I nexterror +(there being nothing further on the stack), but calls +.I pexit +(see +.IR kproc (9)) +instead, +to terminate the process. +.PP +When the need to recover a particular resource has passed, +a function that has called +.I waserror +must +remove the corresponding label from the stack by calling +.IR poperror . +This +must +be done before returning from the function; otherwise, a subsequent call to +.I error +will return to an obsolete activation record, with unpredictable but unpleasant consequences. +.PP +.I Error +copies the given error message, which is limited to +.B ERRMAX +bytes, into the +.B Proc.error +of the current process, +enables interrupts by calling +.I spllo +.RI ( native +only), +and finally calls +.I nexterror +to start invoking the recovery procedures currently stacked by +.IR waserror . +The file +.B /sys/src/9/port/error.h +offer a wide selection of predefined error messages, suitable for almost any occasion. +The message set by the most recent call to +.I error +can be obtained within the kernel by examining +.B up->error +and in an application, by using the +.L %r +directive of +.IR print (2). +.PP +A complex function can have nested error handlers. +A +.I waserror +block will follow the acquisition of a resource, releasing it +on error before calling +.I nexterror, +and a +.I poperror +will precede its release in the normal case. +For example: +.IP +.EX +.DT +void +outer(Thing *t) +{ + qlock(t); + if(waserror()){ /* A */ + qunlock(t); + nexterror(); + } + m = mallocz(READSTR, 0); + if(m == nil) + error(Enomem); + if(waserror()){ /* B */ + free(m); + nexterror(); /* invokes A */ + } + inner(t); + poperror(); /* pops B */ + free(m); + poperror(); /* pops A */ + qunlock(t); +} +.sp 1v +void +inner(Thing *t) +{ + if(t->bad) + error(Egreg); /* error() call returns to B */ + t->valid++; +} +.EE +.SH SOURCE +.B /sys/src/9/port/proc.c +.SH CAVEATS +The description above has many instances of +.IR should , +.IR will , +.I must +and +.IR "must not" . +.SH SEE ALSO +.IR panic (9) diff --git a/sys/man/9/eve b/sys/man/9/eve new file mode 100644 index 0000000000..541566196f --- /dev/null +++ b/sys/man/9/eve @@ -0,0 +1,46 @@ +.TH EVE 9 +.SH NAME +eve, iseve \- privileged user +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +char eve[NAMELEN] = "bootes"; +.PP +.B +int iseve(void) +.SH DESCRIPTION +.I Eve +is a null-terminated string containing the name of the owner of +the Plan 9 system (sometimes called the `host owner', +see +.IR cons (3)). +The identity is set on a terminal to the name of the user who logs in. +It is set on a CPU server to the +.I authid +obtained either from NVRAM or by a console prompt. +The initial process created by system initialisation is given the +.I eve +identity. +.PP +.I Iseve +returns true if the current user is +.IR eve . +Several drivers use +.I iseve +to check the caller's identity +before granting permission to perform certain actions. +For example, the console driver allows only the user +.I eve +to write a new identity into the +.B /dev/user +file. +The privileges are strictly local and do not extend into the network +(in particular, to file servers—even ones running on the local machine). +.SH SOURCE +.B /sys/src/9/port/auth.c +.SH SEE ALSO +.IR auth (2), +.IR cap (3), +.IR cons (3), +.IR authsrv (6), +.IR auth (8) diff --git a/sys/man/9/inb b/sys/man/9/inb new file mode 100644 index 0000000000..2dd1752892 --- /dev/null +++ b/sys/man/9/inb @@ -0,0 +1,83 @@ +.TH INB 9 +.SH NAME +inb, ins, inl, outb, outs, outl, insb, inss, insl, outsb, outss, outsl \- programmed I/O +.SH SYNOPSIS +.ta \w'\fLushort 'u +.B +int inb(int port) +.PP +.B +ushort ins(int port) +.PP +.B +ulong inl(int port) +.PP +.B +void outb(int port, int value) +.PP +.B +void outs(int port, ushort value) +.PP +.B +void outl(int port, ulong value) +.PP +.B +void insb(int port, void *address, int count) +.PP +.B +void inss(int port, void *address, int count) +.PP +.B +void insl(int port, void *address, int count) +.PP +.B +void outsb(int port, void *address, int count) +.PP +.B +void outss(int port, void *address, int count) +.PP +.B +void outsl(int port, void *address, int count) +.SH DESCRIPTION +The +.I x86 +implementation provides functions to allow kernel code +written in C to access the I/O address space. +On several other architectures such as the PowerPC and Strongarm, +the platform-dependent code provides similar functions to access +devices with an I/O space interface, even when that is memory mapped, to encourage portability of device drivers. +.PP +.IR Inb , +.I ins +and +.I inl +apply the corresponding hardware instruction to fetch the next byte, short or long +from the I/O +.IR port . +.IR Outb , +.I outs +and +.I outl +output a +.I value +to the I/O +.IR port . +.PP +The remaining functions transfer +.I count +bytes, shorts, or longs using programmed I/O between a memory +.I address +and +.IR port . +Functions +.BI ins x +copy values into memory; functions +.BI outs x +copy values from memory. +The +.I count +is in elements, not bytes. +.SH SOURCE +.B /sys/src/9/pc/l.s +.SH SEE ALSO +.IR dma (9) diff --git a/sys/man/9/intrenable b/sys/man/9/intrenable new file mode 100644 index 0000000000..713c1c000f --- /dev/null +++ b/sys/man/9/intrenable @@ -0,0 +1,106 @@ +.TH INTRENABLE 9 +.SH NAME +intrenable, intrdisable \- enable (disable) an interrupt handler +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) +.PP +.B +void intrdisable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) +.SH DESCRIPTION +.I Intrenable +registers +.I f +to be called by the kernel's interrupt controller driver each time +an interrupt denoted by +.I v +occurs, and unmasks the corresponding interrupt in the interrupt controller. +The encoding of +.I v +is platform-dependent; it is often an interrupt vector number, but +can be more complex. +.I Tbdf +is a platform-dependent value that might further qualify +.IR v . +It might for instance +denote the type of bus, bus instance, device number and function +(following the PCI device indexing scheme), hence its name, +but can have platform-dependent meaning. +.I Name +is a string that should uniquely identify the corresponding device (eg, \f5"uart0"\fP); +again it is usually platform-dependent. +.I Intrenable +supports sharing of interrupt levels when the hardware does. +.PP +Almost invariably +.I f +is a function defined in a device driver to carry out the device-specific work associated with a given interrupt. +The pointer +.I a +is passed to +.IR f ; +typically it points to the driver's data for a given device or controller. +It also passes +.I f +a +.B Ureg* +value that +contains the registers saved by the interrupt handler (the +contents are platform specific; +see the platform's include file +.BR "ureg.h" ). +.PP +.I F +is invoked by underlying code in the kernel that is invoked directly from the hardware vectors. +It is therefore not running in any process (see +.IR kproc (9); +indeed, on many platforms +the current process pointer +.RB ( up ) +will be nil. +There are many restrictions on kernel functions running outside a process, but a fundamental one is that +they must not +.IR sleep (9), +although they often call +.B wakeup +to signal the occurrence of an event associated with the interrupt. +.IR Qio (9) +and other manual pages note which functions are safe for +.I f +to call. +.PP +The interrupt controller driver does whatever is +required to acknowledge or dismiss the interrupt signal in the interrupt controller, +before calling +.IR f , +for edge-triggered interrupts, +and after calling +.I f +for level-triggered ones. +.I F +is responsible for deal with the cause of the interrupt in the device, including any +acknowledgement required in the device, before it returns. +.PP +.I Intrdisable +removes any registration previously made by +.I intrenable +with matching parameters, and if no other +interrupt is active on +.IR v , +it masks the interrupt in the controller. +Device drivers that are not dynamically configured tend to call +.I intrenable +during reset or initialisation (see +.IR dev (9)), +but can call it at any appropriate time, and +instead of calling +.I intrdisable +they can simply enable or disable interrupts in the device as required. +.SH SOURCE +.B /sys/src/9/*/trap.c +.SH SEE ALSO +.IR malloc (9), +.IR qio (9), +.IR sleep (9), +.IR splhi (9) diff --git a/sys/man/9/kbdputc b/sys/man/9/kbdputc new file mode 100644 index 0000000000..47393c293a --- /dev/null +++ b/sys/man/9/kbdputc @@ -0,0 +1,52 @@ +.TH KBDPUTC 9 +.SH NAME +kbdputc, kbdq \- keyboard interface to \fIcons\fP(3) +.SH SYNOPSIS +.ta \w'\f5extern\ \ \f1'u +.B +.B +void kbdputc(Queue *q, int c) +.PP +.B +extern Queue *kbdq; +.SH DESCRIPTION +This is the internal interface between +.IR cons (3) +and the platform-dependent keyboard driver. +Before calling any of these functions, +the global variable +.B kbdq +must be initialised; +.IR cons (3) +does not initialise it. +This is usually done during system initialisation by the keyboard driver's +.I kbdinit +or +.I kbdenable +function , +as follows: +.IP +.EX +kbdq = qopen(4*1024, 0, 0, 0); +qnoblock(kbdq, 1); +.EE +.PP +.I Kbdputc +puts a Unicode character +.I c +(ie, a `rune') +on the given +.IR q , +as a sequence of bytes in UTF-8 encoding +(see +.IR utf (6)). +It is up to the platform's keyboard driver to map a physical keyboard character, +or a combination of them (for instance, following +.IR keyboard (6)) +to a given Unicode character. +.SH SOURCE +.B /sys/src/9/*/kbd*.c +.SH SEE ALSO +.IR cons (3), +.IR utf (6), +.IR qio (9) diff --git a/sys/man/9/kproc b/sys/man/9/kproc new file mode 100644 index 0000000000..bfe7ada0b4 --- /dev/null +++ b/sys/man/9/kproc @@ -0,0 +1,131 @@ +.TH KPROC 9 +.SH NAME +kproc, pexit, postnote \- kernel process creation, termination and interrupt +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void kproc(char *name, void (*func)(void*), void *arg) +.PP +.B +void pexit(char *note, int freemem) +.PP +.B +void postnote(Proc *p, int dolock, char *n, int flag) +.SH DESCRIPTION +.I Kproc +creates a new kernel process +to run the function +.IR func , +which is invoked as +.BR "(*func)(arg)" . +The string +.I name +is copied into the +.B text +field of the +.B Proc +structure of the new process; this value is the name of the kproc in +the output of +.IR ps (1). +The process is made runnable; it +will run when selected by the scheduler +.IR sched (9). +The process is created with base and current priorities set to +.BR PriKproc . +It shares the kernel process group and thus name space. +.PP +A kernel process terminates only when it calls +.IR pexit , +thereby terminating itself. +There is no mechanism for one process to force the termination of another, +although it can send a software interrupt using +.IR postnote . +.I Note +is a null string on normal termination, or +the cause of +If +.I freemem +is non-zero, +any memory allocated by the process is discarded; +it should normally be non-zero for any process created +by +.IR kproc . +Use the following to terminate a kernel process normally: +.IP +.EX +pexit("", 1); +.EE +.PP +to terminate a kernel process normally. +.PP +.I Postnote +sends a software interrupt to process +.IR p , +causing it, if necessary, to wake from +.IR sleep (9) +or break out of a +.IR rendezvous (2), +with an +.IR error (9) +`interrupted'. +Up to +.B NNOTE +notes can be pending at once (currently 5); +if more than that arrive, the process is forced +out of +.I sleep +and +.IR rendezvous , +but the message itself is discarded. +.I Postnote +returns non-zero iff the note has been +delivered successfully. +If +.I dolock +is non-zero, +.I postnote +synchronises delivery of the note with the debugger +and other operations of +.IR proc (3). +.I Flag +is zero, or one of the following +.TP +.B NDebug +Print the note message on the user's standard error. +Furthermore, suspend the process in a +.B Broken +state, preserving its memory, for later debugging. +.TP +.B NExit +Deliver the note quietly. +.TP +.B NUser +The note comes from another process, not the system. +.PP +The kernel uses +.I postnote +to signal processes that commit grave faults, +and to implement the note and kill functions of +.IR proc (3). +A device driver should use +.I postnote +only to tell a service process, +previously started by the driver using +.I kproc , +that it should stop; +the note will cause that process to raise an +.IR error (9). +For example, a process started to read packets from a network device could +be stopped as follows when the interface is unbound: +.IP +.EX +postnote(readp, 1, "unbind", 0); +.EE +.PP +where +.I readp +points to the appropriate +.BR Proc . +The text of the message is typically irrelevant. +.SH SOURCE +.B /sys/src/9/port/proc.c diff --git a/sys/man/9/lib b/sys/man/9/lib new file mode 100644 index 0000000000..398c7ca296 --- /dev/null +++ b/sys/man/9/lib @@ -0,0 +1,161 @@ +.TH LIB 9 +.SH NAME +lib \- C library functions used by the kernel +.SH SYNOPSIS +.B +#include "../port/lib.h" +.SH DESCRIPTION +A small collection of functions from the normal Plan 9 C +library is used in the kernel. +Only a subset is made available by declarations in +.BR lib.h , +which must be included instead of the usual +.BR . +Here is a list of the manual pages, and the functions from them declared +by +.B lib.h +for kernel use: +.IR +.TP +.IR abs (2) +.br +.I abs +.TP +.IR atof (2) +.br +.IR atoi , +.IR strtol , +.IR strtoul , +.IR strtoll , +and +.I strtoull +.TP +.IR cleanname (2) +.br +.I cleanname +.TP +.IR encode (2) +.IR dec64 +and +.I encodefmt +.TP +.IR fmtinstall (2) +.br +.BR Fmt , +.IR fmtinstall , +.IR fmtprint +and +.IR fmtstrcpy +.TP +.IR getbe (2) +.IR getbe , +.IR putbe , +.IR getle , +and +.I putle +.TP +.IR getcallerpc (2) +.br +.I getcallerpc +.TP +.IR getfields (2) +.br +.I getfields +and +.I tokenize +(see also +.IR parsecmd (9)) +.TP +.IR quote (2) +.br +for +.IR quotefmtinstall +.TP +.IR print (2) +.br +.IR print , +.IR seprint , +.IR snprint , +.IR sprint , +.IR vseprint +and +.IR vsnprint , +.TP +.IR memory (2) +.br +.IR memccpy , +.IR memchr , +.IR memcmp , +.IR memmove +and +.IR memset +.TP +.IR rune (2) +.br +.IR chartorune , +.IR runetochar , +.IR runelen , +.IR utflen +and +.IR utfrune +.TP +.IR open (2) +.br +values +.BR OCEXEC , +.BR OEXCL , +.BR OEXEC , +.BR ORCLOSE , +.BR ORDWR , +.BR OREAD , +.BR OTRUNC +and +.BR OWRITE , +.TP +.IR stat (2) +.br +data structures +.BR Dir +and +.BR Qid , +and values +.B DMDIR +etc. +and +.B QTDIR +etc. +.TP +.IR strcat (2) +.br +.IR strcat , +.IR strchr , +.IR strcmp , +.IR strcpy , +.IR strecpy , +.IR strlen , +.IR strncat , +.IR strncmp , +.IR strncpy , +.IR strrchr +and +.IR strstr +.TP +.IR wait (2) +.br +data structure +.B Waitmsg +.PP +.B lib.h +also defines +.B ERRMAX +(the limit in bytes for error strings) +and +.B KNAMELEN +(fixed-length limit in bytes for device driver file names) +.PP +A few other libraries such as +.IR memdraw (2) +and +.IR mp (2) +are called by specialised kernel components and drivers but they use +the normal include file for each library. diff --git a/sys/man/9/lock b/sys/man/9/lock new file mode 100644 index 0000000000..4df052e9c2 --- /dev/null +++ b/sys/man/9/lock @@ -0,0 +1,106 @@ +.TH LOCK 9 +.SH NAME +lock, canlock, ilock, iunlock, unlock \- spin locks +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void lock(Lock *l) +.PP +.B +int canlock(Lock *l) +.PP +.B +void unlock(Lock *l) +.PP +.B +void ilock(Lock *l) +.PP +.B +void iunlock(Lock *l) +.SH DESCRIPTION +These primitives control access to shared +resources using spin locks. +They in turn are used to build higher-level synchronisation mechanisms +such as those described in +.IR sleep (9), +.IR qlock (9) +and +.IR qio (9). +They should be used only to protect short critical sections +that update shared data structures. +.PP +.I Lock +loops repeatedly attempting acquire the spin lock +.I l +until it succeeds. +.I Lock +should not be used to lock a structure shared with an interrupt handler +unless interrupts are disabled by +.IR splhi (9) +before attempting the lock; +it is better to use +.IR ilock , +below. +.PP +.I Canlock +is non-blocking. +Only one attempt is made for the lock. +It returns non-zero if the lock was successfully acquired; 0 otherwise. +.PP +.I Unlock +releases the lock +.IR l . +A lock must be unlocked only by the locking process. +.PP +When called by a process, the functions above temporarily boost its priority +to the highest priority, +.BR PriLock ; +its original priority is restored at the end of the critical section by +.IR unlock . +On a uniprocessor, if +.I l +is unavailable, +.I lock +can reschedule unless interrupts are disabled before entering +.I lock +or there is no current process (eg, when executing the scheduler). +.PP +.I Ilock +disables interrupts before attempting to acquire the lock. +It should be used to lock a resource shared between a process and an interrupt handler. +On a uniprocessor, disabling interrupts is sufficient to exclude an interrupt handler +from the critical section, +and on a multiprocessor the spin lock excludes an interrupt handler running on another processor. +.I Ilock +never reschedules the caller, nor must a caller allow itself to be rescheduled +(eg, by calling +.IR sleep (9)) +before releasing the lock. +.PP +.I Iunlock +releases a lock previously got by +.IR ilock . +.SH SOURCE +.B /sys/src/9/port/taslock.c +.br +.B /sys/src/9/*/l.s +.SH SEE ALSO +.IR qlock (9) +.SH DIAGNOSTICS +The lock functions +guard against the possibility of never acquiring the lock by capping the number of lock attempts. +If the limit is reached, a message of +the following form is written on the console: +.IP +.EX +lock loop on \fIlock-address\fP key \fIkey-value\fP pc \fIcaller-pc\fP held by pc \fIlock-pc\fP +.EE +.PP +Most lock loops represent deadlocks caused by failing to unlock a resource, +attempting to lock (eg, by recursive call) a resource already held by the process, +inconsistent locking and unlocking of nested resources, using a spin-lock +to guard code that reschedules, using +.I lock +not +.I ilock +to interlock with an interrupt routine, and similar blunders. diff --git a/sys/man/9/malloc b/sys/man/9/malloc new file mode 100644 index 0000000000..245c69eb0c --- /dev/null +++ b/sys/man/9/malloc @@ -0,0 +1,193 @@ +.TH MALLOC 9 +.SH NAME +malloc, mallocz, smalloc, realloc, calloc, free, msize, setmalloctag, setrealloctag, getmalloctag, getrealloctag, malloctopoolblock \- kernel memory allocator +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void* malloc(ulong size) +.PP +.B +void* mallocalign(ulong size, ulong align, long offset, ulong span) +.PP +.B +void* mallocz(ulong size, int clr) +.PP +.B +void* smalloc(ulong size) +.PP +.B +void* realloc(void *p, ulong size) +.PP +.B +void* calloc(ulong n, ulong szelem) +.PP +.B +void free(void *ptr) +.PP +.B +ulong msize(void *ptr) +.PP +.B +void setmalloctag(void *ptr, ulong tag) +.PP +.B +ulong getmalloctag(void *ptr) +.PP +.B +void setrealloctag(void *ptr, ulong tag) +.PP +.B +ulong getrealloctag(void *ptr) +.PP +.B +void* malloctopoolblock(void*) +.PP +.SH DESCRIPTION +These are kernel versions of the functions in +.IR malloc (2). +They allocate memory from the +.B mainmem +memory pool, +which is managed by +the allocator +.IR pool (2), +which in turn replenishes the pool as required by calling +.IR xalloc (9). +All but +.I smalloc +(which calls +.IR sleep (9)) +may safely be called by interrupt handlers. +.PP +.I Malloc +returns a pointer to a block of at least +.I size +bytes, initialised to zero. +The block is suitably aligned for storage of any type of object. +The call +.B malloc(0) +returns a valid pointer rather than null. +.I Mallocz +is similar, but only clears the memory if +.I clr +is non-zero. +.PP +.I Smalloc +returns a pointer to a block of +.I size +bytes, initialised to zero. +If the memory is not immediately available, +.I smalloc +retries every 100 milliseconds until the memory is acquired. +.PP +.I Mallocalign +allocates a block of at least +.I n +bytes of memory respecting alignment contraints. +If +.I align +is non-zero, +the returned pointer is aligned to be equal to +.I offset +modulo +.IR align . +If +.I span +is non-zero, +the +.I n +byte block allocated will not span a +.IR span -byte +boundary. +.PP +.I Realloc +changes the size of the block pointed to by +.I p +to +.I size +bytes, +if possible without moving the data, +and returns a pointer to the block. +The contents are unchanged up to the lesser of old and new sizes, +and any new space allocated is initialised to zero. +.I Realloc +takes on special meanings when one or both arguments are zero: +.TP +.B "realloc(0,\ size) +means +.LR malloc(size) ; +returns a pointer to the newly-allocated memory +.TP +.B "realloc(ptr,\ 0) +means +.LR free(ptr) ; +returns null +.TP +.B "realloc(0,\ 0) +no-op; returns null +.PD +.PP +.I Calloc +returns a pointer to a block of memory of at least +.I "n*szelem" +bytes, initialised to zero. +New code should use +.I mallocz +instead. +.PP +The argument to +.I free +is a pointer to a block of memory allocated by one of the routines above, which +is returned to the allocation pool, or a null pointer, which is ignored. +.PP +When a block is allocated, sometimes there is some extra unused space at the end. +.I Msize +grows the block to encompass this unused space and returns the new number +of bytes that may be used. +.PP +The memory allocator maintains two word-sized fields +associated with each block, the ``malloc tag'' and the ``realloc tag''. +By convention, the malloc tag is the PC that allocated the block, +and the realloc tag the PC that last reallocated the block. +These may be set or examined with +.IR setmalloctag , +.IR getmalloctag , +.IR setrealloctag , +and +.IR getrealloctag . +When allocating blocks directly with +.I malloc +and +.IR realloc , +these tags will be set properly. +If a custom allocator wrapper is used, +the allocator wrapper can set the tags +itself (usually by passing the result of +.IR getcallerpc (2) +to +.IR setmalloctag ) +to provide more useful information about +the source of allocation. +.PP +.I Malloctopoolblock +takes the address of a block returned by +.I malloc +and returns the address of the corresponding +block allocated by the +.IR pool (2) +routines. +.SH SOURCE +.B /sys/src/9/port/alloc.c +.SH DIAGNOSTICS +All functions except +.I smalloc +return a null pointer if space is unavailable. +If the allocated blocks have no malloc or realloc tags, +.I getmalloctag +and +.I getrealloctag +return +.BR ~0 . +.SH SEE ALSO +.IR pool (2), +.IR xalloc (9) diff --git a/sys/man/9/newchan b/sys/man/9/newchan new file mode 100644 index 0000000000..7cba54f9ea --- /dev/null +++ b/sys/man/9/newchan @@ -0,0 +1,225 @@ +.TH NEWCHAN 9 +.SH NAME +newchan, chanfree, cclose, eqqid, eqchan, isdir, fdtochan, namec \- channel operations +.SH SYNOPSIS +.ta \w'\fLChan* 'u +.B +Chan* newchan(void) +.PP +.B +void chanfree(Chan *c) +.PP +.B +int eqqid(Qid a, Qid b) +.PP +.B +int eqchan(Chan *a, Chan *b, int pathonly) +.PP +.B +void isdir(Chan *c) +.PP +.B +Chan* fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref) +.PP +.B +Chan* namec(char *pathname, int amode, int omode, ulong perm) +.PP +.B +void cclose(Chan *c) +.SH DESCRIPTION +A value of type +.B Chan +represents a kernel channel for I/O and name space operations. +It has the following public structure: +.IP +.EX +typedef struct Chan{ + ushort type; /* driver name */ + ulong dev; /* instance number */ + ushort mode; /* open mode */ + ushort flag; /* COPEN set once opened */ + ulong offset; /* current file offset */ + Qid qid; /* unique id (path, vers) */ + Path* path; /* name by which it was accessed */ +.EE +.PP +.I Newchan +returns a pointer to a newly allocated channel (sleeping if necessary until memory is available). +Device drivers do not normally call +.IR newchan +directly, but instead allocate channels using either +.IR devattach , +when a process attaches to the device's root, +or +.IR devclone , +when an existing channel is cloned; +see +.IR devattach (9). +.PP +.I Chanfree +frees the channel structure +.I c +for reuse. +.PP +.I Eqqid +returns 1 if +.B Qid +values +.I a +and +.I b +are equal +(ie, +both their +.B path +and +.B vers +members are equal); +it returns 0 otherwise. +.PP +.I Eqchan +returns 1 if +.I a +and +.I b +have the same +.BR qid , +.BR type +and +.BR dev +members +(ie, they represent the same file); +it returns 0 otherwise. +If +.I pathonly +is non-zero, the comparison of the two +.B qid +members compares only their +.B path +values, +ignoring the version field +.BR vers . +.PP +.I Isdir +checks that a given channel +.I c +is a directory. +If so, it returns; +otherwise, it generates an +.IR error (9), +.BR Enotdir . +.PP +The +.B Fgrp +structure represents an array of open files, each +represented by a +.BR Chan , +indexed by integer file descriptors. +A given +.B Fgrp +can be shared between processes. +.PP +.I Fdtochan +returns a pointer to the +.B Chan +corresponding to file descriptor +.I fd +in file descriptor group +.I f +(almost invariably +.BR up->fgrp , +the file descriptor group for the current process). +If +.I mode +is a valid mode for +.IR open (2), +typically +.BR OREAD , +.B OWRITE +or +.BR ORDWR , +it must correspond to the mode with which +.I fd +was originally opened; if +.I mode +is +.BR -1 , +no check is made. +If +.I chkmnt +is non-zero, +.I c +must not be a channel in use by the mount driver +.IR mnt (3). +On successful return, if +.I iref +is non-zero, the channel's reference count has been incremented. +.I Fdtochan +calls +.IR error (9) +if it detects invalid uses, in particular an invalid file descriptor +.IR fd . +.PP +.I Namec +looks up a +.I pathname +in the current name space and returns a channel. +.I Amode +determines the mode of look up, and must be one of the constants below: +.TF Aaccess +.PD +.TP +.B Aaccess +Access file for information, as in the stat command or call. +.TP +.B Atodir +Access file as directory (the +.B QTDIR +bit of its +.B qid.type +must be set). +.TP +.B Aopen +Access for I/O. +.TP +.B Amount +Access directory to be mounted upon. +.TP +.B Acreate +File is to be created. +.PP +If +.I amode +is +.B Aopen +or +.BR Acreate , +.I omode +should be a mode suitable for +.IR open (2); +if +.BR Acreate , +.I perm +should be valid file permissions. +In all other cases, +.I omode +and +.I perm +can be zero. +.PP +.I Cclose +decrements the reference count on +.IR c ; +if no further references remain, it +calls the corresponding device's +.B Dev.close +to close the channel, and frees +.IR c . +.SH SOURCE +.B /sys/src/9/port/chan.c +.SH DIAGNOSTICS +Most functions call +.IR error (9) +on any sort of error. +.SH SEE ALSO +.IR ref (9) diff --git a/sys/man/9/panic b/sys/man/9/panic new file mode 100644 index 0000000000..2f98be1824 --- /dev/null +++ b/sys/man/9/panic @@ -0,0 +1,25 @@ +.TH PANIC 9 +.SH NAME +panic \- abandon hope +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void panic(char *fmt, ...) +.SH DESCRIPTION +.I Panic +writes a message to the console and +causes the system to give up the ghost. +It enables interrupts, dumps the kernel stack, +and halts the current processor; +if more than one, others will gradually come to a halt. +Depending on configuration settings, the platform-dependent +.I exit +might reboot the system. +The format +.I fmt +and associated arguments are the same as those for +.IR print (9). +.I Panic +adds a prefix +.L "panic: " +and a trailing newline. diff --git a/sys/man/9/parsecmd b/sys/man/9/parsecmd new file mode 100644 index 0000000000..0c1ef75fe1 --- /dev/null +++ b/sys/man/9/parsecmd @@ -0,0 +1,107 @@ +.TH PARSECMD 9 +.SH NAME +parsecmd, cmderror, lookupcmd \- parse device commands +.SH SYNOPSIS +.ta \w'\fLCmdbuf* 'u +.B +Cmdbuf* parsecmd(char *a, int n) +.PP +.B +void cmderror(Cmdbuf *cb, char *s) +.PP +.B +Cmdtab* lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) +.SH DESCRIPTION +.I Parsecmd +is an interface to +.I tokenize +(see +.IR getfields (2)), +that safely parses a command, with blank-separated fields, as might be +written to a device's +.B ctl +file. +The buffer +.I a +and count +.I n +can be those passed to the driver's +.I write +function. +.I Parsecmd +converts the byte array (which might not be null-terminated) to a null-terminated string, +trimming any trailing new line, +before invoking +.I tokenize +to break the string into arguments, interpreting blank and tab as field separators +when they are not quoted +(in the style of +.IR rc (1)). +It returns a pointer to a dynamically-allocated +.B Cmdbuf +structure, +which holds a copy of the string as +modified by +.IR parsefields , +and the resulting fields; it is defined as follows: +.IP +.EX +.ta 6n +\w'char* 'u +typedef +struct Cmdbuf +{ + char buf[128]; + char *f[16]; + int nf; +} Cmdbuf; +.EE +.PP +The array +.B f +holds the field pointers; +.B nf +gives the number of fields. +.B Cmdbuf +is allocated by +.I smalloc +(see +.IR malloc (9)), +and the caller is responsible for freeing it using +.IR free . +.I Cmderror +prepends the given format with the original command, +then calls +.IR error (9). +.PP +Command strings may be turned into a (typically enumerated) +integer with +.IR lookupcmd . +The catchall +.L * +matches any text. Unrecognized commands, or commands +given an unacceptable number of arguments generate a +call to +.IR error . +The definition is as follows +.IP +.EX +.ta 6n +\w'char* 'u +struct Cmdtab +{ + int index; + char *cmd; + int narg; +}; +.EE +.PP +The integer +.B index +is the number returned on command match. +The string +.B cmd +is the command name, and +.B narg +is 0 (indicating a varadic function) or the +number of arguments. +.SH SOURCE +.B /sys/src/9/port/parse.c diff --git a/sys/man/9/qio b/sys/man/9/qio new file mode 100644 index 0000000000..32e9b28fdc --- /dev/null +++ b/sys/man/9/qio @@ -0,0 +1,480 @@ +.TH QIO 9 +.SH NAME +qio: qget, qdiscard, qconsume, qpass, qproduce, qcopy, qopen, qbread, qread, qbwrite, qwrite, qiwrite, qfree, qclose, qhangup, qreopen, qlen, qwindow, qcanread, qsetlimit, qnoblock, qflush, qfull \- queued I/O for devices +.SH SYNOPSIS +.ta \w'\fLQueue* 'u +.B +Queue* qopen(int limit,int msg, void (*kick)(void*),void *arg) +.PP +.B +void qhangup(Queue *q, char *reason) +.PP +.B +void qclose(Queue *q) +.PP +.B +void qreopen(Queue *q) +.PP +.B +void qfree(Queue *q) +.PP +.B +long qbwrite(Queue *q, Block *b) +.PP +.B +long qwrite(Queue *q, void *buf, int len) +.PP +.B +int qpass(Queue *q, Block *b) +.PP +.B +int qpassnolim(Queue *q, Block *b) +.PP +.B +int qproduce(Queue *q, void *buf, int len) +.PP +.B +int qiwrite(Queue *q, void *buf, int len) +.PP +.B +Block* qbread(Queue *q, int len) +.PP +.B +long qread(Queue *q, void *buf, int len) +.PP +.B +Block* qcopy(Queue *q, int len, ulong offset) +.PP +.B +Block* qget(Queue *q) +.PP +.B +int qconsume(Queue *q, void *buf, int len) +.PP +.B +int qdiscard(Queue *q, int len) +.PP +.B +void qflush(Queue *q) +.PP +.B +int qlen(Queue *q) +.PP +.B +int qwindow(Queue *q) +.PP +.B +int qcanread(Queue *q) +.PP +.B +void qsetlimit(Queue *q, int limit) +.PP +.B +void qnoblock(Queue *q, int nonblock) +.PP +.B +int qfull(Queue *q) +.SH DESCRIPTION +This suite of functions provides serial data buffering for device drivers. +Data is stored in a +.B Queue +structure as a sequence of variable-sized +.BR Blocks ; +see +.IR allocb (9). +.PP +.I Qopen +initialises and returns a pointer to a new +.BR Queue , +configuring it according to the following parameters: +.TF limit +.PD +.TP +.I limit +Set the queue limit (high water mark) in bytes. +.TP +.I msg +Set message mode if non-zero; otherwise, stream mode (discussed below). +.TP +.I kick +Optional flow-control function called by +.I qbread +to restart writers, and by +.I qbwrite +(also +.IR qiwrite ) +to restart readers. +.TP +.I arg +Argument to pass to +.I kick +.PP +.I Qhangup +marks +.I q +as `hung up' +for the given +.IR reason +.RB ( Ehungup +by default). +Subsequent attempts to write to the queue raise an +.IR error (9). +.I Qhangup +does not flush the queue: subsequent read requests are +handled normally until the queue empties. +.I Qread +and the other functions then return their conventional values +for a hungup stream: 0, -1 or a null pointer, depending on the function. +After a few such attempts by any process, an +.IR error (9) +is raised (typically +.BR Ehungup ) +on each subsequent read. +.PP +If queued data is left unread, and not flushed by +.I qflush +or +.IR qclose , +the data will again be readable following a subsequent +.IR qreopen . +.PP +.I Qclose +also marks a given +.I q +as `hung up', +but removes and frees any queued data Blocks. +.I Qclose +ignores calls when +.I q +is null. +.PP +.I Qreopen +makes a closed or hung up queue available for use again. +The queue's data limit is reset to the +.I limit +value given when the queue was first created by +.IR qopen , +cancelling the effect of any previous call to +.IR qsetlimit . +.PP +.I Qfree +closes +.I q +with +.I qclose +and frees it. +The caller must ensure that no references remain; +these functions do not keep a reference count. +.SS "Flow control" +The queue I/O routines provide a flow control mechanism to coordinate producers and consumers. +Each queue has a limit on the number of bytes queued, its `high water mark', +initially set when the queue is created, but adjustable by +.IR qsetlimit , +below. +The low water mark is not set explicitly: +it is always half the current queue limit. +When the high water mark is exceeded, writes normally block until a reader drains the +queue below its low water mark; the writer is then allowed to proceed. +Conversely, readers normally block when the queue is empty, until a writer +arrives with data, or the queue is closed. +.PP +A queue can be given a +.I kick +function when the queue is created by +.IR qopen . +The function is invoked by +.IR qread +and +.IR qbread , +to prod an output routine when the queue falls below the low-water mark, and by +.IR qwrite , +.IR qbwrite +and +.IR qiwrite , +to notify a reader that a queue is no longer empty. +Because +.I kick +is called from the reading (or writing) process, or an interrupt handler, it +must not block. +.PP +Interrupt handlers must not +.IR sleep (9), +and are therefore restricted to using only the non-blocking functions described below. +.SS "Stream mode and message mode" +In stream mode, +no read will return more than one +block +of data, but +a read can split a block that contains more data than requested, leaving the remainder +in a new block at the front of the Queue. +Writes of more than the maximum +.B Block +size (currently 128k bytes) +are split into as many Blocks as required, each written separately to the queue, +in order, but with possible flow-control between them. +The queue is locked meanwhile, however, so that data from other writers is not intermingled. +.PP +In message mode, by contrast, a read will return at most +one block's worth of data, but the remainder of a partially-read block will be discarded, +not returned to the queue. +If a write count exceeds the maximum +.B Block +size, the excess data is discarded: +at most a single block can be queued. +.PP +The mode of the queue should be taken into account in the descriptions below +of the following functions: +.IR qwrite , +.IR qiwrite , +.IR qbread +and +.IR qconsume . +No other functions are aware of the distinction. +.SS "Write operations (flow controlled)" +.I Qwrite +copies +.I len +bytes of data from +.I buf +into one or more +.B Blocks +which it places on the +.IR q . +.I Qwrite +always returns +.IR len . +It can implement message mode. +.PP +.I Qbwrite +places the single Block +.I b +on the tail of +.IR q , +waking any sleeping reader. +If the queue is full, the +writing process blocks until a reader +has reduced the queued data to +the low-water mark; +if the queue is non-blocking +(see +.I qnoblock +below), +the data is discarded without notice. +.I Qbwrite +normally returns +.IR len , +but raises an +.IR error (9) +if the queue is closed (see +.I qhangup +and +.IR qclose ). +The block +.I b +is always freed. +Note that +.I b +can be empty (zero-length), to punctuate the data in a queue. +.I Qbwrite +cannot handle a list of Blocks; +.I qpass +must be used instead. +.SS Non-blocking writes +.PP +.I Qproduce +returns -1immediately if +.I q +is full. +Otherwise, it queues +.I len +bytes of data from +.I buf +in a single +.B Block +on +.I q +and returns the number of bytes written. +.PP +.I Qpass +attempts to place the list of Blocks headed by +.I b +on +.IR q , +returning the number of bytes written if successful. +If +.I q +was full, it +frees the Block list +.I b +and returns -1. +.PP +.I Qpassnolim +puts the Block list +.I b +on +.I q +regardless of flow control; it returns the number of bytes in the list +.IR b . +.PP +.I Qiwrite +is a variant of +.I qwrite +used exclusively by the kernel print function, +to allow printing by interrupt handlers; +.I qiwrite +could be used with care by other routines, but +.IR qproduce +is preferable. +.I Qiwrite +writes the +.I len +bytes of data at +.I buf +into the +.I q +without regard to flow control; +the writer never blocks. +The queue is assumed to be open. +.I Qiwrite +always returns +.IR len . +It can implement message mode. +.SS "Read operations (flow controlled)" +.I Qbread +blocks until data arrives on +.IR q , +then +returns the first +.BR Block ; +it limits the data returned +to +.I len +bytes (in the manner depending on the mode of +.IR q ). +It returns a null pointer if the queue has hung up. +.PP +.I Qread +reads a Block of up to +.I len +bytes from +.I q +using +.IR qbread , +and copies the data in the Block into +.IR buf , +then frees the Block and returns +the number of bytes read. +.I Qread +returns 0 on end of file or error (hangup). +It can implement message mode. +.PP +.I Qcopy +returns a Block with a copy of data from the queue (the data remains on the queue). +The copy begins +.I offset +bytes into the queue's data and proceeds until +.I len +bytes have been copied or no more data remains. +The Block's read and write pointers delimit the data copied into it. +.I Qcopy +can be used by a reliable transport protocol to copy a packet for transmission, +leaving the data queued for possible retransmission, if unacknowledged. +.SS Non-blocking reads +.PP +.I Qconsume +returns -1 immediately if +.I q +is empty. +Otherwise, it +copies up to +.I len +bytes from the first +.B Block +on the queue into +.IR buf , +returning the number of bytes copied. +It can implement message mode. +.PP +.I Qget +returns a null pointer immediately if +.I q +is empty or closed. +Otherwise, it +returns the first +.B Block +on the queue. +.SS "Discard and flush" +.I Qdiscard +removes the first +.I len +data bytes from +.IR q ; +it returns the number of bytes actually discarded, in case +the queue is shorter than +.IR len . +If the queue drains below the low-water mark, +.I qdiscard +wakes any sleeping writers. +Since it does not block, +.I qdiscard +can safely be called from interrupt handlers. +It is useful in transport protocol drivers to remove data from the queue +once acknowledged. +.PP +.I Qflush +discards all data waiting on +.IR q , +waking any waiting writer. +.SS "Queue status" +The following functions return a Queue's status. +Note that between a call to one of these functions and another operation, +the state can change if a driver allows concurrent access by +either another process or an interrupt handler. +.PP +.I Qlen +returns the number of bytes queued on +.IR q . +.PP +.I Qwindow +returns the number of bytes that can be written before reaching the queue's high-water mark. +A return of 0 means that a write operation will certainly block; +a non-zero return gives no guarantees (see +.IR qfull , +below). +.PP +.I Qcanread +returns 1 if any data queued is queued. A subsequent read operation will not block. +.PP +.I Qfull +returns non-zero if +.I q +is flow-controlled and a write would block or a non-blocking write would return an error. +(Note that the implementation allows +.I qwindow +to return non-zero yet +.I qfull +to return true.) +.SS "Queue control" +.I Qsetlimit +sets the high water mark for the queue to +.IR limit . +Note that +.I qopen +saves the initial queue limit. +If the queue is closed and reopened (by +.IR qreopen ) +that initial limit is restored. +.PP +.I Qnoblock +sets or resets non-blocking mode. +If +.I nonblock +is non-zero, +the queue becomes non-blocking, and +data written to a queue beyond its high water mark is discarded +by calls that would otherwise block. +.SH SOURCE +.B /sys/src/9/port/qio.c +.SH SEE ALSO +.IR allocb (9), +.IR ref (9) diff --git a/sys/man/9/qlock b/sys/man/9/qlock new file mode 100644 index 0000000000..d0acf170ca --- /dev/null +++ b/sys/man/9/qlock @@ -0,0 +1,105 @@ +.TH QLOCK 9 +.SH NAME +qlock, qunlock, canqlock, rlock, runlock, wlock, wunlock \- serial synchronisation +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void qlock(QLock *l) +.PP +.B +void qunlock(QLock *l) +.PP +.B +int canqlock(QLock *l) +.PP +.B +void rlock(RWlock *l) +.PP +.B +void runlock(RWlock *l) +.PP +.B +int canrlock(RWlock *l) +.PP +.B +void wlock(RWlock *l) +.PP +.B +void wunlock(RWlock *l) +.SH DESCRIPTION +The primitive locking functions described in +.IR lock (9) +guarantee mutual exclusion, but they implement spin locks, +and should not be used if the process might +.IR sleep (9) +within a critical section. +The following functions serialise access to a resource by forming an orderly +queue of processes. +.PP +Each resource to be controlled is given an associated +.B QLock +structure; it is usually most straightforward to put the +.B QLock +in the structure that represents the resource. +It must be initialised to zero before use +(as guaranteed for global variables and for structures allocated by +.IR malloc ). +.PP +On return from +.IR qlock , +the process has acquired the lock +.IR l , +and can assume exclusive access to the associated resource. +If the lock is not immediately available, the requesting process is placed on a +FIFO queue of processes that have requested the lock. +Processes on this list are blocked in the +.L Queueing +state. +.PP +.I Qunlock +unlocks +.I l +and schedules the first process queued for it (if any). +.PP +.I Canqlock +is a non-blocking form of +.IR qlock . +It tries to obtain the lock +.I l +and returns true if successful, and 0 otherwise; +it always returns immediately. +.PP +.B RWlock +is a form of lock for resources that have distinct readers and writers. +It allows concurrent readers but gives each writer exclusive access. +A caller announces its read or write intentions by choice of lock (and unlock) function; +the system assumes the caller will not modify a structure accessed under read lock. +.PP +.I Rlock +acquires +.I l +for reading. +The holder can read but agrees not to modify the resource. +There may be several concurrent readers. +.I Canrlock +is non-blocking: it returns non-zero if it successfully acquired the lock immediately, +and 0 if the resource was unavailable. +.PP +.I Runlock +returns a read lock; +the last reader out enables the first writer waiting (if any). +.PP +.I Wlock +acquires a write lock. +The holder of such a lock may assume exclusive access to the resource, +and is allowed to modify it. +.PP +.I Wunlock +returns a write lock. +The next pending process, whether reader or writer, is scheduled. +.SH SOURCE +.B /sys/src/9/port/qlock.c +.br +.SH SEE ALSO +.IR lock (9), +.IR splhi (9) diff --git a/sys/man/9/readnum b/sys/man/9/readnum new file mode 100644 index 0000000000..05944d3bdc --- /dev/null +++ b/sys/man/9/readnum @@ -0,0 +1,58 @@ +.TH READNUM 9 +.SH NAME +readnum, readstr \- return values from read from device +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +int readstr(ulong off, char *buf, ulong n, char *str) +.PP +.B +int readnum(ulong off, char *buf, ulong n, ulong val, int size) +.SH DESCRIPTION +.I Readstr +and +.I readnum +simplify the return of strings and numbers from device +.I read +routines, +because they deal with any buffering and boundary cases. +Several parameters to the read call are often handed on directly +to these functions: +the file offset, as +.IR off ; +the address of the user's buffer, as +.IR buf ; +and the number of bytes requested, as +.IR n . +Both functions return the number of bytes they have stored in +.IR buf , +and which can often be returned directly from the device read routine. +.PP +.I Readstr +satisfies a read by copying data into +.I buf +from the NUL-terminated string in +.IR str . +The data transferred is selected and limited by +.IR off , +.I n +and the length of +.IR str . +.PP +.I Readnum +converts the unsigned integer +.I val +to a decimal representation in +.IR buf . +The value is right-justified in a field of +.IR size "-1" +places and is followed by a blank. +.I Size +can be the global constant +.L NUMSIZE +for 32-bit integers; +the largest +.I size +allowed is 64 bytes. +.SH SOURCE +.B /sys/src/9/port/devcons.c diff --git a/sys/man/9/ref b/sys/man/9/ref new file mode 100644 index 0000000000..25d0349b72 --- /dev/null +++ b/sys/man/9/ref @@ -0,0 +1,59 @@ +.TH REF 9 +.SH NAME +Ref, incref, decref \- reference counts +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.PP +.B +int incref(Ref *r) +.PP +.B +int decref(Ref *r) +.SH DESCRIPTION +A +.B Ref +structure holds a reference count for a data structure: +.IP +.EX +typedef struct +struct Ref +{ + Lock; + long ref; +} Ref; +.EE +.PP +The reference count proper is found in +.BR ref ; +the +.B Lock +prevents concurrent updates +(see +.IR lock (9)). +.PP +.I Incref +atomically increments the reference count +.IR r , +and returns the new count. +.PP +.I Decref +atomically decrements the reference count +.IR r , +and returns the new count. +.SH EXAMPLES +Release a structure containing a +.B Ref +on last use. +.IP +.EX +if(decref(s) == 0) + free(s); +.EE +.SH SOURCE +.B /sys/src/9/port/chan.c +.SH DIAGNOSTICS +.I Decref +will +.IR panic (9) +if the count goes negative, +revealing a reference counting bug. diff --git a/sys/man/9/seconds b/sys/man/9/seconds new file mode 100644 index 0000000000..7f211cb36b --- /dev/null +++ b/sys/man/9/seconds @@ -0,0 +1,93 @@ +.TH SECONDS 9 +.SH NAME +seconds, ticks, fastticks, HZ, MS2HZ, MS2TK, TK2MS, TK2SEC \- kernel times and time conversions +.SH SYNOPSIS +.ta \w'\fL#define 'u +.B +long seconds(void) +.PP +.B +m->ticks +.br +MACHP(0)->ticks +.PP +.B +vlong fastticks(uvlong *hz) +.PP +.EX +#define HZ ... +#define MS2HZ(t) ... +#define TK2SEC(t) ... +#define TK2MS(t) ... +#define MS2TK(m) ... +.EE +.SH DESCRIPTION +.I Seconds +returns the system's idea of the current time as the number of seconds +since the start of the epoch +(00:00:00 GMT, January 1, 1970). +.PP +The +.B ticks +field of the +.B Mach +structure pointed to by +.B m +returns the number of system-dependent clock ticks on the +given processor since system boot. +On a multiprocessor, +.B MACHP(0) +is sometimes used to provide a reference time, since the tick value +might vary slightly across processors. +.PP +.I Fastticks +returns the number of ticks since boot as measured by the +fastest clock provided by the platform. +The frequency of the clock, in ticks per second, +is returned through +.IR hz , +unless it is nil. +.PP +The system clock frequencies are platform-dependent. +Several symbolic constants and macro functions are defined by +the file +.B mem.h +to convert between different time units: +.TF TK2SEC(t) +.PD +.TP +.B HZ +The number of clock ticks per second. +.TP +.B MS2HZ +Milliseconds per clock tick. +.TP +.BI TK2SEC( t ) +Convert +.I t +clock ticks to seconds and return the result (truncating not rounding). +.TP +.BI TK2MS( t ) +Convert +.I t +clock ticks to milliseconds and return the result. +.TP +.BI MS2TK( m ) +Convert +.I m +milliseconds to clock ticks and return the result (truncating). +.PP +The functions are often used to calculate delays for timing functions, +for instance: +.IP +.EX +if(atactlrwait(dp->cp, DHmagic, 0, MS2TK(100))){ + ... +} +.EE +.SH SOURCE +.B /sys/src/9/*/mem.h +.br +.B /sys/src/9/*/clock.c +.br +.B /sys/src/9/port/tod.c diff --git a/sys/man/9/sleep b/sys/man/9/sleep new file mode 100644 index 0000000000..7c3aa445ce --- /dev/null +++ b/sys/man/9/sleep @@ -0,0 +1,123 @@ +.TH SLEEP 9 +.SH NAME +sleep, wakeup, tsleep, return0 \- process synchronisation +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void sleep(Rendez *r, int (*f)(void*), void *arg) +.PP +.B +void wakeup(Rendez *r) +.PP +.B +void tsleep(Rendez *r, int (*f)(void*), void *arg, int ms) +.PP +.B +int return0(void *arg) +.PP +.SH DESCRIPTION +A process running in the kernel can use these functions to +synchronise with an interrupt handler or another kernel process. +In particular, they are used by device drivers to wait for an event to be signalled on +receipt of an interrupt. +(In practice, they are most often used indirectly, through +.IR qio (9) +for instance.) +.PP +The caller of +.I sleep +and a caller of +.I wakeup +share a +.B Rendez +structure, to provide a rendezvous point between them +to synchronise on an event. +.I Sleep +uses a condition function +.I f +that returns true if the event has occurred. +.PP +.I Sleep +evaluates +.IB f ( arg ). +If true, the event has happened and +.I sleep +returns immediately. +Otherwise, +.I sleep +blocks on the event variable +.IR r , +awaiting +.IR wakeup . +.PP +.I Wakeup +is called by either a process or an interrupt handler to wake any process +sleeping at +.IR r , +signifying that the corresponding condition is true (the event has occurred). +It has no effect if there is no sleeping process. +.PP +.I Tsleep +is similar to +.IR sleep , +except that if the condition +.IB f ( arg ) +is false and the caller does sleep, +and nothing else wakes it within +.I ms +millliseconds, +the system will wake it. +.IR Tsleep 's +caller must check its environment to decide whether timeout or the event +occurred. +The timing provided by +.I tsleep +is imprecise, but adequate in practice for the normal use of protecting against +lost interrupts and otherwise unresponsive devices or software. +.PP +.I Return0 +ignores its arguments and returns zero. It is commonly used as +the predicate +.I f +in a call to +.I tsleep +to obtain a time delay, using a +.B Rendez +variable +.B sleep +in the +.B Proc +structure, for example: +.IP +.B tsleep(&up->sleep, return0, nil, 10); +.PP +Both +.I sleep +and +.I tsleep +can be interrupted by +.IR swiproc +(see +.IR kproc (9)), +causing a non-local goto through a call to +.IR error (9). +.SH SOURCE +.B /sys/src/9/port/proc.c +.SH DIAGNOSTICS +There can be at most one process waiting on a +.BR Rendez , +and if two processes collide, the system will +.IR panic (9) +.RB (`` "double sleep" ''). +Access to a +.B Rendez +must therefore be serialised by some other mechanism, usually +.IR qlock (9). +.SH SEE ALSO +.IR lock (9), +.IR qlock (9), +.IR delay (9) +.br +``Process Sleep and Wakeup on a Shared-memory Multiprocessor'', +in +.I "Plan 9 Programmer's Manual: Volume 2". diff --git a/sys/man/9/splhi b/sys/man/9/splhi new file mode 100644 index 0000000000..66483850cc --- /dev/null +++ b/sys/man/9/splhi @@ -0,0 +1,57 @@ +.TH SPLHI 9 +.SH NAME +splhi, spllo, splx, islo \- enable and disable interrupts +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +int spllo(void) +.PP +.B +int splhi(void) +.PP +.B +void splx(int x) +.PP +.B +int islo(void) +.SH DESCRIPTION +These primitives enable and disable maskable interrupts on the current +processor. +Generally, device drivers should use +.I ilock +(see +.IR lock (9)), +.IR sleep (9), +or the functions in +.IR qio (9) +to control interaction between processes and interrupt handlers. +Those routines (but not these) provide correct synchronisation on multiprocessors. +.PP +.I Spllo +enables interrupts and returns a flag representing the previous interrupt enable state. +It must not normally be called from interrupt level. +.PP +.I Splhi +disables all maskable interrupts and returns the previous interrupt enable state. +The period during which interrupts are disabled had best be short, +or real-time applications will suffer. +.PP +.I Splx +restores the interrupt enable state +state to +.IR x , +which must be a value returned +by a previous call to +.I splhi +or +.IR spllo . +.PP +.I Islo +returns true (non-zero) if interrupts are currently enabled, and 0 otherwise. +.SH SOURCE +.B /sys/src/9/*/l.s +.SH SEE ALSO +.IR lock (9), +.IR qio (9), +.IR sleep (9), +.IR intrenable (9) diff --git a/sys/man/9/uartp8250 b/sys/man/9/uartp8250 new file mode 100644 index 0000000000..2db0312ab6 --- /dev/null +++ b/sys/man/9/uartp8250 @@ -0,0 +1,77 @@ +.TH UARTP8250 9 +.SH NAME +uartp8250 \- portable 8250-style uarts +.SH SYNOPSIS +.EX +#include "../port/uartp8250.h" + +typedef struct Ctlr Ctlr; +struct Ctlr { + void *reg; + uint (*get)(void*, int); + void (*set)(void*, int, uint); + int (*itr)(Uart*, int); + + int irq; + int tbdf; + int iena; + + uchar sticky[8]; + + Lock; + int hasfifo; + int checkfifo; + int fena; +}; +.EE +.PP +.ta \w'\fLPhysUart 'u +.PP +.B +PhysUart p8250physuart; +.PP +.B +void i8250interrupt(Ureg*, void*); +.SH DESCRIPTION +P8250 provides a portable interface for 8250-style uarts. +All necessary functions are provided except for +.BR get , +.BR set , +and +.BR itr . +These functions get or set an 8250 register or enable +or disable the interrupt, respectively. Since the +.B PhysUart +structure is required for device discovery, a dummy +version needs to be provided +.IP +.EX +PhysUart myphysuart = { + .name = "myuart", + .pnp = mypnp, +}; +.EE +.PP +On entry of the pnp function, the +.B PhysUart +can be filled out: +.EX + memmove(&myphysuart, &p8250physuart, sizeof(PhysUart)); + myphysuart.name = "myuart"; + myphysuart.pnp = mypnp; +.EE +.PP +as can the +.B Ctlr +structure, which is assigned to +.BR "uart->regs" . +.SH SOURCE +.B /sys/src/9/port/uartp8250.h +.br +.B /sys/src/9/port/uartp8250.c +.SH "SEE ALSO" +.IR uart (3). +.SH BUGS +The +.B PhysUart +is uncomfortable to use for device discovery. diff --git a/sys/man/9/xalloc b/sys/man/9/xalloc new file mode 100644 index 0000000000..dc63223fc0 --- /dev/null +++ b/sys/man/9/xalloc @@ -0,0 +1,72 @@ +.TH XALLOC 9 +.SH NAME +xalloc, xspanalloc, xfree \- basic memory management +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void* xalloc(ulong size) +.PP +.B +void* xspanalloc(ulong size, int align, ulong span) +.PP +.B +void xfree(void *p) +.SH DESCRIPTION +.I Xalloc +and +.I xfree +are primitives used by higher-level memory allocators in the kernel, +such as +.IR malloc (9). +They are not intended for use directly by most kernel routines. +The main exceptions are routines that permanently allocate large structures, +or need the special alignment properties guaranteed by +.IR xspanalloc . +.PP +.I Xalloc +returns a pointer to a range of size bytes of memory. The memory will be zero filled and aligned on a 8 byte +.RB ( BY2V ) +address. If the memory is not available, +.B xalloc +returns a null pointer. +.PP +.I Xspanalloc +allocates memory given alignment and spanning constraints. +The block returned will contain +.I size +bytes, aligned on a boundary that is +.BI "0 mod" " align," +in such a way that the memory in the block does not +span an address that is +.BI "0 mod" " span." +.I Xspanalloc +is intended for use +allocating hardware data structures (eg, page tables) or I/O buffers +that must satisfy specific alignment restrictions. +If +.I xspanalloc +cannot allocate memory to satisfy the given constraints, it will +.IR panic (9). +The technique it uses can sometimes cause memory to be wasted. +Consequently, +.I xspanalloc +should be used sparingly. +.PP +.I Xfree +frees the block of memory at +.IR p , +which must be an address previously returned by +.I xalloc +(not +.IR xspanalloc ). +.SS Allocation status +Some memory allocation statistics are written to the console in response to +the debugging sequence +.LR "control-T control-T x" . +The output includes the total free space, the number of free holes, +and a summary of active holes. +Each line shows `address top size'. +.SH SOURCE +.B /sys/src/9/port/xalloc.c +.SH SEE ALSO +.IR malloc (9) From 1382f5f6ffcec43cd25fce745825bbaee1396bbc Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 20 Jan 2016 12:37:38 +0000 Subject: [PATCH 222/402] sys/man: add kernel function manuals to HTML manual index --- sys/lib/man/mkhtmlindex | 2 ++ sys/man/index.html | 2 ++ sys/man/mkfile | 12 ++++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sys/lib/man/mkhtmlindex b/sys/lib/man/mkhtmlindex index 93cd333f41..b7d41e85e4 100755 --- a/sys/lib/man/mkhtmlindex +++ b/sys/lib/man/mkhtmlindex @@ -23,6 +23,8 @@ case 7 echo -n Databases case 8 echo -n System Administration +case 9 + echo -n Kernel Functions } echo '' echo '
' diff --git a/sys/man/index.html b/sys/man/index.html index 26e92fdae2..d1853cf798 100644 --- a/sys/man/index.html +++ b/sys/man/index.html @@ -26,6 +26,7 @@

Plan 9 Manual Section by Section in HTML

6File formats, misc 7Databases 8System administration +9Kernel functions

Keyword search

@@ -53,6 +54,7 @@

Look up a specific man page