Фэндом


LinuxBIOS поддерживает большое количество разных вариантов «загрузок», к примеру, загрузка ELF образов из памяти FLASH. В этом документе описывается процедура внедрения DOS программы 9load в FLASH, которая позволит загружать узлы как выделенные Plan 9 CPU узлы.

ПРИМЕЧАНИЕ: за дополнительной информацией посетите: http://www.acl.lanl.gov/plan9/flash/.

Этот документ поможет вам настроить загрузку Plan 9 из LinuxBIOS. Он состоит из таких частей:

0. Преамбула
1. Настройка — с чего начать. Файловая организация Plan 9 и Linux
2. Объяснение исходного кода — diff-файлы к исходному коду 4-ой версии Plan 9 с комментариями
3. Исходный код

ПреамбулаПравить

В документе обсуждаются изменения, подвергнув которым исходный код Plan 9, можно получить хотя бы одну машину, загружающуюся из LinuxBIOS. Целью проекта является создание автономного CPU сервера Plan 9, которому не требуются перемещаемые части. Большая часть работы выполнена Роном Майнничем (Ron Minnich).

1. НастройкаПравить

Для удачной модификации исходного кода требуются следующие вещи:

1.1 Сеть Plan 9 (включая файловые серверы, CPU серверы и терминалы
1.1.1 Автономный терминал Plan 9, так как сама настройка довольно хитрая
1.2 Исходный код Plan 9 (можно получить из сети Plan 9 и/или стандартной установки системы)
1.3 Linux машина (используется для компиляции LinuxBIOS)
1.4 Аппаратное обеспечение, на котором может работать LinuxBIOS
1.5-9 Немного терпения

Настройка Plan 9Править

В настройке используется поддержка концепции союзных каталогов. Она дает возможность хранения только тех файлов, которые мы модифицируем в локальном каталоге, и связываем их при необходимости на верхушке стандартного дерева ядра (в /sys/src/)… Фактически, это происходит в специальном пространстве имен, которое может использоваться в едином терминальном окне (или же, в целом сеансе rio на CPU сервере) для представления скромной среды разработки, тем временем остальная часть экрана, сеанс или терминалы содержат общий, не разработческий вид системы. В конце концов, это позволяет нескольким разным разработчикам работать в одно и то же время (скоро будет показан пример этого) — компиляция ядер в одном окне, загрузчиков 9load в другом, при этом в третьем окне будет видно не модифицированное дерево ядра. Все в одном каталоге.

Каким образом все это работаетПравить

В двух словах, когда запускается LinuxBIOS, он выполняет поиск и загрузку загрузчика Plan 9 (9load замаскирован как образ elf32, таким образом, он распознается LinuxBIOS), затем 9load вызывает ядро или же другие варианты загрузки, закачивает, извлекает его и выполняет переход на него. Вуаля.

Детали ниже:

Компиляция (сборка) образа 9load, приспособленного для работы с LinuxBIOS:

p9% lbbind # связывает дерево разработки…
p9% mk 9loadlb # в mkfile со специальной
8a -DLinuxBios -o ll.8 l.s # конфигурацией для linuxbios
8c -FVw -I. alarm.c # ядер по требованию
8c -FVw -I. cga.c # определение и связывание 9load
8c -FVw -I. clock.c # по адресу 0x800000
8c -FVw -I. console.c
8c -FVw -I. dosboot.c
8c -FVw -I. donprint.c
8c -FVw -I. devfloppy.c
8c -FVw -I. dma.c
8c -FVw -I. ilock.c
8c -FVw -I. kbd.c
8c -FVw -I. queue.c
8c -FVw -I. trap.c
8c -FVw -I. 8250.c
warning: 8250.c:130 param declared and not used: arg
8c -FVw -I. apm.c
8c -FVw -I. boot.c
8c -FVw -I. devpccard.c
8c -FVw -I. conf.c
8c -FVw -I. devi82365.c
8c -FVw -I. devsd.c
8c -FVw -I. inflate.c
8c -FVw -I. load.c
warning: load.c:159 no return at end of function: myboot
load.c:280 function args not checked: pcihinv
8c -FVw -I. memory.c
8c -FVw -I. part.c
8c -FVw -I. pci.c
8c -FVw -I. sdata.c
8c -FVw -I. sdmylex.c
8c -FVw -I. sd53c8xx.c
8c -FVw -I. sdscsi.c
8c -FVw -I. bootp.c
8c -FVw -I. ether.c
8c -FVw -I. ether2114x.c
8c -FVw -I. ether2000.c
8c -FVw -I. ether589.c
8c -FVw -I. ether79c970.c
8c -FVw -I. ether8003.c
8c -FVw -I. ether8139.c
8c -FVw -I. ether82557.c
8c -FVw -I. ether83815.c
8c -FVw -I. ether8390.c
8c -FVw -I. etherec2t.c
8c -FVw -I. etherelnk3.c

ls -l 9loadlb

--rwxr-xr-x M 9 andrey andrey 178320 Jun 20 11:34 9loadlb

p9% 8l -o 9loadlb -H3 -T0x80800000 -l ll.8 alarm.8 cga.8 clock.8 console.8 dosboot.8 donprint.8 devfloppy.8 dma.8 ilock.8 kbd.8 queue.8 trap.8 8250.8 apm.8 boot.8 devpccard.8 conf.8 devi82365.8 devsd.8 inflate.8 load.8 memory.8 part.8 pci.8 sdata.8 sdmylex.8 sd53c8xx.8 sdscsi.8 bootp.8 ether.8 ether2114x.8 ether2000.8 ether589.8 ether79c970.8 ether8003.8 ether8139.8 ether82557.8 ether83815.8 ether8390.8 etherec2t.8 etherelnk3.8 -lflate -lc

9loadlb — это специальная конфигурация в mkfile, которая

#определяет «LinuxBIOS» в течение компиляции и связывает 9loadlb по адресу 0x800000 (отсюда начинается переход LinuxBIOS).

Следующий шаг — копирование 9loadlb на linux машину:

fbsd$ scp plan9:src/boot/pc/9loadlb ../9load.800000

andrey@plan9.acl.lanl.gov's password:

9loadlb 100% |*****************************| 174 KB 00:00

fbsd$

Далее запускаем сценарий mymk из mkelf:

snares$ pwd
/users/andrey/kern/mkelf
snares$ ./mymk

#!/bin/sh -v
cd 9load
cp ~/kern/9load.800000 .
make all4
./mkas < 9load.800000 > 9l.s
as -o 9l.o 9l.s
ld -T elfImage.lds.800000 -o 9l.elf 9l.o
ld: warning: cannot find entry symbol startup_32; defaulting to 00800000
cp 9l.elf ..
cd ..

Running gcc -O2 -DDEFAULT_ROOT_DEV='(((0x3<<8)| 0))' -DDEFAULT_COMMAND_LINE='""' -DDEFAULT_PROGRAM_VERSION='""' -c /users/andrey/kern/mkelf/share/mkelfImage/elf32-i386/convert_params.c -o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/convert_params_6384.o

Running gcc -O2 -DDEFAULT_ROOT_DEV='(((0x3<<8)| 0))' -DDEFAULT_COMMAND_LINE='""' -DDEFAULT_PROGRAM_VERSION='""' -c /users/andrey/kern/mkelf/share/mkelfImage/elf32-i386/head.S -o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/head_6384.o

Running ld -o elfImage.fat -T /users/andrey/kern/mkelf/share/mkelfImage/elf32-i386/elfImage.lds /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/kernel_piggy_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/ramdisk_piggy_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/convert_params_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/head_6384.o Running ld -o elfImage.fat -T /users/andrey/kern/mkelf/share/mkelfImage/elf32-i386/elfImage.lds /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/kernel_piggy_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/ramdisk_piggy_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/convert_params_6384.o /am/mother-v2-e5/vol/vol0/u0/andrey/kern/mkelf/head_6384.oBFD: elfImage.fat: warning: Empty loadable segment detected checksum: dc7c echo done done bin/mkelfImage --kernel=9l.elf

Сценарий порядком уродлив, но нам незачем красота… Вы увидите его ниже, или в linux bundle… Следующий шаг — копирование (команда scp) 9load (замаскированный под elfImage) в то место, откуда он может быть записан на flash:

fbsd$ scp elfImage plan9:/386/9pcblah
andrey@plan9.acl.lanl.gov's password:
elfImage 100% |*****************************| 190 KB 00:00
scp: can't wstat /386/9pcblah: wstat -- attempt to change qid.vers
fbsd$

Если вы видите сообщения об ошибках — просто игнорируйте их… Dhcp сервер будет проинструктирован работать с /386/9pcblah как с ядром и отвечать на запросы bootp от машины, на которой выполняется работа (запрос основан на ethernet адресе машины).

ПРИМЕЧАНИЕ: если вы уверены в том, что 9load подходит вам, попросите Рона записать его вам. В этом случае вам нужно будет лишь поместить ядро 9pccpuв /386/9pcblah :)

