You are on page 1of 23

BootingARMLinux

VincentSanders
<vince@arm.linux.org.uk>

Reviewandadvice,largechunksoftheARMLinuxkernel,allaroundgoodguy:RussellKing
Review,adviceandnumerousclarifications.:NicolasPitre
Reviewandadvice:ErikMouw,ZwaneMwaikambo,JeffSutherland,RalphSiemsen,DanielSilverstone,MartinMichlmayr,Michael
Stevens,LesleyMitchell,MatthewRichardson
Reviewandreferencedinformation(seebibliography):Wookey
Copyright2004VincentSanders
ThisdocumentisreleasedunderaGPLlicence.
Alltrademarksareacknowledged.
Whileeveryprecautionhasbeentakeninthepreparationofthisarticle,thepublisherassumesnoresponsibilityforerrorsoromissions,or
fordamagesresultingfromtheuseoftheinformationcontainedherein.
20040604
RevisionHistory
Revision1.00
InitialRelease.
Revision1.10

10thMay2004

VRS

4thJune2004

VRS

Updateexamplecodetobemorecomplete.
Improvewordinginplaces,changessuggestedbyNicolasPitre.
UpdateSection2,Otherbootloaders.
Updateacknowledgements.

TableofContents
1.Aboutthisdocument
2.Otherbootloaders
3.Overview
4.Configuringthesystem'smemory
5.Loadingthekernelimage
6.LoadinganinitialRAMdisk
7.Initialisingaconsole
8.Kernelparameters
9.ObtainingtheARMLinuxmachinetype
10.Startingthekernel
A.TagReference
B.Completeexample
Bibliography
Abstract
Thisdocumentdefinesinclearconciseterms,withimplementationguidanceandexamples,therequirementsandproceduresfora
bootloadertostartanARMLinuxkernel.

1.Aboutthisdocument
Thisdocumentdescribesthe"new"bootingprocedurewhichallversion2.4.18andlaterkernelsuse.Thelegacy"struct"methodmustnot
beused.
Thisdocumentcontainsinformationfromawidevarietyofsources(seetheBibliography)andauthors,youareencouragedtoconsultthese
sourcesformoreinformationbeforeaskingquestionsoftheMaintainers,orontheARMLinuxmailinglists.Mostoftheseareashavebeen
coveredrepeatedlyinthepastandyouarelikelytobeignoredifyouhaven'tdoneatleastbasicresearch.
Additionallyitshouldbenotedthatprovidedtheguidanceinthisdocumentisfollowed,thereshouldbenoneedforanimplementorto
understandeverynuanceoftheassemblerthatstartsthekernel.Experiencehasshownonnumerousoccasionsthatmostbootingproblems
areunlikelytoberelatedtothiscode,saidcodeisalsoquitetrickyandunlikelytogiveanyinsightintotheproblem.

2.Otherbootloaders
Beforeembarkingonwritinganewbootloaderadevelopershouldconsiderifoneoftheexistingloadersisappropriate.Thereareexamples

ofloadersinmostareas,fromsimpleGPLloaderstofullblowncommercialofferings.Ashortlistisprovidedherebutthedocumentsinthe
Bibliographyoffermoresolutions.
Table1.Bootloaders
Name
Blob

URL
Blobbootloader

Description
GPLbootloaderforSA11x0(StrongARM)platforms.

Bootldr Bootldr

BothGPLandnonGPLversionsavailable,mainlyusedforhandhelddevices.

Redboot Redboot
UBoot UBoot

RedhatloaderreleasedundertheireCoslicence.
GPLuniversalbootloader,providessupportforseveralCPUs.

ABLE

ABLEbootloader Commercialbootloaderwithcomprehensivefeatureset

