8 Star 0 Fork 48

src-anolis-os/grub2

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
1002-Add-LoongArch64-support-and-update-interface-to-v40.patch 106.50 KB
Copy Edit Raw Blame History
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444
From 478205a88ea71b0c546987602cd879027819125e Mon Sep 17 00:00:00 2001
From: yangqiming <yangqiming@loongson.cn>
Date: Thu, 7 Jul 2022 11:25:02 +0800
Subject: [PATCH] Add LoongArch64 support and update interface to V40
diff --git a/conf/Makefile.common b/conf/Makefile.common
index 521cdda..d9f058b 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -20,6 +20,10 @@ endif
if COND_powerpc_ieee1275
CFLAGS_PLATFORM += -mcpu=powerpc
endif
+if COND_loongarch64
+ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large
+ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large
+endif
# Other options
diff --git a/configure.ac b/configure.ac
index f59a7b8..4715d17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -116,6 +116,10 @@ case "$target_cpu" in
i[[3456]]86) target_cpu=i386 ;;
amd64) target_cpu=x86_64 ;;
sparc) target_cpu=sparc64 ;;
+ loongarch64)
+ target_cpu=loongarch64
+ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_LOONGARCH64=1"
+ ;;
mipsel|mips64el)
target_cpu=mipsel
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1"
@@ -148,6 +152,7 @@ if test "x$with_platform" = x; then
powerpc64-*) platform=ieee1275 ;;
powerpc64le-*) platform=ieee1275 ;;
sparc64-*) platform=ieee1275 ;;
+ loongarch64-*) platform=efi;;
mipsel-*) platform=loongson ;;
mips-*) platform=arc ;;
ia64-*) platform=efi ;;
@@ -196,6 +201,7 @@ case "$target_cpu"-"$platform" in
mipsel-yeeloong) platform=loongson ;;
mipsel-fuloong) platform=loongson ;;
mipsel-loongson) ;;
+ loongarch64-efi) ;;
arm-uboot) ;;
arm-coreboot) ;;
arm-efi) ;;
@@ -251,6 +257,7 @@ case "$platform" in
pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;;
emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;;
loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1" ;;
+ loongson64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_LOONARCH64=1" ;;
qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1" ;;
arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;;
esac
@@ -2098,6 +2105,8 @@ AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu =
AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275])
AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu])
AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275])
+AM_CONDITIONAL([COND_loongarch64_efi], [test x$target_cpu = xloongarch64 -a x$platform = xefi])
+AM_CONDITIONAL([COND_loongarch64], [test x$target_cpu = xloongarch64])
AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
diff --git a/gentpl.py b/gentpl.py
index d662c30..3afd642 100644
--- a/gentpl.py
+++ b/gentpl.py
@@ -32,7 +32,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
"mips_loongson", "sparc64_ieee1275",
"powerpc_ieee1275", "mips_arc", "ia64_efi",
"mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
- "arm_coreboot"]
+ "arm_coreboot", "loongarch64_efi"]
GROUPS = {}
@@ -44,13 +44,14 @@ GROUPS["x86_64"] = [ "x86_64_efi" ]
GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
+GROUPS["loongarch64"] = [ "loongarch64_efi" ]
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
GROUPS["arm64"] = [ "arm64_efi" ]
# Groups based on firmware
GROUPS["pc"] = [ "i386_pc" ]
-GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ]
+GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", "loongarch64_efi"]
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
GROUPS["uboot"] = [ "arm_uboot" ]
GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ]
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 308ad88..a976fad 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -222,6 +222,14 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
endif
+if COND_loongarch64_efi
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h
+endif
+
if COND_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index ef06f8c..54f6bf0 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -95,6 +95,9 @@ kernel = {
arm_coreboot_ldflags = '-Wl,-r,-d';
arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
+ loongarch64_efi_ldflags = '-Wl,-r,-d';
+ loongarch64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
+
i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S;
x86_64_efi_startup = kern/x86_64/efi/startup.S;
@@ -105,6 +108,7 @@ kernel = {
i386_coreboot_startup = kern/i386/coreboot/startup.S;
i386_multiboot_startup = kern/i386/coreboot/startup.S;
mips_startup = kern/mips/startup.S;
+ loongarch64_efi_startup = kern/loongarch64/efi/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
arm_uboot_startup = kern/arm/startup.S;
@@ -295,6 +299,15 @@ kernel = {
extra_dist = video/sis315_init.c;
mips_loongson = commands/keylayouts.c;
+ loongarch64 = kern/loongarch64/init.c;
+ loongarch64 = kern/loongarch64/dl.c;
+ loongarch64 = kern/loongarch64/cache.S;
+ loongarch64 = kern/generic/rtc_get_time_ms.c;
+ loongarch64 = kern/efi/fdt.c;
+ loongarch64 = lib/fdt.c;
+ loongarch64_efi = kern/loongarch64/efi/init.c;
+ loongarch64_efi = lib/loongarch64/efi/loongson.c;
+
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
@@ -810,6 +823,7 @@ module = {
enable = sparc64_ieee1275;
enable = powerpc_ieee1275;
enable = mips_arc;
+ enable = loongarch64_efi;
enable = ia64_efi;
enable = arm_efi;
enable = arm64_efi;
@@ -896,6 +910,7 @@ module = {
i386_qemu = lib/i386/halt.c;
xen = lib/xen/halt.c;
efi = lib/efi/halt.c;
+ loongarch64_efi = commands/acpihalt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
uboot = lib/dummy/halt.c;
@@ -911,6 +926,7 @@ module = {
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
+ loongarch64_efi = lib/loongson/reboot.c;
xen = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c;
arm_coreboot = lib/dummy/reboot.c;
@@ -1608,6 +1624,8 @@ module = {
efi = lib/efi/relocator.c;
mips = lib/mips/relocator_asm.S;
mips = lib/mips/relocator.c;
+ loongarch64 = lib/loongarch64/relocator_asm.S;
+ loongarch64 = lib/loongarch64/relocator.c;
powerpc = lib/powerpc/relocator_asm.S;
powerpc = lib/powerpc/relocator.c;
xen = lib/xen/relocator.c;
@@ -1620,6 +1638,7 @@ module = {
extra_dist = kern/powerpc/cache_flush.S;
enable = mips;
+ enable = loongarch64;
enable = powerpc;
enable = x86;
enable = xen;
@@ -1737,6 +1756,7 @@ module = {
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
+ loongarch64 = loader/loongarch64/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
ia64_efi = loader/ia64/efi/linux.c;
@@ -1838,6 +1858,7 @@ module = {
enable = arm_efi;
enable = arm64_efi;
enable = mips;
+ enable = loongarch64_efi;
};
module = {
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 8a89614..0b5f158 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -122,7 +122,11 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
grub_efi_boot_services_t *b;
grub_efi_physical_address_t address = max;
+#ifdef GRUB_CPU_LOONGARCH64
+ if (max > grub_efi_max_usable_address())
+#else
if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
+#endif
return 0;
b = grub_efi_system_table->boot_services;
@@ -157,11 +161,19 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
grub_efi_physical_address_t ret = address;
/* Limit the memory access to less than 4GB for 32-bit platforms. */
+#ifdef GRUB_CPU_LOONGARCH64
+ if (address > grub_efi_max_usable_address())
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("invalid memory address 0x%llx"),
+ address);
+#else
if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("invalid memory address (0x%llx > 0x%llx)"),
address, GRUB_EFI_MAX_USABLE_ADDRESS);
+#endif
return NULL;
}
@@ -177,7 +189,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
{
/* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */
+#ifdef GRUB_CPU_LOONGARCH64
+ ret = grub_efi_max_usable_address();
+#else
ret = address;
+#endif
status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret);
grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS)
@@ -195,9 +211,15 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
void *
grub_efi_allocate_any_pages (grub_efi_uintn_t pages)
{
+#ifdef GRUB_CPU_LOONGARCH64
+ return grub_efi_allocate_pages_real (grub_efi_max_usable_address(),
+ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+#else
return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS,
pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
GRUB_EFI_LOADER_DATA);
+#endif
}
void *
@@ -471,7 +493,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-#if 1
+#ifdef GRUB_CPU_LOONGARCH64
+ && desc->physical_start <= grub_efi_max_usable_address()
+#else
&& desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
#endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
@@ -487,7 +511,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
desc->physical_start = 0x100000;
}
-#if 1
+#ifdef GRUB_CPU_LOONGARCH64
+ if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ + filtered_desc->num_pages
+ > BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address()))
+ filtered_desc->num_pages
+ = (BYTES_TO_PAGES_DOWN (grub_efi_max_usable_address())
+ - BYTES_TO_PAGES (filtered_desc->physical_start));
+#else
if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages
> BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
@@ -765,7 +796,7 @@ grub_efi_mm_init (void)
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
}
-#if defined (__aarch64__) || defined (__arm__)
+#if defined (__aarch64__) || defined (__arm__) || defined (__loongarch__)
grub_err_t
grub_efi_get_ram_base(grub_addr_t *base_addr)
{
@@ -784,9 +815,15 @@ grub_efi_get_ram_base(grub_addr_t *base_addr)
if (ret < 1)
return GRUB_ERR_BUG;
+#ifdef GRUB_CPU_LOONGARCH64
+ for (desc = memory_map, *base_addr = grub_efi_max_usable_address();
+ (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
+ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+#else
for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS;
(grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+#endif
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY &&
(desc->attribute & GRUB_EFI_MEMORY_WB))
@@ -800,7 +837,11 @@ grub_efi_get_ram_base(grub_addr_t *base_addr)
}
}
+#ifdef GRUB_CPU_LOONGARCH64
+ if (*base_addr == grub_efi_max_usable_address())
+#else
if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS)
+#endif
grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr);
grub_free(memory_map);
diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S
new file mode 100644
index 0000000..d291c67
--- /dev/null
+++ b/grub-core/kern/loongarch64/cache.S
@@ -0,0 +1,26 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+FUNCTION (grub_arch_sync_caches)
+ jr $ra
+
+FUNCTION (grub_arch_sync_dma_caches)
+ jr $ra
+
diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c
new file mode 100644
index 0000000..7d9e2a1
--- /dev/null
+++ b/grub-core/kern/loongarch64/dl.c
@@ -0,0 +1,266 @@
+/* loongarch64/dl.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2007,2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/cpu/types.h>
+#include <grub/mm.h>
+#include <grub/i18n.h>
+
+/* Check if EHDR is a valid ELF header. */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+ Elf_Ehdr *e = ehdr;
+
+ /* Check the magic numbers. */
+ if (e->e_ident[EI_CLASS] != ELFCLASS64
+ || e->e_ident[EI_DATA] != ELFDATA2LSB
+ || e->e_machine != EM_LOONGARCH64)
+ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
+
+ return GRUB_ERR_NONE;
+}
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+grub_err_t
+grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
+ grub_size_t *tramp, grub_size_t *got)
+{
+ *tramp = 0;
+ *got = 0;
+ return GRUB_ERR_NONE;
+}
+
+/* Relocate symbols. */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ Elf_Shdr *s, grub_dl_segment_t seg)
+{
+ Elf_Ehdr *e = ehdr;
+ Elf_Rel *rel, *max;
+ grub_uint64_t oprs[10240]={0};
+ int opri=-1;
+ grub_uint32_t la_abs = 0;
+
+ for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
+ max = (Elf_Rel *) ((char *) rel + s->sh_size);
+ rel < max;
+ rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
+ {
+ grub_uint8_t *addr;
+ Elf_Sym *sym;
+ Elf_Addr r_info;
+ grub_uint64_t sym_value;
+
+ if (seg->size < rel->r_offset)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "reloc offset is out of the segment");
+
+ r_info = (grub_uint64_t) (rel->r_info);
+
+ addr = (grub_uint8_t *) ((char*)seg->addr + rel->r_offset);
+ sym = (Elf_Sym *) ((char*)mod->symtab
+ + mod->symsize * ELF_R_SYM (r_info));
+ sym_value = sym->st_value;
+ if (s->sh_type == SHT_RELA)
+ {
+ sym_value += ((Elf_Rela *) rel)->r_addend;
+ }
+ switch (ELF_R_TYPE (r_info))
+ {
+ case R_LARCH_64:
+ {
+ *(grub_uint64_t *)addr=(grub_uint64_t)sym_value;
+ }
+ break;
+ case R_LARCH_MARK_LA:
+ {
+ la_abs=1;
+ }
+ break;
+ case R_LARCH_SOP_PUSH_PCREL:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr);
+ }
+ break;
+ case R_LARCH_SOP_PUSH_ABSOLUTE:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)sym_value;
+ }
+ break;
+ case R_LARCH_SOP_PUSH_PLT_PCREL:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)(sym_value-(grub_uint64_t)addr);
+ }
+ break;
+ case R_LARCH_SOP_SUB:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 - opr2;
+ }
+ break;
+ case R_LARCH_SOP_SL:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 << opr2;
+ }
+ break;
+ case R_LARCH_SOP_SR:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 >> opr2;
+ }
+ break;
+ case R_LARCH_SOP_ADD:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 + opr2;
+ }
+ break;
+ case R_LARCH_SOP_AND:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 & opr2;
+ }
+ break;
+ case R_LARCH_SOP_IF_ELSE:
+ {
+ grub_uint64_t opr3=oprs[opri];
+ opri--;
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ if(opr1){
+ opri++;
+ oprs[opri]=opr2;
+ } else {
+ opri++;
+ oprs[opri]=opr3;
+ }
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_5:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0x1f) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_U_10_12:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_12:
+ {
+ if(la_abs==1)
+ la_abs=0;
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xffff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_5_20:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr= (*(grub_uint64_t *)addr) | ((opr1 & 0xfffff)<<5) ;
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10);
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x1f);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | (((opr1 >> 2) & 0xffff) << 10);
+ *(grub_uint64_t *)addr=(*(grub_uint64_t *)addr) | ((opr1 >> 18) & 0x3ff);
+ }
+ break;
+ default:
+ {
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("relocation 0x%x is not implemented yet"),
+ ELF_R_TYPE (r_info));
+ }
+ break;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+ return 1;
+}
diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c
new file mode 100644
index 0000000..632c39a
--- /dev/null
+++ b/grub-core/kern/loongarch64/efi/init.c
@@ -0,0 +1,74 @@
+/* init.c - initialize an arm-based EFI system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/env.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/efi/efi.h>
+#include <grub/loader.h>
+#include <grub/machine/loongson.h>
+
+static grub_uint64_t tmr;
+static grub_efi_event_t tmr_evt;
+
+static grub_uint64_t
+grub_efi_get_time_ms (void)
+{
+ return tmr;
+}
+
+static void
+grub_loongson_increment_timer (grub_efi_event_t event __attribute__ ((unused)),
+ void *context __attribute__ ((unused)))
+{
+ tmr += 10;
+}
+
+void
+grub_machine_init (void)
+{
+ grub_efi_boot_services_t *b;
+
+ grub_efi_init ();
+
+ b = grub_efi_system_table->boot_services;
+ efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
+ GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt);
+ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
+
+ grub_install_get_time_ms (grub_efi_get_time_ms);
+}
+
+void
+grub_machine_fini (int flags)
+{
+ grub_efi_boot_services_t *b;
+
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
+ return;
+
+ b = grub_efi_system_table->boot_services;
+
+ efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0);
+ efi_call_1 (b->close_event, tmr_evt);
+
+ grub_efi_fini ();
+}
diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S
new file mode 100644
index 0000000..1ffff08
--- /dev/null
+++ b/grub-core/kern/loongarch64/efi/startup.S
@@ -0,0 +1,45 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+ .file "startup.S"
+ .text
+ .globl start, _start
+ .align 4
+
+FUNCTION(start)
+FUNCTION(_start)
+ /*
+ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0.
+ */
+ addi.d $sp, $sp, -16
+ st.d $ra, $sp, 0
+
+ la $a2, grub_efi_image_handle
+ st.d $a0, $a2, 0
+ la $a2, grub_efi_system_table
+ st.d $a1, $a2, 0
+
+ bl grub_main
+
+1:
+ ld.d $ra, $sp, 0
+ addi.d $sp, $sp, 16
+ jr $ra
+
diff --git a/grub-core/kern/loongarch64/init.c b/grub-core/kern/loongarch64/init.c
new file mode 100644
index 0000000..b2de930
--- /dev/null
+++ b/grub-core/kern/loongarch64/init.c
@@ -0,0 +1,47 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/cpu/loongarch64.h>
+
+grub_uint32_t grub_arch_cpuclock;
+
+/* FIXME: use interrupt to count high. */
+grub_uint64_t
+grub_get_rtc (void)
+{
+ static grub_uint32_t high = 0;
+ static grub_uint32_t last = 0;
+ grub_uint32_t low;
+
+ asm volatile ("csrrd %0, " GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT : "=r" (low));
+ if (low < last)
+ high++;
+ last = low;
+
+ return (((grub_uint64_t) high) << 32) | low;
+}
+
+void
+grub_timer_init (grub_uint32_t cpuclock)
+{
+ grub_arch_cpuclock = cpuclock;
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+}
diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c
new file mode 100644
index 0000000..eda1e1c
--- /dev/null
+++ b/grub-core/lib/loongarch64/efi/loongson.c
@@ -0,0 +1,119 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/cache.h>
+#include <grub/efi/efi.h>
+#include <grub/cpu/efi/memory.h>
+#include <grub/cpu/memory.h>
+#include <grub/machine/loongson.h>
+
+unsigned long
+grub_efi_get_bpi_version (const char *str)
+{
+ unsigned long version = GRUB_EFI_BPI_VER_NONE;
+
+ version = grub_strtoul (str + 4, 0, 0);
+
+ return version;
+}
+
+void *
+grub_efi_loongson_get_boot_params (void)
+{
+ static void * boot_params = NULL;
+ grub_efi_configuration_table_t *tables;
+ grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID;
+ unsigned int i;
+
+ if (boot_params)
+ return boot_params;
+
+ /* Look for Loongson boot params interface in UEFI config tables. */
+ tables = grub_efi_system_table->configuration_table;
+
+ for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
+ if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0)
+ {
+ boot_params= tables[i].vendor_table;
+ grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params);
+ break;
+ }
+ return boot_params;
+}
+
+grub_uint8_t
+grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
+{
+ grub_uint8_t sum;
+ grub_efi_uintn_t count;
+
+ for (sum = 0, count = 0; count < length; count++)
+ {
+ sum = (grub_uint8_t) (sum + *(buffer + count));
+ }
+ return sum;
+}
+
+grub_uint8_t
+grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
+{
+ grub_uint8_t checksum;
+
+ checksum = grub_efi_loongson_calculatesum8(buffer, length);
+
+ return (grub_uint8_t) (0x100 - checksum);
+}
+
+
+grub_uint32_t
+grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length,
+ mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype)
+{
+ grub_uint64_t tempmemsize = 0;
+ grub_uint32_t j = 0;
+ grub_uint32_t t = 0;
+
+ for(j = 0; j < length;)
+ {
+ tempmemsize = array[j].memsize;
+ for(t = j + 1; t < length; t++)
+ {
+ if(array[j].memstart + tempmemsize == array[t].memstart)
+ {
+ tempmemsize += array[t].memsize;
+ }
+ else
+ {
+ break;
+ }
+ }
+ bpmem->map[index].memtype = memtype;
+ bpmem->map[index].memstart = array[j].memstart;
+ bpmem->map[index].memsize = tempmemsize;
+ grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n",
+ index,
+ bpmem->map[index].memtype,
+ bpmem->map[index].memstart,
+ bpmem->map[index].memstart+ bpmem->map[index].memsize
+ );
+ j = t;
+ index++;
+ }
+ return index;
+}
diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c
new file mode 100644
index 0000000..4b253ca
--- /dev/null
+++ b/grub-core/lib/loongarch64/relocator.c
@@ -0,0 +1,163 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+#include <grub/types.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/cache.h>
+
+#include <grub/loongarch64/relocator.h>
+#include <grub/relocator_private.h>
+
+extern grub_uint8_t grub_relocator_forward_start;
+extern grub_uint8_t grub_relocator_forward_end;
+extern grub_uint8_t grub_relocator_backward_start;
+extern grub_uint8_t grub_relocator_backward_end;
+
+#define REGW_SIZEOF (4 * sizeof (grub_uint32_t))
+#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t))
+
+#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \
+ - &grub_relocator_##x##_start)
+#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \
+ + REGW_SIZEOF * 3)
+grub_size_t grub_relocator_align = sizeof (grub_uint64_t);
+grub_size_t grub_relocator_forward_size;
+grub_size_t grub_relocator_backward_size;
+grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF;
+
+void
+grub_cpu_relocator_init (void)
+{
+ grub_relocator_forward_size = RELOCATOR_SIZEOF(forward);
+ grub_relocator_backward_size = RELOCATOR_SIZEOF(backward);
+}
+
+static void
+write_reg (int regn, grub_uint64_t val, void **target)
+{
+ grub_uint32_t lu12iw=0x14000000;
+ grub_uint32_t ori=0x03800000;
+ grub_uint32_t lu32id=0x16000000;
+ grub_uint32_t lu52id=0x03000000;
+
+ *(grub_uint32_t *) *target = (lu12iw | (grub_uint32_t)((val & 0xfffff000)>>12<<5) | (grub_uint32_t)regn);;
+ *target = ((grub_uint32_t *) *target) + 1;
+ *(grub_uint32_t *) *target = (ori | (grub_uint32_t)((val & 0xfff)<<10) | (grub_uint32_t)(regn | regn<<5));
+ *target = ((grub_uint32_t *) *target) + 1;
+ *(grub_uint32_t *) *target = (lu32id | (grub_uint32_t)((val & 0xfffff00000000)>>32<<5) | (grub_uint32_t)regn);;
+ *target = ((grub_uint32_t *) *target) + 1;
+ *(grub_uint32_t *) *target = (lu52id | (grub_uint32_t)((val & 0xfff0000000000000)>>52<<10) | (grub_uint32_t)(regn | regn<<5));;
+ *target = ((grub_uint32_t *) *target) + 1;
+}
+
+static void
+write_jump (int regn, void **target)
+{
+ grub_uint32_t jirl=0x4c000000;
+
+ *(grub_uint32_t *) *target = (jirl | (grub_uint32_t)(regn<<5));
+ *target = ((grub_uint32_t *) *target) + 1;
+}
+
+void
+grub_cpu_relocator_jumper (void *rels, grub_addr_t addr)
+{
+ write_reg (1, addr, &rels);
+ write_jump (1, &rels);
+}
+
+void
+grub_cpu_relocator_backward (void *ptr0, void *src, void *dest,
+ grub_size_t size)
+{
+ void *ptr = ptr0;
+ write_reg (8, (grub_uint64_t) src, &ptr);
+ write_reg (9, (grub_uint64_t) dest, &ptr);
+ write_reg (10, (grub_uint64_t) size, &ptr);
+ grub_memcpy (ptr, &grub_relocator_backward_start,
+ RELOCATOR_SRC_SIZEOF (backward));
+}
+
+void
+grub_cpu_relocator_forward (void *ptr0, void *src, void *dest,
+ grub_size_t size)
+{
+ void *ptr = ptr0;
+ write_reg (8, (grub_uint64_t) src, &ptr);
+ write_reg (9, (grub_uint64_t) dest, &ptr);
+ write_reg (10, (grub_uint64_t) size, &ptr);
+ grub_memcpy (ptr, &grub_relocator_forward_start,
+ RELOCATOR_SRC_SIZEOF (forward));
+}
+
+grub_err_t
+grub_relocator64_boot (struct grub_relocator *rel,
+ struct grub_relocator64_state state)
+{
+ grub_relocator_chunk_t ch;
+ void *ptr;
+ grub_err_t err;
+ void *relst;
+ grub_size_t relsize;
+ grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF;
+ unsigned i;
+ grub_addr_t vtarget;
+
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+ (0xffffffff - stateset_size)
+ + 1, stateset_size,
+ grub_relocator_align,
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+ if (err)
+ return err;
+
+ ptr = get_virtual_current_address (ch);
+ for (i = 1; i < 32; i++)
+ write_reg (i, state.gpr[i], &ptr);
+ write_jump (state.jumpreg, &ptr);
+
+ vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch),
+ stateset_size);
+
+ err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize);
+ if (err)
+ return err;
+
+ grub_arch_sync_caches ((void *) relst, relsize);
+
+ asm volatile (
+ "ibar 0 \n");
+
+ grub_uint64_t val;
+ __asm__ __volatile__(
+ "li.w %0, 0x4\n\t"
+ "csrxchg $r0, %0, 0x0\n\t"
+ : "=r"(val)
+ :
+ :
+ );
+
+ ((void (*) (void)) relst) ();
+
+ /* Not reached. */
+ return GRUB_ERR_NONE;
+}
diff --git a/grub-core/lib/loongarch64/relocator_asm.S b/grub-core/lib/loongarch64/relocator_asm.S
new file mode 100644
index 0000000..cf1724d
--- /dev/null
+++ b/grub-core/lib/loongarch64/relocator_asm.S
@@ -0,0 +1,51 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+ .p2align 4 /* force 16-byte alignment */
+
+VARIABLE (grub_relocator_forward_start)
+
+copycont1:
+ ld.d $r11,$r8,0
+ st.d $r11,$r9,0
+ addi.d $r8, $r8, 8
+ addi.d $r10, $r10, -8
+ addi.d $r9, $r9, 8
+ bne $r10, $r0, copycont1
+
+VARIABLE (grub_relocator_forward_end)
+
+VARIABLE (grub_relocator_backward_start)
+
+ add.d $r9, $r9, $r10
+ add.d $r8, $r8, $r10
+ /* Backward movsl is implicitly off-by-one. compensate that. */
+ addi.d $r9, $r9, -8
+ addi.d $r8, $r8, -8
+copycont2:
+ ld.w $r11,$r8,0
+ st.w $r11,$r9,0
+ addi.d $r8, $r8, -8
+ addi.d $r10, $r10, -8
+ addi.d $r9, $r9, -8
+ bne $r10, $r0, copycont2
+
+VARIABLE (grub_relocator_backward_end)
+
diff --git a/grub-core/lib/loongarch64/setjmp.S b/grub-core/lib/loongarch64/setjmp.S
new file mode 100644
index 0000000..47db814
--- /dev/null
+++ b/grub-core/lib/loongarch64/setjmp.S
@@ -0,0 +1,74 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+#include <grub/loongarch64/asm.h>
+
+ .file "setjmp.S"
+
+GRUB_MOD_LICENSE "GPLv3+"
+
+ .text
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+ GRUB_ASM_REG_S $s0, $a0,0
+ GRUB_ASM_REG_S $s1, $a0,8
+ GRUB_ASM_REG_S $s2, $a0,16
+ GRUB_ASM_REG_S $s3, $a0,24
+ GRUB_ASM_REG_S $s4, $a0,32
+ GRUB_ASM_REG_S $s5, $a0,40
+ GRUB_ASM_REG_S $s6, $a0,48
+ GRUB_ASM_REG_S $s7, $a0,56
+ GRUB_ASM_REG_S $s8, $a0,64
+ GRUB_ASM_REG_S $fp, $a0,72
+ GRUB_ASM_REG_S $sp, $a0,80
+ GRUB_ASM_REG_S $ra, $a0,88
+ move $v0, $zero
+ move $v1, $zero
+ jr $ra
+ nop
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+ GRUB_ASM_REG_L $s0, $a0,0
+ GRUB_ASM_REG_L $s1, $a0,8
+ GRUB_ASM_REG_L $s2, $a0,16
+ GRUB_ASM_REG_L $s3, $a0,24
+ GRUB_ASM_REG_L $s4, $a0,32
+ GRUB_ASM_REG_L $s5, $a0,40
+ GRUB_ASM_REG_L $s6, $a0,48
+ GRUB_ASM_REG_L $s7, $a0,56
+ GRUB_ASM_REG_L $s8, $a0,64
+ GRUB_ASM_REG_L $fp, $a0,72
+ GRUB_ASM_REG_L $sp, $a0,80
+ GRUB_ASM_REG_L $ra, $a0,88
+ addi.w $v0, $zero, 1
+ /*
+ * replace: movn $v0, $a1, $a1
+ */
+ bnez $a1, .ZW0
+ addi.d $v0, $a1, 0
+.ZW0:
+ addi.d $v1,$zero,0
+ jr $ra
+ nop
diff --git a/grub-core/lib/loongson/reboot.c b/grub-core/lib/loongson/reboot.c
new file mode 100644
index 0000000..107787a
--- /dev/null
+++ b/grub-core/lib/loongson/reboot.c
@@ -0,0 +1,33 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/kernel.h>
+#include <grub/loader.h>
+
+void
+grub_la_reboot (void)
+{
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+ for (;;) ;
+}
diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S
index f6e4905..023dc90 100644
--- a/grub-core/lib/setjmp.S
+++ b/grub-core/lib/setjmp.S
@@ -15,6 +15,8 @@
#include "./arm/setjmp.S"
#elif defined(__aarch64__)
#include "./arm64/setjmp.S"
+#elif defined(__loongarch64)
+#include "./loongarch64/setjmp.S"
#else
#error "Unknown target cpu type"
#endif
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index b72e6bd..f4066b5 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -343,6 +343,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) =
GRUB_PE32_MACHINE_I386;
#elif defined(__ia64__)
GRUB_PE32_MACHINE_IA64;
+#elif defined(__loongarch64)
+ GRUB_PE32_MACHINE_LOONGARCH64;
#else
#error this architecture is not supported by grub2
#endif
diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c
new file mode 100644
index 0000000..7594ca2
--- /dev/null
+++ b/grub-core/loader/loongarch64/linux.c
@@ -0,0 +1,690 @@
+/* linux.c - boot Linux */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/elf.h>
+#include <grub/elfload.h>
+#include <grub/loader.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/command.h>
+#include <grub/cpu/relocator.h>
+#include <grub/machine/loongson.h>
+#include <grub/memory.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
+#include <grub/fdt.h>
+#include <grub/efi/memory.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+typedef unsigned long size_t;
+
+#define FDT_ADDR_CELLS_STRING "#address-cells"
+#define FDT_SIZE_CELLS_STRING "#size-cells"
+#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \
+ sizeof (FDT_ADDR_CELLS_STRING) + \
+ sizeof (FDT_SIZE_CELLS_STRING))
+
+static grub_dl_t my_mod;
+static int loaded;
+static int initrd_loaded = 0;
+static grub_size_t linux_size;
+
+static struct grub_relocator *relocator;
+static grub_addr_t target_addr, entry_addr;
+static int linux_argc;
+static grub_uint8_t *linux_args_addr;
+static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off;
+
+static void *fdt;
+static int is_fdt_boot;
+static grub_addr_t initrd_start, initrd_end;
+static char *fdt_linux_args;
+
+static grub_err_t
+allocate_fdt_and_exit_boot (void)
+{
+ int node, retval;
+ grub_err_t err;
+ unsigned int size;
+ grub_efi_uintn_t mmap_size;
+ grub_efi_uintn_t desc_size;
+ grub_efi_uint32_t desc_version;
+ grub_efi_memory_descriptor_t *mmap_buf;
+
+ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE;
+
+ fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size));
+ if (!fdt)
+ return GRUB_ERR_OUT_OF_MEMORY;
+
+ grub_fdt_create_empty_tree (fdt, size);
+ grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2);
+ grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2);
+
+ node = grub_fdt_find_subnode (fdt, 0, "chosen");
+ if (node < 0)
+ node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ if (node < 1)
+ goto failure;
+
+ grub_dprintf ("loongson", "command_line %s, len %ld\n",
+ fdt_linux_args, grub_strlen(fdt_linux_args) + 1);
+ if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) {
+ retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args,
+ grub_strlen(fdt_linux_args) + 1);
+ if (retval)
+ goto failure;
+ }
+
+ /* Set initrd info */
+ if (initrd_start && initrd_end > initrd_start)
+ {
+ grub_dprintf ("linux", "Initrd @ %p-%p\n",
+ (void *) initrd_start, (void *) initrd_end);
+
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
+ initrd_start);
+ if (retval)
+ goto failure;
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
+ initrd_end);
+ if (retval)
+ goto failure;
+ }
+
+ node = grub_fdt_find_subnode (fdt, 0, "chosen");
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table",
+ (grub_uint64_t)grub_efi_system_table);
+ if (retval)
+ goto failure;
+
+ mmap_size = grub_efi_find_mmap_size ();
+ if (! mmap_size)
+ return grub_errno;
+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size));
+ if (! mmap_buf)
+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map");
+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL,
+ &desc_size, &desc_version);
+ if (err)
+ return err;
+
+ if (!mmap_buf || !mmap_size || !desc_size)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start",
+ (grub_uint64_t)mmap_buf);
+ if (retval)
+ goto failure;
+
+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size",
+ mmap_size);
+ if (retval)
+ goto failure;
+
+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size",
+ desc_size);
+ if (retval)
+ goto failure;
+
+ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver",
+ desc_version);
+ if (retval)
+ goto failure;
+
+ return GRUB_ERR_NONE;
+
+failure:
+ if (!fdt) {
+ return GRUB_ERR_BAD_OS;
+ }
+ grub_efi_free_pages ((grub_addr_t) fdt,
+ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
+ fdt = NULL;
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+
+static grub_err_t
+allocate_boot_params_and_exit_boot (void)
+{
+ grub_efi_uintn_t mmap_size;
+ grub_efi_uintn_t desc_size;
+ grub_efi_uint32_t desc_version;
+ grub_efi_memory_descriptor_t *mmap_buf;
+ grub_efi_memory_descriptor_t * lsdesc = NULL;
+ grub_err_t err;
+ struct boot_params_interface * boot_params;
+ mem_map_v1 * mem_map_v1_table = NULL;
+ unsigned long bpi_version = 0;
+ grub_int8_t checksum = 0;
+ grub_uint32_t tmp_index = 0;
+ grub_uint32_t free_index = 0;
+ grub_uint32_t reserve_index = 0;
+ grub_uint32_t acpi_table_index = 0;
+ grub_uint32_t acpi_nvs_index = 0;
+
+ struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX];
+ struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX];
+ struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX];
+ struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX];
+
+ grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX);
+ grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX);
+ grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX);
+ grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX);
+
+ boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params();
+
+ ext_list * listpointer = NULL;
+ /* Check extlist headers */
+ listpointer = boot_params->extlist;
+ for( ;listpointer != NULL; listpointer = listpointer->next)
+ {
+ char *pl= (char *)&(listpointer->signature);
+ if(grub_strncmp(pl, "MEM", 3) == 0)
+ {
+ mem_map_v1_table = (mem_map_v1 *)listpointer;
+ break;
+ }
+ }
+
+ mmap_size = grub_efi_find_mmap_size ();
+ if (! mmap_size)
+ return grub_errno;
+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size));
+ if (! mmap_buf)
+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map");
+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL,
+ &desc_size, &desc_version);
+ if (err)
+ return err;
+
+ if (!mmap_buf || !mmap_size || !desc_size)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ char *p = (char *)&(boot_params->signature);
+ bpi_version = grub_efi_get_bpi_version(p);
+ grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version);
+
+ if (bpi_version <= GRUB_EFI_BPI_VER_V2)
+ {
+ /*
+ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \
+ now we can fill platform specific memory structure.
+ */
+ for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size);
+ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size))
+ {
+ grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type,
+ lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE);
+
+ /* System RAM */
+ if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \
+ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \
+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \
+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \
+ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \
+ (lsdesc->type != GRUB_EFI_PAL_CODE))
+ {
+ free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM;
+ free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS;
+ free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE;
+ free_index++;
+
+ /*ACPI*/
+ } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){
+ acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE;
+ acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS;
+ acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE;
+ acpi_table_index++;
+ } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){
+ acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS;
+ acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS;
+ acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE;
+ acpi_nvs_index++;
+
+ /* Reserve */
+ } else {
+ reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED;
+ reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS;
+ reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE;
+ reserve_index++;
+ }
+ }
+
+ tmp_index = mem_map_v1_table->mapcount;
+ /*System RAM Sort*/
+ tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table,
+ tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM);
+ /*ACPI Sort*/
+ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index,
+ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE);
+ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index,
+ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS);
+ /*Reserve Sort*/
+ {
+ grub_uint64_t loongarch_addr;
+ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr));
+ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000)
+ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index,
+ mem_map_v1_table, tmp_index,
+ GRUB_EFI_LOONGSON_MEMORY_RESERVED);
+ else
+ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index,
+ mem_map_v1_table, tmp_index,
+ GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1);
+ }
+ mem_map_v1_table->mapcount = tmp_index;
+ mem_map_v1_table->header.checksum = 0;
+
+ checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table,
+ mem_map_v1_table->header.length);
+ mem_map_v1_table->header.checksum = checksum;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+ struct grub_relocator64_state state;
+
+ grub_memset (&state, 0, sizeof (state));
+
+ /* Boot the kernel. */
+ state.gpr[1] = entry_addr;
+ grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]);
+
+ if (is_fdt_boot == 1)
+ {
+ if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE)
+ return grub_errno;
+
+ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT;
+ state.gpr[5] = (grub_uint64_t)fdt;
+ state.gpr[6] = 0;
+ } else {
+ state.gpr[4] = linux_argc;
+ state.gpr[5] = (grub_addr_t) linux_args_addr;
+ state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params();
+
+ if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE)
+ return grub_errno;
+ }
+ grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n",
+ state.gpr[4], state.gpr[5], state.gpr[6]);
+
+ state.jumpreg = 1;
+ grub_relocator64_boot (relocator, state);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+ grub_relocator_unload (relocator);
+ grub_dl_unref (my_mod);
+ loaded = 0;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_load64 (grub_elf_t elf, const char *filename)
+{
+ Elf64_Addr base;
+ grub_err_t err;
+ grub_uint8_t *playground;
+ grub_uint64_t addr;
+ int flag;
+
+ /* Linux's entry point incorrectly contains a virtual address. */
+ entry_addr = elf->ehdr.ehdr64.e_entry;
+ grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr);
+
+ linux_size = grub_elf64_size (elf, &base, 0);
+ grub_dprintf("loongson", "base = 0x%lx\n", base);
+
+ if (linux_size == 0)
+ return grub_errno;
+ target_addr = base;
+ linux_size = ALIGN_UP (base + linux_size - base, 8);
+
+ asm volatile ("csrrd %0, 0x181" : "=r" (addr));
+ if (addr & 0x1) {
+ flag = GRUB_ELF_LOAD_FLAGS_NONE;
+ } else {
+ flag = GRUB_ELF_LOAD_FLAGS_30BITS;
+ base &= ~ELF64_LOADMASK;
+ entry_addr &= ~ELF64_LOADMASK;
+ }
+
+ relocator = grub_relocator_new ();
+ if (!relocator)
+ return grub_errno;
+
+ {
+ grub_relocator_chunk_t ch;
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+ grub_vtop ((void *) target_addr),
+ linux_size);
+ if (err)
+ return err;
+ playground = get_virtual_current_address (ch);
+ }
+
+ /* Now load the segments into the area we claimed. */
+ return grub_elf64_load (elf, filename, playground - base, flag, 0, 0);
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_elf_t elf = 0;
+ grub_err_t err;
+ int args_size = 0;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ }
+
+ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
+ if (! elf)
+ return grub_errno;
+
+ if (elf->ehdr.ehdr64.e_type != ET_EXEC)
+ {
+ grub_elf_close (elf);
+ return grub_error (GRUB_ERR_UNKNOWN_OS,
+ N_("this ELF file is not of the right type"));
+ }
+
+ /* Release the previously used memory. */
+ grub_loader_unset ();
+ loaded = 0;
+
+ if (grub_elf_is_elf64 (elf))
+ err = grub_linux_load64 (elf, argv[0]);
+ else
+ err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
+
+ grub_elf_close (elf);
+
+ if (err)
+ return err;
+
+ if (grub_efi_loongson_get_boot_params() == NULL) {
+ grub_size_t cmdline_size;
+
+ is_fdt_boot = 1;
+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+ fdt_linux_args = grub_malloc (cmdline_size);
+ if (!fdt_linux_args)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+ grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+ err = grub_create_loader_cmdline (argc, argv,
+ fdt_linux_args + sizeof (LINUX_IMAGE) - 1,
+ cmdline_size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
+ grub_dprintf("loongson", "fdt linux args:%s\n",
+ fdt_linux_args + sizeof (LINUX_IMAGE) - 1);
+
+ } else {
+ int i;
+ grub_uint64_t *linux_argv;
+ char *linux_args;
+
+ is_fdt_boot = 0;
+ /* For arguments. */
+ linux_argc = argc;
+ /* Main arguments. */
+ args_size = (linux_argc) * sizeof (grub_uint64_t);
+ /* Initrd address/size and initrd */
+ args_size += 3 * sizeof (grub_uint64_t);
+ /* NULL terminator. */
+ args_size += sizeof (grub_uint64_t);
+ /* First argument is always "a0". */
+ args_size += ALIGN_UP (sizeof ("a0"), 4);
+ /* Normal arguments. */
+ for (i = 1; i < argc; i++)
+ args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
+
+ /* rd arguments. */
+ args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
+ args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
+ args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4);
+
+ args_size = ALIGN_UP (args_size, 8);
+
+ linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size));
+ grub_dprintf ("linux", "linux args numpages: %lld\n",
+ (long long) GRUB_EFI_BYTES_TO_PAGES (args_size));
+ if (!linux_args_addr)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+ linux_argv = (grub_uint64_t *) linux_args_addr;
+ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3));
+
+ grub_memcpy (linux_args, "a0", sizeof ("a0"));
+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args;
+ linux_argv++;
+ linux_args += ALIGN_UP (sizeof ("a0"), 4);
+
+ for (i = 1; i < argc; i++)
+ {
+ grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1);
+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args;
+ linux_argv++;
+ linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
+ }
+
+ /* Reserve space for rd arguments. */
+ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr;
+ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
+ *linux_argv = 0;
+ linux_argv++;
+
+ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr;
+ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
+ *linux_argv = 0;
+ linux_argv++;
+
+ /* Reserve space for initrd arguments. */
+ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr;
+ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4);
+ *linux_argv = 0;
+ linux_argv++;
+
+ *linux_argv = 0;
+ }
+
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+ loaded = 1;
+ }
+
+ initrd_loaded = 0;
+
+fail:
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ }
+
+ if (fdt_linux_args && !loaded)
+ grub_free (fdt_linux_args);
+
+ if (linux_args_addr && !loaded)
+ grub_efi_free_pages ((grub_addr_t) linux_args_addr,
+ GRUB_EFI_BYTES_TO_PAGES (args_size));
+
+ return grub_errno;
+}
+
+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+
+/*
+ * This function returns a pointer to a legally allocated initrd buffer,
+ * or NULL if unsuccessful
+ */
+static void *
+allocate_initrd_mem (int initrd_pages)
+{
+ grub_addr_t max_addr;
+
+ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+ return NULL;
+
+ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+
+ return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_size_t initrd_size, initrd_pages;
+ grub_err_t err;
+ void *initrd_mem = NULL;
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ if (!loaded)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+
+ if (initrd_loaded)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued.");
+
+ if (grub_initrd_init (argc, argv, &initrd_ctx))
+ goto fail;
+
+ initrd_size = grub_get_initrd_size (&initrd_ctx);
+
+ if (is_fdt_boot == 1) //fdt
+ {
+ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
+ initrd_mem = allocate_initrd_mem (initrd_pages);
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+ } else {
+ grub_relocator_chunk_t ch;
+ err = grub_relocator_alloc_chunk_align (relocator, &ch,
+ 0, (0xffffffff - initrd_size) + 1,
+ initrd_size, 0x10000,
+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
+
+ if (err)
+ return err;
+ initrd_mem = get_virtual_current_address (ch);
+ }
+
+ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
+ goto fail;
+
+ initrd_start = (grub_addr_t) initrd_mem;
+ initrd_end = initrd_start + initrd_size;
+ grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n",
+ (void *) initrd_start, initrd_size);
+
+ if (is_fdt_boot == 0) //bpi
+ {
+ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off,
+ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"),
+ "rd_start=0x%lx",
+ (grub_uint64_t) initrd_mem);
+ ((grub_uint64_t *) linux_args_addr)[linux_argc]
+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off);
+ linux_argc++;
+
+ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off,
+ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx",
+ (grub_uint64_t) initrd_size);
+ ((grub_uint64_t *) linux_args_addr)[linux_argc]
+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off);
+ linux_argc++;
+
+ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off,
+ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"),
+ "initrd=0x%lx,0x%lx",
+ ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS),
+ (grub_uint64_t) initrd_size);
+ ((grub_uint64_t *) linux_args_addr)[linux_argc]
+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off);
+ linux_argc++;
+ }
+
+ initrd_loaded = 1;
+
+ fail:
+ grub_initrd_close (&initrd_ctx);
+ if (is_fdt_boot == 1)
+ if (initrd_mem && !initrd_start)
+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+
+ return grub_errno;
+}
+
+static grub_command_t cmd_linux, cmd_initrd;
+
+GRUB_MOD_INIT(linux)
+{
+ cmd_linux = grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+}
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 6f46b7e..50e04ac 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -360,7 +360,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
#define GRUB_ARCH_DL_GOT_ALIGN 4
#endif
-#if defined (__aarch64__) || defined (__sparc__)
+#if defined (__aarch64__) || defined (__sparc__) || defined (__loongarch64)
#define GRUB_ARCH_DL_TRAMP_ALIGN 8
#define GRUB_ARCH_DL_GOT_ALIGN 8
#endif
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 510a403..a57187f 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -2117,7 +2117,8 @@ struct grub_efi_memory_attribute_protocol
typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t;
#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
- || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
+ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
+ || defined (__loongarch64)
#define efi_call_0(func) func()
#define efi_call_1(func, a) func(a)
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 8ca8c38..fe1df9d 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -138,7 +138,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
extern grub_addr_t EXPORT_VAR(grub_stack_addr);
extern grub_size_t EXPORT_VAR(grub_stack_size);
-#if defined(__arm__) || defined(__aarch64__)
+#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__)
void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
#include <grub/cpu/linux.h>
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index 45c9f8b..f612a55 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -89,6 +89,7 @@ struct grub_pe32_coff_header
};
#define GRUB_PE32_MACHINE_I386 0x14c
+#define GRUB_PE32_MACHINE_LOONGARCH64 0x6264
#define GRUB_PE32_MACHINE_IA64 0x200
#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2
@@ -355,6 +356,7 @@ struct grub_pe32_fixup_block
#define GRUB_PE32_REL_BASED_IA64_IMM64 9
#define GRUB_PE32_REL_BASED_DIR64 10
#define GRUB_PE32_REL_BASED_HIGH3ADJ 11
+#define GRUB_PE32_REL_BASED_LOONGARCH64 8
struct grub_pe32_symbol
{
diff --git a/include/grub/elf.h b/include/grub/elf.h
index c8492f9..2c0b163 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -247,6 +247,7 @@ typedef struct
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
#define EM_NUM 95
#define EM_AARCH64 183 /* ARM 64-bit architecture */
+#define EM_LOONGARCH64 258 /* LoongArch64 architecture */
/* If it is necessary to assign new unofficial EM_* values, please
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@@ -1448,6 +1449,60 @@ typedef struct
#define OHWA0_R4KEOP_CHECKED 0x00000001
#define OHWA1_R4KEOP_CLEAN 0x00000002
+/* LOONGARCH64 relocs. */
+#define R_LARCH_NONE 0
+#define R_LARCH_32 1
+#define R_LARCH_64 2
+#define R_LARCH_RELATIVE 3
+#define R_LARCH_COPY 4
+#define R_LARCH_JUMP_SLOT 5
+#define R_LARCH_TLS_DTPMOD32 6
+#define R_LARCH_TLS_DTPMOD64 7
+#define R_LARCH_TLS_DTPREL32 8
+#define R_LARCH_TLS_DTPREL64 9
+#define R_LARCH_TLS_TPREL32 10
+#define R_LARCH_TLS_TPREL64 11
+#define R_LARCH_IRELATIVE 12
+#define R_LARCH_MARK_LA 20
+#define R_LARCH_MARK_PCREL 21
+#define R_LARCH_SOP_PUSH_PCREL 22
+#define R_LARCH_SOP_PUSH_ABSOLUTE 23
+#define R_LARCH_SOP_PUSH_DUP 24
+#define R_LARCH_SOP_PUSH_GPREL 25
+#define R_LARCH_SOP_PUSH_TLS_TPREL 26
+#define R_LARCH_SOP_PUSH_TLS_GOT 27
+#define R_LARCH_SOP_PUSH_TLS_GD 28
+#define R_LARCH_SOP_PUSH_PLT_PCREL 29
+#define R_LARCH_SOP_ASSERT 30
+#define R_LARCH_SOP_NOT 31
+#define R_LARCH_SOP_SUB 32
+#define R_LARCH_SOP_SL 33
+#define R_LARCH_SOP_SR 34
+#define R_LARCH_SOP_ADD 35
+#define R_LARCH_SOP_AND 36
+#define R_LARCH_SOP_IF_ELSE 37
+#define R_LARCH_SOP_POP_32_S_10_5 38
+#define R_LARCH_SOP_POP_32_U_10_12 39
+#define R_LARCH_SOP_POP_32_S_10_12 40
+#define R_LARCH_SOP_POP_32_S_10_16 41
+#define R_LARCH_SOP_POP_32_S_10_16_S2 42
+#define R_LARCH_SOP_POP_32_S_5_20 43
+#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44
+#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45
+#define R_LARCH_SOP_POP_32_U 46
+#define R_LARCH_ADD8 47
+#define R_LARCH_ADD16 48
+#define R_LARCH_ADD24 49
+#define R_LARCH_ADD32 50
+#define R_LARCH_ADD64 51
+#define R_LARCH_SUB8 52
+#define R_LARCH_SUB16 53
+#define R_LARCH_SUB24 54
+#define R_LARCH_SUB32 55
+#define R_LARCH_SUB64 56
+#define R_LARCH_GNU_VTINHERIT 57
+#define R_LARCH_GNU_VTENTRY 58
+
/* MIPS relocs. */
#define R_MIPS_NONE 0 /* No reloc */
diff --git a/include/grub/fdt.h b/include/grub/fdt.h
index 6ee57e1..a0710ab 100644
--- a/include/grub/fdt.h
+++ b/include/grub/fdt.h
@@ -19,11 +19,14 @@
#ifndef GRUB_FDT_HEADER
#define GRUB_FDT_HEADER 1
-#if defined(__arm__) || defined(__aarch64__)
+#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__)
#include <grub/types.h>
#include <grub/symbol.h>
+/* Space required when preparing the /chosen node after boot has been called. */
+#define GRUB_EFI_LINUX_FDT_EXTRA_SPACE 0x400
+
#define FDT_MAGIC 0xD00DFEED
typedef struct {
diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h
new file mode 100644
index 0000000..c3e77e9
--- /dev/null
+++ b/include/grub/loongarch64/asm.h
@@ -0,0 +1,10 @@
+#ifndef GRUB_LOONGARCH64_ASM_HEADER
+#define GRUB_LOONGARCH64_ASM_HEADER 1
+
+#define GRUB_ASM_T4 $a4
+#define GRUB_ASM_T5 $a5
+#define GRUB_ASM_SZREG 8
+#define GRUB_ASM_REG_S st.d
+#define GRUB_ASM_REG_L ld.d
+
+#endif
diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h
new file mode 100644
index 0000000..7a9ccb4
--- /dev/null
+++ b/include/grub/loongarch64/efi/loongson.h
@@ -0,0 +1,113 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_LOONGSON_HEADER
+#define GRUB_EFI_LOONGSON_HEADER 1
+
+#include <grub/types.h>
+
+#include <grub/efi/api.h>
+
+#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \
+ { 0x4660f721, 0x2ec5, 0x416a, \
+ { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \
+ }
+
+#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL
+#define ELF32_LOADMASK (0xf0000000UL)
+#define ELF64_LOADMASK (0xf000000000000000ULL)
+#define FLAGS_EFI_SUPPORT_BIT 0
+#define GRUB_EFI_LOONGSON_MMAP_MAX 128
+
+typedef enum
+ {
+ GRUB_EFI_LOONGSON_SYSTEM_RAM = 1,
+ GRUB_EFI_LOONGSON_MEMORY_RESERVED,
+ GRUB_EFI_LOONGSON_ACPI_TABLE,
+ GRUB_EFI_LOONGSON_ACPI_NVS,
+ GRUB_EFI_LOONGSON_MAX_MEMORY_TYPE
+ }
+grub_efi_loongson_memory_type;
+
+typedef enum
+ {
+ GRUB_EFI_BPI_VER_NONE = 0,
+ GRUB_EFI_BPI_VER_V1 = 1000,
+ GRUB_EFI_BPI_VER_V2 = 1001,
+ }
+ grub_efi_loongson_bpi_version;
+
+grub_uint8_t
+EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer,
+ grub_efi_uintn_t Length);
+
+grub_uint8_t
+EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer,
+ grub_efi_uintn_t Length);
+
+unsigned long
+EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str);
+
+void *
+EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void);
+
+typedef struct _extention_list_hdr {
+ grub_uint64_t signature;
+ grub_uint32_t length;
+ grub_uint8_t revision;
+ grub_uint8_t checksum;
+ union {
+ struct _extention_list_hdr *next;
+ grub_uint64_t next_offset;
+ };
+}GRUB_PACKED
+ext_list;
+
+typedef struct boot_params_interface {
+ grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'}
+ grub_efi_system_table_t *systemtable;
+ union {
+ ext_list *extlist;
+ grub_uint64_t extlist_offset;
+ };
+ grub_uint64_t flags;
+}GRUB_PACKED
+boot_params_interface;
+
+typedef struct {
+ ext_list header; //{MEM}
+ grub_uint8_t mapcount;
+ struct GRUB_PACKED memmap_v1 {
+ grub_uint32_t memtype;
+ grub_uint64_t memstart;
+ grub_uint64_t memsize;
+ } map[GRUB_EFI_LOONGSON_MMAP_MAX];
+}GRUB_PACKED
+mem_map_v1;
+
+typedef struct {
+ ext_list header; //{VBIOS}
+ grub_uint64_t vbiosaddr;
+}GRUB_PACKED
+vbios;
+
+grub_uint32_t
+EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[],
+ grub_uint32_t length, mem_map_v1 * mem,
+ grub_uint32_t index, grub_uint32_t memtype);
+#endif /* ! GRUB_EFI_LOONGSON_HEADER */
diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h
new file mode 100644
index 0000000..73641a1
--- /dev/null
+++ b/include/grub/loongarch64/efi/memory.h
@@ -0,0 +1,12 @@
+#ifndef GRUB_MEMORY_CPU_HEADER
+#include <grub/efi/memory.h>
+
+static inline grub_uint64_t
+grub_efi_max_usable_address(void)
+{
+ grub_uint64_t addr;
+ asm volatile ("csrrd %0, 0x181" : "=r" (addr));
+ return addr |= 0xffffffffffUL;
+}
+
+#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/loongarch64/efi/time.h b/include/grub/loongarch64/efi/time.h
new file mode 100644
index 0000000..e69de29
diff --git a/include/grub/loongarch64/io.h b/include/grub/loongarch64/io.h
new file mode 100644
index 0000000..5f34103
--- /dev/null
+++ b/include/grub/loongarch64/io.h
@@ -0,0 +1,62 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_IO_H
+#define GRUB_IO_H 1
+
+#include <grub/types.h>
+
+typedef grub_addr_t grub_port_t;
+
+static __inline unsigned char
+grub_inb (grub_port_t port)
+{
+ return *(volatile grub_uint8_t *) port;
+}
+
+static __inline unsigned short int
+grub_inw (grub_port_t port)
+{
+ return *(volatile grub_uint16_t *) port;
+}
+
+static __inline unsigned int
+grub_inl (grub_port_t port)
+{
+ return *(volatile grub_uint32_t *) port;
+}
+
+static __inline void
+grub_outb (unsigned char value, grub_port_t port)
+{
+ *(volatile grub_uint8_t *) port = value;
+}
+
+static __inline void
+grub_outw (unsigned short int value, grub_port_t port)
+{
+ *(volatile grub_uint16_t *) port = value;
+}
+
+static __inline void
+grub_outl (unsigned int value, grub_port_t port)
+{
+ *(volatile grub_uint32_t *) port = value;
+}
+
+#endif /* _SYS_IO_H */
diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h
new file mode 100644
index 0000000..3c6cf65
--- /dev/null
+++ b/include/grub/loongarch64/linux.h
@@ -0,0 +1,74 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2021 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_LOONGARCH64_LINUX_HEADER
+#define GRUB_LOONGARCH64_LINUX_HEADER 1
+
+#include <grub/types.h>
+
+/* LoongArch linux kernel type */
+#define GRUB_LOONGARCH_LINUX_BAD 0
+#define GRUB_LOONGARCH_LINUX_ELF 1
+#define GRUB_LOONGARCH_LINUX_EFI 2
+
+#define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128
+
+#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */
+#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */
+#define linux_arch_kernel_header linux_loongarch64_kernel_header
+
+/* From linux/Documentation/loongarch/booting.txt
+ *
+ * 0-1: MZ
+ * 0x28: LoongArch\0
+ * 0x3c: PE/COFF头偏移
+ * 0x20e:内核版本号偏移-512
+ * riscv的version字段在0x20偏移处,现在LoongArch没有使用,是0
+ */
+struct linux_loongarch64_kernel_header
+{
+ grub_uint32_t code0; /* Executable code */
+ grub_uint32_t code1; /* Executable code */
+ grub_uint64_t text_offset; /* Image load offset */
+ grub_uint64_t res0; /* reserved */
+ grub_uint64_t res1; /* reserved */
+ grub_uint64_t res2; /* reserved */
+ grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */
+ grub_uint32_t magic1; /* Magic number, little endian, "h" */
+ grub_uint64_t res3; /* reserved */
+ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */
+};
+
+struct linux_loongarch64_kernel_params
+{
+ grub_addr_t kernel_addr; /* kernel entry address */
+ grub_size_t kernel_size; /* kernel size */
+ grub_addr_t ramdisk_addr; /* initrd load address */
+ grub_size_t ramdisk_size; /* initrd size */
+ int linux_argc;
+ grub_addr_t linux_argv;
+ void* linux_args;
+};
+
+#include <grub/efi/efi.h>
+#include <grub/elfload.h>
+
+#define ELF32_LOADMASK (0xf0000000UL)
+#define ELF64_LOADMASK (0xf000000000000000ULL)
+
+#endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */
diff --git a/include/grub/loongarch64/loongarch64.h b/include/grub/loongarch64/loongarch64.h
new file mode 100644
index 0000000..ea3be3d
--- /dev/null
+++ b/include/grub/loongarch64/loongarch64.h
@@ -0,0 +1,30 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_REGISTERS_CPU_HEADER
+#define GRUB_REGISTERS_CPU_HEADER 1
+
+#ifdef ASM_FILE
+#define GRUB_CPU_REGISTER_WRAP(x) x
+#else
+#define GRUB_CPU_REGISTER_WRAP(x) #x
+#endif
+
+#define GRUB_CPU_LOONGARCH_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP(9)
+
+#endif
diff --git a/include/grub/loongarch64/memory.h b/include/grub/loongarch64/memory.h
new file mode 100644
index 0000000..8281dab
--- /dev/null
+++ b/include/grub/loongarch64/memory.h
@@ -0,0 +1,60 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MEMORY_CPU_HEADER
+#define GRUB_MEMORY_CPU_HEADER 1
+
+#ifndef ASM_FILE
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#ifndef ASM_FILE
+
+typedef grub_addr_t grub_phys_addr_t;
+
+static inline grub_phys_addr_t
+grub_vtop (void *a)
+{
+ if (-1 == ((grub_int64_t) a >> 32))
+ return ((grub_phys_addr_t) a) & 0x1fffffffUL;
+ return ((grub_phys_addr_t) a) & 0xffffffffffffUL;
+}
+
+static inline void *
+grub_map_memory (grub_phys_addr_t a,
+ grub_size_t size __attribute__ ((unused)))
+{
+ grub_uint64_t addr;
+ asm volatile ("csrrd %0, 0x181" : "=r" (addr));
+ if (addr & 0x1)
+ return (void *) (a | (addr & 0xffffffffffffff00UL));
+ else
+ return (void *) a;
+}
+
+static inline void
+grub_unmap_memory (void *a __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
+
+#endif
+
+#endif
diff --git a/include/grub/loongarch64/relocator.h b/include/grub/loongarch64/relocator.h
new file mode 100644
index 0000000..8815314
--- /dev/null
+++ b/include/grub/loongarch64/relocator.h
@@ -0,0 +1,38 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_RELOCATOR_CPU_HEADER
+#define GRUB_RELOCATOR_CPU_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/relocator.h>
+
+struct grub_relocator64_state
+{
+ /* gpr[0] is ignored since it's hardwired to 0. */
+ grub_uint64_t gpr[32];
+ /* Register holding target $pc. */
+ int jumpreg;
+};
+
+grub_err_t
+grub_relocator64_boot (struct grub_relocator *rel,
+ struct grub_relocator64_state state);
+
+#endif /* ! GRUB_RELOCATOR_CPU_HEADER */
diff --git a/include/grub/loongarch64/setjmp.h b/include/grub/loongarch64/setjmp.h
new file mode 100644
index 0000000..d9a0776
--- /dev/null
+++ b/include/grub/loongarch64/setjmp.h
@@ -0,0 +1,27 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004,2006,2007,2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+typedef grub_uint64_t grub_jmp_buf[12];
+
+int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE;
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/loongarch64/time.h b/include/grub/loongarch64/time.h
new file mode 100644
index 0000000..c9a7334
--- /dev/null
+++ b/include/grub/loongarch64/time.h
@@ -0,0 +1,39 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+#ifndef GRUB_UTIL
+
+#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2)
+
+void grub_timer_init (grub_uint32_t cpuclock);
+
+/* Return the real time in ticks. */
+grub_uint64_t grub_get_rtc (void);
+
+extern grub_uint32_t grub_arch_cpuclock;
+#endif
+
+static inline void
+grub_cpu_idle(void)
+{
+}
+
+#endif
diff --git a/include/grub/loongarch64/types.h b/include/grub/loongarch64/types.h
new file mode 100644
index 0000000..5dc7f21
--- /dev/null
+++ b/include/grub/loongarch64/types.h
@@ -0,0 +1,34 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2006,2007,2009,2017 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *. */
+#define GRUB_TARGET_SIZEOF_VOID_P 8
+
+/* The size of long. */
+#define GRUB_TARGET_SIZEOF_LONG 8
+
+#ifdef GRUB_CPU_LOONGARCH
+/* loongarch is little-endian. */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
+
+#endif
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index dad1756..33feae9 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -107,6 +107,7 @@ enum grub_install_plat
GRUB_INSTALL_PLATFORM_X86_64_XEN,
GRUB_INSTALL_PLATFORM_ARM64_EFI,
GRUB_INSTALL_PLATFORM_ARM_COREBOOT,
+ GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI,
GRUB_INSTALL_PLATFORM_MAX
};
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index fde4ca7..6504637 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -738,27 +738,28 @@ static struct
const char *platform;
} platforms[GRUB_INSTALL_PLATFORM_MAX] =
{
- [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" },
- [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" },
- [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" },
- [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" },
- [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" },
- [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" },
- [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" },
- [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" },
- [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" },
- [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" },
- [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" },
- [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" },
- [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" },
- [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" },
- [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" },
- [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" },
- [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" },
- [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" },
- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" },
- [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" },
- [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" },
+ [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" },
+ [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" },
+ [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" },
+ [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" },
+ [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" },
+ [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" },
+ [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" },
+ [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" },
+ [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" },
+ [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" },
+ [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" },
+ [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" },
+ [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" },
+ [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" },
+ [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" },
+ [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" },
+ [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" },
+ [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" },
+ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" },
+ [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" },
+ [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" },
+ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64", "efi" },
};
char *
diff --git a/util/grub-install.c b/util/grub-install.c
index 65bb2f9..28b5d74 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -322,6 +322,8 @@ get_default_platform (void)
return "arm-uboot";
#elif defined (__aarch64__)
return "arm64-efi";
+#elif defined (__loongarch64)
+ return "loongarch64-efi";
#elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__)
return grub_install_get_default_x86_platform ();
#else
@@ -477,6 +479,7 @@ have_bootdev (enum grub_install_plat pl)
case GRUB_INSTALL_PLATFORM_IA64_EFI:
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
@@ -895,6 +898,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_I386_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
is_efi = 1;
grub_util_error (_("this utility cannot be used for EFI platforms"
" because it does not support UEFI Secure Boot"));
@@ -921,6 +925,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
@@ -965,6 +970,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
case GRUB_INSTALL_PLATFORM_I386_QEMU:
@@ -1110,6 +1116,9 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
efi_file = "BOOTAA64.EFI";
break;
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
+ efi_file = "BOOTLOONGARCH64.EFI";
+ break;
default:
grub_util_error ("%s", _("You've found a bug"));
break;
@@ -1137,6 +1146,9 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
efi_file = "grubaa64.efi";
break;
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
+ efi_file = "grubloongarch64.efi";
+ break;
default:
efi_file = "grub.efi";
break;
@@ -1440,6 +1452,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
g = grub_util_guess_efi_drive (*curdev);
break;
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
@@ -1581,6 +1594,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
core_name = "core.efi";
snprintf (mkimage_target, sizeof (mkimage_target),
"%s-%s",
@@ -1683,6 +1697,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
@@ -1917,6 +1932,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI:
{
char *dst = grub_util_path_concat (2, efidir, efi_file);
grub_install_copy_file (imgfile, dst, 1);
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 1bb5eb8..240e193 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -783,6 +783,9 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
grub_uint64_t *gpptr = (void *) (pe_target + got_off);
unsigned unmatched_adr_got_page = 0;
+ grub_uint64_t oprs[10240]= {0};
+ int opri = -1;
+ grub_uint32_t la_abs = 0;
#define MASK19 ((1 << 19) - 1)
#else
grub_uint32_t *tr = (void *) (pe_target + tramp_off);
@@ -1122,6 +1125,173 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
}
break;
}
+ case EM_LOONGARCH64:
+ {
+ sym_addr += addend;
+ switch (ELF_R_TYPE (info))
+ {
+ case R_LARCH_64:
+ {
+ *target=(grub_uint64_t)sym_addr;
+ }
+ break;
+ case R_LARCH_MARK_LA:
+ {
+ la_abs=1;
+ }
+ break;
+ case R_LARCH_SOP_PUSH_PCREL:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset));
+ }
+ break;
+ case R_LARCH_SOP_PUSH_ABSOLUTE:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)sym_addr;
+ }
+ break;
+ case R_LARCH_SOP_PUSH_PLT_PCREL:
+ {
+ opri++;
+ oprs[opri]=(grub_uint64_t)(sym_addr-(target_section_addr+offset+image_target->vaddr_offset));
+ }
+ break;
+ case R_LARCH_SOP_SUB:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 - opr2;
+ }
+ break;
+ case R_LARCH_SOP_SL:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 << opr2;
+ }
+ break;
+ case R_LARCH_SOP_SR:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 >> opr2;
+ }
+ break;
+ case R_LARCH_SOP_ADD:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 + opr2;
+ }
+ break;
+ case R_LARCH_SOP_AND:
+ {
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ opri++;
+ oprs[opri]=opr1 & opr2;
+ }
+ break;
+ case R_LARCH_SOP_IF_ELSE:
+ {
+ grub_uint64_t opr3=oprs[opri];
+ opri--;
+ grub_uint64_t opr2=oprs[opri];
+ opri--;
+ grub_uint64_t opr1=oprs[opri];
+ opri--;
+ if(opr1){
+ opri++;
+ oprs[opri]=opr2;
+ } else {
+ opri++;
+ oprs[opri]=opr3;
+ }
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_5:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target=(*target) | ((opr1 & 0x1f) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_U_10_12:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target=(*target) | ((opr1 & 0xfff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_12:
+ {
+ if(la_abs==1)
+ la_abs=0;
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target = (*target) | ((opr1 & 0xfff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target = (*target) | ((opr1 & 0xffff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target = (*target) | (((opr1 >> 2) & 0xffff) << 10);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_5_20:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target = (*target) | ((opr1 & 0xfffff)<<5) ;
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10);
+ *target =(*target) | ((opr1 >> 18) & 0x1f);
+ }
+ break;
+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
+ {
+ grub_uint64_t opr1 = oprs[opri];
+ opri--;
+ *target =(*target) | (((opr1 >> 2) & 0xffff) << 10);
+ *target =(*target) | ((opr1 >> 18) & 0x3ff);
+ }
+ break;
+ default:
+ grub_util_error (_("relocation 0x%x is not implemented yet"),
+ (unsigned int) ELF_R_TYPE (info));
+ break;
+ }
+ break;
+ }
#endif
#if defined(MKIMAGE_ELF32)
case EM_ARM:
@@ -1310,7 +1480,10 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
/* The spec does not mention the requirement of a Page RVA.
Here, align the address with a 4K boundary for safety. */
- b->page_rva = (addr & ~(0x1000 - 1));
+#ifdef GRUB_CPU_LOONGARCH64
+ if (type)
+#endif
+ b->page_rva = (addr & ~(0x1000 - 1));
b->block_size = sizeof (*b);
}
@@ -1320,7 +1493,11 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
/* Add a new entry. */
cur_index = ((b->block_size - sizeof (*b)) >> 1);
+#ifdef GRUB_CPU_LOONGARCH64
+ entry = GRUB_PE32_FIXUP_ENTRY (type, type ? (addr - b->page_rva) : addr);
+#else
entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
+#endif
b->entries[cur_index] = grub_host_to_target16 (entry);
b->block_size += 2;
}
@@ -1366,6 +1543,10 @@ static void
translate_relocation_pe (struct translate_context *ctx,
Elf_Addr addr,
Elf_Addr info,
+#ifdef GRUB_CPU_LOONGARCH64
+ Elf_Addr sym_addr,
+ Elf_Addr addend,
+#endif
const struct grub_install_image_target_desc *image_target)
{
/* Necessary to relocate only absolute addresses. */
@@ -1477,6 +1658,133 @@ translate_relocation_pe (struct translate_context *ctx,
}
break;
break;
+ case EM_LOONGARCH64:
+ switch (ELF_R_TYPE (info))
+ {
+ case R_LARCH_NONE:
+ break;
+ case R_LARCH_32:
+ break;
+ case R_LARCH_64:
+ {
+ ctx->current_address = add_fixup_entry (
+ &ctx->lst,
+ GRUB_PE32_REL_BASED_DIR64,
+ addr, 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_LARCH_RELATIVE:
+ break;
+ case R_LARCH_COPY:
+ break;
+ case R_LARCH_JUMP_SLOT:
+ break;
+ case R_LARCH_TLS_DTPMOD32:
+ break;
+ case R_LARCH_TLS_DTPMOD64:
+ break;
+ case R_LARCH_TLS_DTPREL32:
+ break;
+ case R_LARCH_TLS_DTPREL64:
+ break;
+ case R_LARCH_TLS_TPREL32:
+ break;
+ case R_LARCH_TLS_TPREL64:
+ break;
+ case R_LARCH_IRELATIVE:
+ break;
+ case R_LARCH_MARK_LA:
+ {
+ ctx->current_address = add_fixup_entry (
+ &ctx->lst,
+ GRUB_PE32_REL_BASED_LOONGARCH64,
+ addr, 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_LARCH_MARK_PCREL:
+ break;
+ case R_LARCH_SOP_PUSH_PCREL:
+ break;
+ case R_LARCH_SOP_PUSH_ABSOLUTE:
+ break;
+ case R_LARCH_SOP_PUSH_DUP:
+ break;
+ case R_LARCH_SOP_PUSH_GPREL:
+ break;
+ case R_LARCH_SOP_PUSH_TLS_TPREL:
+ break;
+ case R_LARCH_SOP_PUSH_TLS_GOT:
+ break;
+ case R_LARCH_SOP_PUSH_TLS_GD:
+ break;
+ case R_LARCH_SOP_PUSH_PLT_PCREL:
+ break;
+ case R_LARCH_SOP_ASSERT:
+ break;
+ case R_LARCH_SOP_NOT:
+ break;
+ case R_LARCH_SOP_SUB:
+ break;
+ case R_LARCH_SOP_SL:
+ break;
+ case R_LARCH_SOP_SR:
+ break;
+ case R_LARCH_SOP_ADD:
+ break;
+ case R_LARCH_SOP_AND:
+ break;
+ case R_LARCH_SOP_IF_ELSE:
+ break;
+ case R_LARCH_SOP_POP_32_S_10_5:
+ break;
+ case R_LARCH_SOP_POP_32_U_10_12:
+ break;
+ case R_LARCH_SOP_POP_32_S_10_12:
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16:
+ break;
+ case R_LARCH_SOP_POP_32_S_10_16_S2:
+ break;
+ case R_LARCH_SOP_POP_32_S_5_20:
+ break;
+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
+ break;
+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
+ break;
+ case R_LARCH_SOP_POP_32_U:
+ break;
+ case R_LARCH_ADD8:
+ break;
+ case R_LARCH_ADD16:
+ break;
+ case R_LARCH_ADD24:
+ break;
+ case R_LARCH_ADD32:
+ break;
+ case R_LARCH_ADD64:
+ break;
+ case R_LARCH_SUB8:
+ break;
+ case R_LARCH_SUB16:
+ break;
+ case R_LARCH_SUB24:
+ break;
+ case R_LARCH_SUB32:
+ break;
+ case R_LARCH_SUB64:
+ break;
+ case R_LARCH_GNU_VTINHERIT:
+ break;
+ case R_LARCH_GNU_VTENTRY:
+ break;
+ default:
+ grub_util_error (_("relocation 0x%x is not implemented yet"),
+ (unsigned int) ELF_R_TYPE (info));
+ break;
+ }
+ break;
#if defined(MKIMAGE_ELF32)
case EM_ARM:
switch (ELF_R_TYPE (info))
@@ -1565,10 +1873,18 @@ static void
translate_relocation (struct translate_context *ctx,
Elf_Addr addr,
Elf_Addr info,
+#ifdef GRUB_CPU_LOONGARCH64
+ Elf_Addr sym_addr,
+ Elf_Addr addend,
+#endif
const struct grub_install_image_target_desc *image_target)
{
if (image_target->id == IMAGE_EFI)
+#ifdef GRUB_CPU_LOONGARCH64
+ translate_relocation_pe (ctx, addr, info, sym_addr, addend, image_target);
+#else
translate_relocation_pe (ctx, addr, info, image_target);
+#endif
else
translate_relocation_raw (ctx, addr, info, image_target);
}
@@ -1709,11 +2025,21 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
(grub_target_to_host32 (s->sh_type) == SHT_RELA))
{
+#ifdef GRUB_CPU_LOONGARCH64
+ Elf_Rela *r;
+#else
Elf_Rel *r;
+#endif
Elf_Word rtab_size, r_size, num_rs;
Elf_Off rtab_offset;
Elf_Addr section_address;
Elf_Word j;
+#ifdef GRUB_CPU_LOONGARCH64
+ Elf_Shdr *symtab_section;
+
+ symtab_section = (Elf_Shdr *) ((char *) smd->sections
+ + (grub_target_to_host32 (s->sh_link) * smd->section_entsize));
+#endif
if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
{
@@ -1732,20 +2058,39 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
+#ifdef GRUB_CPU_LOONGARCH64
+ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
+ j < num_rs;
+ j++, r = (Elf_Rela *) ((char *) r + r_size))
+#else
for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
j < num_rs;
j++, r = (Elf_Rel *) ((char *) r + r_size))
+#endif
{
Elf_Addr info;
Elf_Addr offset;
Elf_Addr addr;
+#ifdef GRUB_CPU_LOONGARCH64
+ Elf_Addr sym_addr;
+ Elf_Addr addend;
+#endif
offset = grub_target_to_host (r->r_offset);
info = grub_target_to_host (r->r_info);
-
+#ifdef GRUB_CPU_LOONGARCH64
+ sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
+ ELF_R_SYM (info), image_target);
+ addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
+ grub_target_to_host (r->r_addend) : 0;
+#endif
addr = section_address + offset;
+#ifdef GRUB_CPU_LOONGARCH64
+ translate_relocation (&ctx, addr, info, sym_addr, addend, image_target);
+#else
translate_relocation (&ctx, addr, info, image_target);
+#endif
}
}
diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c
index ae31271..c998850 100644
--- a/util/grub-mknetdir.c
+++ b/util/grub-mknetdir.c
@@ -112,7 +112,8 @@ static struct
[GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" },
[GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" },
[GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" },
- [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }
+ [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" },
+ [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64-efi", "efinet", ".efi" }
};
static void
diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
index 03ba1ab..4a9943a 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -119,6 +119,52 @@ struct grub_module_verifier_arch archs[] = {
-1
}
},
+ { "loongarch64", 8, 0, EM_LOONGARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+ R_LARCH_NONE,
+ R_LARCH_32,
+ R_LARCH_64,
+ R_LARCH_RELATIVE,
+ R_LARCH_COPY,
+ R_LARCH_JUMP_SLOT,
+ R_LARCH_TLS_DTPMOD32,
+ R_LARCH_TLS_DTPMOD64,
+ R_LARCH_TLS_DTPREL32,
+ R_LARCH_TLS_DTPREL64,
+ R_LARCH_TLS_TPREL32,
+ R_LARCH_TLS_TPREL64,
+ R_LARCH_IRELATIVE,
+ R_LARCH_MARK_LA,
+ R_LARCH_MARK_PCREL,
+ R_LARCH_SOP_PUSH_PCREL,
+ R_LARCH_SOP_PUSH_ABSOLUTE,
+ R_LARCH_SOP_PUSH_DUP,
+ R_LARCH_SOP_PUSH_GPREL,
+ R_LARCH_SOP_PUSH_TLS_TPREL,
+ R_LARCH_SOP_PUSH_TLS_GOT,
+ R_LARCH_SOP_PUSH_TLS_GD,
+ R_LARCH_SOP_PUSH_PLT_PCREL,
+ R_LARCH_SOP_ASSERT,
+ R_LARCH_SOP_NOT,
+ R_LARCH_SOP_SUB,
+ R_LARCH_SOP_SL,
+ R_LARCH_SOP_SR,
+ R_LARCH_SOP_ADD,
+ R_LARCH_SOP_AND,
+ R_LARCH_SOP_IF_ELSE,
+ R_LARCH_SOP_POP_32_S_10_5,
+ R_LARCH_SOP_POP_32_U_10_12,
+ R_LARCH_SOP_POP_32_S_10_12,
+ R_LARCH_SOP_POP_32_S_10_16,
+ R_LARCH_SOP_POP_32_S_10_16_S2,
+ R_LARCH_SOP_POP_32_S_5_20,
+ R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
+ R_LARCH_SOP_POP_32_S_0_10_10_16_S2,
+ R_LARCH_SOP_POP_32_U,
+ -1
+ }, (int[]){
+ -1
+ }
+ },
};
struct platform_whitelist {
diff --git a/util/mkimage.c b/util/mkimage.c
index c770259..250ca81 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -609,6 +609,22 @@ static const struct grub_install_image_target_desc image_targets[] =
.pe_target = GRUB_PE32_MACHINE_ARM64,
.elf_target = EM_AARCH64,
},
+ {
+ .dirname = "loongarch64-efi",
+ .names = { "loongarch64-efi", NULL },
+ .voidp_sizeof = 8,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = EFI64_HEADER_SIZE,
+ .pe_target = GRUB_PE32_MACHINE_LOONGARCH64,
+ .elf_target = EM_LOONGARCH64,
+ },
};
#include <grub/lib/LzmaEnc.h>
--
2.1.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-anolis-os/grub2.git
git@gitee.com:src-anolis-os/grub2.git
src-anolis-os
grub2
grub2
a8

Search

23e8dbc6 1850385 7e0993f3 1850385