Файловая организацияПравить

Создайте каталог $home/src для хранения всех модифицируемых файлов, затем в нем создайте организацию каталогов /sys/src, у меня оказалось три каталога:/sys/src/9, /sys/src/boot, /sys/src/libauthconfig, после этого рекурсивно создайте все оставшиеся каталоги, вот что получилось у меня:

p9% du /usr/andrey/src | awk '{print $2}'
/usr/andrey/src/9/pc
/usr/andrey/src/9/ip
/usr/andrey/src/9/alphapc
/usr/andrey/src/9/bitsy
/usr/andrey/src/9/boot
/usr/andrey/src/9/port
/usr/andrey/src/9/mtx
/usr/andrey/src/9
/usr/andrey/src/libauthsrv
/usr/andrey/src/boot/alphapc
/usr/andrey/src/boot/arm
/usr/andrey/src/boot/pc
/usr/andrey/src/boot
/usr/andrey/src/cmd/aux/vga
/usr/andrey/src/cmd/aux
/usr/andrey/src/cmd/auth/factotum
/usr/andrey/src/cmd/auth/lib
/usr/andrey/src/cmd/auth/secstore
/usr/andrey/src/cmd/auth
/usr/andrey/src/cmd
/usr/andrey/src
p9%

Далее если вы хотите отредактировать /sys/src/9/pc/pci.c, выполните команду:

cp /sys/src/9/pc/pci.c $home/src/9/pc/pci.c

СценарииПравить

Несколько сценариев используются для автоматизации процесса связывания и облегчения вашей жизни. Помните, что после загрузки машина будет находится в состоянии «вне разработки», например, она не знает что вы сделали модификации в исходном тексте ядра — поэтому вам нужно сообщить ей об соответствующем изменении пространства имен, так что после введения вами mk в /sys/src/9/pc она скомпилирует ваши собственные файлы взамен всех других. Сценарии сами сделают модификации в пространстве имен, вам лишь остается выполнить их перед тем как вы начнете работу над кодом. Вот эти сценарии (они отличаются поскольку один выполняет связывание $home/src/9 как ядерного дерева — я использую его для написания драйверов поддержки нескольких графических карт, т.е. не LinuxBIOS ядер) а другой связывает $home/src/linuxbios/, который эквивалентен $home/src/9, но файлы в нем LinuxBIOS-связанные. Скопируйте сценарии в $home/bin/rc и проделайте над ними chmod 755:

p9% cat /usr/andrey/bin/rc/kbind
#!/bin/rc
# выполняет связывания для исходного текста ядра не-linuxbios
# и исходных текстов 9load linuxbios
# 9
bind -cb $home/src/9/pc /sys/src/9/pc
bind -cb $home/src/9/ip /sys/src/9/ip
bind -cb $home/src/9/alphapc /sys/src/9/alphapc
bind -cb $home/src/9/bitsy /sys/src/9/bitsy
bind -cb $home/src/9/boot /sys/src/9/boot
bind -cb $home/src/9/port /sys/src/9/port
bind -cb $home/src/9/mtx /sys/src/9/mtx

#boot

bind -cb $home/src/boot/alphapc /sys/src/boot/alphapc
bind -cb $home/src/boot/arm /sys/src/boot/arm
bind -cb $home/src/boot/pc /sys/src/boot/pc

#fs

bind -cb $home/src/fs/port /sys/src/fs/port
bind -cb $home/src/fs/choline /sys/src/fs/choline
bind -cb $home/src/fs/dev /sys/src/fs/dev
bind -cb $home/src/fs/emelie /sys/src/fs/emelie
bind -cb $home/src/fs/ip /sys/src/fs/ip
bind -cb $home/src/fs/pc /sys/src/fs/pc
bind -cb $home/src/fs/roro /sys/src/fs/roro
bind -cb $home/src/fs/sony /sys/src/fs/sony