3.Overview
ARMLinuxcannotbestartedonamachinewithoutasmallamountofmachinespecificcodetoinitialisethesystem.ARMLinuxrequires
thebootloadercodetodoverylittle,althoughseveralbootloadersdoprovideextensiveadditionalfunctionality.Theminimalrequirements
are:
Configurethememorysystem.
Loadthekernelimageatthecorrectmemoryaddress.
OptionallyloadaninitialRAMdiskatthecorrectmemoryaddress.
Initialisethebootparameterstopasstothekernel.
ObtaintheARMLinuxmachinetype
Enterthekernelwiththeappropriateregistervalues.
Itisusuallyexpectedthatthebootloaderwillinitialiseaserialorvideoconsoleforthekernelinadditiontothesebasictasks.Indeedaserial
portisalmostconsideredmandatoryinmostsystemconfigurations.
Eachofthesestepswillbeexaminedinthefollowingsections.

4.Configuringthesystem'smemory
ThebootloaderisexpectedtofindandinitialiseallRAMthatthekernelwilluseforvolatiledatastorageinthesystem.Itperformsthisina

machinedependentmanner.ItmayuseinternalalgorithmstoautomaticallylocateandsizeallRAM,oritmayuseknowledgeoftheRAM
inthemachine,oranyothermethodthebootloaderdesignerseesfit.
Inallcasesitshouldbenotedthatallsetupisperformedbythebootloader.Thekernelshouldhavenoknowledgeofthesetupor
configurationoftheRAMwithinasystemotherthanthatprovidedbythebootloader.Theuseofmachine_fixup()withinthekernelismost
definitelynotthecorrectplaceforthis.Thereisacleardistinctionbetweenthebootloadersresponsibilityandthekernelinthisarea.
ThephysicalmemorylayoutispassedtothekernelusingtheATAG_MEMparameter.Memorydoesnotnecessarilyhavetobecompletely
contiguous,althoughtheminimumnumberoffragmentsispreferred.MultipleATAG_MEMblocksallowforseveralmemoryregions.The
kernelwillcoalesceblockspassedtoitiftheyarecontiguousphysicalregions.
Thebootloadermayalsomanipulatethememorywiththekernelscommandline,usingthe'mem='parameter,theoptionsforthisparameter
arefullydocumentedinlinux/Documentation/kernelparameters.txt
Thekernelcommandline'mem='hasthesyntaxmem=<size>[KM][,@<phys_offset>]whichallowsthesizeandphysicalmemorylocationfor
amemoryareatobedefined.Thisallowsforspecifyingmultiplediscontigousmemoryblocksatdifferingoffsetsbyprovidingthemem=
parametermultipletimes.

5.Loadingthekernelimage
Kernelimagesgeneratedbythekernelbuildprocessareeitheruncompressed"Image"filesorcompressedzImagefiles.
TheuncompressedImagefilesaregenerallynotused,astheydonotcontainareadilyidentifiablemagicnumber.ThecompressedzImage
formatisalmostuniversallyusedinpreference.
ThezImagehasseveralbenefitsinadditiontothemagicnumber.Typically,thedecompressionoftheimageisfasterthanreadingfrom
someexternalmedia.Theintegrityoftheimagecanbeassured,asanyerrorswillresultinafaileddecompress.Thekernelhasknowledge
ofitsinternalstructureandstate,whichallowsforbetterresultsthanagenericexternalcompressionmethod.
ThezImagehasamagicnumberandsomeusefulinformationnearitsbeginning.
Table2.UsefulfieldsinzImageheadcode
OffsetintozImage
Value
Description
0x24
0x016F2818 MagicnumberusedtoidentifythisisanARMLinuxzImage
0x28
startaddress TheaddressthezImagestartsat
0x2C

endaddress TheaddressthezImageendsat

Thestartandendoffsetscanbeusedtodeterminethelengthofthecompressedimage(size=endstart).Thisisusedbyseveral
bootloaderstodetermineifanydataisappendedtothekernelimage.ThisdataistypicallyusedforaninitialRAMdisk(initrd).Thestart
addressisusually0asthezImagecodeispositionindependent.
ThezImagecodeisPositionIndependentCode(PIC)somaybeloadedanywherewithintheavailableaddressspace.Themaximumkernel
sizeafterdecompressionis4Megabytes.ThisisahardlimitandwouldincludetheinitrdifabootpImagetargetwasused.