#cmd

bind -cb $home/src/cmd /sys/src/cmd

p9%

Часть #cmd не обязательна, но все равно пусть она там будет

Материал, создаваемый командами Plan 9…

p9% cat /usr/andrey/bin/rc/lbbind
#!/bin/rc
# материал linuxbios
# 9

bind -cb $home/src/linuxbios/pc /sys/src/9/pc
bind -cb $home/src/linuxbios/ip /sys/src/9/ip
bind -cb $home/src/linuxbios/alphapc /sys/src/9/alphapc
bind -cb $home/src/linuxbios/bitsy /sys/src/9/bitsy
bind -cb $home/src/linuxbios/boot /sys/src/9/boot
bind -cb $home/src/linuxbios/port /sys/src/9/port
bind -cb $home/src/linuxbios/mtx /sys/src/9/mtx

#boot

bind -cb $home/src/boot/alphapc /sys/src/boot/alphapc
bind -cb $home/src/boot/arm /sys/src/boot/arm
bind -cb $home/src/boot/pc /sys/src/boot/pc

#fs

bind -cb $home/src/fs/port /sys/src/fs/port
bind -cb $home/src/fs/choline /sys/src/fs/choline
bind -cb $home/src/fs/dev /sys/src/fs/dev
bind -cb $home/src/fs/emelie /sys/src/fs/emelie
bind -cb $home/src/fs/ip /sys/src/fs/ip
bind -cb $home/src/fs/pc /sys/src/fs/pc
bind -cb $home/src/fs/roro /sys/src/fs/roro
bind -cb $home/src/fs/sony /sys/src/fs/sony

#cmd

bind -cb $home/src/cmd /sys/src/cmd

p9%

Реально нам нужна лишь команда lbbind, она связывает все исходные тексты в одном дереве.

Пример типичного сеанса Plan 9:

p9% lbbind
p9% cd /sys/src/9/pc

# редактирование файлов, внесение изменений, и т.п...

# сборка ядра cpu

p9% mk 'CONF=pccpu'
8c -FVw ether79c970.c
8c -FVw vgabt485.c

# здесь происходит компиляция большого количества файлов, могут появляться ошибки

#

# итак, теперь у вас есть скромное ядро, скопируйте его куда-нибудь, откуда его можно будет загружать

p9% cp 9pccpu

# этап очистки - не обязательно, но иногда очень забавно :)

p9% mk clean
rm -f *.v4586xq7 *.root.s cfs.h fs.h init.h conf.h *.out
for(i in pc pccpu pcdisk)
	mk $i.clean
	rm -f pc.c 9bzpc 9bzpc.gz bootpc.*
	rm -f pccpu.c 9bzpccpu 9bzpccpu.gz bootpccpu.*
	rm -f pcdisk.c 9bzpcdisk 9bzpcdisk.gz bootpcdisk.*
p9%

# для завершения сеанса разработки удалите окно терминала

# ваши файлы будут сохранены там :)

LinuxПравить

Здесь обратимся за помощью к Рону! Обновление CVS из дистрибутива freebios, затем разархивирование включаемого файла mkelf.tgz, далее зовем Рона, чтобы сделать LinuxBIOS подходящим для объединения с 9loadlb… Я совершенно ничего не знаю об этом процессе. Мне остается лишь отрешенно сидеть перед экраном как цыпленок пока Рон работает… После настройки остается лишь использовать сценарий mymk как показано выше и наслаждаться результатом работы :)

2. Diff-файлы исходного кода с комментариями:Править

/sys/src/boot/pc/mkfile — файл был изменен для соответствия моим привычкам Plan 9. Добавлена новая цель, а именно ядро 9loadlb linuxbios. Различие в том, что код linuxbios есть #ifdef-ed LinuxBios:

p9% diff boot/pc/mkfile /sys/src/boot/pc/mkfile
7d6
< 9loadlb\
95,98d93
< 9loadlb: ll.$O $CORE $LOAD $ETHER
< $LD -o $target -H3 -T0x80800000 -l $prereq -lflate -lc
< ls -l $target
<
118,120d112
<
< ll.$O: l.s
< $AS -DLinuxBios -o ll.$O l.s
p9%