Note
AlthoughthezImagemaybelocatedanywhere,careshouldbetaken.Startingacompressedkernelrequiresadditional
memoryfortheimagetobeuncompressedinto.Thisspacehascertainconstraints.
ThezImagedecompressioncodewillensureitisnotgoingtooverwritethecompresseddata.Ifthekerneldetectssucha
conflictitwilluncompresstheimageimmediatelyafterthecompressedzImagedataandrelocatethekernelafter
decompression.ThisobviouslyhastheimpactthatthememoryregionthezImageisloadedintomusthaveupto4Megabytes
ofspaceafterit(themaximumuncompressedkernelsize),i.e.placingthezImageinthesame4Megabytebankasits
ZRELADDRwouldprobablynotworkasexpected.
DespitetheabilitytoplacezImageanywherewithinmemory,conventionhasitthatitisloadedatthebaseofphysicalRAMplusanoffset
of0x8000(32K).Thisleavesspacefortheparameterblockusuallyplacedatoffset0x100,zeropageexceptionvectorsandpagetables.
Thisconventionisverycommon.

6.LoadinganinitialRAMdisk
AninitialRAMdiskisacommonrequirementonmanysystems.Itprovidesawaytohavearootfilesystemavailablewithoutaccessto
otherdriversorconfigurations.Fulldetailscanbeobtainedfromlinux/Documentation/initrd.txt
TherearetwomethodsavailableonARMLinuxtoobtainaninitialRAMdisk.ThefirstisaspecialbuildtargetbootpImagewhichtakesan
initialRAMdiskatbuildtimeandappendsittoazImage.Thismethodhasthebenefitthatitneedsnobootloaderintervention,butrequires
thekernelbuildprocesstohaveknowledgeofthephysicaladdresstoplacetheramdisk(usingtheINITRD_PHYSdefinition).Thehardsize
limitfortheuncompressedkernelandinitrdof4Megabytesapplies.Becauseoftheselimitationsthistargetisrarelyusedinpractice.
Thesecondandmuchmorewidelyusedmethodisforthebootloadertoplaceagiveninitialramdiskimage,obtainedfromwhatevermedia,
intomemoryatasetlocation.ThislocationispassedtothekernelusingATAG_INITRD2andATAG_RAMDISK.
Conventionallytheinitrdisplaced8Megabytesfromthebaseofphysicalmemory.Whereveritisplacedtheremustbesufficientmemory
afterboottodecompresstheinitialramdiskintoarealramdiski.e.enoughmemoryforzImage+decompressedzImage+initrd+
uncompressedramdisk.Thecompressedinitialramdiskmemorywillbefreedafterthedecompressionhashappened.Limitationstothe

positionoftheramdiskare:
Itmustliecompletelywithinasinglememoryregion(mustnotcrossbetweenareasdefinedbydifferentATAG_MEMparameters)
Itmustbealignedtoapageboundary(typically4k)
ItmustnotconflictwiththememorythezImageheadcodeusestodecompressthekerneloritwillbeoverwrittenasnocheckingis
performed.

7.Initialisingaconsole
Aconsoleishighlyrecommendedasamethodtoseewhatactionsthekernelisperformingwheninitialisingasystem.Thiscanbeanyinput
outputdevicewithasuitabledriver,themostcommoncasesareavideoframebufferdriveroraserialdriver.SystemsthatARMLinuxruns
ontendtoalmostalwaysprovideaserialconsoleport.
Thebootloadershouldinitialiseandenableoneserialportonthetarget.Thisincludesenablinganyhardwarepowermanagementetc.,touse
theport.Thisallowsthekernelserialdrivertoautomaticallydetectwhichserialportitshoulduseforthekernelconsole(generallyusedfor
debuggingpurposes,orcommunicationwiththetarget.)
Asanalternative,thebootloadercanpasstherelevant'console='optiontothekernel,viathecommandlineparameterspecifyingtheport,
andserialformatoptionsasdescribedinlinux/Documentation/kernelparameters.txt