/sys/src/boot/pc/l.s — код режима реального времени, 9load загружается в защищенном режиме. Код добавлен для загрузки GDT. Несколько попыток для устранения проблемы с маршрутизацией IRQ, но ничего широко не тестировалось. Мы давным-давно закончили погоню за ошибкой посредством:

MOV AX, SS

теперь ошибка никогда не появляется при нормальной загрузке BIOS…

Материал

MOVL $0x80, DX
MOVB $0x19, AL
OUTB

diff:

p9% diff boot/pc/l.s /sys/src/boot/pc/l.s
20,24d19
<
< MOVL $0x80, DX
< MOVB $0x11, AL
< OUTB
<
27c22
< #ifndef LinuxBios
---
>
200,202d194
<
<
<
209c201
< MOVL $1,AX
---
> LWI(1, rAX)
213,216d204
< /* MOVL CR0,AX
< ORL $1,AX
< MOVL AX,CR0
< */
227,238c215,218
<
< #endif /* LinuxBios */
<
<
< MOVL $0x80, DX
< MOVB $0x11, AL
< OUTB
<
< MOVL tgdtptr-KZERO(SB),GDTR /**/
<
<
< MOVW $SELECTOR(1, SELGDT, 0),AX /**/
---
> /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
> BYTE $0xc7
> BYTE $0xc0
> WORD $SELECTOR(1, SELGDT, 0)
239a220
> MOVW AX,SS
243d223
< MOVW AX,SS
245,249d224
< MOVL $0x80, DX
< MOVB $0x12, AL
< OUTB
<
< #ifndef LinuxBios
255,256c230,231
< #endif /* linuxbios */
< TEXT mode32bit(SB),$0
---
>
> TEXT mode32bit(SB),$0
266,270d240
<
< MOVL $0x80, DX
< MOVB $0x13, AL
< OUTB
<
274,277d243
< MOVL $0x80, DX
< MOVB $0x14, AL
< OUTB
<
290,292d255
<
<
<
308d270
<
320d281
<
345,348d305
< MOVL $0x80, DX
< MOVB $0x17, AL
< OUTB
<
361,363d317
< MOVL $0x80, DX
< MOVB $0x18, AL
< OUTB
371,374d324
<
< MOVL $0x80, DX
< MOVB $0x19, AL
< OUTB
p9%

/sys/src/boot/pc/ether.c — модифицирован для апробации ethernet карт без их конфигурирования в plan9.ini (здесь не используется plan9.ini). Все найденные устройства ether получают irq 9.