8.Kernelparameters
Thebootloadermustpassparameterstothekerneltodescribethesetupithasperformed,thesizeandshapeofmemoryinthesystemand,
optionally,numerousothervalues.
Thetaggedlistshouldconformtothefollowingconstraints
ThelistmustbestoredinRAMandplacedinaregionofmemorywhereneitherthekerneldecompressernorinitrdmanipulationwill
overwriteit.Therecommendedplacementisinthefirst16KiBofRAM,usuallythestartofphysicalRAMplus0x100(whichavoidszero
pageexceptionvectors).
ThephysicaladdressofthetaggedlistmustbeplacedinR2onentrytothekernel,howeverhistoricallythishasnotbeenmandatoryand
thekernelhasusedthefixedvalueofthestartofphysicalRAMplus0x100.Thismustnotberelieduponinthefuture.
Thelistmustnotextendpastthe0x4000boundarywherethekernel'sinitialtranslationpagetableiscreated.Thekernelperformsno
boundscheckingandwilloverwritetheparameterlistifitdoesso.
Thelistmustbealignedtoaword(32bit,4byte)boundary(ifnotusingtherecommendedlocation)

ThelistmustbeginwithanATAG_COREandendwithATAG_NONE
ThelistmustcontainatleastoneATAG_MEM
Eachtaginthelistconsistsofaheadercontainingtwounsigned32bitvalues,thesizeofthetag(in32bit,4bytewords)andthetagvalue
structatag_header{
u32size;/*legthoftaginwordsincludingthisheader*/
u32tag;/*tagvalue*/
};

Eachtagheaderisfollowedbydataassociatedwiththattag,exceptingATAG_NONEwhichhasnodataandATAG_COREwherethedata
isoptional.Thesizeofthedataisdeterminedbythesizefieldinheader,theminimumsizeis2astheheaderssizeisincludedinthisvalue.
TheATAG_NONEisuniqueinthatitssizefieldissettozero.
Atagmaycontainadditionaldataafterthemandatedstructuresprovidedthesizeisadjustedtocovertheextrainformation,thisallowsfor
futureexpansionandforabootloadertoextendthedataprovidedtothekernel.Forexampleabootloadermayprovideadditionalserial
numberinformationinanATAG_SERIALwhichcouldthembeinterpretedbyamodifiedkernel.
Theorderofthetagsintheparameterlistisunimportant,theymayappearasmanytimesasrequiredalthoughinterpretationofduplicate
tagsistagdependant.
ThedataforeachindividualtagisdescribedintheAppendixA,TagReferencesection.
Table3.Listofusabletags
Tagname
ATAG_NONE
ATAG_CORE

Value
Size
0x00000000 2
0x54410001 5(2ifempty)

Description
Emptytagusedtoendlist
Firsttagusedtostartlist

ATAG_MEM
0x54410002 4
ATAG_VIDEOTEXT 0x54410003 5
ATAG_RAMDISK 0x54410004 5

Describesaphysicalareaofmemory
DescribesaVGAtextdisplay
Describeshowtheramdiskwillbeusedinkernel

ATAG_INITRD2

0x54420005 4

Describeswherethecompressedramdiskimageisplacedin
memory

ATAG_SERIAL
ATAG_REVISION

0x54410006 4
0x54410007 3

64bitboardserialnumber
32bitboardrevisionnumber

ATAG_VIDEOLFB

0x54410008 8

Initialvaluesforvesafbtypeframebuffers

ATAG_CMDLINE

0x54410009

2+((length_of_cmdline+3)/
4)

Commandlinetopasstokernel

Forimplementationpurposesastructurecanbedefinedforatag
structatag{
structatag_headerhdr;
union{
structatag_corecore;
structatag_memmem;
structatag_videotextvideotext;
structatag_ramdiskramdisk;
structatag_initrd2initrd2;
structatag_serialnrserialnr;
structatag_revisionrevision;
structatag_videolfbvideolfb;
structatag_cmdlinecmdline;
}u;
};

Oncethesestructureshavebeendefinedanimplementationneedstocreatethelistthiscanbeimplementedwithcodesimilarto
#definetag_next(t)((structtag*)((u32*)(t)+(t)>hdr.size))
#definetag_size(type)((sizeof(structtag_header)+sizeof(structtype))>>2)
staticstructatag*params;/*usedtopointatthecurrenttag*/
staticvoid
setup_core_tag(void*address,longpagesize)
{
params=(structtag*)address;/*Initialiseparameterstostartatgivenaddress*/
params>hdr.tag=ATAG_CORE;/*startwiththecoretag*/
params>hdr.size=tag_size(atag_core);/*sizethetag*/
params>u.core.flags=1;/*ensurereadonly*/
params>u.core.pagesize=pagesize;/*systemspagesize(4k)*/
params>u.core.rootdev=0;/*zerorootdevice(typicalyoveriddenfromcommandline)*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_mem_tag(u32_tstart,u32_tlen)

{
params>hdr.tag=ATAG_MEM;/*Memorytag*/
params>hdr.size=tag_size(atag_mem);/*sizetag*/
params>u.mem.start=start;/*Startofmemoryarea(physicaladdress)*/
params>u.mem.size=len;/*Lengthofarea*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_end_tag(void)
{
params>hdr.tag=ATAG_NONE;/*Emptytagendslist*/
params>hdr.size=0;/*zerolength*/
}
staticvoid
setup_tags(void)
{
setup_core_tag(0x100,4096);/*standardcoretag4kpagesize*/
setup_mem_tag(0x10000000,0x400000);/*64Mbat0x10000000*/
setup_mem_tag(0x18000000,0x400000);/*64Mbat0x18000000*/
setup_end_tag(void);/*endoftags*/
}

Whilethiscodefragmentiscompleteitillustratestheabsoluteminimalrequirementsforaparametersetandisintendedtodemonstratethe
conceptsexpressedearlierinthissection.Arealbootloaderwouldprobablypassadditionalvaluesandwouldprobablyprobeforthe
memoryactuallyinasystemratherthanusingfixedvalues.AmorecompleteexamplecanbefoundinAppendixB,Completeexample

9.ObtainingtheARMLinuxmachinetype
Theonlyadditionalinformationthebootloaderneedstoprovideisthemachinetype,thisisasimplenumberuniqueforeachARMsystem
oftenreferredtoasaMACH_TYPE.
ThemachinetypenumberisobtainedviatheARMLinuxwebsiteMachineRegistry.Amachinetypeshouldbeobtainedasearlyina
projectslifeaspossible,ithasanumberoframificationsforthekernelportitself(machinedefinitionsetc.)andchangingdefinitions
afterwardsmayleadtoanumberofundesirableissues.Thesevaluesarerepresentedbyalistofdefineswithinthekernelsource
(linux/arch/arm/tools/machtypes)
Thebootloadermustobtainthemachinetypevaluebysomemethod.Whetherthisisahardcodedvalueoranalgorithmthatlooksatthe

connectedhardware.Implementationiscompletelysystemspecificandisbeyondthescopeofthisdocument.

10.Startingthekernel
OncethebootloaderhasperformedalltheotherstepsitmuststartexecutionofthekernelwiththecorrectvaluesintheCPUregisters.
Theentryrequirementsare:
TheCPUmustbeinSVC(supervisor)modewithbothIRQandFIQinterruptsdisabled.
TheMMUmustbeoff,i.e.coderunningfromphysicalRAMwithnotranslatedaddressing.
Datacachemustbeoff
Instructioncachemaybeeitheronoroff
CPUregister0mustbe0
CPUregister1mustbetheARMLinuxmachinetype
CPUregister2mustbethephysicaladdressoftheparameterlist
Thebootloaderisexpectedtocallthekernelimagebyjumpingdirectlytothefirstinstructionofthekernelimage.