p9% diff boot/pc/ether.c /sys/src/boot/pc/ether.c
41d40
<
62,63c61,62
< // if(isaconfig("ether", ctlrno, ctlr) == 0)
< // continue;
---
> if(isaconfig("ether", ctlrno, ctlr) == 0)
> continue;
66,67d64
< memset(ctlr, 0, sizeof(Ether));
< strcpy(ctlr->type, ethercardsn.type);
73,74c70
< i = (*ethercardsn.reset)(ctlr);
< if(i < 0) {
---
> if((*ethercardsn.reset)(ctlr)){
76,78d71
< continue;
< } else if(i) {
< splx(x);
86d78
< //ctlr->irq = 9;
p9%

/sys/src/boot/pc/load.c — переделан для загрузки вне ether0 после завершения поиска и конфигурирования устройств pci и жестких дисков. Если bootp ether0 терпит неудачу (например, дано плохое ядро) load.c запрашивает другое устройство загрузки. Проверка «я слишком большой» закомментирована. Поддержка консоли аппаратная (нет plan9.ini для ее включения). Инициализация console() идет одной из первых — просто я желаю столько вывода отладки, сколько это возможно!

p9% diff boot/pc/load.c /sys/src/boot/pc/load.c
125d124
<
149,162d147
< static int
< myboot(char* file)
< {
< char *eth = "ether0";
< Type *tp;
< Medium *mp;
<
< for(tp = types; tp->type != Tnil; tp++)
< for(mp = tp->media; mp; mp = mp->next)
< if(strcmp(mp->name, eth) == 0)
< boot(mp, file);
<
< }
<
252,254d236
< delay(100000);
<
< outb(0x80, 0x20);
256d237
< outb(0x80, 0x21);
258,264d238
< outb(0x80, 0x22);
<
< outb(0x80, 0x27);
< consinit("0", "115200");
< outb(0x80, 0x28);
< kbdinit();
<
266d239
< outb(0x80, 0x23);
268d240
< outb(0x80, 0x24);
270d241
< outb(0x80, 0x25);
272d242
< outb(0x80, 0x26);
274,277c244
< outb(0x80, 0x27);
< // consinit("0", "115200");
< outb(0x80, 0x28);
< // kbdinit();
---
> kbdinit();
279,283c246,247
< print("hi!\n");
< pcihinv(nil);
< outb(0x80, 0x29);
< // if((ulong)&end > (KZERO|(640*1024)))
< // panic("я слишком большой\n");
---
> if((ulong)&end > (KZERO|(640*1024)))
> panic("я слишком большой\n");
285d248
< outb(0x80, 0x30);
287d249
< outb(0x80, 0x31);
297d258
< outb(0x80, 0x32);
299d259
< outb(0x80, 0x33);
301,304c261,262
< // if((p = getconf("console")) != nil)
< // consinit(p, getconf("baud"));
<
< outb(0x80, 0x34);
---
> if((p = getconf("console")) != nil)
> consinit(p, getconf("baud"));
306d263
< outb(0x80, 0x35);
308d264
< outb(0x80, 0x36);
318d273
< outb(0x80, 0x37);
322d276
< outb(0x80, 0x38);
337d290
< outb(0x80, 0x39);
365,368d317
< outb(0x80, 0x40);
< myboot(file); /* переделанная загрузка ether0 */
< outb(0x80, 0x41);
<
443a393,395
> extern void diff(char*);
>
> ulong palloc;
447,448d398
<
< static ulong palloc;
464d413
<
p9%

Все остальное вы найдете в каталоге, основная часть моих попыток относится к решению проблемы с прерываниями в эмуляторе 8259 (trap.c), вы безболезненно можете удалить эти файлы.

Изменения в ядре Plan 9Править

Конфигурационные файлы существенно упрощены — я стремился к уменьшению драйверов насколько это было возможно. У меня получилось ядро в 365 KB, упрощенное и компрессированное…

/sys/src/9/pc/main.c — просто море информации для отладки.

В main() я хотел сделать так, чтобы при возникновении аварийной ситуации я знал что и где полетело… Также была добавлена некоторая отладочная информация о pci (pcihinv() выводит устройства pci).

p9% diff linuxbios/pc/main.c /sys/src/9/pc/main.c
76d75
< outb(0x80, 0xA0);
78d76
< outb(0x80, 0xA0);
80d77
< outb(0x80, 0xA1);
82,83d78
< outb(0x80, 0xA2);
< kbdinit();
85d79
< outb(0x80, 0xA3);
88d81
< outb(0x80, 0xA4);
91c84
< outb(0x80, 0xA6);
---
> kbdinit();
93d85
< outb(0x80, 0xA7);
95d86
< outb(0x80, 0xA8);
97d87
< outb(0x80, 0xA9);
99d88
< outb(0x80, 0xAa);
101d89
< outb(0x80, 0xAb);
103d90
< outb(0x80, 0xAc);
105d91
< outb(0x80, 0xAd);
107d92
< outb(0x80, 0xAe);
109d93
< outb(0x80, 0xAf);
111d94
< outb(0x80, 0xb0);
113d95
< outb(0x80, 0xb1);
116d97
< outb(0x80, 0xb2);
118d98
< outb(0x80, 0xb3);
120d99
< outb(0x80, 0xb4

Copyright © 2003 Перевод Андрей С. Кухар. Последняя модификация 27.08.2003

Обнаружено использование расширения AdBlock.


Викия — это свободный ресурс, который существует и развивается за счёт рекламы. Для блокирующих рекламу пользователей мы предоставляем модифицированную версию сайта.

Викия не будет доступна для последующих модификаций. Если вы желаете продолжать работать со страницей, то, пожалуйста, отключите расширение для блокировки рекламы.

Также на Фэндоме

Случайная вики