A.TagReference
ATAG_CORE
ATAG_COREStarttagusedtobeginlist

Value
0x54410001

Size
5(2ifnodata)

Structuremembers

structatag_core{
u32flags;/*bit0=readonly*/
u32pagesize;/*systemspagesize(usually4k)*/
u32rootdev;/*rootdevicenumber*/
};

Description
Thistagmustbeusedtostartthelist,itcontainsthebasicinformationanybootloadermustpass,ataglengthof2indicatesthetaghasno
structureattached.

ATAG_NONE
ATAG_NONEEmptytagusedtoendlist

Value
0x00000000

Size
2

Structuremembers
None

Description
Thistagisusedtoindicatethelistend.Itisuniqueinthatitssizefieldintheheadershouldbesetto0(not2).

ATAG_MEM

ATAG_MEMTagusedtodescribeaphysicalareaofmemory.

Value
0x54410002

Size
4

Structuremembers
structatag_mem{
u32size;/*sizeofthearea*/
u32start;/*physicalstartaddress*/
};

Description
Describesanareaofphysicalmemorythekernelistouse.

ATAG_VIDEOTEXT
ATAG_VIDEOTEXTTagusedtodescribeVGAtexttypedisplays

Value
0x54410003

Size
5

Structuremembers
structatag_videotext{
u8x;/*widthofdisplay*/
u8y;/*heightofdisplay*/
u16video_page;
u8video_mode;
u8video_cols;
u16video_ega_bx;
u8video_lines;
u8video_isvga;
u16video_points;
};

Description
ATAG_RAMDISK
ATAG_RAMDISKTagdescribinghowtheramdiskwillbeusedbythekernel

Value
0x54410004

Size
5

Structuremembers
structatag_ramdisk{
u32flags;/*bit0=load,bit1=prompt*/
u32size;/*decompressedramdisksizein_kilo_bytes*/
u32start;/*startingblockoffloppybasedRAMdiskimage*/
};

Description
Describeshowthe(initial)ramdiskwillbeconfiguredbythekernel,specificallythisallowsforthebootloadertoensuretheramdiskwillbe
largeenoughtotakethedecompressedinitialramdiskimagethebootloaderispassingusingATAG_INITRD2.

ATAG_INITRD2
ATAG_INITRD2Tagdescribingthephysicallocationofthecompressedramdiskimage

Value
0x54420005

Size
4

Structuremembers
structatag_initrd2{
u32start;/*physicalstartaddress*/
u32size;/*sizeofcompressedramdiskimageinbytes*/
};

Description
Locationofacompressedramdiskimage,usuallycombinedwithanATAG_RAMDISK.Canbeusedasaninitialrootfilesystemwiththe
additionofacommandlineparameterof'root=/dev/ram'.ThistagsupersedestheoriginalATAG_INITRDwhichusedvirtualaddressing,
thiswasamistakeandproducedissuesonsomesystems.Allnewbootloadersshouldusethistaginpreference.

ATAG_SERIAL
ATAG_SERIALTagwith64bitserialnumberoftheboard

Value
0x54410006

Size
4

Structuremembers
structatag_serialnr{
u32low;
u32high;
};

Description
ATAG_REVISION
ATAG_REVISIONTagfortheboardrevision

Value
0x54410007

Size
3

Structuremembers
structatag_revision{
u32rev;
};

Description
ATAG_VIDEOLFB
ATAG_VIDEOLFBTagdescribingparametersforaframebuffertypedisplay

Value
0x54410008

Size
8

Structuremembers
structatag_videolfb{
u16lfb_width;
u16lfb_height;
u16lfb_depth;
u16lfb_linelength;
u32lfb_base;
u32lfb_size;
u8red_size;
u8red_pos;
u8green_size;
u8green_pos;
u8blue_size;
u8blue_pos;

u8rsvd_size;
u8rsvd_pos;
};

Description
ATAG_CMDLINE
ATAG_CMDLINETagusedtopassthecommandlinetothekernel

Value
0x54410009

Size
2+((length_of_cmdline+3)/4)

Structuremembers
structatag_cmdline{
charcmdline[1];/*thisistheminimumsize*/
};

Description
Usedtopasscommandlineparameterstothekernel.ThecommandlinemustbeNULLterminated.Thelength_of_cmdlinevariableshould
includetheterminator.

B.Completeexample
Thisisaworkedexampleofasimplebootloaderandshowsalltheinformationexplainedthroughoutthisdocument.Morecodewouldbe

requiredforarealbootloaderthisexampleispurelyillustrative.
ThecodeinthisexampleisdistributedunderaBSDlicence,itmaybefreelycopiedandusedifnecessary.
/*example.c
*exampleARMLinuxbootloadercode
*thisexampleisdistributedundertheBSDlicence
*/
/*listofpossibletags*/
#defineATAG_NONE0x00000000
#defineATAG_CORE0x54410001
#defineATAG_MEM0x54410002
#defineATAG_VIDEOTEXT0x54410003
#defineATAG_RAMDISK0x54410004
#defineATAG_INITRD20x54420005
#defineATAG_SERIAL0x54410006
#defineATAG_REVISION0x54410007
#defineATAG_VIDEOLFB0x54410008
#defineATAG_CMDLINE0x54410009
/*structuresforeachatag*/
structatag_header{
u32size;/*lengthoftaginwordsincludingthisheader*/
u32tag;/*tagtype*/
};
structatag_core{
u32flags;
u32pagesize;
u32rootdev;
};
structatag_mem{
u32size;
u32start;
};
structatag_videotext{
u8x;
u8y;
u16video_page;
u8video_mode;
u8video_cols;
u16video_ega_bx;

u8video_lines;
u8video_isvga;
u16video_points;
};
structatag_ramdisk{
u32flags;
u32size;
u32start;
};
structatag_initrd2{
u32start;
u32size;
};
structatag_serialnr{
u32low;
u32high;
};
structatag_revision{
u32rev;
};
structatag_videolfb{
u16lfb_width;
u16lfb_height;
u16lfb_depth;
u16lfb_linelength;
u32lfb_base;
u32lfb_size;
u8red_size;
u8red_pos;
u8green_size;
u8green_pos;
u8blue_size;
u8blue_pos;
u8rsvd_size;
u8rsvd_pos;
};
structatag_cmdline{
charcmdline[1];
};

structatag{
structatag_headerhdr;
union{
structatag_corecore;
structatag_memmem;
structatag_videotextvideotext;
structatag_ramdiskramdisk;
structatag_initrd2initrd2;
structatag_serialnrserialnr;
structatag_revisionrevision;
structatag_videolfbvideolfb;
structatag_cmdlinecmdline;
}u;
};
#definetag_next(t)((structtag*)((u32*)(t)+(t)>hdr.size))
#definetag_size(type)((sizeof(structtag_header)+sizeof(structtype))>>2)
staticstructatag*params;/*usedtopointatthecurrenttag*/
staticvoid
setup_core_tag(void*address,longpagesize)
{
params=(structtag*)address;/*Initialiseparameterstostartatgivenaddress*/
params>hdr.tag=ATAG_CORE;/*startwiththecoretag*/
params>hdr.size=tag_size(atag_core);/*sizethetag*/
params>u.core.flags=1;/*ensurereadonly*/
params>u.core.pagesize=pagesize;/*systemspagesize(4k)*/
params>u.core.rootdev=0;/*zerorootdevice(typicalyoveriddenfromcommandline)*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_ramdisk_tag(u32_tsize)
{
params>hdr.tag=ATAG_RAMDISK;/*Ramdisktag*/
params>hdr.size=tag_size(atag_ramdisk);/*sizetag*/
params>u.ramdisk.flags=0;/*Loadtheramdisk*/
params>u.ramdisk.size=size;/*Decompressedramdisksize*/
params>u.ramdisk.start=0;/*Unused*/
params=tag_next(params);/*movepointertonexttag*/

}
staticvoid
setup_initrd2_tag(u32_tstart,u32_tsize)
{
params>hdr.tag=ATAG_INITRD2;/*Initrd2tag*/
params>hdr.size=tag_size(atag_initrd2);/*sizetag*/
params>u.initrd2.start=start;/*physicalstart*/
params>u.initrd2.size=size;/*compressedramdisksize*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_mem_tag(u32_tstart,u32_tlen)
{
params>hdr.tag=ATAG_MEM;/*Memorytag*/
params>hdr.size=tag_size(atag_mem);/*sizetag*/
params>u.mem.start=start;/*Startofmemoryarea(physicaladdress)*/
params>u.mem.size=len;/*Lengthofarea*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_cmdline_tag(constchar*line)
{
intlinelen=strlen(line);
if(!linelen)
return;/*donotinsertatagforanemptycommandline*/
params>hdr.tag=ATAG_CMDLINE;/*Commandlinetag*/
params>hdr.size=(sizeof(structatag_header)+linelen+1+4)>>2;
strcpy(params>u.cmdline.cmdline,line);/*placecommandlineintotag*/
params=tag_next(params);/*movepointertonexttag*/
}
staticvoid
setup_end_tag(void)
{
params>hdr.tag=ATAG_NONE;/*Emptytagendslist*/

params>hdr.size=0;/*zerolength*/
}
#defineDRAM_BASE0x10000000
#defineZIMAGE_LOAD_ADDRESSDRAM_BASE+0x8000
#defineINITRD_LOAD_ADDRESSDRAM_BASE+0x800000
staticvoid
setup_tags(parameters)
{
setup_core_tag(parameters,4096);/*standardcoretag4kpagesize*/
setup_mem_tag(DRAM_BASE,0x4000000);/*64Mbat0x10000000*/
setup_mem_tag(DRAM_BASE+0x8000000,0x4000000);/*64Mbat0x18000000*/
setup_ramdisk_tag(4096);/*create4Mbramdisk*/
setup_initrd2_tag(INITRD_LOAD_ADDRESS,0x100000);/*1Mbofcompresseddataplaced8Mbintomemory*/
setup_cmdline_tag("root=/dev/ram0");/*commandlinesettingrootdevice*/
setup_end_tag(void);/*endoftags*/
}
int
start_linux(char*name,char*rdname)
{
void(*theKernel)(intzero,intarch,u32params);
u32exec_at=(u32)1;
u32parm_at=(u32)1;
u32machine_type;
exec_at=ZIMAGE_LOAD_ADDRESS;
parm_at=DRAM_BASE+0x100
load_image(name,exec_at);/*copyimageintoRAM*/
load_image(rdname,INITRD_LOAD_ADDRESS);/*copyinitialramdiskimageintoRAM*/
setup_tags(parm_at);/*setsupparameters*/
machine_type=get_mach_type();/*getmachinetype*/
irq_shutdown();/*stopirq*/
cpu_op(CPUOP_MMUCHANGE,NULL);/*turnMMUoff*/
theKernel=(void(*)(int,int,u32))exec_at;/*setthekerneladdress*/
theKernel(0,machine_type,parm_at);/*jumptokernelwithregisterset*/

return0;
}

Bibliography
ARMLinuxwebsiteDocumentation.RussellMKing.
LinuxKernelDocumentation/arm/booting.txt.RussellMKing.
SettingR2correctlyforbootingthekernel(explanationofbootingrequirements).RussellMKing.
Wookey'spostsummarisingbooting.Wookey.
Makefiledefinesandsymbols.RussellMKing.
Bootloaderguide.Wookey.
Kernelbootorder.RussellMKing.
Adviceforhead.SDebugging.RussellMKing.
Linuxkernel2.4startup.BillGatliff.
Blobbootloader.ErikMouw.
Blobbootloaderonlart.ErikMouw.